Commit a1d68507 authored by Mark Brown's avatar Mark Brown

ASoC: SOF: Intel: hda-mlink: HDaudio multi-link

Merge series from Peter Ujfalusi <peter.ujfalusi@linux.intel.com>:

The following series adds the core support to handle the recently updated
HDaudio multi-link support to hanlde non HDA links, like SoundWire/DMIC/SSP on
Intel platform.

For details, please see the first patch which documents the current mlink
support (introduced at Skylake) and the new extensions, arriving with LNL.

There is no change in functionality for existing HDA support, the extension is
backwards compatible with existing implementations.
parents 3e5f7972 681f27f3
......@@ -9,3 +9,4 @@ HD-Audio
controls
dp-mst
realtek-pc-beep
intel-multi-link
This diff is collapsed.
/* 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) 2022-2023 Intel Corporation. All rights reserved.
*/
struct hdac_bus;
struct hdac_ext_link;
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_MLINK)
int hda_bus_ml_init(struct hdac_bus *bus);
void hda_bus_ml_free(struct hdac_bus *bus);
int hdac_bus_eml_get_count(struct hdac_bus *bus, bool alt, int elid);
void hdac_bus_eml_enable_interrupt(struct hdac_bus *bus, bool alt, int elid, bool enable);
bool hdac_bus_eml_check_interrupt(struct hdac_bus *bus, bool alt, int elid);
int hdac_bus_eml_set_syncprd_unlocked(struct hdac_bus *bus, bool alt, int elid, u32 syncprd);
int hdac_bus_eml_sdw_set_syncprd_unlocked(struct hdac_bus *bus, u32 syncprd);
int hdac_bus_eml_wait_syncpu_unlocked(struct hdac_bus *bus, bool alt, int elid);
int hdac_bus_eml_sdw_wait_syncpu_unlocked(struct hdac_bus *bus);
void hdac_bus_eml_sync_arm_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink);
void hdac_bus_eml_sdw_sync_arm_unlocked(struct hdac_bus *bus, int sublink);
int hdac_bus_eml_sync_go_unlocked(struct hdac_bus *bus, bool alt, int elid);
int hdac_bus_eml_sdw_sync_go_unlocked(struct hdac_bus *bus);
bool hdac_bus_eml_check_cmdsync_unlocked(struct hdac_bus *bus, bool alt, int elid);
bool hdac_bus_eml_sdw_check_cmdsync_unlocked(struct hdac_bus *bus);
int hdac_bus_eml_power_up(struct hdac_bus *bus, bool alt, int elid, int sublink);
int hdac_bus_eml_power_up_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink);
int hdac_bus_eml_power_down(struct hdac_bus *bus, bool alt, int elid, int sublink);
int hdac_bus_eml_power_down_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink);
int hdac_bus_eml_sdw_power_up_unlocked(struct hdac_bus *bus, int sublink);
int hdac_bus_eml_sdw_power_down_unlocked(struct hdac_bus *bus, int sublink);
int hdac_bus_eml_sdw_set_lsdiid(struct hdac_bus *bus, int sublink, int dev_num);
void hda_bus_ml_put_all(struct hdac_bus *bus);
void hda_bus_ml_reset_losidv(struct hdac_bus *bus);
int hda_bus_ml_resume(struct hdac_bus *bus);
int hda_bus_ml_suspend(struct hdac_bus *bus);
struct hdac_ext_link *hdac_bus_eml_ssp_get_hlink(struct hdac_bus *bus);
struct hdac_ext_link *hdac_bus_eml_dmic_get_hlink(struct hdac_bus *bus);
struct mutex *hdac_bus_eml_get_mutex(struct hdac_bus *bus, bool alt, int elid);
int hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enable);
#else
static inline int
hda_bus_ml_init(struct hdac_bus *bus) { return 0; }
static inline void hda_bus_ml_free(struct hdac_bus *bus) { }
static inline int
hdac_bus_eml_get_count(struct hdac_bus *bus, bool alt, int elid) { return 0; }
static inline void
hdac_bus_eml_enable_interrupt(struct hdac_bus *bus, bool alt, int elid, bool enable) { }
static inline bool
hdac_bus_eml_check_interrupt(struct hdac_bus *bus, bool alt, int elid) { return false; }
static inline int
hdac_bus_eml_set_syncprd_unlocked(struct hdac_bus *bus, bool alt, int elid, u32 syncprd)
{
return 0;
}
static inline int
hdac_bus_eml_sdw_set_syncprd_unlocked(struct hdac_bus *bus, u32 syncprd)
{
return 0;
}
static inline int
hdac_bus_eml_wait_syncpu_unlocked(struct hdac_bus *bus, bool alt, int elid)
{
return 0;
}
static inline int
hdac_bus_eml_sdw_wait_syncpu_unlocked(struct hdac_bus *bus) { return 0; }
static inline void
hdac_bus_eml_sync_arm_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink) { }
static inline void
hdac_bus_eml_sdw_sync_arm_unlocked(struct hdac_bus *bus, int sublink) { }
static inline int
hdac_bus_eml_sync_go_unlocked(struct hdac_bus *bus, bool alt, int elid) { return 0; }
static inline int
hdac_bus_eml_sdw_sync_go_unlocked(struct hdac_bus *bus) { return 0; }
static inline bool
hdac_bus_eml_check_cmdsync_unlocked(struct hdac_bus *bus, bool alt, int elid) { return false; }
static inline bool
hdac_bus_eml_sdw_check_cmdsync_unlocked(struct hdac_bus *bus) { return false; }
static inline int
hdac_bus_eml_power_up(struct hdac_bus *bus, bool alt, int elid, int sublink)
{
return 0;
}
static inline int
hdac_bus_eml_power_up_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink)
{
return 0;
}
static inline int
hdac_bus_eml_power_down(struct hdac_bus *bus, bool alt, int elid, int sublink)
{
return 0;
}
static inline int
hdac_bus_eml_power_down_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink)
{
return 0;
}
static inline int
hdac_bus_eml_sdw_power_up_unlocked(struct hdac_bus *bus, int sublink) { return 0; }
static inline int
hdac_bus_eml_sdw_power_down_unlocked(struct hdac_bus *bus, int sublink) { return 0; }
static inline int
hdac_bus_eml_sdw_set_lsdiid(struct hdac_bus *bus, int sublink, int dev_num) { return 0; }
static inline void hda_bus_ml_put_all(struct hdac_bus *bus) { }
static inline void hda_bus_ml_reset_losidv(struct hdac_bus *bus) { }
static inline int hda_bus_ml_resume(struct hdac_bus *bus) { return 0; }
static inline int hda_bus_ml_suspend(struct hdac_bus *bus) { return 0; }
static inline struct hdac_ext_link *
hdac_bus_eml_ssp_get_hlink(struct hdac_bus *bus) { return NULL; }
static inline struct hdac_ext_link *
hdac_bus_eml_dmic_get_hlink(struct hdac_bus *bus) { return NULL; }
static inline struct mutex *
hdac_bus_eml_get_mutex(struct hdac_bus *bus, bool alt, int elid) { return NULL; }
static inline int
hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enable)
{
return 0;
}
#endif /* CONFIG_SND_SOC_SOF_HDA */
......@@ -258,14 +258,27 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define AZX_ML_BASE 0x40
#define AZX_ML_INTERVAL 0x40
/* HDaudio registers valid for HDaudio and HDaudio extended links */
#define AZX_REG_ML_LCAP 0x00
#define AZX_REG_ML_LCTL 0x04
#define AZX_ML_HDA_LCAP_ALT BIT(28)
#define AZX_ML_HDA_LCAP_ALT_HDA 0x0
#define AZX_ML_HDA_LCAP_ALT_HDA_EXT 0x1
#define AZX_ML_HDA_LCAP_INTC BIT(27) /* only used if ALT == 1 */
#define AZX_ML_HDA_LCAP_OFLS BIT(26) /* only used if ALT == 1 */
#define AZX_ML_HDA_LCAP_LSS BIT(23) /* only used if ALT == 1 */
#define AZX_ML_HDA_LCAP_SLCOUNT GENMASK(22, 20) /* only used if ALT == 1 */
#define AZX_REG_ML_LCTL 0x04
#define AZX_ML_LCTL_INTSTS BIT(31) /* only used if ALT == 1 */
#define AZX_ML_LCTL_CPA BIT(23)
#define AZX_ML_LCTL_CPA_SHIFT 23
#define AZX_ML_LCTL_SPA BIT(16)
#define AZX_ML_LCTL_SPA_SHIFT 16
#define AZX_ML_LCTL_SCF GENMASK(3, 0)
#define AZX_ML_LCTL_INTEN BIT(5) /* only used if ALT == 1 */
#define AZX_ML_LCTL_OFLEN BIT(4) /* only used if ALT == 1 */
#define AZX_ML_LCTL_SCF GENMASK(3, 0) /* only used if ALT == 0 */
#define AZX_REG_ML_LOSIDV 0x08
......@@ -273,12 +286,35 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define AZX_ML_LOSIDV_STREAM_MASK 0xFFFE
#define AZX_REG_ML_LSDIID 0x0C
#define AZX_REG_ML_LSDIID_OFFSET(x) (0x0C + (x) * 0x02) /* only used if ALT == 1 */
/* HDaudio registers only valid if LCAP.ALT == 0 */
#define AZX_REG_ML_LPSOO 0x10
#define AZX_REG_ML_LPSIO 0x12
#define AZX_REG_ML_LWALFC 0x18
#define AZX_REG_ML_LOUTPAY 0x20
#define AZX_REG_ML_LINPAY 0x30
/* HDaudio Extended link registers only valid if LCAP.ALT == 1 */
#define AZX_REG_ML_LSYNC 0x1C
#define AZX_REG_ML_LSYNC_CMDSYNC BIT(24)
#define AZX_REG_ML_LSYNC_CMDSYNC_SHIFT 24
#define AZX_REG_ML_LSYNC_SYNCGO BIT(23)
#define AZX_REG_ML_LSYNC_SYNCPU BIT(20)
#define AZX_REG_ML_LSYNC_SYNCPRD GENMASK(19, 0)
#define AZX_REG_ML_LEPTR 0x20
#define AZX_REG_ML_LEPTR_ID GENMASK(31, 24)
#define AZX_REG_ML_LEPTR_ID_SHIFT 24
#define AZX_REG_ML_LEPTR_ID_SDW 0x00
#define AZX_REG_ML_LEPTR_ID_INTEL_SSP 0xC0
#define AZX_REG_ML_LEPTR_ID_INTEL_DMIC 0xC1
#define AZX_REG_ML_LEPTR_ID_INTEL_UAOL 0xC2
#define AZX_REG_ML_LEPTR_VER GENMASK(23, 20)
#define AZX_REG_ML_LEPTR_PTR GENMASK(19, 0)
/* registers for DMA Resume Capability Structure */
#define AZX_DRSM_CAP_ID 0x5
#define AZX_REG_DRSM_CTL 0x4
......
......@@ -269,6 +269,13 @@ config SND_SOC_SOF_HDA_COMMON
select SND_INTEL_DSP_CONFIG
select SND_SOC_SOF_HDA_LINK_BASELINE
select SND_SOC_SOF_HDA_PROBES
select SND_SOC_SOF_HDA_MLINK if SND_SOC_SOF_HDA_LINK
help
This option is not user-selectable but automagically handled by
'select' statements at a higher level.
config SND_SOC_SOF_HDA_MLINK
tristate
help
This option is not user-selectable but automagically handled by
'select' statements at a higher level.
......
......@@ -5,10 +5,12 @@ snd-sof-acpi-intel-bdw-objs := bdw.o
snd-sof-intel-hda-common-objs := hda.o hda-loader.o hda-stream.o hda-trace.o \
hda-dsp.o hda-ipc.o hda-ctrl.o hda-pcm.o \
hda-dai.o hda-dai-ops.o hda-bus.o hda-mlink.o \
hda-dai.o hda-dai-ops.o hda-bus.o \
skl.o hda-loader-skl.o \
apl.o cnl.o tgl.o icl.o mtl.o hda-common-ops.o
snd-sof-intel-hda-mlink-objs := hda-mlink.o
snd-sof-intel-hda-common-$(CONFIG_SND_SOC_SOF_HDA_PROBES) += hda-probes.o
snd-sof-intel-hda-objs := hda-codec.o
......@@ -19,6 +21,7 @@ obj-$(CONFIG_SND_SOC_SOF_INTEL_ATOM_HIFI_EP) += snd-sof-intel-atom.o
obj-$(CONFIG_SND_SOC_SOF_BAYTRAIL) += snd-sof-acpi-intel-byt.o
obj-$(CONFIG_SND_SOC_SOF_BROADWELL) += snd-sof-acpi-intel-bdw.o
obj-$(CONFIG_SND_SOC_SOF_HDA_COMMON) += snd-sof-intel-hda-common.o
obj-$(CONFIG_SND_SOC_SOF_HDA_MLINK) += snd-sof-intel-hda-mlink.o
obj-$(CONFIG_SND_SOC_SOF_HDA) += snd-sof-intel-hda.o
snd-sof-pci-intel-tng-objs := pci-tng.o
......
......@@ -19,6 +19,7 @@
#include <sound/hdaudio_ext.h>
#include <sound/hda_register.h>
#include <sound/hda_component.h>
#include <sound/hda-mlink.h>
#include "../ops.h"
#include "hda.h"
......
......@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <sound/hdaudio_ext.h>
#include <sound/hda_register.h>
#include <sound/hda-mlink.h>
#include <trace/events/sof_intel.h>
#include "../sof-audio.h"
#include "../ops.h"
......
This diff is collapsed.
......@@ -26,6 +26,7 @@
#include <sound/intel-nhlt.h>
#include <sound/sof.h>
#include <sound/sof/xtensa.h>
#include <sound/hda-mlink.h>
#include "../sof-audio.h"
#include "../sof-pci-dev.h"
#include "../ops.h"
......@@ -917,7 +918,7 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
return ret;
}
hda_bus_ml_get_capabilities(bus);
hda_bus_ml_init(bus);
/* Skip SoundWire if it is not supported */
if (!(interface_mask & BIT(SOF_DAI_INTEL_ALH)))
......@@ -1730,3 +1731,4 @@ MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);
MODULE_IMPORT_NS(SND_INTEL_SOUNDWIRE_ACPI);
MODULE_IMPORT_NS(SOUNDWIRE_INTEL_INIT);
MODULE_IMPORT_NS(SOUNDWIRE_INTEL);
MODULE_IMPORT_NS(SND_SOC_SOF_HDA_MLINK);
......@@ -763,26 +763,6 @@ static inline int hda_codec_i915_exit(struct snd_sof_dev *sdev) { return 0; }
#endif
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
void hda_bus_ml_get_capabilities(struct hdac_bus *bus);
void hda_bus_ml_free(struct hdac_bus *bus);
void hda_bus_ml_put_all(struct hdac_bus *bus);
void hda_bus_ml_reset_losidv(struct hdac_bus *bus);
int hda_bus_ml_resume(struct hdac_bus *bus);
int hda_bus_ml_suspend(struct hdac_bus *bus);
#else
static inline void hda_bus_ml_get_capabilities(struct hdac_bus *bus) { }
static inline void hda_bus_ml_free(struct hdac_bus *bus) { }
static inline void hda_bus_ml_put_all(struct hdac_bus *bus) { }
static inline void hda_bus_ml_reset_losidv(struct hdac_bus *bus) { }
static inline int hda_bus_ml_resume(struct hdac_bus *bus) { return 0; }
static inline int hda_bus_ml_suspend(struct hdac_bus *bus) { return 0; }
#endif /* CONFIG_SND_SOC_SOF_HDA */
/*
* Trace Control.
*/
......
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