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

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: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com
Reviewed-by: Rander Wang <rander.wang@intel.com
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com
Link: https://lore.kernel.org/r/20230512174611.84372-7-pierre-louis.bossart@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org
parent 9643456e
......@@ -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; }
......
......@@ -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;
......
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