Commit a882f4d7 authored by Cezary Rojewski's avatar Cezary Rojewski Committed by Mark Brown

ASoC: Intel: Remove skylake driver

The avs-driver found in sound/soc/intel/avs is a direct replacement to
the existing skylake-driver. It covers all features supported by it and
more and aligns with the recommended flows and requirements based on
Windows driver equivalent.

For the official kernel tree the deprecation begun with v6.0. Most
skylake-drivers users moved to avs- or SOF-driver when AudioDSP
capabilities are available on the platform or to snd-hda-intel
(sound/pci/hda) when such capabilities are not.

For the supported trees the deprecation begun with v5.4 with v5.15 being
the first where the skylake-driver is disabled entirely.

All machine board drivers that consume the DSP driver have their
replacements present within sound/soc/intel/avs/boards/ directory.
Acked-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: default avatarCezary Rojewski <cezary.rojewski@intel.com>
Link: https://patch.msgid.link/20240814083929.1217319-14-cezary.rojewski@intel.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 6de8dddc
......@@ -67,126 +67,6 @@ config SND_SST_ATOM_HIFI2_PLATFORM_ACPI
Baytrail/Cherrytrail. If you want to enable SOF on
Baytrail/Cherrytrail, you need to deselect this option first.
config SND_SOC_INTEL_SKYLAKE
tristate "All Skylake/SST Platforms"
depends on PCI && ACPI
depends on COMMON_CLK
select SND_SOC_INTEL_SKL
select SND_SOC_INTEL_APL
select SND_SOC_INTEL_KBL
select SND_SOC_INTEL_GLK
select SND_SOC_INTEL_CNL
select SND_SOC_INTEL_CFL
help
This is a backwards-compatible option to select all devices
supported by the Intel SST/Skylake driver. This option is no
longer recommended and will be deprecated when the SOF
driver is introduced. Distributions should explicitly
select which platform uses this driver.
config SND_SOC_INTEL_SKL
tristate "Skylake Platforms"
depends on PCI && ACPI
depends on COMMON_CLK
select SND_SOC_INTEL_SKYLAKE_FAMILY
help
If you have a Intel Skylake platform with the DSP enabled
in the BIOS then enable this option by saying Y or m.
config SND_SOC_INTEL_APL
tristate "Broxton/ApolloLake Platforms"
depends on PCI && ACPI
depends on COMMON_CLK
select SND_SOC_INTEL_SKYLAKE_FAMILY
help
If you have a Intel Broxton/ApolloLake platform with the DSP
enabled in the BIOS then enable this option by saying Y or m.
config SND_SOC_INTEL_KBL
tristate "Kabylake Platforms"
depends on PCI && ACPI
depends on COMMON_CLK
select SND_SOC_INTEL_SKYLAKE_FAMILY
help
If you have a Intel Kabylake platform with the DSP
enabled in the BIOS then enable this option by saying Y or m.
config SND_SOC_INTEL_GLK
tristate "GeminiLake Platforms"
depends on PCI && ACPI
depends on COMMON_CLK
select SND_SOC_INTEL_SKYLAKE_FAMILY
help
If you have a Intel GeminiLake platform with the DSP
enabled in the BIOS then enable this option by saying Y or m.
config SND_SOC_INTEL_CNL
tristate "CannonLake/WhiskyLake Platforms"
depends on PCI && ACPI
depends on COMMON_CLK
select SND_SOC_INTEL_SKYLAKE_FAMILY
help
If you have a Intel CNL/WHL platform with the DSP
enabled in the BIOS then enable this option by saying Y or m.
config SND_SOC_INTEL_CFL
tristate "CoffeeLake Platforms"
depends on PCI && ACPI
depends on COMMON_CLK
select SND_SOC_INTEL_SKYLAKE_FAMILY
help
If you have a Intel CoffeeLake platform with the DSP
enabled in the BIOS then enable this option by saying Y or m.
config SND_SOC_INTEL_CML_H
tristate "CometLake-H Platforms"
depends on PCI && ACPI
depends on COMMON_CLK
select SND_SOC_INTEL_SKYLAKE_FAMILY
help
If you have a Intel CometLake-H platform with the DSP
enabled in the BIOS then enable this option by saying Y or m.
config SND_SOC_INTEL_CML_LP
tristate "CometLake-LP Platforms"
depends on PCI && ACPI
depends on COMMON_CLK
select SND_SOC_INTEL_SKYLAKE_FAMILY
help
If you have a Intel CometLake-LP platform with the DSP
enabled in the BIOS then enable this option by saying Y or m.
config SND_SOC_INTEL_SKYLAKE_FAMILY
tristate
select SND_SOC_INTEL_SKYLAKE_COMMON
if SND_SOC_INTEL_SKYLAKE_FAMILY
config SND_SOC_INTEL_SKYLAKE_SSP_CLK
tristate
config SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC
bool "HDAudio codec support"
help
If you have Intel Skylake or Kabylake with HDAudio codec
and DMIC present then enable this option by saying Y.
config SND_SOC_INTEL_SKYLAKE_COMMON
tristate
select SND_HDA_EXT_CORE
select SND_HDA_DSP_LOADER
select SND_SOC_TOPOLOGY
select SND_SOC_INTEL_SST
select SND_SOC_HDAC_HDA
select SND_SOC_ACPI_INTEL_MATCH
select SND_INTEL_DSP_CONFIG
help
If you have a Intel Skylake/Broxton/ApolloLake/KabyLake/
GeminiLake or CannonLake platform with the DSP enabled in the BIOS
then enable this option by saying Y or m.
endif ## SND_SOC_INTEL_SKYLAKE_FAMILY
endif ## SND_SOC_INTEL_SST_TOPLEVEL
if SND_SOC_INTEL_SST_TOPLEVEL || SND_SOC_SOF_INTEL_TOPLEVEL
......
......@@ -5,7 +5,6 @@ obj-$(CONFIG_SND_SOC) += common/
# Platform Support
obj-$(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM) += atom/
obj-$(CONFIG_SND_SOC_INTEL_CATPT) += catpt/
obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE_COMMON) += skylake/
obj-$(CONFIG_SND_SOC_INTEL_KEEMBAY) += keembay/
obj-$(CONFIG_SND_SOC_INTEL_AVS) += avs/
......
......@@ -300,7 +300,7 @@ config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH
endif ## SND_SOC_SOF_GEMINILAKE
if SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC || SND_SOC_SOF_HDA_AUDIO_CODEC
if SND_SOC_SOF_HDA_AUDIO_CODEC
config SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH
tristate "Skylake+ with HDA Codecs"
......@@ -316,7 +316,7 @@ config SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH
Say Y or m if you have such a device. This is a recommended option.
If unsure select "N".
endif ## SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC || SND_SOC_SOF_HDA_AUDIO_CODEC
endif ## SND_SOC_SOF_HDA_AUDIO_CODEC
if SND_SOC_SOF_HDA_LINK || SND_SOC_SOF_BAYTRAIL
config SND_SOC_INTEL_SOF_RT5682_MACH
......
# SPDX-License-Identifier: GPL-2.0-only
snd-soc-skl-y := skl.o skl-pcm.o skl-nhlt.o skl-messages.o skl-topology.o \
skl-sst-ipc.o skl-sst-dsp.o cnl-sst-dsp.o skl-sst-cldma.o \
skl-sst.o bxt-sst.o cnl-sst.o skl-sst-utils.o
ifdef CONFIG_DEBUG_FS
snd-soc-skl-y += skl-debug.o
endif
obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE_COMMON) += snd-soc-skl.o
#Skylake Clock device support
snd-soc-skl-ssp-clk-y := skl-ssp-clk.o
obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE_SSP_CLK) += snd-soc-skl-ssp-clk.o
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0-only
/*
* cnl-sst-dsp.c - CNL SST library generic function
*
* Copyright (C) 2016-17, Intel Corporation.
* Author: Guneshwor Singh <guneshwor.o.singh@intel.com>
*
* Modified from:
* SKL SST library generic function
* Copyright (C) 2014-15, Intel Corporation.
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#include <linux/device.h>
#include "../common/sst-dsp.h"
#include "../common/sst-ipc.h"
#include "../common/sst-dsp-priv.h"
#include "cnl-sst-dsp.h"
/* various timeout values */
#define CNL_DSP_PU_TO 50
#define CNL_DSP_PD_TO 50
#define CNL_DSP_RESET_TO 50
static int
cnl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask)
{
/* update bits */
sst_dsp_shim_update_bits_unlocked(ctx,
CNL_ADSP_REG_ADSPCS, CNL_ADSPCS_CRST(core_mask),
CNL_ADSPCS_CRST(core_mask));
/* poll with timeout to check if operation successful */
return sst_dsp_register_poll(ctx,
CNL_ADSP_REG_ADSPCS,
CNL_ADSPCS_CRST(core_mask),
CNL_ADSPCS_CRST(core_mask),
CNL_DSP_RESET_TO,
"Set reset");
}
static int
cnl_dsp_core_unset_reset_state(struct sst_dsp *ctx, unsigned int core_mask)
{
/* update bits */
sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
CNL_ADSPCS_CRST(core_mask), 0);
/* poll with timeout to check if operation successful */
return sst_dsp_register_poll(ctx,
CNL_ADSP_REG_ADSPCS,
CNL_ADSPCS_CRST(core_mask),
0,
CNL_DSP_RESET_TO,
"Unset reset");
}
static bool is_cnl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask)
{
int val;
bool is_enable;
val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPCS);
is_enable = (val & CNL_ADSPCS_CPA(core_mask)) &&
(val & CNL_ADSPCS_SPA(core_mask)) &&
!(val & CNL_ADSPCS_CRST(core_mask)) &&
!(val & CNL_ADSPCS_CSTALL(core_mask));
dev_dbg(ctx->dev, "DSP core(s) enabled? %d: core_mask %#x\n",
is_enable, core_mask);
return is_enable;
}
static int cnl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask)
{
/* stall core */
sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
CNL_ADSPCS_CSTALL(core_mask),
CNL_ADSPCS_CSTALL(core_mask));
/* set reset state */
return cnl_dsp_core_set_reset_state(ctx, core_mask);
}
static int cnl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask)
{
int ret;
/* unset reset state */
ret = cnl_dsp_core_unset_reset_state(ctx, core_mask);
if (ret < 0)
return ret;
/* run core */
sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
CNL_ADSPCS_CSTALL(core_mask), 0);
if (!is_cnl_dsp_core_enable(ctx, core_mask)) {
cnl_dsp_reset_core(ctx, core_mask);
dev_err(ctx->dev, "DSP core mask %#x enable failed\n",
core_mask);
ret = -EIO;
}
return ret;
}
static int cnl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask)
{
/* update bits */
sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
CNL_ADSPCS_SPA(core_mask),
CNL_ADSPCS_SPA(core_mask));
/* poll with timeout to check if operation successful */
return sst_dsp_register_poll(ctx, CNL_ADSP_REG_ADSPCS,
CNL_ADSPCS_CPA(core_mask),
CNL_ADSPCS_CPA(core_mask),
CNL_DSP_PU_TO,
"Power up");
}
static int cnl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask)
{
/* update bits */
sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
CNL_ADSPCS_SPA(core_mask), 0);
/* poll with timeout to check if operation successful */
return sst_dsp_register_poll(ctx,
CNL_ADSP_REG_ADSPCS,
CNL_ADSPCS_CPA(core_mask),
0,
CNL_DSP_PD_TO,
"Power down");
}
int cnl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask)
{
int ret;
/* power up */
ret = cnl_dsp_core_power_up(ctx, core_mask);
if (ret < 0) {
dev_dbg(ctx->dev, "DSP core mask %#x power up failed",
core_mask);
return ret;
}
return cnl_dsp_start_core(ctx, core_mask);
}
int cnl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask)
{
int ret;
ret = cnl_dsp_reset_core(ctx, core_mask);
if (ret < 0) {
dev_err(ctx->dev, "DSP core mask %#x reset failed\n",
core_mask);
return ret;
}
/* power down core*/
ret = cnl_dsp_core_power_down(ctx, core_mask);
if (ret < 0) {
dev_err(ctx->dev, "DSP core mask %#x power down failed\n",
core_mask);
return ret;
}
if (is_cnl_dsp_core_enable(ctx, core_mask)) {
dev_err(ctx->dev, "DSP core mask %#x disable failed\n",
core_mask);
ret = -EIO;
}
return ret;
}
irqreturn_t cnl_dsp_sst_interrupt(int irq, void *dev_id)
{
struct sst_dsp *ctx = dev_id;
u32 val;
irqreturn_t ret = IRQ_NONE;
spin_lock(&ctx->spinlock);
val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS);
ctx->intr_status = val;
if (val == 0xffffffff) {
spin_unlock(&ctx->spinlock);
return IRQ_NONE;
}
if (val & CNL_ADSPIS_IPC) {
cnl_ipc_int_disable(ctx);
ret = IRQ_WAKE_THREAD;
}
spin_unlock(&ctx->spinlock);
return ret;
}
void cnl_dsp_free(struct sst_dsp *dsp)
{
cnl_ipc_int_disable(dsp);
free_irq(dsp->irq, dsp);
cnl_ipc_op_int_disable(dsp);
cnl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK);
}
EXPORT_SYMBOL_GPL(cnl_dsp_free);
void cnl_ipc_int_enable(struct sst_dsp *ctx)
{
sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_ADSPIC,
CNL_ADSPIC_IPC, CNL_ADSPIC_IPC);
}
void cnl_ipc_int_disable(struct sst_dsp *ctx)
{
sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPIC,
CNL_ADSPIC_IPC, 0);
}
void cnl_ipc_op_int_enable(struct sst_dsp *ctx)
{
/* enable IPC DONE interrupt */
sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
CNL_ADSP_REG_HIPCCTL_DONE,
CNL_ADSP_REG_HIPCCTL_DONE);
/* enable IPC BUSY interrupt */
sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
CNL_ADSP_REG_HIPCCTL_BUSY,
CNL_ADSP_REG_HIPCCTL_BUSY);
}
void cnl_ipc_op_int_disable(struct sst_dsp *ctx)
{
/* disable IPC DONE interrupt */
sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
CNL_ADSP_REG_HIPCCTL_DONE, 0);
/* disable IPC BUSY interrupt */
sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
CNL_ADSP_REG_HIPCCTL_BUSY, 0);
}
bool cnl_ipc_int_status(struct sst_dsp *ctx)
{
return sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS) &
CNL_ADSPIS_IPC;
}
void cnl_ipc_free(struct sst_generic_ipc *ipc)
{
cnl_ipc_op_int_disable(ipc->dsp);
sst_ipc_fini(ipc);
}
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Cannonlake SST DSP Support
*
* Copyright (C) 2016-17, Intel Corporation.
*/
#ifndef __CNL_SST_DSP_H__
#define __CNL_SST_DSP_H__
struct sst_dsp;
struct sst_dsp_device;
struct sst_generic_ipc;
/* Intel HD Audio General DSP Registers */
#define CNL_ADSP_GEN_BASE 0x0
#define CNL_ADSP_REG_ADSPCS (CNL_ADSP_GEN_BASE + 0x04)
#define CNL_ADSP_REG_ADSPIC (CNL_ADSP_GEN_BASE + 0x08)
#define CNL_ADSP_REG_ADSPIS (CNL_ADSP_GEN_BASE + 0x0c)
/* Intel HD Audio Inter-Processor Communication Registers */
#define CNL_ADSP_IPC_BASE 0xc0
#define CNL_ADSP_REG_HIPCTDR (CNL_ADSP_IPC_BASE + 0x00)
#define CNL_ADSP_REG_HIPCTDA (CNL_ADSP_IPC_BASE + 0x04)
#define CNL_ADSP_REG_HIPCTDD (CNL_ADSP_IPC_BASE + 0x08)
#define CNL_ADSP_REG_HIPCIDR (CNL_ADSP_IPC_BASE + 0x10)
#define CNL_ADSP_REG_HIPCIDA (CNL_ADSP_IPC_BASE + 0x14)
#define CNL_ADSP_REG_HIPCIDD (CNL_ADSP_IPC_BASE + 0x18)
#define CNL_ADSP_REG_HIPCCTL (CNL_ADSP_IPC_BASE + 0x28)
/* HIPCTDR */
#define CNL_ADSP_REG_HIPCTDR_BUSY BIT(31)
/* HIPCTDA */
#define CNL_ADSP_REG_HIPCTDA_DONE BIT(31)
/* HIPCIDR */
#define CNL_ADSP_REG_HIPCIDR_BUSY BIT(31)
/* HIPCIDA */
#define CNL_ADSP_REG_HIPCIDA_DONE BIT(31)
/* CNL HIPCCTL */
#define CNL_ADSP_REG_HIPCCTL_DONE BIT(1)
#define CNL_ADSP_REG_HIPCCTL_BUSY BIT(0)
/* CNL HIPCT */
#define CNL_ADSP_REG_HIPCT_BUSY BIT(31)
/* Intel HD Audio SRAM Window 1 */
#define CNL_ADSP_SRAM1_BASE 0xa0000
#define CNL_ADSP_MMIO_LEN 0x10000
#define CNL_ADSP_W0_STAT_SZ 0x1000
#define CNL_ADSP_W0_UP_SZ 0x1000
#define CNL_ADSP_W1_SZ 0x1000
#define CNL_FW_STS_MASK 0xf
#define CNL_ADSPIC_IPC 0x1
#define CNL_ADSPIS_IPC 0x1
#define CNL_DSP_CORES 4
#define CNL_DSP_CORES_MASK ((1 << CNL_DSP_CORES) - 1)
/* core reset - asserted high */
#define CNL_ADSPCS_CRST_SHIFT 0
#define CNL_ADSPCS_CRST(x) (x << CNL_ADSPCS_CRST_SHIFT)
/* core run/stall - when set to 1 core is stalled */
#define CNL_ADSPCS_CSTALL_SHIFT 8
#define CNL_ADSPCS_CSTALL(x) (x << CNL_ADSPCS_CSTALL_SHIFT)
/* set power active - when set to 1 turn core on */
#define CNL_ADSPCS_SPA_SHIFT 16
#define CNL_ADSPCS_SPA(x) (x << CNL_ADSPCS_SPA_SHIFT)
/* current power active - power status of cores, set by hardware */
#define CNL_ADSPCS_CPA_SHIFT 24
#define CNL_ADSPCS_CPA(x) (x << CNL_ADSPCS_CPA_SHIFT)
int cnl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask);
int cnl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask);
irqreturn_t cnl_dsp_sst_interrupt(int irq, void *dev_id);
void cnl_dsp_free(struct sst_dsp *dsp);
void cnl_ipc_int_enable(struct sst_dsp *ctx);
void cnl_ipc_int_disable(struct sst_dsp *ctx);
void cnl_ipc_op_int_enable(struct sst_dsp *ctx);
void cnl_ipc_op_int_disable(struct sst_dsp *ctx);
bool cnl_ipc_int_status(struct sst_dsp *ctx);
void cnl_ipc_free(struct sst_generic_ipc *ipc);
int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
const char *fw_name, struct skl_dsp_loader_ops dsp_ops,
struct skl_dev **dsp);
int cnl_sst_init_fw(struct device *dev, struct skl_dev *skl);
void cnl_sst_dsp_cleanup(struct device *dev, struct skl_dev *skl);
#endif /*__CNL_SST_DSP_H__*/
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0-only
/*
* skl-debug.c - Debugfs for skl driver
*
* Copyright (C) 2016-17 Intel Corp
*/
#include <linux/pci.h>
#include <linux/debugfs.h>
#include <uapi/sound/skl-tplg-interface.h>
#include "skl.h"
#include "skl-sst-dsp.h"
#include "skl-sst-ipc.h"
#include "skl-topology.h"
#include "../common/sst-dsp.h"
#include "../common/sst-dsp-priv.h"
#define MOD_BUF PAGE_SIZE
#define FW_REG_BUF PAGE_SIZE
#define FW_REG_SIZE 0x60
struct skl_debug {
struct skl_dev *skl;
struct device *dev;
struct dentry *fs;
struct dentry *modules;
u8 fw_read_buff[FW_REG_BUF];
};
static ssize_t skl_print_pins(struct skl_module_pin *m_pin, char *buf,
int max_pin, ssize_t size, bool direction)
{
int i;
ssize_t ret = 0;
for (i = 0; i < max_pin; i++) {
ret += scnprintf(buf + size, MOD_BUF - size,
"%s %d\n\tModule %d\n\tInstance %d\n\t"
"In-used %s\n\tType %s\n"
"\tState %d\n\tIndex %d\n",
direction ? "Input Pin:" : "Output Pin:",
i, m_pin[i].id.module_id,
m_pin[i].id.instance_id,
m_pin[i].in_use ? "Used" : "Unused",
m_pin[i].is_dynamic ? "Dynamic" : "Static",
m_pin[i].pin_state, i);
size += ret;
}
return ret;
}
static ssize_t skl_print_fmt(struct skl_module_fmt *fmt, char *buf,
ssize_t size, bool direction)
{
return scnprintf(buf + size, MOD_BUF - size,
"%s\n\tCh %d\n\tFreq %d\n\tBit depth %d\n\t"
"Valid bit depth %d\n\tCh config %#x\n\tInterleaving %d\n\t"
"Sample Type %d\n\tCh Map %#x\n",
direction ? "Input Format:" : "Output Format:",
fmt->channels, fmt->s_freq, fmt->bit_depth,
fmt->valid_bit_depth, fmt->ch_cfg,
fmt->interleaving_style, fmt->sample_type,
fmt->ch_map);
}
static ssize_t module_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct skl_module_cfg *mconfig = file->private_data;
struct skl_module *module = mconfig->module;
struct skl_module_res *res = &module->resources[mconfig->res_idx];
char *buf;
ssize_t ret;
buf = kzalloc(MOD_BUF, GFP_KERNEL);
if (!buf)
return -ENOMEM;
ret = scnprintf(buf, MOD_BUF, "Module:\n\tUUID %pUL\n\tModule id %d\n"
"\tInstance id %d\n\tPvt_id %d\n", mconfig->guid,
mconfig->id.module_id, mconfig->id.instance_id,
mconfig->id.pvt_id);
ret += scnprintf(buf + ret, MOD_BUF - ret,
"Resources:\n\tCPC %#x\n\tIBS %#x\n\tOBS %#x\t\n",
res->cpc, res->ibs, res->obs);
ret += scnprintf(buf + ret, MOD_BUF - ret,
"Module data:\n\tCore %d\n\tIn queue %d\n\t"
"Out queue %d\n\tType %s\n",
mconfig->core_id, mconfig->max_in_queue,
mconfig->max_out_queue,
mconfig->is_loadable ? "loadable" : "inbuilt");
ret += skl_print_fmt(mconfig->in_fmt, buf, ret, true);
ret += skl_print_fmt(mconfig->out_fmt, buf, ret, false);
ret += scnprintf(buf + ret, MOD_BUF - ret,
"Fixup:\n\tParams %#x\n\tConverter %#x\n",
mconfig->params_fixup, mconfig->converter);
ret += scnprintf(buf + ret, MOD_BUF - ret,
"Module Gateway:\n\tType %#x\n\tVbus %#x\n\tHW conn %#x\n\tSlot %#x\n",
mconfig->dev_type, mconfig->vbus_id,
mconfig->hw_conn_type, mconfig->time_slot);
ret += scnprintf(buf + ret, MOD_BUF - ret,
"Pipeline:\n\tID %d\n\tPriority %d\n\tConn Type %d\n\t"
"Pages %#x\n", mconfig->pipe->ppl_id,
mconfig->pipe->pipe_priority, mconfig->pipe->conn_type,
mconfig->pipe->memory_pages);
ret += scnprintf(buf + ret, MOD_BUF - ret,
"\tParams:\n\t\tHost DMA %d\n\t\tLink DMA %d\n",
mconfig->pipe->p_params->host_dma_id,
mconfig->pipe->p_params->link_dma_id);
ret += scnprintf(buf + ret, MOD_BUF - ret,
"\tPCM params:\n\t\tCh %d\n\t\tFreq %d\n\t\tFormat %d\n",
mconfig->pipe->p_params->ch,
mconfig->pipe->p_params->s_freq,
mconfig->pipe->p_params->s_fmt);
ret += scnprintf(buf + ret, MOD_BUF - ret,
"\tLink %#x\n\tStream %#x\n",
mconfig->pipe->p_params->linktype,
mconfig->pipe->p_params->stream);
ret += scnprintf(buf + ret, MOD_BUF - ret,
"\tState %d\n\tPassthru %s\n",
mconfig->pipe->state,
mconfig->pipe->passthru ? "true" : "false");
ret += skl_print_pins(mconfig->m_in_pin, buf,
mconfig->max_in_queue, ret, true);
ret += skl_print_pins(mconfig->m_out_pin, buf,
mconfig->max_out_queue, ret, false);
ret += scnprintf(buf + ret, MOD_BUF - ret,
"Other:\n\tDomain %d\n\tHomogeneous Input %s\n\t"
"Homogeneous Output %s\n\tIn Queue Mask %d\n\t"
"Out Queue Mask %d\n\tDMA ID %d\n\tMem Pages %d\n\t"
"Module Type %d\n\tModule State %d\n",
mconfig->domain,
mconfig->homogenous_inputs ? "true" : "false",
mconfig->homogenous_outputs ? "true" : "false",
mconfig->in_queue_mask, mconfig->out_queue_mask,
mconfig->dma_id, mconfig->mem_pages, mconfig->m_state,
mconfig->m_type);
ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
kfree(buf);
return ret;
}
static const struct file_operations mcfg_fops = {
.open = simple_open,
.read = module_read,
.llseek = default_llseek,
};
void skl_debug_init_module(struct skl_debug *d,
struct snd_soc_dapm_widget *w,
struct skl_module_cfg *mconfig)
{
debugfs_create_file(w->name, 0444, d->modules, mconfig,
&mcfg_fops);
}
static ssize_t fw_softreg_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct skl_debug *d = file->private_data;
struct sst_dsp *sst = d->skl->dsp;
size_t w0_stat_sz = sst->addr.w0_stat_sz;
void __iomem *in_base = sst->mailbox.in_base;
void __iomem *fw_reg_addr;
unsigned int offset;
char *tmp;
ssize_t ret = 0;
tmp = kzalloc(FW_REG_BUF, GFP_KERNEL);
if (!tmp)
return -ENOMEM;
fw_reg_addr = in_base - w0_stat_sz;
memset(d->fw_read_buff, 0, FW_REG_BUF);
if (w0_stat_sz > 0)
__ioread32_copy(d->fw_read_buff, fw_reg_addr, w0_stat_sz >> 2);
for (offset = 0; offset < FW_REG_SIZE; offset += 16) {
ret += scnprintf(tmp + ret, FW_REG_BUF - ret, "%#.4x: ", offset);
hex_dump_to_buffer(d->fw_read_buff + offset, 16, 16, 4,
tmp + ret, FW_REG_BUF - ret, 0);
ret += strlen(tmp + ret);
/* print newline for each offset */
if (FW_REG_BUF - ret > 0)
tmp[ret++] = '\n';
}
ret = simple_read_from_buffer(user_buf, count, ppos, tmp, ret);
kfree(tmp);
return ret;
}
static const struct file_operations soft_regs_ctrl_fops = {
.open = simple_open,
.read = fw_softreg_read,
.llseek = default_llseek,
};
struct skl_debug *skl_debugfs_init(struct skl_dev *skl)
{
struct skl_debug *d;
d = devm_kzalloc(&skl->pci->dev, sizeof(*d), GFP_KERNEL);
if (!d)
return NULL;
/* create the debugfs dir with platform component's debugfs as parent */
d->fs = debugfs_create_dir("dsp", skl->component->debugfs_root);
d->skl = skl;
d->dev = &skl->pci->dev;
/* now create the module dir */
d->modules = debugfs_create_dir("modules", d->fs);
debugfs_create_file("fw_soft_regs_rd", 0444, d->fs, d,
&soft_regs_ctrl_fops);
return d;
}
void skl_debugfs_exit(struct skl_dev *skl)
{
struct skl_debug *d = skl->debugfs;
debugfs_remove_recursive(d->fs);
d = NULL;
}
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* skl-i2s.h - i2s blob mapping
*
* Copyright (C) 2017 Intel Corp
* Author: Subhransu S. Prusty < subhransu.s.prusty@intel.com>
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#ifndef __SOUND_SOC_SKL_I2S_H
#define __SOUND_SOC_SKL_I2S_H
#define SKL_I2S_MAX_TIME_SLOTS 8
#define SKL_MCLK_DIV_CLK_SRC_MASK GENMASK(17, 16)
#define SKL_MNDSS_DIV_CLK_SRC_MASK GENMASK(21, 20)
#define SKL_SHIFT(x) (ffs(x) - 1)
#define SKL_MCLK_DIV_RATIO_MASK GENMASK(11, 0)
#define is_legacy_blob(x) (x.signature != 0xEE)
#define ext_to_legacy_blob(i2s_config_blob_ext) \
((struct skl_i2s_config_blob_legacy *) i2s_config_blob_ext)
#define get_clk_src(mclk, mask) \
((mclk.mdivctrl & mask) >> SKL_SHIFT(mask))
struct skl_i2s_config {
u32 ssc0;
u32 ssc1;
u32 sscto;
u32 sspsp;
u32 sstsa;
u32 ssrsa;
u32 ssc2;
u32 sspsp2;
u32 ssc3;
u32 ssioc;
} __packed;
struct skl_i2s_config_mclk {
u32 mdivctrl;
u32 mdivr;
};
struct skl_i2s_config_mclk_ext {
u32 mdivctrl;
u32 mdivr_count;
u32 mdivr[];
} __packed;
struct skl_i2s_config_blob_signature {
u32 minor_ver : 8;
u32 major_ver : 8;
u32 resvdz : 8;
u32 signature : 8;
} __packed;
struct skl_i2s_config_blob_header {
struct skl_i2s_config_blob_signature sig;
u32 size;
};
/**
* struct skl_i2s_config_blob_legacy - Structure defines I2S Gateway
* configuration legacy blob
*
* @gtw_attr: Gateway attribute for the I2S Gateway
* @tdm_ts_group: TDM slot mapping against channels in the Gateway.
* @i2s_cfg: I2S HW registers
* @mclk: MCLK clock source and divider values
*/
struct skl_i2s_config_blob_legacy {
u32 gtw_attr;
u32 tdm_ts_group[SKL_I2S_MAX_TIME_SLOTS];
struct skl_i2s_config i2s_cfg;
struct skl_i2s_config_mclk mclk;
};
struct skl_i2s_config_blob_ext {
u32 gtw_attr;
struct skl_i2s_config_blob_header hdr;
u32 tdm_ts_group[SKL_I2S_MAX_TIME_SLOTS];
struct skl_i2s_config i2s_cfg;
struct skl_i2s_config_mclk_ext mclk;
} __packed;
#endif /* __SOUND_SOC_SKL_I2S_H */
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0-only
/*
* skl-nhlt.c - Intel SKL Platform NHLT parsing
*
* Copyright (C) 2015 Intel Corp
* Author: Sanjiv Kumar <sanjiv.kumar@intel.com>
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#include <linux/pci.h>
#include <sound/intel-nhlt.h>
#include "skl.h"
#include "skl-i2s.h"
static void skl_nhlt_trim_space(char *trim)
{
char *s = trim;
int cnt;
int i;
cnt = 0;
for (i = 0; s[i]; i++) {
if (!isspace(s[i]))
s[cnt++] = s[i];
}
s[cnt] = '\0';
}
int skl_nhlt_update_topology_bin(struct skl_dev *skl)
{
struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt;
struct hdac_bus *bus = skl_to_bus(skl);
struct device *dev = bus->dev;
dev_dbg(dev, "oem_id %.6s, oem_table_id %.8s oem_revision %d\n",
nhlt->header.oem_id, nhlt->header.oem_table_id,
nhlt->header.oem_revision);
snprintf(skl->tplg_name, sizeof(skl->tplg_name), "%x-%.6s-%.8s-%d%s",
skl->pci_id, nhlt->header.oem_id, nhlt->header.oem_table_id,
nhlt->header.oem_revision, "-tplg.bin");
skl_nhlt_trim_space(skl->tplg_name);
return 0;
}
static ssize_t platform_id_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct pci_dev *pci = to_pci_dev(dev);
struct hdac_bus *bus = pci_get_drvdata(pci);
struct skl_dev *skl = bus_to_skl(bus);
struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt;
char platform_id[32];
sprintf(platform_id, "%x-%.6s-%.8s-%d", skl->pci_id,
nhlt->header.oem_id, nhlt->header.oem_table_id,
nhlt->header.oem_revision);
skl_nhlt_trim_space(platform_id);
return sysfs_emit(buf, "%s\n", platform_id);
}
static DEVICE_ATTR_RO(platform_id);
int skl_nhlt_create_sysfs(struct skl_dev *skl)
{
struct device *dev = &skl->pci->dev;
if (sysfs_create_file(&dev->kobj, &dev_attr_platform_id.attr))
dev_warn(dev, "Error creating sysfs entry\n");
return 0;
}
void skl_nhlt_remove_sysfs(struct skl_dev *skl)
{
struct device *dev = &skl->pci->dev;
if (skl->nhlt)
sysfs_remove_file(&dev->kobj, &dev_attr_platform_id.attr);
}
/*
* Queries NHLT for all the fmt configuration for a particular endpoint and
* stores all possible rates supported in a rate table for the corresponding
* sclk/sclkfs.
*/
static void skl_get_ssp_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks,
struct nhlt_fmt *fmt, u8 id)
{
struct skl_i2s_config_blob_ext *i2s_config_ext;
struct skl_i2s_config_blob_legacy *i2s_config;
struct skl_clk_parent_src *parent;
struct skl_ssp_clk *sclk, *sclkfs;
struct nhlt_fmt_cfg *fmt_cfg;
struct wav_fmt_ext *wav_fmt;
unsigned long rate;
int rate_index = 0;
u16 channels, bps;
u8 clk_src;
int i, j;
u32 fs;
sclk = &ssp_clks[SKL_SCLK_OFS];
sclkfs = &ssp_clks[SKL_SCLKFS_OFS];
if (fmt->fmt_count == 0)
return;
fmt_cfg = (struct nhlt_fmt_cfg *)fmt->fmt_config;
for (i = 0; i < fmt->fmt_count; i++) {
struct nhlt_fmt_cfg *saved_fmt_cfg = fmt_cfg;
bool present = false;
wav_fmt = &saved_fmt_cfg->fmt_ext;
channels = wav_fmt->fmt.channels;
bps = wav_fmt->fmt.bits_per_sample;
fs = wav_fmt->fmt.samples_per_sec;
/*
* In case of TDM configuration on a ssp, there can
* be more than one blob in which channel masks are
* different for each usecase for a specific rate and bps.
* But the sclk rate will be generated for the total
* number of channels used for that endpoint.
*
* So for the given fs and bps, choose blob which has
* the superset of all channels for that endpoint and
* derive the rate.
*/
for (j = i; j < fmt->fmt_count; j++) {
struct nhlt_fmt_cfg *tmp_fmt_cfg = fmt_cfg;
wav_fmt = &tmp_fmt_cfg->fmt_ext;
if ((fs == wav_fmt->fmt.samples_per_sec) &&
(bps == wav_fmt->fmt.bits_per_sample)) {
channels = max_t(u16, channels,
wav_fmt->fmt.channels);
saved_fmt_cfg = tmp_fmt_cfg;
}
/* Move to the next nhlt_fmt_cfg */
tmp_fmt_cfg = (struct nhlt_fmt_cfg *)(tmp_fmt_cfg->config.caps +
tmp_fmt_cfg->config.size);
}
rate = channels * bps * fs;
/* check if the rate is added already to the given SSP's sclk */
for (j = 0; (j < SKL_MAX_CLK_RATES) &&
(sclk[id].rate_cfg[j].rate != 0); j++) {
if (sclk[id].rate_cfg[j].rate == rate) {
present = true;
break;
}
}
/* Fill rate and parent for sclk/sclkfs */
if (!present) {
struct nhlt_fmt_cfg *first_fmt_cfg;
first_fmt_cfg = (struct nhlt_fmt_cfg *)fmt->fmt_config;
i2s_config_ext = (struct skl_i2s_config_blob_ext *)
first_fmt_cfg->config.caps;
/* MCLK Divider Source Select */
if (is_legacy_blob(i2s_config_ext->hdr.sig)) {
i2s_config = ext_to_legacy_blob(i2s_config_ext);
clk_src = get_clk_src(i2s_config->mclk,
SKL_MNDSS_DIV_CLK_SRC_MASK);
} else {
clk_src = get_clk_src(i2s_config_ext->mclk,
SKL_MNDSS_DIV_CLK_SRC_MASK);
}
parent = skl_get_parent_clk(clk_src);
/* Move to the next nhlt_fmt_cfg */
fmt_cfg = (struct nhlt_fmt_cfg *)(fmt_cfg->config.caps +
fmt_cfg->config.size);
/*
* Do not copy the config data if there is no parent
* clock available for this clock source select
*/
if (!parent)
continue;
sclk[id].rate_cfg[rate_index].rate = rate;
sclk[id].rate_cfg[rate_index].config = saved_fmt_cfg;
sclkfs[id].rate_cfg[rate_index].rate = rate;
sclkfs[id].rate_cfg[rate_index].config = saved_fmt_cfg;
sclk[id].parent_name = parent->name;
sclkfs[id].parent_name = parent->name;
rate_index++;
}
}
}
static void skl_get_mclk(struct skl_dev *skl, struct skl_ssp_clk *mclk,
struct nhlt_fmt *fmt, u8 id)
{
struct skl_i2s_config_blob_ext *i2s_config_ext;
struct skl_i2s_config_blob_legacy *i2s_config;
struct nhlt_fmt_cfg *fmt_cfg;
struct skl_clk_parent_src *parent;
u32 clkdiv, div_ratio;
u8 clk_src;
fmt_cfg = (struct nhlt_fmt_cfg *)fmt->fmt_config;
i2s_config_ext = (struct skl_i2s_config_blob_ext *)fmt_cfg->config.caps;
/* MCLK Divider Source Select and divider */
if (is_legacy_blob(i2s_config_ext->hdr.sig)) {
i2s_config = ext_to_legacy_blob(i2s_config_ext);
clk_src = get_clk_src(i2s_config->mclk,
SKL_MCLK_DIV_CLK_SRC_MASK);
clkdiv = i2s_config->mclk.mdivr &
SKL_MCLK_DIV_RATIO_MASK;
} else {
clk_src = get_clk_src(i2s_config_ext->mclk,
SKL_MCLK_DIV_CLK_SRC_MASK);
clkdiv = i2s_config_ext->mclk.mdivr[0] &
SKL_MCLK_DIV_RATIO_MASK;
}
/* bypass divider */
div_ratio = 1;
if (clkdiv != SKL_MCLK_DIV_RATIO_MASK)
/* Divider is 2 + clkdiv */
div_ratio = clkdiv + 2;
/* Calculate MCLK rate from source using div value */
parent = skl_get_parent_clk(clk_src);
if (!parent)
return;
mclk[id].rate_cfg[0].rate = parent->rate/div_ratio;
mclk[id].rate_cfg[0].config = fmt_cfg;
mclk[id].parent_name = parent->name;
}
void skl_get_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks)
{
struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt;
struct nhlt_endpoint *epnt;
struct nhlt_fmt *fmt;
int i;
u8 id;
epnt = (struct nhlt_endpoint *)nhlt->desc;
for (i = 0; i < nhlt->endpoint_count; i++) {
if (epnt->linktype == NHLT_LINK_SSP) {
id = epnt->virtual_bus_id;
fmt = (struct nhlt_fmt *)(epnt->config.caps
+ epnt->config.size);
skl_get_ssp_clks(skl, ssp_clks, fmt, id);
skl_get_mclk(skl, ssp_clks, fmt, id);
}
epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length);
}
}
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0-only
// Copyright(c) 2015-17 Intel Corporation
/*
* skl-ssp-clk.c - ASoC skylake ssp clock driver
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <sound/intel-nhlt.h>
#include "skl.h"
#include "skl-ssp-clk.h"
#include "skl-topology.h"
#define to_skl_clk(_hw) container_of(_hw, struct skl_clk, hw)
struct skl_clk_parent {
struct clk_hw *hw;
struct clk_lookup *lookup;
};
struct skl_clk {
struct clk_hw hw;
struct clk_lookup *lookup;
unsigned long rate;
struct skl_clk_pdata *pdata;
u32 id;
};
struct skl_clk_data {
struct skl_clk_parent parent[SKL_MAX_CLK_SRC];
struct skl_clk *clk[SKL_MAX_CLK_CNT];
u8 avail_clk_cnt;
};
static int skl_get_clk_type(u32 index)
{
switch (index) {
case 0 ... (SKL_SCLK_OFS - 1):
return SKL_MCLK;
case SKL_SCLK_OFS ... (SKL_SCLKFS_OFS - 1):
return SKL_SCLK;
case SKL_SCLKFS_OFS ... (SKL_MAX_CLK_CNT - 1):
return SKL_SCLK_FS;
default:
return -EINVAL;
}
}
static int skl_get_vbus_id(u32 index, u8 clk_type)
{
switch (clk_type) {
case SKL_MCLK:
return index;
case SKL_SCLK:
return index - SKL_SCLK_OFS;
case SKL_SCLK_FS:
return index - SKL_SCLKFS_OFS;
default:
return -EINVAL;
}
}
static void skl_fill_clk_ipc(struct skl_clk_rate_cfg_table *rcfg, u8 clk_type)
{
struct nhlt_fmt_cfg *fmt_cfg;
union skl_clk_ctrl_ipc *ipc;
struct wav_fmt *wfmt;
if (!rcfg)
return;
ipc = &rcfg->dma_ctl_ipc;
if (clk_type == SKL_SCLK_FS) {
fmt_cfg = (struct nhlt_fmt_cfg *)rcfg->config;
wfmt = &fmt_cfg->fmt_ext.fmt;
/* Remove TLV Header size */
ipc->sclk_fs.hdr.size = sizeof(struct skl_dmactrl_sclkfs_cfg) -
sizeof(struct skl_tlv_hdr);
ipc->sclk_fs.sampling_frequency = wfmt->samples_per_sec;
ipc->sclk_fs.bit_depth = wfmt->bits_per_sample;
ipc->sclk_fs.valid_bit_depth =
fmt_cfg->fmt_ext.sample.valid_bits_per_sample;
ipc->sclk_fs.number_of_channels = wfmt->channels;
} else {
ipc->mclk.hdr.type = DMA_CLK_CONTROLS;
/* Remove TLV Header size */
ipc->mclk.hdr.size = sizeof(struct skl_dmactrl_mclk_cfg) -
sizeof(struct skl_tlv_hdr);
}
}
/* Sends dma control IPC to turn the clock ON/OFF */
static int skl_send_clk_dma_control(struct skl_dev *skl,
struct skl_clk_rate_cfg_table *rcfg,
u32 vbus_id, u8 clk_type,
bool enable)
{
struct nhlt_specific_cfg *sp_cfg;
u32 i2s_config_size, node_id = 0;
struct nhlt_fmt_cfg *fmt_cfg;
union skl_clk_ctrl_ipc *ipc;
void *i2s_config = NULL;
u8 *data, size;
int ret;
if (!rcfg)
return -EIO;
ipc = &rcfg->dma_ctl_ipc;
fmt_cfg = (struct nhlt_fmt_cfg *)rcfg->config;
sp_cfg = &fmt_cfg->config;
if (clk_type == SKL_SCLK_FS) {
ipc->sclk_fs.hdr.type =
enable ? DMA_TRANSMITION_START : DMA_TRANSMITION_STOP;
data = (u8 *)&ipc->sclk_fs;
size = sizeof(struct skl_dmactrl_sclkfs_cfg);
} else {
/* 1 to enable mclk, 0 to enable sclk */
if (clk_type == SKL_SCLK)
ipc->mclk.mclk = 0;
else
ipc->mclk.mclk = 1;
ipc->mclk.keep_running = enable;
ipc->mclk.warm_up_over = enable;
ipc->mclk.clk_stop_over = !enable;
data = (u8 *)&ipc->mclk;
size = sizeof(struct skl_dmactrl_mclk_cfg);
}
i2s_config_size = sp_cfg->size + size;
i2s_config = kzalloc(i2s_config_size, GFP_KERNEL);
if (!i2s_config)
return -ENOMEM;
/* copy blob */
memcpy(i2s_config, sp_cfg->caps, sp_cfg->size);
/* copy additional dma controls information */
memcpy(i2s_config + sp_cfg->size, data, size);
node_id = ((SKL_DMA_I2S_LINK_INPUT_CLASS << 8) | (vbus_id << 4));
ret = skl_dsp_set_dma_control(skl, (u32 *)i2s_config,
i2s_config_size, node_id);
kfree(i2s_config);
return ret;
}
static struct skl_clk_rate_cfg_table *skl_get_rate_cfg(
struct skl_clk_rate_cfg_table *rcfg,
unsigned long rate)
{
int i;
for (i = 0; (i < SKL_MAX_CLK_RATES) && rcfg[i].rate; i++) {
if (rcfg[i].rate == rate)
return &rcfg[i];
}
return NULL;
}
static int skl_clk_change_status(struct skl_clk *clkdev,
bool enable)
{
struct skl_clk_rate_cfg_table *rcfg;
int vbus_id, clk_type;
clk_type = skl_get_clk_type(clkdev->id);
if (clk_type < 0)
return clk_type;
vbus_id = skl_get_vbus_id(clkdev->id, clk_type);
if (vbus_id < 0)
return vbus_id;
rcfg = skl_get_rate_cfg(clkdev->pdata->ssp_clks[clkdev->id].rate_cfg,
clkdev->rate);
if (!rcfg)
return -EINVAL;
return skl_send_clk_dma_control(clkdev->pdata->pvt_data, rcfg,
vbus_id, clk_type, enable);
}
static int skl_clk_prepare(struct clk_hw *hw)
{
struct skl_clk *clkdev = to_skl_clk(hw);
return skl_clk_change_status(clkdev, true);
}
static void skl_clk_unprepare(struct clk_hw *hw)
{
struct skl_clk *clkdev = to_skl_clk(hw);
skl_clk_change_status(clkdev, false);
}
static int skl_clk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct skl_clk *clkdev = to_skl_clk(hw);
struct skl_clk_rate_cfg_table *rcfg;
int clk_type;
if (!rate)
return -EINVAL;
rcfg = skl_get_rate_cfg(clkdev->pdata->ssp_clks[clkdev->id].rate_cfg,
rate);
if (!rcfg)
return -EINVAL;
clk_type = skl_get_clk_type(clkdev->id);
if (clk_type < 0)
return clk_type;
skl_fill_clk_ipc(rcfg, clk_type);
clkdev->rate = rate;
return 0;
}
static unsigned long skl_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct skl_clk *clkdev = to_skl_clk(hw);
if (clkdev->rate)
return clkdev->rate;
return 0;
}
/* Not supported by clk driver. Implemented to satisfy clk fw */
static long skl_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
return rate;
}
/*
* prepare/unprepare are used instead of enable/disable as IPC will be sent
* in non-atomic context.
*/
static const struct clk_ops skl_clk_ops = {
.prepare = skl_clk_prepare,
.unprepare = skl_clk_unprepare,
.set_rate = skl_clk_set_rate,
.round_rate = skl_clk_round_rate,
.recalc_rate = skl_clk_recalc_rate,
};
static void unregister_parent_src_clk(struct skl_clk_parent *pclk,
unsigned int id)
{
while (id--) {
clkdev_drop(pclk[id].lookup);
clk_hw_unregister_fixed_rate(pclk[id].hw);
}
}
static void unregister_src_clk(struct skl_clk_data *dclk)
{
while (dclk->avail_clk_cnt--)
clkdev_drop(dclk->clk[dclk->avail_clk_cnt]->lookup);
}
static int skl_register_parent_clks(struct device *dev,
struct skl_clk_parent *parent,
struct skl_clk_parent_src *pclk)
{
int i, ret;
for (i = 0; i < SKL_MAX_CLK_SRC; i++) {
/* Register Parent clock */
parent[i].hw = clk_hw_register_fixed_rate(dev, pclk[i].name,
pclk[i].parent_name, 0, pclk[i].rate);
if (IS_ERR(parent[i].hw)) {
ret = PTR_ERR(parent[i].hw);
goto err;
}
parent[i].lookup = clkdev_hw_create(parent[i].hw, pclk[i].name,
NULL);
if (!parent[i].lookup) {
clk_hw_unregister_fixed_rate(parent[i].hw);
ret = -ENOMEM;
goto err;
}
}
return 0;
err:
unregister_parent_src_clk(parent, i);
return ret;
}
/* Assign fmt_config to clk_data */
static struct skl_clk *register_skl_clk(struct device *dev,
struct skl_ssp_clk *clk,
struct skl_clk_pdata *clk_pdata, int id)
{
struct clk_init_data init;
struct skl_clk *clkdev;
int ret;
clkdev = devm_kzalloc(dev, sizeof(*clkdev), GFP_KERNEL);
if (!clkdev)
return ERR_PTR(-ENOMEM);
init.name = clk->name;
init.ops = &skl_clk_ops;
init.flags = CLK_SET_RATE_GATE;
init.parent_names = &clk->parent_name;
init.num_parents = 1;
clkdev->hw.init = &init;
clkdev->pdata = clk_pdata;
clkdev->id = id;
ret = devm_clk_hw_register(dev, &clkdev->hw);
if (ret) {
clkdev = ERR_PTR(ret);
return clkdev;
}
clkdev->lookup = clkdev_hw_create(&clkdev->hw, init.name, NULL);
if (!clkdev->lookup)
clkdev = ERR_PTR(-ENOMEM);
return clkdev;
}
static int skl_clk_dev_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device *parent_dev = dev->parent;
struct skl_clk_parent_src *parent_clks;
struct skl_clk_pdata *clk_pdata;
struct skl_clk_data *data;
struct skl_ssp_clk *clks;
int ret, i;
clk_pdata = dev_get_platdata(&pdev->dev);
parent_clks = clk_pdata->parent_clks;
clks = clk_pdata->ssp_clks;
if (!parent_clks || !clks)
return -EIO;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
/* Register Parent clock */
ret = skl_register_parent_clks(parent_dev, data->parent, parent_clks);
if (ret < 0)
return ret;
for (i = 0; i < clk_pdata->num_clks; i++) {
/*
* Only register valid clocks
* i.e. for which nhlt entry is present.
*/
if (clks[i].rate_cfg[0].rate == 0)
continue;
data->clk[data->avail_clk_cnt] = register_skl_clk(dev,
&clks[i], clk_pdata, i);
if (IS_ERR(data->clk[data->avail_clk_cnt])) {
ret = PTR_ERR(data->clk[data->avail_clk_cnt]);
goto err_unreg_skl_clk;
}
data->avail_clk_cnt++;
}
platform_set_drvdata(pdev, data);
return 0;
err_unreg_skl_clk:
unregister_src_clk(data);
unregister_parent_src_clk(data->parent, SKL_MAX_CLK_SRC);
return ret;
}
static void skl_clk_dev_remove(struct platform_device *pdev)
{
struct skl_clk_data *data;
data = platform_get_drvdata(pdev);
unregister_src_clk(data);
unregister_parent_src_clk(data->parent, SKL_MAX_CLK_SRC);
}
static struct platform_driver skl_clk_driver = {
.driver = {
.name = "skl-ssp-clk",
},
.probe = skl_clk_dev_probe,
.remove_new = skl_clk_dev_remove,
};
module_platform_driver(skl_clk_driver);
MODULE_DESCRIPTION("Skylake clock driver");
MODULE_AUTHOR("Jaikrishna Nemallapudi <jaikrishnax.nemallapudi@intel.com>");
MODULE_AUTHOR("Subhransu S. Prusty <subhransu.s.prusty@intel.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:skl-ssp-clk");
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* skl-ssp-clk.h - Skylake ssp clock information and ipc structure
*
* Copyright (C) 2017 Intel Corp
* Author: Jaikrishna Nemallapudi <jaikrishnax.nemallapudi@intel.com>
* Author: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#ifndef SOUND_SOC_SKL_SSP_CLK_H
#define SOUND_SOC_SKL_SSP_CLK_H
#define SKL_MAX_SSP 6
/* xtal/cardinal/pll, parent of ssp clocks and mclk */
#define SKL_MAX_CLK_SRC 3
#define SKL_MAX_SSP_CLK_TYPES 3 /* mclk, sclk, sclkfs */
#define SKL_MAX_CLK_CNT (SKL_MAX_SSP * SKL_MAX_SSP_CLK_TYPES)
/* Max number of configurations supported for each clock */
#define SKL_MAX_CLK_RATES 10
#define SKL_SCLK_OFS SKL_MAX_SSP
#define SKL_SCLKFS_OFS (SKL_SCLK_OFS + SKL_MAX_SSP)
enum skl_clk_type {
SKL_MCLK,
SKL_SCLK,
SKL_SCLK_FS,
};
enum skl_clk_src_type {
SKL_XTAL,
SKL_CARDINAL,
SKL_PLL,
};
struct skl_clk_parent_src {
u8 clk_id;
const char *name;
unsigned long rate;
const char *parent_name;
};
struct skl_tlv_hdr {
u32 type;
u32 size;
};
struct skl_dmactrl_mclk_cfg {
struct skl_tlv_hdr hdr;
/* DMA Clk TLV params */
u32 clk_warm_up:16;
u32 mclk:1;
u32 warm_up_over:1;
u32 rsvd0:14;
u32 clk_stop_delay:16;
u32 keep_running:1;
u32 clk_stop_over:1;
u32 rsvd1:14;
};
struct skl_dmactrl_sclkfs_cfg {
struct skl_tlv_hdr hdr;
/* DMA SClk&FS TLV params */
u32 sampling_frequency;
u32 bit_depth;
u32 channel_map;
u32 channel_config;
u32 interleaving_style;
u32 number_of_channels : 8;
u32 valid_bit_depth : 8;
u32 sample_type : 8;
u32 reserved : 8;
};
union skl_clk_ctrl_ipc {
struct skl_dmactrl_mclk_cfg mclk;
struct skl_dmactrl_sclkfs_cfg sclk_fs;
};
struct skl_clk_rate_cfg_table {
unsigned long rate;
union skl_clk_ctrl_ipc dma_ctl_ipc;
void *config;
};
/*
* rate for mclk will be in rates[0]. For sclk and sclkfs, rates[] store
* all possible clocks ssp can generate for that platform.
*/
struct skl_ssp_clk {
const char *name;
const char *parent_name;
struct skl_clk_rate_cfg_table rate_cfg[SKL_MAX_CLK_RATES];
};
struct skl_clk_pdata {
struct skl_clk_parent_src *parent_clks;
int num_clks;
struct skl_ssp_clk *ssp_clks;
void *pvt_data;
};
#endif /* SOUND_SOC_SKL_SSP_CLK_H */
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Intel Code Loader DMA support
*
* Copyright (C) 2015, Intel Corporation.
*/
#ifndef SKL_SST_CLDMA_H_
#define SKL_SST_CLDMA_H_
#define FW_CL_STREAM_NUMBER 0x1
#define DMA_ADDRESS_128_BITS_ALIGNMENT 7
#define BDL_ALIGN(x) (x >> DMA_ADDRESS_128_BITS_ALIGNMENT)
#define SKL_ADSPIC_CL_DMA 0x2
#define SKL_ADSPIS_CL_DMA 0x2
#define SKL_CL_DMA_SD_INT_DESC_ERR 0x10 /* Descriptor error interrupt */
#define SKL_CL_DMA_SD_INT_FIFO_ERR 0x08 /* FIFO error interrupt */
#define SKL_CL_DMA_SD_INT_COMPLETE 0x04 /* Buffer completion interrupt */
/* Intel HD Audio Code Loader DMA Registers */
#define HDA_ADSP_LOADER_BASE 0x80
/* Stream Registers */
#define SKL_ADSP_REG_CL_SD_CTL (HDA_ADSP_LOADER_BASE + 0x00)
#define SKL_ADSP_REG_CL_SD_STS (HDA_ADSP_LOADER_BASE + 0x03)
#define SKL_ADSP_REG_CL_SD_LPIB (HDA_ADSP_LOADER_BASE + 0x04)
#define SKL_ADSP_REG_CL_SD_CBL (HDA_ADSP_LOADER_BASE + 0x08)
#define SKL_ADSP_REG_CL_SD_LVI (HDA_ADSP_LOADER_BASE + 0x0c)
#define SKL_ADSP_REG_CL_SD_FIFOW (HDA_ADSP_LOADER_BASE + 0x0e)
#define SKL_ADSP_REG_CL_SD_FIFOSIZE (HDA_ADSP_LOADER_BASE + 0x10)
#define SKL_ADSP_REG_CL_SD_FORMAT (HDA_ADSP_LOADER_BASE + 0x12)
#define SKL_ADSP_REG_CL_SD_FIFOL (HDA_ADSP_LOADER_BASE + 0x14)
#define SKL_ADSP_REG_CL_SD_BDLPL (HDA_ADSP_LOADER_BASE + 0x18)
#define SKL_ADSP_REG_CL_SD_BDLPU (HDA_ADSP_LOADER_BASE + 0x1c)
/* CL: Software Position Based FIFO Capability Registers */
#define SKL_ADSP_REG_CL_SPBFIFO (HDA_ADSP_LOADER_BASE + 0x20)
#define SKL_ADSP_REG_CL_SPBFIFO_SPBFCH (SKL_ADSP_REG_CL_SPBFIFO + 0x0)
#define SKL_ADSP_REG_CL_SPBFIFO_SPBFCCTL (SKL_ADSP_REG_CL_SPBFIFO + 0x4)
#define SKL_ADSP_REG_CL_SPBFIFO_SPIB (SKL_ADSP_REG_CL_SPBFIFO + 0x8)
#define SKL_ADSP_REG_CL_SPBFIFO_MAXFIFOS (SKL_ADSP_REG_CL_SPBFIFO + 0xc)
/* CL: Stream Descriptor x Control */
/* Stream Reset */
#define CL_SD_CTL_SRST_SHIFT 0
#define CL_SD_CTL_SRST_MASK (1 << CL_SD_CTL_SRST_SHIFT)
#define CL_SD_CTL_SRST(x) \
((x << CL_SD_CTL_SRST_SHIFT) & CL_SD_CTL_SRST_MASK)
/* Stream Run */
#define CL_SD_CTL_RUN_SHIFT 1
#define CL_SD_CTL_RUN_MASK (1 << CL_SD_CTL_RUN_SHIFT)
#define CL_SD_CTL_RUN(x) \
((x << CL_SD_CTL_RUN_SHIFT) & CL_SD_CTL_RUN_MASK)
/* Interrupt On Completion Enable */
#define CL_SD_CTL_IOCE_SHIFT 2
#define CL_SD_CTL_IOCE_MASK (1 << CL_SD_CTL_IOCE_SHIFT)
#define CL_SD_CTL_IOCE(x) \
((x << CL_SD_CTL_IOCE_SHIFT) & CL_SD_CTL_IOCE_MASK)
/* FIFO Error Interrupt Enable */
#define CL_SD_CTL_FEIE_SHIFT 3
#define CL_SD_CTL_FEIE_MASK (1 << CL_SD_CTL_FEIE_SHIFT)
#define CL_SD_CTL_FEIE(x) \
((x << CL_SD_CTL_FEIE_SHIFT) & CL_SD_CTL_FEIE_MASK)
/* Descriptor Error Interrupt Enable */
#define CL_SD_CTL_DEIE_SHIFT 4
#define CL_SD_CTL_DEIE_MASK (1 << CL_SD_CTL_DEIE_SHIFT)
#define CL_SD_CTL_DEIE(x) \
((x << CL_SD_CTL_DEIE_SHIFT) & CL_SD_CTL_DEIE_MASK)
/* FIFO Limit Change */
#define CL_SD_CTL_FIFOLC_SHIFT 5
#define CL_SD_CTL_FIFOLC_MASK (1 << CL_SD_CTL_FIFOLC_SHIFT)
#define CL_SD_CTL_FIFOLC(x) \
((x << CL_SD_CTL_FIFOLC_SHIFT) & CL_SD_CTL_FIFOLC_MASK)
/* Stripe Control */
#define CL_SD_CTL_STRIPE_SHIFT 16
#define CL_SD_CTL_STRIPE_MASK (0x3 << CL_SD_CTL_STRIPE_SHIFT)
#define CL_SD_CTL_STRIPE(x) \
((x << CL_SD_CTL_STRIPE_SHIFT) & CL_SD_CTL_STRIPE_MASK)
/* Traffic Priority */
#define CL_SD_CTL_TP_SHIFT 18
#define CL_SD_CTL_TP_MASK (1 << CL_SD_CTL_TP_SHIFT)
#define CL_SD_CTL_TP(x) \
((x << CL_SD_CTL_TP_SHIFT) & CL_SD_CTL_TP_MASK)
/* Bidirectional Direction Control */
#define CL_SD_CTL_DIR_SHIFT 19
#define CL_SD_CTL_DIR_MASK (1 << CL_SD_CTL_DIR_SHIFT)
#define CL_SD_CTL_DIR(x) \
((x << CL_SD_CTL_DIR_SHIFT) & CL_SD_CTL_DIR_MASK)
/* Stream Number */
#define CL_SD_CTL_STRM_SHIFT 20
#define CL_SD_CTL_STRM_MASK (0xf << CL_SD_CTL_STRM_SHIFT)
#define CL_SD_CTL_STRM(x) \
((x << CL_SD_CTL_STRM_SHIFT) & CL_SD_CTL_STRM_MASK)
/* CL: Stream Descriptor x Status */
/* Buffer Completion Interrupt Status */
#define CL_SD_STS_BCIS(x) CL_SD_CTL_IOCE(x)
/* FIFO Error */
#define CL_SD_STS_FIFOE(x) CL_SD_CTL_FEIE(x)
/* Descriptor Error */
#define CL_SD_STS_DESE(x) CL_SD_CTL_DEIE(x)
/* FIFO Ready */
#define CL_SD_STS_FIFORDY(x) CL_SD_CTL_FIFOLC(x)
/* CL: Stream Descriptor x Last Valid Index */
#define CL_SD_LVI_SHIFT 0
#define CL_SD_LVI_MASK (0xff << CL_SD_LVI_SHIFT)
#define CL_SD_LVI(x) ((x << CL_SD_LVI_SHIFT) & CL_SD_LVI_MASK)
/* CL: Stream Descriptor x FIFO Eviction Watermark */
#define CL_SD_FIFOW_SHIFT 0
#define CL_SD_FIFOW_MASK (0x7 << CL_SD_FIFOW_SHIFT)
#define CL_SD_FIFOW(x) \
((x << CL_SD_FIFOW_SHIFT) & CL_SD_FIFOW_MASK)
/* CL: Stream Descriptor x Buffer Descriptor List Pointer Lower Base Address */
/* Protect Bits */
#define CL_SD_BDLPLBA_PROT_SHIFT 0
#define CL_SD_BDLPLBA_PROT_MASK (1 << CL_SD_BDLPLBA_PROT_SHIFT)
#define CL_SD_BDLPLBA_PROT(x) \
((x << CL_SD_BDLPLBA_PROT_SHIFT) & CL_SD_BDLPLBA_PROT_MASK)
/* Buffer Descriptor List Lower Base Address */
#define CL_SD_BDLPLBA_SHIFT 7
#define CL_SD_BDLPLBA_MASK (0x1ffffff << CL_SD_BDLPLBA_SHIFT)
#define CL_SD_BDLPLBA(x) \
((BDL_ALIGN(lower_32_bits(x)) << CL_SD_BDLPLBA_SHIFT) & CL_SD_BDLPLBA_MASK)
/* Buffer Descriptor List Upper Base Address */
#define CL_SD_BDLPUBA_SHIFT 0
#define CL_SD_BDLPUBA_MASK (0xffffffff << CL_SD_BDLPUBA_SHIFT)
#define CL_SD_BDLPUBA(x) \
((upper_32_bits(x) << CL_SD_BDLPUBA_SHIFT) & CL_SD_BDLPUBA_MASK)
/*
* Code Loader - Software Position Based FIFO
* Capability Registers x Software Position Based FIFO Header
*/
/* Next Capability Pointer */
#define CL_SPBFIFO_SPBFCH_PTR_SHIFT 0
#define CL_SPBFIFO_SPBFCH_PTR_MASK (0xff << CL_SPBFIFO_SPBFCH_PTR_SHIFT)
#define CL_SPBFIFO_SPBFCH_PTR(x) \
((x << CL_SPBFIFO_SPBFCH_PTR_SHIFT) & CL_SPBFIFO_SPBFCH_PTR_MASK)
/* Capability Identifier */
#define CL_SPBFIFO_SPBFCH_ID_SHIFT 16
#define CL_SPBFIFO_SPBFCH_ID_MASK (0xfff << CL_SPBFIFO_SPBFCH_ID_SHIFT)
#define CL_SPBFIFO_SPBFCH_ID(x) \
((x << CL_SPBFIFO_SPBFCH_ID_SHIFT) & CL_SPBFIFO_SPBFCH_ID_MASK)
/* Capability Version */
#define CL_SPBFIFO_SPBFCH_VER_SHIFT 28
#define CL_SPBFIFO_SPBFCH_VER_MASK (0xf << CL_SPBFIFO_SPBFCH_VER_SHIFT)
#define CL_SPBFIFO_SPBFCH_VER(x) \
((x << CL_SPBFIFO_SPBFCH_VER_SHIFT) & CL_SPBFIFO_SPBFCH_VER_MASK)
/* Software Position in Buffer Enable */
#define CL_SPBFIFO_SPBFCCTL_SPIBE_SHIFT 0
#define CL_SPBFIFO_SPBFCCTL_SPIBE_MASK (1 << CL_SPBFIFO_SPBFCCTL_SPIBE_SHIFT)
#define CL_SPBFIFO_SPBFCCTL_SPIBE(x) \
((x << CL_SPBFIFO_SPBFCCTL_SPIBE_SHIFT) & CL_SPBFIFO_SPBFCCTL_SPIBE_MASK)
/* SST IPC SKL defines */
#define SKL_WAIT_TIMEOUT 500 /* 500 msec */
#define SKL_MAX_BUFFER_SIZE (32 * PAGE_SIZE)
enum skl_cl_dma_wake_states {
SKL_CL_DMA_STATUS_NONE = 0,
SKL_CL_DMA_BUF_COMPLETE,
SKL_CL_DMA_ERR, /* TODO: Expand the error states */
};
struct sst_dsp;
struct skl_cl_dev_ops {
void (*cl_setup_bdle)(struct sst_dsp *ctx,
struct snd_dma_buffer *dmab_data,
__le32 **bdlp, int size, int with_ioc);
void (*cl_setup_controller)(struct sst_dsp *ctx,
struct snd_dma_buffer *dmab_bdl,
unsigned int max_size, u32 page_count);
void (*cl_setup_spb)(struct sst_dsp *ctx,
unsigned int size, bool enable);
void (*cl_cleanup_spb)(struct sst_dsp *ctx);
void (*cl_trigger)(struct sst_dsp *ctx, bool enable);
void (*cl_cleanup_controller)(struct sst_dsp *ctx);
int (*cl_copy_to_dmabuf)(struct sst_dsp *ctx,
const void *bin, u32 size, bool wait);
void (*cl_stop_dma)(struct sst_dsp *ctx);
};
/**
* skl_cl_dev - holds information for code loader dma transfer
*
* @dmab_data: buffer pointer
* @dmab_bdl: buffer descriptor list
* @bufsize: ring buffer size
* @frags: Last valid buffer descriptor index in the BDL
* @curr_spib_pos: Current position in ring buffer
* @dma_buffer_offset: dma buffer offset
* @ops: operations supported on CL dma
* @wait_queue: wait queue to wake for wake event
* @wake_status: DMA wake status
* @wait_condition: condition to wait on wait queue
* @cl_dma_lock: for synchronized access to cldma
*/
struct skl_cl_dev {
struct snd_dma_buffer dmab_data;
struct snd_dma_buffer dmab_bdl;
unsigned int bufsize;
unsigned int frags;
unsigned int curr_spib_pos;
unsigned int dma_buffer_offset;
struct skl_cl_dev_ops ops;
wait_queue_head_t wait_queue;
int wake_status;
bool wait_condition;
};
#endif /* SKL_SST_CLDMA_H_ */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment