Unverified Commit d41a7d87 authored by Mark Brown's avatar Mark Brown
Browse files

ASoC: Merge HDA/ext cleanup

Merge branch 'topic/hda-ext-cleanup' of
https://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound into
asoc-6.2 for further AVS work.
parents 625d2753 62582341
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -495,6 +495,13 @@ static inline u16 snd_hdac_reg_readw(struct hdac_bus *bus, void __iomem *addr)
	snd_hdac_chip_writeb(chip, reg, \
			     (snd_hdac_chip_readb(chip, reg) & ~(mask)) | (val))

/* update register macro */
#define snd_hdac_updatel(addr, reg, mask, val)		\
	writel(((readl(addr + reg) & ~(mask)) | (val)), addr + reg)

#define snd_hdac_updatew(addr, reg, mask, val)		\
	writew(((readw(addr + reg) & ~(mask)) | (val)), addr + reg)

/*
 * HD-audio stream
 */
@@ -511,6 +518,13 @@ struct hdac_stream {

	void __iomem *sd_addr;	/* stream descriptor pointer */

	void __iomem *spib_addr; /* software position in buffers stream pointer */
	void __iomem *fifo_addr; /* software position Max fifos stream pointer */

	void __iomem *dpibr_addr; /* DMA position in buffer resume pointer */
	u32 dpib;		/* DMA position in buffer */
	u32 lpib;		/* Linear position in buffer */

	u32 sd_int_sta_mask;	/* stream int status mask */

	/* pcm support */
@@ -575,6 +589,18 @@ void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev,
int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus,
				struct snd_pcm_substream *substream);

void snd_hdac_stream_spbcap_enable(struct hdac_bus *chip,
				   bool enable, int index);
int snd_hdac_stream_set_spib(struct hdac_bus *bus,
			     struct hdac_stream *azx_dev, u32 value);
int snd_hdac_stream_get_spbmaxfifo(struct hdac_bus *bus,
				   struct hdac_stream *azx_dev);
void snd_hdac_stream_drsm_enable(struct hdac_bus *bus,
				 bool enable, int index);
int snd_hdac_stream_set_dpibr(struct hdac_bus *bus,
			      struct hdac_stream *azx_dev, u32 value);
int snd_hdac_stream_set_lpib(struct hdac_stream *azx_dev, u32 value);

/*
 * macros for easy use
 */
+16 −50
Original line number Diff line number Diff line
@@ -23,12 +23,9 @@ void snd_hdac_ext_bus_device_remove(struct hdac_bus *bus);
void snd_hdac_ext_bus_ppcap_enable(struct hdac_bus *chip, bool enable);
void snd_hdac_ext_bus_ppcap_int_enable(struct hdac_bus *chip, bool enable);

void snd_hdac_ext_stream_spbcap_enable(struct hdac_bus *chip,
				 bool enable, int index);

int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_bus *bus);
struct hdac_ext_link *snd_hdac_ext_bus_link_at(struct hdac_bus *bus, int addr);
struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_bus *bus,
struct hdac_ext_link *snd_hdac_ext_bus_get_hlink_by_addr(struct hdac_bus *bus, int addr);
struct hdac_ext_link *snd_hdac_ext_bus_get_hlink_by_name(struct hdac_bus *bus,
							 const char *codec_name);

enum hdac_ext_stream_type {
@@ -43,11 +40,6 @@ enum hdac_ext_stream_type {
 * @hstream: hdac_stream
 * @pphc_addr: processing pipe host stream pointer
 * @pplc_addr: processing pipe link stream pointer
 * @spib_addr: software position in buffers stream pointer
 * @fifo_addr: software position Max fifos stream pointer
 * @dpibr_addr: DMA position in buffer resume pointer
 * @dpib: DMA position in buffer
 * @lpib: Linear position in buffer
 * @decoupled: stream host and link is decoupled
 * @link_locked: link is locked
 * @link_prepared: link is prepared
@@ -59,13 +51,6 @@ struct hdac_ext_stream {
	void __iomem *pphc_addr;
	void __iomem *pplc_addr;

	void __iomem *spib_addr;
	void __iomem *fifo_addr;

	void __iomem *dpibr_addr;

	u32 dpib;
	u32 lpib;
	bool decoupled:1;
	bool link_locked:1;
	bool link_prepared;
@@ -80,7 +65,7 @@ struct hdac_ext_stream {
int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx,
				 int num_stream, int dir);
void snd_hdac_ext_stream_free_all(struct hdac_bus *bus);
void snd_hdac_link_free_all(struct hdac_bus *bus);
void snd_hdac_ext_link_free_all(struct hdac_bus *bus);
struct hdac_ext_stream *snd_hdac_ext_stream_assign(struct hdac_bus *bus,
					   struct snd_pcm_substream *substream,
					   int type);
@@ -90,20 +75,10 @@ void snd_hdac_ext_stream_decouple_locked(struct hdac_bus *bus,
void snd_hdac_ext_stream_decouple(struct hdac_bus *bus,
				struct hdac_ext_stream *azx_dev, bool decouple);

int snd_hdac_ext_stream_set_spib(struct hdac_bus *bus,
				 struct hdac_ext_stream *hext_stream, u32 value);
int snd_hdac_ext_stream_get_spbmaxfifo(struct hdac_bus *bus,
				       struct hdac_ext_stream *hext_stream);
void snd_hdac_ext_stream_drsm_enable(struct hdac_bus *bus,
				bool enable, int index);
int snd_hdac_ext_stream_set_dpibr(struct hdac_bus *bus,
				struct hdac_ext_stream *hext_stream, u32 value);
int snd_hdac_ext_stream_set_lpib(struct hdac_ext_stream *hext_stream, u32 value);

void snd_hdac_ext_link_stream_start(struct hdac_ext_stream *hext_stream);
void snd_hdac_ext_link_stream_clear(struct hdac_ext_stream *hext_stream);
void snd_hdac_ext_link_stream_reset(struct hdac_ext_stream *hext_stream);
int snd_hdac_ext_link_stream_setup(struct hdac_ext_stream *hext_stream, int fmt);
void snd_hdac_ext_stream_start(struct hdac_ext_stream *hext_stream);
void snd_hdac_ext_stream_clear(struct hdac_ext_stream *hext_stream);
void snd_hdac_ext_stream_reset(struct hdac_ext_stream *hext_stream);
int snd_hdac_ext_stream_setup(struct hdac_ext_stream *hext_stream, int fmt);

struct hdac_ext_link {
	struct hdac_bus *bus;
@@ -117,29 +92,20 @@ struct hdac_ext_link {
	struct list_head list;
};

int snd_hdac_ext_bus_link_power_up(struct hdac_ext_link *link);
int snd_hdac_ext_bus_link_power_down(struct hdac_ext_link *link);
int snd_hdac_ext_bus_link_power_up(struct hdac_ext_link *hlink);
int snd_hdac_ext_bus_link_power_down(struct hdac_ext_link *hlink);
int snd_hdac_ext_bus_link_power_up_all(struct hdac_bus *bus);
int snd_hdac_ext_bus_link_power_down_all(struct hdac_bus *bus);
void snd_hdac_ext_link_set_stream_id(struct hdac_ext_link *link,
void snd_hdac_ext_bus_link_set_stream_id(struct hdac_ext_link *hlink,
					 int stream);
void snd_hdac_ext_link_clear_stream_id(struct hdac_ext_link *link,
void snd_hdac_ext_bus_link_clear_stream_id(struct hdac_ext_link *hlink,
					   int stream);

int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, struct hdac_ext_link *link);
int snd_hdac_ext_bus_link_put(struct hdac_bus *bus, struct hdac_ext_link *link);
int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, struct hdac_ext_link *hlink);
int snd_hdac_ext_bus_link_put(struct hdac_bus *bus, struct hdac_ext_link *hlink);

void snd_hdac_ext_bus_link_power(struct hdac_device *codec, bool enable);

/* update register macro */
#define snd_hdac_updatel(addr, reg, mask, val)		\
	writel(((readl(addr + reg) & ~(mask)) | (val)), \
		addr + reg)

#define snd_hdac_updatew(addr, reg, mask, val)		\
	writew(((readw(addr + reg) & ~(mask)) | (val)), \
		addr + reg)

#define snd_hdac_adsp_writeb(chip, reg, value) \
	snd_hdac_reg_writeb(chip, (chip)->dsp_ba + (reg), value)
#define snd_hdac_adsp_readb(chip, reg) \
+67 −49
Original line number Diff line number Diff line
@@ -108,49 +108,47 @@ int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_bus *bus)
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_get_ml_capabilities);

/**
 * snd_hdac_link_free_all- free hdac extended link objects
 * snd_hdac_ext_link_free_all- free hdac extended link objects
 *
 * @bus: the pointer to HDAC bus object
 */

void snd_hdac_link_free_all(struct hdac_bus *bus)
void snd_hdac_ext_link_free_all(struct hdac_bus *bus)
{
	struct hdac_ext_link *l;
	struct hdac_ext_link *hlink;

	while (!list_empty(&bus->hlink_list)) {
		l = list_first_entry(&bus->hlink_list, struct hdac_ext_link, list);
		list_del(&l->list);
		kfree(l);
		hlink = list_first_entry(&bus->hlink_list, struct hdac_ext_link, list);
		list_del(&hlink->list);
		kfree(hlink);
	}
}
EXPORT_SYMBOL_GPL(snd_hdac_link_free_all);
EXPORT_SYMBOL_GPL(snd_hdac_ext_link_free_all);

/**
 * snd_hdac_ext_bus_link_at - get link at specified address
 * @bus: link's parent bus device
 * snd_hdac_ext_bus_get_hlink_by_addr - get hlink at specified address
 * @bus: hlink's parent bus device
 * @addr: codec device address
 *
 * Returns link object or NULL if matching link is not found.
 * Returns hlink object or NULL if matching hlink is not found.
 */
struct hdac_ext_link *snd_hdac_ext_bus_link_at(struct hdac_bus *bus, int addr)
struct hdac_ext_link *snd_hdac_ext_bus_get_hlink_by_addr(struct hdac_bus *bus, int addr)
{
	struct hdac_ext_link *hlink;
	int i;

	list_for_each_entry(hlink, &bus->hlink_list, list)
		for (i = 0; i < HDA_MAX_CODECS; i++)
		if (hlink->lsdiid & (0x1 << addr))
			return hlink;
	return NULL;
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_at);
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_get_hlink_by_addr);

/**
 * snd_hdac_ext_bus_get_link - get link based on codec name
 * snd_hdac_ext_bus_get_hlink_by_name - get hlink based on codec name
 * @bus: the pointer to HDAC bus object
 * @codec_name: codec name
 */
struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_bus *bus,
struct hdac_ext_link *snd_hdac_ext_bus_get_hlink_by_name(struct hdac_bus *bus,
							 const char *codec_name)
{
	int bus_idx, addr;
@@ -162,11 +160,11 @@ struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_bus *bus,
	if (addr < 0 || addr > 31)
		return NULL;

	return snd_hdac_ext_bus_link_at(bus, addr);
	return snd_hdac_ext_bus_get_hlink_by_addr(bus, addr);
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_get_link);
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_get_hlink_by_name);

static int check_hdac_link_power_active(struct hdac_ext_link *link, bool enable)
static int check_hdac_link_power_active(struct hdac_ext_link *hlink, bool enable)
{
	int timeout;
	u32 val;
@@ -176,7 +174,7 @@ static int check_hdac_link_power_active(struct hdac_ext_link *link, bool enable)
	timeout = 150;

	do {
		val = readl(link->ml_addr + AZX_REG_ML_LCTL);
		val = readl(hlink->ml_addr + AZX_REG_ML_LCTL);
		if (enable) {
			if (((val & mask) >> AZX_ML_LCTL_CPA_SHIFT))
				return 0;
@@ -192,26 +190,26 @@ static int check_hdac_link_power_active(struct hdac_ext_link *link, bool enable)

/**
 * snd_hdac_ext_bus_link_power_up -power up hda link
 * @link: HD-audio extended link
 * @hlink: HD-audio extended link
 */
int snd_hdac_ext_bus_link_power_up(struct hdac_ext_link *link)
int snd_hdac_ext_bus_link_power_up(struct hdac_ext_link *hlink)
{
	snd_hdac_updatel(link->ml_addr, AZX_REG_ML_LCTL,
	snd_hdac_updatel(hlink->ml_addr, AZX_REG_ML_LCTL,
			 AZX_ML_LCTL_SPA, AZX_ML_LCTL_SPA);

	return check_hdac_link_power_active(link, true);
	return check_hdac_link_power_active(hlink, true);
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_up);

/**
 * snd_hdac_ext_bus_link_power_down -power down hda link
 * @link: HD-audio extended link
 * @hlink: HD-audio extended link
 */
int snd_hdac_ext_bus_link_power_down(struct hdac_ext_link *link)
int snd_hdac_ext_bus_link_power_down(struct hdac_ext_link *hlink)
{
	snd_hdac_updatel(link->ml_addr, AZX_REG_ML_LCTL, AZX_ML_LCTL_SPA, 0);
	snd_hdac_updatel(hlink->ml_addr, AZX_REG_ML_LCTL, AZX_ML_LCTL_SPA, 0);

	return check_hdac_link_power_active(link, false);
	return check_hdac_link_power_active(hlink, false);
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_down);

@@ -225,9 +223,7 @@ int snd_hdac_ext_bus_link_power_up_all(struct hdac_bus *bus)
	int ret;

	list_for_each_entry(hlink, &bus->hlink_list, list) {
		snd_hdac_updatel(hlink->ml_addr, AZX_REG_ML_LCTL,
				 AZX_ML_LCTL_SPA, AZX_ML_LCTL_SPA);
		ret = check_hdac_link_power_active(hlink, true);
		ret = snd_hdac_ext_bus_link_power_up(hlink);
		if (ret < 0)
			return ret;
	}
@@ -246,9 +242,7 @@ int snd_hdac_ext_bus_link_power_down_all(struct hdac_bus *bus)
	int ret;

	list_for_each_entry(hlink, &bus->hlink_list, list) {
		snd_hdac_updatel(hlink->ml_addr, AZX_REG_ML_LCTL,
				 AZX_ML_LCTL_SPA, 0);
		ret = check_hdac_link_power_active(hlink, false);
		ret = snd_hdac_ext_bus_link_power_down(hlink);
		if (ret < 0)
			return ret;
	}
@@ -257,8 +251,32 @@ int snd_hdac_ext_bus_link_power_down_all(struct hdac_bus *bus)
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_down_all);

/**
 * snd_hdac_ext_bus_link_set_stream_id - maps stream id to link output
 * @link: HD-audio ext link to set up
 * @stream: stream id
 */
void snd_hdac_ext_bus_link_set_stream_id(struct hdac_ext_link *link,
					 int stream)
{
	snd_hdac_updatew(link->ml_addr, AZX_REG_ML_LOSIDV, (1 << stream), 1 << stream);
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_set_stream_id);

/**
 * snd_hdac_ext_bus_link_clear_stream_id - maps stream id to link output
 * @link: HD-audio ext link to set up
 * @stream: stream id
 */
void snd_hdac_ext_bus_link_clear_stream_id(struct hdac_ext_link *link,
					   int stream)
{
	snd_hdac_updatew(link->ml_addr, AZX_REG_ML_LOSIDV, (1 << stream), 0);
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_clear_stream_id);

int snd_hdac_ext_bus_link_get(struct hdac_bus *bus,
				struct hdac_ext_link *link)
				struct hdac_ext_link *hlink)
{
	unsigned long codec_mask;
	int ret = 0;
@@ -269,18 +287,18 @@ int snd_hdac_ext_bus_link_get(struct hdac_bus *bus,
	 * if we move from 0 to 1, count will be 1 so power up this link
	 * as well, also check the dma status and trigger that
	 */
	if (++link->ref_count == 1) {
	if (++hlink->ref_count == 1) {
		if (!bus->cmd_dma_state) {
			snd_hdac_bus_init_cmd_io(bus);
			bus->cmd_dma_state = true;
		}

		ret = snd_hdac_ext_bus_link_power_up(link);
		ret = snd_hdac_ext_bus_link_power_up(hlink);

		/*
		 * clear the register to invalidate all the output streams
		 */
		snd_hdac_updatew(link->ml_addr, AZX_REG_ML_LOSIDV,
		snd_hdac_updatew(hlink->ml_addr, AZX_REG_ML_LOSIDV,
				 AZX_ML_LOSIDV_STREAM_MASK, 0);
		/*
		 *  wait for 521usec for codec to report status
@@ -300,10 +318,10 @@ int snd_hdac_ext_bus_link_get(struct hdac_bus *bus,
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_get);

int snd_hdac_ext_bus_link_put(struct hdac_bus *bus,
				struct hdac_ext_link *link)
			      struct hdac_ext_link *hlink)
{
	int ret = 0;
	struct hdac_ext_link *hlink;
	struct hdac_ext_link *hlink_tmp;
	bool link_up = false;

	mutex_lock(&bus->lock);
@@ -312,15 +330,15 @@ int snd_hdac_ext_bus_link_put(struct hdac_bus *bus,
	 * if we move from 1 to 0, count will be 0
	 * so power down this link as well
	 */
	if (--link->ref_count == 0) {
		ret = snd_hdac_ext_bus_link_power_down(link);
	if (--hlink->ref_count == 0) {
		ret = snd_hdac_ext_bus_link_power_down(hlink);

		/*
		 * now check if all links are off, if so turn off
		 * cmd dma as well
		 */
		list_for_each_entry(hlink, &bus->hlink_list, list) {
			if (hlink->ref_count) {
		list_for_each_entry(hlink_tmp, &bus->hlink_list, list) {
			if (hlink_tmp->ref_count) {
				link_up = true;
				break;
			}
@@ -341,7 +359,7 @@ static void hdac_ext_codec_link_up(struct hdac_device *codec)
{
	const char *devname = dev_name(&codec->dev);
	struct hdac_ext_link *hlink =
		snd_hdac_ext_bus_get_link(codec->bus, devname);
		snd_hdac_ext_bus_get_hlink_by_name(codec->bus, devname);

	if (hlink)
		snd_hdac_ext_bus_link_get(codec->bus, hlink);
@@ -351,7 +369,7 @@ static void hdac_ext_codec_link_down(struct hdac_device *codec)
{
	const char *devname = dev_name(&codec->dev);
	struct hdac_ext_link *hlink =
		snd_hdac_ext_bus_get_link(codec->bus, devname);
		snd_hdac_ext_bus_get_hlink_by_name(codec->bus, devname);

	if (hlink)
		snd_hdac_ext_bus_link_put(codec->bus, hlink);
+20 −183
Original line number Diff line number Diff line
@@ -39,20 +39,6 @@ static void snd_hdac_ext_stream_init(struct hdac_bus *bus,
				AZX_PPLC_INTERVAL * idx;
	}

	if (bus->spbcap) {
		hext_stream->spib_addr = bus->spbcap + AZX_SPB_BASE +
					AZX_SPB_INTERVAL * idx +
					AZX_SPB_SPIB;

		hext_stream->fifo_addr = bus->spbcap + AZX_SPB_BASE +
					AZX_SPB_INTERVAL * idx +
					AZX_SPB_MAXFIFO;
	}

	if (bus->drsmcap)
		hext_stream->dpibr_addr = bus->drsmcap + AZX_DRSM_BASE +
					AZX_DRSM_INTERVAL * idx;

	hext_stream->decoupled = false;
	snd_hdac_stream_init(bus, &hext_stream->hstream, idx, direction, tag);
}
@@ -140,36 +126,36 @@ void snd_hdac_ext_stream_decouple(struct hdac_bus *bus,
EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_decouple);

/**
 * snd_hdac_ext_link_stream_start - start a stream
 * snd_hdac_ext_stream_start - start a stream
 * @hext_stream: HD-audio ext core stream to start
 */
void snd_hdac_ext_link_stream_start(struct hdac_ext_stream *hext_stream)
void snd_hdac_ext_stream_start(struct hdac_ext_stream *hext_stream)
{
	snd_hdac_updatel(hext_stream->pplc_addr, AZX_REG_PPLCCTL,
			 AZX_PPLCCTL_RUN, AZX_PPLCCTL_RUN);
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_link_stream_start);
EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_start);

/**
 * snd_hdac_ext_link_stream_clear - stop a stream DMA
 * snd_hdac_ext_stream_clear - stop a stream DMA
 * @hext_stream: HD-audio ext core stream to stop
 */
void snd_hdac_ext_link_stream_clear(struct hdac_ext_stream *hext_stream)
void snd_hdac_ext_stream_clear(struct hdac_ext_stream *hext_stream)
{
	snd_hdac_updatel(hext_stream->pplc_addr, AZX_REG_PPLCCTL, AZX_PPLCCTL_RUN, 0);
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_link_stream_clear);
EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_clear);

/**
 * snd_hdac_ext_link_stream_reset - reset a stream
 * snd_hdac_ext_stream_reset - reset a stream
 * @hext_stream: HD-audio ext core stream to reset
 */
void snd_hdac_ext_link_stream_reset(struct hdac_ext_stream *hext_stream)
void snd_hdac_ext_stream_reset(struct hdac_ext_stream *hext_stream)
{
	unsigned char val;
	int timeout;

	snd_hdac_ext_link_stream_clear(hext_stream);
	snd_hdac_ext_stream_clear(hext_stream);

	snd_hdac_updatel(hext_stream->pplc_addr, AZX_REG_PPLCCTL,
			 AZX_PPLCCTL_STRST, AZX_PPLCCTL_STRST);
@@ -196,20 +182,20 @@ void snd_hdac_ext_link_stream_reset(struct hdac_ext_stream *hext_stream)
	} while (--timeout);

}
EXPORT_SYMBOL_GPL(snd_hdac_ext_link_stream_reset);
EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_reset);

/**
 * snd_hdac_ext_link_stream_setup -  set up the SD for streaming
 * snd_hdac_ext_stream_setup -  set up the SD for streaming
 * @hext_stream: HD-audio ext core stream to set up
 * @fmt: stream format
 */
int snd_hdac_ext_link_stream_setup(struct hdac_ext_stream *hext_stream, int fmt)
int snd_hdac_ext_stream_setup(struct hdac_ext_stream *hext_stream, int fmt)
{
	struct hdac_stream *hstream = &hext_stream->hstream;
	unsigned int val;

	/* make sure the run bit is zero for SD */
	snd_hdac_ext_link_stream_clear(hext_stream);
	snd_hdac_ext_stream_clear(hext_stream);
	/* program the stream_tag */
	val = readl(hext_stream->pplc_addr + AZX_REG_PPLCCTL);
	val = (val & ~AZX_PPLCCTL_STRM_MASK) |
@@ -221,34 +207,10 @@ int snd_hdac_ext_link_stream_setup(struct hdac_ext_stream *hext_stream, int fmt)

	return 0;
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_link_stream_setup);

/**
 * snd_hdac_ext_link_set_stream_id - maps stream id to link output
 * @link: HD-audio ext link to set up
 * @stream: stream id
 */
void snd_hdac_ext_link_set_stream_id(struct hdac_ext_link *link,
				     int stream)
{
	snd_hdac_updatew(link->ml_addr, AZX_REG_ML_LOSIDV, (1 << stream), 1 << stream);
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_link_set_stream_id);

/**
 * snd_hdac_ext_link_clear_stream_id - maps stream id to link output
 * @link: HD-audio ext link to set up
 * @stream: stream id
 */
void snd_hdac_ext_link_clear_stream_id(struct hdac_ext_link *link,
				 int stream)
{
	snd_hdac_updatew(link->ml_addr, AZX_REG_ML_LOSIDV, (1 << stream), 0);
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_link_clear_stream_id);
EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_setup);

static struct hdac_ext_stream *
hdac_ext_link_stream_assign(struct hdac_bus *bus,
hdac_ext_link_dma_stream_assign(struct hdac_bus *bus,
				struct snd_pcm_substream *substream)
{
	struct hdac_ext_stream *res = NULL;
@@ -284,7 +246,7 @@ hdac_ext_link_stream_assign(struct hdac_bus *bus,
}

static struct hdac_ext_stream *
hdac_ext_host_stream_assign(struct hdac_bus *bus,
hdac_ext_host_dma_stream_assign(struct hdac_bus *bus,
				struct snd_pcm_substream *substream)
{
	struct hdac_ext_stream *res = NULL;
@@ -353,10 +315,10 @@ struct hdac_ext_stream *snd_hdac_ext_stream_assign(struct hdac_bus *bus,
		return hext_stream;

	case HDAC_EXT_STREAM_TYPE_HOST:
		return hdac_ext_host_stream_assign(bus, substream);
		return hdac_ext_host_dma_stream_assign(bus, substream);

	case HDAC_EXT_STREAM_TYPE_LINK:
		return hdac_ext_link_stream_assign(bus, substream);
		return hdac_ext_link_dma_stream_assign(bus, substream);

	default:
		return NULL;
@@ -405,128 +367,3 @@ void snd_hdac_ext_stream_release(struct hdac_ext_stream *hext_stream, int type)

}
EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_release);

/**
 * snd_hdac_ext_stream_spbcap_enable - enable SPIB for a stream
 * @bus: HD-audio core bus
 * @enable: flag to enable/disable SPIB
 * @index: stream index for which SPIB need to be enabled
 */
void snd_hdac_ext_stream_spbcap_enable(struct hdac_bus *bus,
				 bool enable, int index)
{
	u32 mask = 0;

	if (!bus->spbcap) {
		dev_err(bus->dev, "Address of SPB capability is NULL\n");
		return;
	}

	mask |= (1 << index);

	if (enable)
		snd_hdac_updatel(bus->spbcap, AZX_REG_SPB_SPBFCCTL, mask, mask);
	else
		snd_hdac_updatel(bus->spbcap, AZX_REG_SPB_SPBFCCTL, mask, 0);
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_spbcap_enable);

/**
 * snd_hdac_ext_stream_set_spib - sets the spib value of a stream
 * @bus: HD-audio core bus
 * @hext_stream: hdac_ext_stream
 * @value: spib value to set
 */
int snd_hdac_ext_stream_set_spib(struct hdac_bus *bus,
				 struct hdac_ext_stream *hext_stream, u32 value)
{

	if (!bus->spbcap) {
		dev_err(bus->dev, "Address of SPB capability is NULL\n");
		return -EINVAL;
	}

	writel(value, hext_stream->spib_addr);

	return 0;
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_set_spib);

/**
 * snd_hdac_ext_stream_get_spbmaxfifo - gets the spib value of a stream
 * @bus: HD-audio core bus
 * @hext_stream: hdac_ext_stream
 *
 * Return maxfifo for the stream
 */
int snd_hdac_ext_stream_get_spbmaxfifo(struct hdac_bus *bus,
				 struct hdac_ext_stream *hext_stream)
{

	if (!bus->spbcap) {
		dev_err(bus->dev, "Address of SPB capability is NULL\n");
		return -EINVAL;
	}

	return readl(hext_stream->fifo_addr);
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_get_spbmaxfifo);

/**
 * snd_hdac_ext_stream_drsm_enable - enable DMA resume for a stream
 * @bus: HD-audio core bus
 * @enable: flag to enable/disable DRSM
 * @index: stream index for which DRSM need to be enabled
 */
void snd_hdac_ext_stream_drsm_enable(struct hdac_bus *bus,
				bool enable, int index)
{
	u32 mask = 0;

	if (!bus->drsmcap) {
		dev_err(bus->dev, "Address of DRSM capability is NULL\n");
		return;
	}

	mask |= (1 << index);

	if (enable)
		snd_hdac_updatel(bus->drsmcap, AZX_REG_DRSM_CTL, mask, mask);
	else
		snd_hdac_updatel(bus->drsmcap, AZX_REG_DRSM_CTL, mask, 0);
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_drsm_enable);

/**
 * snd_hdac_ext_stream_set_dpibr - sets the dpibr value of a stream
 * @bus: HD-audio core bus
 * @hext_stream: hdac_ext_stream
 * @value: dpib value to set
 */
int snd_hdac_ext_stream_set_dpibr(struct hdac_bus *bus,
				  struct hdac_ext_stream *hext_stream, u32 value)
{

	if (!bus->drsmcap) {
		dev_err(bus->dev, "Address of DRSM capability is NULL\n");
		return -EINVAL;
	}

	writel(value, hext_stream->dpibr_addr);

	return 0;
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_set_dpibr);

/**
 * snd_hdac_ext_stream_set_lpib - sets the lpib value of a stream
 * @hext_stream: hdac_ext_stream
 * @value: lpib value to set
 */
int snd_hdac_ext_stream_set_lpib(struct hdac_ext_stream *hext_stream, u32 value)
{
	snd_hdac_stream_writel(&hext_stream->hstream, SD_LPIB, value);

	return 0;
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_set_lpib);
+136 −0
Original line number Diff line number Diff line
@@ -103,6 +103,20 @@ void snd_hdac_stream_init(struct hdac_bus *bus, struct hdac_stream *azx_dev,
	azx_dev->stream_tag = tag;
	snd_hdac_dsp_lock_init(azx_dev);
	list_add_tail(&azx_dev->list, &bus->stream_list);

	if (bus->spbcap) {
		azx_dev->spib_addr = bus->spbcap + AZX_SPB_BASE +
					AZX_SPB_INTERVAL * idx +
					AZX_SPB_SPIB;

		azx_dev->fifo_addr = bus->spbcap + AZX_SPB_BASE +
					AZX_SPB_INTERVAL * idx +
					AZX_SPB_MAXFIFO;
	}

	if (bus->drsmcap)
		azx_dev->dpibr_addr = bus->drsmcap + AZX_DRSM_BASE +
					AZX_DRSM_INTERVAL * idx;
}
EXPORT_SYMBOL_GPL(snd_hdac_stream_init);

@@ -718,6 +732,128 @@ void snd_hdac_stream_sync(struct hdac_stream *azx_dev, bool start,
}
EXPORT_SYMBOL_GPL(snd_hdac_stream_sync);

/**
 * snd_hdac_stream_spbcap_enable - enable SPIB for a stream
 * @bus: HD-audio core bus
 * @enable: flag to enable/disable SPIB
 * @index: stream index for which SPIB need to be enabled
 */
void snd_hdac_stream_spbcap_enable(struct hdac_bus *bus,
				   bool enable, int index)
{
	u32 mask = 0;

	if (!bus->spbcap) {
		dev_err(bus->dev, "Address of SPB capability is NULL\n");
		return;
	}

	mask |= (1 << index);

	if (enable)
		snd_hdac_updatel(bus->spbcap, AZX_REG_SPB_SPBFCCTL, mask, mask);
	else
		snd_hdac_updatel(bus->spbcap, AZX_REG_SPB_SPBFCCTL, mask, 0);
}
EXPORT_SYMBOL_GPL(snd_hdac_stream_spbcap_enable);

/**
 * snd_hdac_stream_set_spib - sets the spib value of a stream
 * @bus: HD-audio core bus
 * @azx_dev: hdac_stream
 * @value: spib value to set
 */
int snd_hdac_stream_set_spib(struct hdac_bus *bus,
			     struct hdac_stream *azx_dev, u32 value)
{
	if (!bus->spbcap) {
		dev_err(bus->dev, "Address of SPB capability is NULL\n");
		return -EINVAL;
	}

	writel(value, azx_dev->spib_addr);

	return 0;
}
EXPORT_SYMBOL_GPL(snd_hdac_stream_set_spib);

/**
 * snd_hdac_stream_get_spbmaxfifo - gets the spib value of a stream
 * @bus: HD-audio core bus
 * @azx_dev: hdac_stream
 *
 * Return maxfifo for the stream
 */
int snd_hdac_stream_get_spbmaxfifo(struct hdac_bus *bus,
				   struct hdac_stream *azx_dev)
{
	if (!bus->spbcap) {
		dev_err(bus->dev, "Address of SPB capability is NULL\n");
		return -EINVAL;
	}

	return readl(azx_dev->fifo_addr);
}
EXPORT_SYMBOL_GPL(snd_hdac_stream_get_spbmaxfifo);

/**
 * snd_hdac_stream_drsm_enable - enable DMA resume for a stream
 * @bus: HD-audio core bus
 * @enable: flag to enable/disable DRSM
 * @index: stream index for which DRSM need to be enabled
 */
void snd_hdac_stream_drsm_enable(struct hdac_bus *bus,
				 bool enable, int index)
{
	u32 mask = 0;

	if (!bus->drsmcap) {
		dev_err(bus->dev, "Address of DRSM capability is NULL\n");
		return;
	}

	mask |= (1 << index);

	if (enable)
		snd_hdac_updatel(bus->drsmcap, AZX_REG_DRSM_CTL, mask, mask);
	else
		snd_hdac_updatel(bus->drsmcap, AZX_REG_DRSM_CTL, mask, 0);
}
EXPORT_SYMBOL_GPL(snd_hdac_stream_drsm_enable);

/**
 * snd_hdac_stream_set_dpibr - sets the dpibr value of a stream
 * @bus: HD-audio core bus
 * @azx_dev: hdac_stream
 * @value: dpib value to set
 */
int snd_hdac_stream_set_dpibr(struct hdac_bus *bus,
			      struct hdac_stream *azx_dev, u32 value)
{
	if (!bus->drsmcap) {
		dev_err(bus->dev, "Address of DRSM capability is NULL\n");
		return -EINVAL;
	}

	writel(value, azx_dev->dpibr_addr);

	return 0;
}
EXPORT_SYMBOL_GPL(snd_hdac_stream_set_dpibr);

/**
 * snd_hdac_stream_set_lpib - sets the lpib value of a stream
 * @azx_dev: hdac_stream
 * @value: lpib value to set
 */
int snd_hdac_stream_set_lpib(struct hdac_stream *azx_dev, u32 value)
{
	snd_hdac_stream_writel(azx_dev, SD_LPIB, value);

	return 0;
}
EXPORT_SYMBOL_GPL(snd_hdac_stream_set_lpib);

#ifdef CONFIG_SND_HDA_DSP_LOADER
/**
 * snd_hdac_dsp_prepare - prepare for DSP loading
Loading