Unverified Commit ccc2f0c1 authored by Pierre-Louis Bossart's avatar Pierre-Louis Bossart Committed by Mark Brown
Browse files

ASoC: SOF: Intel: hda-mlink: add helper to program SoundWire PCMSyCM registers



These registers enable the HDaudio DMA hardware to split/merge data
from different PDIs, possibly on different links.

This capability exists for all types of HDaudio extended links, but
for now is only required for SoundWire. In the SSP/DMIC case, the IP
is programmed by the DSP firmware.

Signed-off-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: default avatarBard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: default avatarRander Wang <rander.wang@intel.com>
Reviewed-by: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Link: https://lore.kernel.org/r/20230512174611.84372-7-pierre-louis.bossart@linux.intel.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 9643456e
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -44,6 +44,9 @@ 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);

int hdac_bus_eml_sdw_map_stream_ch(struct hdac_bus *bus, int sublink, int y,
				   int channel_mask, int stream_id, int dir);

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);
@@ -145,6 +148,13 @@ hdac_bus_eml_sdw_power_down_unlocked(struct hdac_bus *bus, int sublink) { return
static inline int
hdac_bus_eml_sdw_set_lsdiid(struct hdac_bus *bus, int sublink, int dev_num) { return 0; }

static inline int
hdac_bus_eml_sdw_map_stream_ch(struct hdac_bus *bus, int sublink, int y,
			       int channel_mask, int stream_id, int dir)
{
	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; }
+50 −0
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ struct hdac_ext2_link {
#define AZX_REG_SDW_SHIM_OFFSET				0x0
#define AZX_REG_SDW_IP_OFFSET				0x100
#define AZX_REG_SDW_VS_SHIM_OFFSET			0x6000
#define AZX_REG_SDW_SHIM_PCMSyCM(y)			(0x16 + 0x4 * (y))

/* only one instance supported */
#define AZX_REG_INTEL_DMIC_SHIM_OFFSET			0x0
@@ -340,6 +341,21 @@ static void hdaml_link_set_lsdiid(u32 __iomem *lsdiid, int dev_num)
	writel(val, lsdiid);
}

static void hdaml_shim_map_stream_ch(u16 __iomem *pcmsycm, int lchan, int hchan,
				     int stream_id, int dir)
{
	u16 val;

	val = readw(pcmsycm);

	u16p_replace_bits(&val, lchan, GENMASK(3, 0));
	u16p_replace_bits(&val, hchan, GENMASK(7, 4));
	u16p_replace_bits(&val, stream_id, GENMASK(13, 8));
	u16p_replace_bits(&val, dir, BIT(15));

	writew(val, pcmsycm);
}

static void hdaml_lctl_offload_enable(u32 __iomem *lctl, bool enable)
{
	u32 val = readl(lctl);
@@ -756,6 +772,40 @@ int hdac_bus_eml_sdw_set_lsdiid(struct hdac_bus *bus, int sublink, int dev_num)
	return 0;
} EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_set_lsdiid, SND_SOC_SOF_HDA_MLINK);

/*
 * the 'y' parameter comes from the PCMSyCM hardware register naming. 'y' refers to the
 * PDI index, i.e. the FIFO used for RX or TX
 */
int hdac_bus_eml_sdw_map_stream_ch(struct hdac_bus *bus, int sublink, int y,
				   int channel_mask, int stream_id, int dir)
{
	struct hdac_ext2_link *h2link;
	u16 __iomem *pcmsycm;
	u16 val;

	h2link = find_ext2_link(bus, true, AZX_REG_ML_LEPTR_ID_SDW);
	if (!h2link)
		return -ENODEV;

	pcmsycm = h2link->base_ptr + h2link->shim_offset +
		h2link->instance_offset * sublink +
		AZX_REG_SDW_SHIM_PCMSyCM(y);

	mutex_lock(&h2link->eml_lock);

	hdaml_shim_map_stream_ch(pcmsycm, 0, hweight32(channel_mask),
				 stream_id, dir);

	mutex_unlock(&h2link->eml_lock);

	val = readw(pcmsycm);

	dev_dbg(bus->dev, "channel_mask %#x stream_id %d dir %d pcmscm %#x\n",
		channel_mask, stream_id, dir, val);

	return 0;
} EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_map_stream_ch, SND_SOC_SOF_HDA_MLINK);

void hda_bus_ml_put_all(struct hdac_bus *bus)
{
	struct hdac_ext_link *hlink;