Skip to content

Commit

Permalink
Merge pull request #4158 from plbossart/hdaudio/extended-multi-link
Browse files Browse the repository at this point in the history
ASoC: SOF: Intel: hda-mlink: add support for Extended Multi Links
  • Loading branch information
plbossart authored Feb 16, 2023
2 parents 157a850 + f423930 commit d0bbcf3
Show file tree
Hide file tree
Showing 11 changed files with 1,329 additions and 46 deletions.
1 change: 1 addition & 0 deletions Documentation/sound/hd-audio/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ HD-Audio
controls
dp-mst
realtek-pc-beep
intel-multi-link
310 changes: 310 additions & 0 deletions Documentation/sound/hd-audio/intel-multi-link.rst

Large diffs are not rendered by default.

166 changes: 166 additions & 0 deletions include/sound/hda-mlink.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/* 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_get_capabilities(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_get_capabilities(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 */
40 changes: 38 additions & 2 deletions include/sound/hda_register.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,27 +258,63 @@ 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

/* bit0 is reserved, with BIT(1) mapping to stream1 */
#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
Expand Down
7 changes: 7 additions & 0 deletions sound/soc/sof/intel/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
5 changes: 4 additions & 1 deletion sound/soc/sof/intel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions sound/soc/sof/intel/hda-ctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down
1 change: 1 addition & 0 deletions sound/soc/sof/intel/hda-dsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Loading

0 comments on commit d0bbcf3

Please sign in to comment.