Skip to content

Commit

Permalink
ASoC: SOF: Intel: hda-mlink: add helper to program SoundWire PCMSyCM …
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
Pierre-Louis Bossart authored and Mark Brown committed May 15, 2023
1 parent 9643456 commit ccc2f0c
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 0 deletions.
10 changes: 10 additions & 0 deletions include/sound/hda-mlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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; }
Expand Down
50 changes: 50 additions & 0 deletions sound/soc/sof/intel/hda-mlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit ccc2f0c

Please sign in to comment.