Commit 84526820 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

Merge branch 'topic/hda-cleanup' into for-next

parents e8750940 fb1d8ac2
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -17,8 +17,6 @@
#include "hda_local.h"
#include "hda_auto_parser.h"

#define SFX	"hda_codec: "

/*
 * Helper for automatic pin configuration
 */
+70 −130
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/reboot.h>
#include <sound/core.h>
#include <sound/initval.h>
#include "hda_priv.h"
@@ -152,11 +153,11 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
		      upper_32_bits(azx_dev->bdl.addr));

	/* enable the position buffer */
	if (chip->position_fix[0] != POS_FIX_LPIB ||
	    chip->position_fix[1] != POS_FIX_LPIB) {
		if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
	if (chip->get_position[0] != azx_get_pos_lpib ||
	    chip->get_position[1] != azx_get_pos_lpib) {
		if (!(azx_readl(chip, DPLBASE) & AZX_DPLBASE_ENABLE))
			azx_writel(chip, DPLBASE,
				(u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
				(u32)chip->posbuf.addr | AZX_DPLBASE_ENABLE);
	}

	/* set the interrupt enable bits in the descriptor control register */
@@ -673,125 +674,40 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
	return 0;
}

/* get the current DMA position with correction on VIA chips */
static unsigned int azx_via_get_position(struct azx *chip,
					 struct azx_dev *azx_dev)
unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev)
{
	unsigned int link_pos, mini_pos, bound_pos;
	unsigned int mod_link_pos, mod_dma_pos, mod_mini_pos;
	unsigned int fifo_size;

	link_pos = azx_sd_readl(chip, azx_dev, SD_LPIB);
	if (azx_dev->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		/* Playback, no problem using link position */
		return link_pos;
	}

	/* Capture */
	/* For new chipset,
	 * use mod to get the DMA position just like old chipset
	 */
	mod_dma_pos = le32_to_cpu(*azx_dev->posbuf);
	mod_dma_pos %= azx_dev->period_bytes;

	/* azx_dev->fifo_size can't get FIFO size of in stream.
	 * Get from base address + offset.
	 */
	fifo_size = readw(chip->remap_addr + VIA_IN_STREAM0_FIFO_SIZE_OFFSET);

	if (azx_dev->insufficient) {
		/* Link position never gather than FIFO size */
		if (link_pos <= fifo_size)
			return 0;

		azx_dev->insufficient = 0;
	}

	if (link_pos <= fifo_size)
		mini_pos = azx_dev->bufsize + link_pos - fifo_size;
	else
		mini_pos = link_pos - fifo_size;

	/* Find nearest previous boudary */
	mod_mini_pos = mini_pos % azx_dev->period_bytes;
	mod_link_pos = link_pos % azx_dev->period_bytes;
	if (mod_link_pos >= fifo_size)
		bound_pos = link_pos - mod_link_pos;
	else if (mod_dma_pos >= mod_mini_pos)
		bound_pos = mini_pos - mod_mini_pos;
	else {
		bound_pos = mini_pos - mod_mini_pos + azx_dev->period_bytes;
		if (bound_pos >= azx_dev->bufsize)
			bound_pos = 0;
	return azx_sd_readl(chip, azx_dev, SD_LPIB);
}
EXPORT_SYMBOL_GPL(azx_get_pos_lpib);

	/* Calculate real DMA position we want */
	return bound_pos + mod_dma_pos;
unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev)
{
	return le32_to_cpu(*azx_dev->posbuf);
}
EXPORT_SYMBOL_GPL(azx_get_pos_posbuf);

unsigned int azx_get_position(struct azx *chip,
			      struct azx_dev *azx_dev,
			      bool with_check)
			      struct azx_dev *azx_dev)
{
	struct snd_pcm_substream *substream = azx_dev->substream;
	struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
	unsigned int pos;
	int stream = substream->stream;
	struct hda_pcm_stream *hinfo = apcm->hinfo[stream];
	int delay = 0;

	switch (chip->position_fix[stream]) {
	case POS_FIX_LPIB:
		/* read LPIB */
		pos = azx_sd_readl(chip, azx_dev, SD_LPIB);
		break;
	case POS_FIX_VIACOMBO:
		pos = azx_via_get_position(chip, azx_dev);
		break;
	default:
		/* use the position buffer */
		pos = le32_to_cpu(*azx_dev->posbuf);
		if (with_check && chip->position_fix[stream] == POS_FIX_AUTO) {
			if (!pos || pos == (u32)-1) {
				dev_info(chip->card->dev,
					 "Invalid position buffer, using LPIB read method instead.\n");
				chip->position_fix[stream] = POS_FIX_LPIB;
				pos = azx_sd_readl(chip, azx_dev, SD_LPIB);
			} else
				chip->position_fix[stream] = POS_FIX_POSBUF;
		}
		break;
	}
	if (chip->get_position[stream])
		pos = chip->get_position[stream](chip, azx_dev);
	else /* use the position buffer as default */
		pos = azx_get_pos_posbuf(chip, azx_dev);

	if (pos >= azx_dev->bufsize)
		pos = 0;

	/* calculate runtime delay from LPIB */
	if (substream->runtime &&
	    chip->position_fix[stream] == POS_FIX_POSBUF &&
	    (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) {
		unsigned int lpib_pos = azx_sd_readl(chip, azx_dev, SD_LPIB);
		if (stream == SNDRV_PCM_STREAM_PLAYBACK)
			delay = pos - lpib_pos;
		else
			delay = lpib_pos - pos;
		if (delay < 0) {
			if (delay >= azx_dev->delay_negative_threshold)
				delay = 0;
			else
				delay += azx_dev->bufsize;
		}
		if (delay >= azx_dev->period_bytes) {
			dev_info(chip->card->dev,
				 "Unstable LPIB (%d >= %d); disabling LPIB delay counting\n",
				 delay, azx_dev->period_bytes);
			delay = 0;
			chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY;
		}
		delay = bytes_to_frames(substream->runtime, delay);
	}

	if (substream->runtime) {
		struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
		struct hda_pcm_stream *hinfo = apcm->hinfo[stream];

		if (chip->get_delay[stream])
			delay += chip->get_delay[stream](chip, azx_dev, pos);
		if (hinfo->ops.get_delay)
			delay += hinfo->ops.get_delay(hinfo, apcm->codec,
						      substream);
@@ -809,7 +725,7 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
	struct azx *chip = apcm->chip;
	struct azx_dev *azx_dev = get_azx_dev(substream);
	return bytes_to_frames(substream->runtime,
			       azx_get_position(chip, azx_dev, false));
			       azx_get_position(chip, azx_dev));
}

static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream,
@@ -1059,10 +975,10 @@ static void azx_init_cmd_io(struct azx *chip)
	azx_writew(chip, CORBWP, 0);

	/* reset the corb hw read pointer */
	azx_writew(chip, CORBRP, ICH6_CORBRP_RST);
	azx_writew(chip, CORBRP, AZX_CORBRP_RST);
	if (!(chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR)) {
		for (timeout = 1000; timeout > 0; timeout--) {
			if ((azx_readw(chip, CORBRP) & ICH6_CORBRP_RST) == ICH6_CORBRP_RST)
			if ((azx_readw(chip, CORBRP) & AZX_CORBRP_RST) == AZX_CORBRP_RST)
				break;
			udelay(1);
		}
@@ -1082,7 +998,7 @@ static void azx_init_cmd_io(struct azx *chip)
	}

	/* enable corb dma */
	azx_writeb(chip, CORBCTL, ICH6_CORBCTL_RUN);
	azx_writeb(chip, CORBCTL, AZX_CORBCTL_RUN);

	/* RIRB set up */
	chip->rirb.addr = chip->rb.addr + 2048;
@@ -1095,14 +1011,14 @@ static void azx_init_cmd_io(struct azx *chip)
	/* set the rirb size to 256 entries (ULI requires explicitly) */
	azx_writeb(chip, RIRBSIZE, 0x02);
	/* reset the rirb hw write pointer */
	azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST);
	azx_writew(chip, RIRBWP, AZX_RIRBWP_RST);
	/* set N=1, get RIRB response interrupt for new entry */
	if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND)
		azx_writew(chip, RINTCNT, 0xc0);
	else
		azx_writew(chip, RINTCNT, 1);
	/* enable rirb dma and response irq */
	azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN);
	azx_writeb(chip, RIRBCTL, AZX_RBCTL_DMA_EN | AZX_RBCTL_IRQ_EN);
	spin_unlock_irq(&chip->reg_lock);
}
EXPORT_SYMBOL_GPL(azx_init_cmd_io);
@@ -1146,7 +1062,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
		return -EIO;
	}
	wp++;
	wp %= ICH6_MAX_CORB_ENTRIES;
	wp %= AZX_MAX_CORB_ENTRIES;

	rp = azx_readw(chip, CORBRP);
	if (wp == rp) {
@@ -1164,7 +1080,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
	return 0;
}

#define ICH6_RIRB_EX_UNSOL_EV	(1<<4)
#define AZX_RIRB_EX_UNSOL_EV	(1<<4)

/* retrieve RIRB entry - called from interrupt handler */
static void azx_update_rirb(struct azx *chip)
@@ -1185,7 +1101,7 @@ static void azx_update_rirb(struct azx *chip)

	while (chip->rirb.rp != wp) {
		chip->rirb.rp++;
		chip->rirb.rp %= ICH6_MAX_RIRB_ENTRIES;
		chip->rirb.rp %= AZX_MAX_RIRB_ENTRIES;

		rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */
		res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]);
@@ -1196,8 +1112,7 @@ static void azx_update_rirb(struct azx *chip)
				res, res_ex,
				chip->rirb.rp, wp);
			snd_BUG();
		}
		else if (res_ex & ICH6_RIRB_EX_UNSOL_EV)
		} else if (res_ex & AZX_RIRB_EX_UNSOL_EV)
			snd_hda_queue_unsol_event(chip->bus, res, res_ex);
		else if (chip->rirb.cmds[addr]) {
			chip->rirb.res[addr] = res;
@@ -1305,7 +1220,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
	/* release CORB/RIRB */
	azx_free_cmd_io(chip);
	/* disable unsolicited responses */
	azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_UNSOL);
	azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~AZX_GCTL_UNSOL);
	return -1;
}

@@ -1326,7 +1241,7 @@ static int azx_single_wait_for_response(struct azx *chip, unsigned int addr)

	while (timeout--) {
		/* check IRV busy bit */
		if (azx_readw(chip, IRS) & ICH6_IRS_VALID) {
		if (azx_readw(chip, IRS) & AZX_IRS_VALID) {
			/* reuse rirb.res as the response return value */
			chip->rirb.res[addr] = azx_readl(chip, IR);
			return 0;
@@ -1350,13 +1265,13 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
	bus->rirb_error = 0;
	while (timeout--) {
		/* check ICB busy bit */
		if (!((azx_readw(chip, IRS) & ICH6_IRS_BUSY))) {
		if (!((azx_readw(chip, IRS) & AZX_IRS_BUSY))) {
			/* Clear IRV valid bit */
			azx_writew(chip, IRS, azx_readw(chip, IRS) |
				   ICH6_IRS_VALID);
				   AZX_IRS_VALID);
			azx_writel(chip, IC, val);
			azx_writew(chip, IRS, azx_readw(chip, IRS) |
				   ICH6_IRS_BUSY);
				   AZX_IRS_BUSY);
			return azx_single_wait_for_response(chip, addr);
		}
		udelay(1);
@@ -1585,10 +1500,10 @@ void azx_enter_link_reset(struct azx *chip)
	unsigned long timeout;

	/* reset controller */
	azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET);
	azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~AZX_GCTL_RESET);

	timeout = jiffies + msecs_to_jiffies(100);
	while ((azx_readb(chip, GCTL) & ICH6_GCTL_RESET) &&
	while ((azx_readb(chip, GCTL) & AZX_GCTL_RESET) &&
			time_before(jiffies, timeout))
		usleep_range(500, 1000);
}
@@ -1599,7 +1514,7 @@ static void azx_exit_link_reset(struct azx *chip)
{
	unsigned long timeout;

	azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET);
	azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | AZX_GCTL_RESET);

	timeout = jiffies + msecs_to_jiffies(100);
	while (!azx_readb(chip, GCTL) &&
@@ -1640,7 +1555,7 @@ static int azx_reset(struct azx *chip, bool full_reset)
	/* Accept unsolicited responses */
	if (!chip->single_cmd)
		azx_writel(chip, GCTL, azx_readl(chip, GCTL) |
			   ICH6_GCTL_UNSOL);
			   AZX_GCTL_UNSOL);

	/* detect codecs */
	if (!chip->codec_mask) {
@@ -1657,7 +1572,7 @@ static void azx_int_enable(struct azx *chip)
{
	/* enable controller CIE and GIE */
	azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) |
		   ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN);
		   AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN);
}

/* disable interrupts */
@@ -1678,7 +1593,7 @@ static void azx_int_disable(struct azx *chip)

	/* disable controller CIE and GIE */
	azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) &
		   ~(ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN));
		   ~(AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN));
}

/* clear interrupts */
@@ -1699,7 +1614,7 @@ static void azx_int_clear(struct azx *chip)
	azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);

	/* clear int status */
	azx_writel(chip, INTSTS, ICH6_INT_CTRL_EN | ICH6_INT_ALL_STREAM);
	azx_writel(chip, INTSTS, AZX_INT_CTRL_EN | AZX_INT_ALL_STREAM);
}

/*
@@ -2031,5 +1946,30 @@ int azx_init_stream(struct azx *chip)
}
EXPORT_SYMBOL_GPL(azx_init_stream);

/*
 * reboot notifier for hang-up problem at power-down
 */
static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf)
{
	struct azx *chip = container_of(nb, struct azx, reboot_notifier);
	snd_hda_bus_reboot_notify(chip->bus);
	azx_stop_chip(chip);
	return NOTIFY_OK;
}

void azx_notifier_register(struct azx *chip)
{
	chip->reboot_notifier.notifier_call = azx_halt;
	register_reboot_notifier(&chip->reboot_notifier);
}
EXPORT_SYMBOL_GPL(azx_notifier_register);

void azx_notifier_unregister(struct azx *chip)
{
	if (chip->reboot_notifier.notifier_call)
		unregister_reboot_notifier(&chip->reboot_notifier);
}
EXPORT_SYMBOL_GPL(azx_notifier_unregister);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Common HDA driver funcitons");
+6 −3
Original line number Diff line number Diff line
@@ -25,9 +25,9 @@ static inline struct azx_dev *get_azx_dev(struct snd_pcm_substream *substream)
{
	return substream->runtime->private_data;
}
unsigned int azx_get_position(struct azx *chip,
			      struct azx_dev *azx_dev,
			      bool with_check);
unsigned int azx_get_position(struct azx *chip, struct azx_dev *azx_dev);
unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev);
unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev);

/* Stream control. */
void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev);
@@ -50,4 +50,7 @@ int azx_codec_configure(struct azx *chip);
int azx_mixer_create(struct azx *chip);
int azx_init_stream(struct azx *chip);

void azx_notifier_register(struct azx *chip);
void azx_notifier_unregister(struct azx *chip);

#endif /* __SOUND_HDA_CONTROLLER_H */
+251 −70

File changed.

Preview size limit exceeded, changes collapsed.

+93 −160
Original line number Diff line number Diff line
@@ -22,107 +22,87 @@
/*
 * registers
 */
#define ICH6_REG_GCAP			0x00
#define   ICH6_GCAP_64OK	(1 << 0)   /* 64bit address support */
#define   ICH6_GCAP_NSDO	(3 << 1)   /* # of serial data out signals */
#define   ICH6_GCAP_BSS		(31 << 3)  /* # of bidirectional streams */
#define   ICH6_GCAP_ISS		(15 << 8)  /* # of input streams */
#define   ICH6_GCAP_OSS		(15 << 12) /* # of output streams */
#define ICH6_REG_VMIN			0x02
#define ICH6_REG_VMAJ			0x03
#define ICH6_REG_OUTPAY			0x04
#define ICH6_REG_INPAY			0x06
#define ICH6_REG_GCTL			0x08
#define   ICH6_GCTL_RESET	(1 << 0)   /* controller reset */
#define   ICH6_GCTL_FCNTRL	(1 << 1)   /* flush control */
#define   ICH6_GCTL_UNSOL	(1 << 8)   /* accept unsol. response enable */
#define ICH6_REG_WAKEEN			0x0c
#define ICH6_REG_STATESTS		0x0e
#define ICH6_REG_GSTS			0x10
#define   ICH6_GSTS_FSTS	(1 << 1)   /* flush status */
#define ICH6_REG_INTCTL			0x20
#define ICH6_REG_INTSTS			0x24
#define ICH6_REG_WALLCLK		0x30	/* 24Mhz source */
#define ICH6_REG_OLD_SSYNC		0x34	/* SSYNC for old ICH */
#define ICH6_REG_SSYNC			0x38
#define ICH6_REG_CORBLBASE		0x40
#define ICH6_REG_CORBUBASE		0x44
#define ICH6_REG_CORBWP			0x48
#define ICH6_REG_CORBRP			0x4a
#define   ICH6_CORBRP_RST	(1 << 15)  /* read pointer reset */
#define ICH6_REG_CORBCTL		0x4c
#define   ICH6_CORBCTL_RUN	(1 << 1)   /* enable DMA */
#define   ICH6_CORBCTL_CMEIE	(1 << 0)   /* enable memory error irq */
#define ICH6_REG_CORBSTS		0x4d
#define   ICH6_CORBSTS_CMEI	(1 << 0)   /* memory error indication */
#define ICH6_REG_CORBSIZE		0x4e

#define ICH6_REG_RIRBLBASE		0x50
#define ICH6_REG_RIRBUBASE		0x54
#define ICH6_REG_RIRBWP			0x58
#define   ICH6_RIRBWP_RST	(1 << 15)  /* write pointer reset */
#define ICH6_REG_RINTCNT		0x5a
#define ICH6_REG_RIRBCTL		0x5c
#define   ICH6_RBCTL_IRQ_EN	(1 << 0)   /* enable IRQ */
#define   ICH6_RBCTL_DMA_EN	(1 << 1)   /* enable DMA */
#define   ICH6_RBCTL_OVERRUN_EN	(1 << 2)   /* enable overrun irq */
#define ICH6_REG_RIRBSTS		0x5d
#define   ICH6_RBSTS_IRQ	(1 << 0)   /* response irq */
#define   ICH6_RBSTS_OVERRUN	(1 << 2)   /* overrun irq */
#define ICH6_REG_RIRBSIZE		0x5e

#define ICH6_REG_IC			0x60
#define ICH6_REG_IR			0x64
#define ICH6_REG_IRS			0x68
#define   ICH6_IRS_VALID	(1<<1)
#define   ICH6_IRS_BUSY		(1<<0)

#define ICH6_REG_DPLBASE		0x70
#define ICH6_REG_DPUBASE		0x74
#define   ICH6_DPLBASE_ENABLE	0x1	/* Enable position buffer */
#define AZX_REG_GCAP			0x00
#define   AZX_GCAP_64OK		(1 << 0)   /* 64bit address support */
#define   AZX_GCAP_NSDO		(3 << 1)   /* # of serial data out signals */
#define   AZX_GCAP_BSS		(31 << 3)  /* # of bidirectional streams */
#define   AZX_GCAP_ISS		(15 << 8)  /* # of input streams */
#define   AZX_GCAP_OSS		(15 << 12) /* # of output streams */
#define AZX_REG_VMIN			0x02
#define AZX_REG_VMAJ			0x03
#define AZX_REG_OUTPAY			0x04
#define AZX_REG_INPAY			0x06
#define AZX_REG_GCTL			0x08
#define   AZX_GCTL_RESET	(1 << 0)   /* controller reset */
#define   AZX_GCTL_FCNTRL	(1 << 1)   /* flush control */
#define   AZX_GCTL_UNSOL	(1 << 8)   /* accept unsol. response enable */
#define AZX_REG_WAKEEN			0x0c
#define AZX_REG_STATESTS		0x0e
#define AZX_REG_GSTS			0x10
#define   AZX_GSTS_FSTS		(1 << 1)   /* flush status */
#define AZX_REG_INTCTL			0x20
#define AZX_REG_INTSTS			0x24
#define AZX_REG_WALLCLK			0x30	/* 24Mhz source */
#define AZX_REG_OLD_SSYNC		0x34	/* SSYNC for old ICH */
#define AZX_REG_SSYNC			0x38
#define AZX_REG_CORBLBASE		0x40
#define AZX_REG_CORBUBASE		0x44
#define AZX_REG_CORBWP			0x48
#define AZX_REG_CORBRP			0x4a
#define   AZX_CORBRP_RST	(1 << 15)  /* read pointer reset */
#define AZX_REG_CORBCTL			0x4c
#define   AZX_CORBCTL_RUN	(1 << 1)   /* enable DMA */
#define   AZX_CORBCTL_CMEIE	(1 << 0)   /* enable memory error irq */
#define AZX_REG_CORBSTS			0x4d
#define   AZX_CORBSTS_CMEI	(1 << 0)   /* memory error indication */
#define AZX_REG_CORBSIZE		0x4e

#define AZX_REG_RIRBLBASE		0x50
#define AZX_REG_RIRBUBASE		0x54
#define AZX_REG_RIRBWP			0x58
#define   AZX_RIRBWP_RST	(1 << 15)  /* write pointer reset */
#define AZX_REG_RINTCNT			0x5a
#define AZX_REG_RIRBCTL			0x5c
#define   AZX_RBCTL_IRQ_EN	(1 << 0)   /* enable IRQ */
#define   AZX_RBCTL_DMA_EN	(1 << 1)   /* enable DMA */
#define   AZX_RBCTL_OVERRUN_EN	(1 << 2)   /* enable overrun irq */
#define AZX_REG_RIRBSTS			0x5d
#define   AZX_RBSTS_IRQ		(1 << 0)   /* response irq */
#define   AZX_RBSTS_OVERRUN	(1 << 2)   /* overrun irq */
#define AZX_REG_RIRBSIZE		0x5e

#define AZX_REG_IC			0x60
#define AZX_REG_IR			0x64
#define AZX_REG_IRS			0x68
#define   AZX_IRS_VALID		(1<<1)
#define   AZX_IRS_BUSY		(1<<0)

#define AZX_REG_DPLBASE			0x70
#define AZX_REG_DPUBASE			0x74
#define   AZX_DPLBASE_ENABLE	0x1	/* Enable position buffer */

/* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };

/* stream register offsets from stream base */
#define ICH6_REG_SD_CTL			0x00
#define ICH6_REG_SD_STS			0x03
#define ICH6_REG_SD_LPIB		0x04
#define ICH6_REG_SD_CBL			0x08
#define ICH6_REG_SD_LVI			0x0c
#define ICH6_REG_SD_FIFOW		0x0e
#define ICH6_REG_SD_FIFOSIZE		0x10
#define ICH6_REG_SD_FORMAT		0x12
#define ICH6_REG_SD_BDLPL		0x18
#define ICH6_REG_SD_BDLPU		0x1c
#define AZX_REG_SD_CTL			0x00
#define AZX_REG_SD_STS			0x03
#define AZX_REG_SD_LPIB			0x04
#define AZX_REG_SD_CBL			0x08
#define AZX_REG_SD_LVI			0x0c
#define AZX_REG_SD_FIFOW		0x0e
#define AZX_REG_SD_FIFOSIZE		0x10
#define AZX_REG_SD_FORMAT		0x12
#define AZX_REG_SD_BDLPL		0x18
#define AZX_REG_SD_BDLPU		0x1c

/* PCI space */
#define ICH6_PCIREG_TCSEL	0x44
#define AZX_PCIREG_TCSEL		0x44

/*
 * other constants
 */

/* max number of SDs */
/* ICH, ATI and VIA have 4 playback and 4 capture */
#define ICH6_NUM_CAPTURE	4
#define ICH6_NUM_PLAYBACK	4

/* ULI has 6 playback and 5 capture */
#define ULI_NUM_CAPTURE		5
#define ULI_NUM_PLAYBACK	6

/* ATI HDMI may have up to 8 playbacks and 0 capture */
#define ATIHDMI_NUM_CAPTURE	0
#define ATIHDMI_NUM_PLAYBACK	8

/* TERA has 4 playback and 3 capture */
#define TERA_NUM_CAPTURE	3
#define TERA_NUM_PLAYBACK	4

/* this number is statically defined for simplicity */
#define MAX_AZX_DEV		16

/* max number of fragments - we may use more if allocating more pages for BDL */
#define BDL_SIZE		4096
#define AZX_MAX_BDL_ENTRIES	(BDL_SIZE / 16)
@@ -160,13 +140,13 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define SD_STS_FIFO_READY	0x20	/* FIFO ready */

/* INTCTL and INTSTS */
#define ICH6_INT_ALL_STREAM	0xff	   /* all stream interrupts */
#define ICH6_INT_CTRL_EN	0x40000000 /* controller interrupt enable bit */
#define ICH6_INT_GLOBAL_EN	0x80000000 /* global interrupt enable bit */
#define AZX_INT_ALL_STREAM	0xff	   /* all stream interrupts */
#define AZX_INT_CTRL_EN	0x40000000 /* controller interrupt enable bit */
#define AZX_INT_GLOBAL_EN	0x80000000 /* global interrupt enable bit */

/* below are so far hardcoded - should read registers in future */
#define ICH6_MAX_CORB_ENTRIES	256
#define ICH6_MAX_RIRB_ENTRIES	256
#define AZX_MAX_CORB_ENTRIES	256
#define AZX_MAX_RIRB_ENTRIES	256

/* driver quirks (capabilities) */
/* bits 0-7 are used for indicating driver type */
@@ -191,35 +171,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define AZX_DCAPS_I915_POWERWELL (1 << 27)	/* HSW i915 powerwell support */
#define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28)	/* CORBRP clears itself after reset */

/* position fix mode */
enum {
	POS_FIX_AUTO,
	POS_FIX_LPIB,
	POS_FIX_POSBUF,
	POS_FIX_VIACOMBO,
	POS_FIX_COMBO,
};

/* Defines for ATI HD Audio support in SB450 south bridge */
#define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR   0x42
#define ATI_SB450_HDAUDIO_ENABLE_SNOOP      0x02

/* Defines for Nvidia HDA support */
#define NVIDIA_HDA_TRANSREG_ADDR      0x4e
#define NVIDIA_HDA_ENABLE_COHBITS     0x0f
#define NVIDIA_HDA_ISTRM_COH          0x4d
#define NVIDIA_HDA_OSTRM_COH          0x4c
#define NVIDIA_HDA_ENABLE_COHBIT      0x01

/* Defines for Intel SCH HDA snoop control */
#define INTEL_SCH_HDA_DEVC      0x78
#define INTEL_SCH_HDA_DEVC_NOSNOOP       (0x1<<11)

/* Define IN stream 0 FIFO size offset in VIA controller */
#define VIA_IN_STREAM0_FIFO_SIZE_OFFSET	0x90
/* Define VIA HD Audio Device ID*/
#define VIA_HDAC_DEVICE_ID		0x3288

/* HD Audio class code */
#define PCI_CLASS_MULTIMEDIA_HD_AUDIO	0x0403

@@ -324,6 +275,9 @@ struct azx_pcm {
	struct list_head list;
};

typedef unsigned int (*azx_get_pos_callback_t)(struct azx *, struct azx_dev *);
typedef int (*azx_get_delay_callback_t)(struct azx *, struct azx_dev *, unsigned int pos);

struct azx {
	struct snd_card *card;
	struct pci_dev *pci;
@@ -342,6 +296,10 @@ struct azx {
	/* Register interaction. */
	const struct hda_controller_ops *ops;

	/* position adjustment callbacks */
	azx_get_pos_callback_t get_position[2];
	azx_get_delay_callback_t get_delay[2];

	/* pci resources */
	unsigned long addr;
	void __iomem *remap_addr;
@@ -350,7 +308,6 @@ struct azx {
	/* locks */
	spinlock_t reg_lock;
	struct mutex open_mutex; /* Prevents concurrent open/close operations */
	struct completion probe_wait;

	/* streams (x num_streams) */
	struct azx_dev *azx_dev;
@@ -377,7 +334,6 @@ struct azx {
#endif

	/* flags */
	int position_fix[2]; /* for both playback/capture streams */
	const int *bdl_pos_adj;
	int poll_count;
	unsigned int running:1;
@@ -385,46 +341,23 @@ struct azx {
	unsigned int single_cmd:1;
	unsigned int polling_mode:1;
	unsigned int msi:1;
	unsigned int irq_pending_warned:1;
	unsigned int probing:1; /* codec probing phase */
	unsigned int snoop:1;
	unsigned int align_buffer_size:1;
	unsigned int region_requested:1;

	/* VGA-switcheroo setup */
	unsigned int use_vga_switcheroo:1;
	unsigned int vga_switcheroo_registered:1;
	unsigned int init_failed:1; /* delayed init failed */
	unsigned int disabled:1; /* disabled by VGA-switcher */

	/* for debugging */
	unsigned int last_cmd[AZX_MAX_CODECS];

	/* for pending irqs */
	struct work_struct irq_pending_work;

	struct work_struct probe_work;

	/* reboot notifier (for mysterious hangup problem at power-down) */
	struct notifier_block reboot_notifier;

	/* card list (for power_save trigger) */
	struct list_head list;

#ifdef CONFIG_SND_HDA_DSP_LOADER
	struct azx_dev saved_azx_dev;
#endif

	/* secondary power domain for hdmi audio under vga device */
	struct dev_pm_domain hdmi_pm_domain;
};

#ifdef CONFIG_SND_VERBOSE_PRINTK
#define SFX	/* nop */
#else
#define SFX	"hda-intel "
#endif

#ifdef CONFIG_X86
#define azx_snoop(chip)		((chip)->snoop)
#else
@@ -436,29 +369,29 @@ struct azx {
 */

#define azx_writel(chip, reg, value) \
	((chip)->ops->reg_writel(value, (chip)->remap_addr + ICH6_REG_##reg))
	((chip)->ops->reg_writel(value, (chip)->remap_addr + AZX_REG_##reg))
#define azx_readl(chip, reg) \
	((chip)->ops->reg_readl((chip)->remap_addr + ICH6_REG_##reg))
	((chip)->ops->reg_readl((chip)->remap_addr + AZX_REG_##reg))
#define azx_writew(chip, reg, value) \
	((chip)->ops->reg_writew(value, (chip)->remap_addr + ICH6_REG_##reg))
	((chip)->ops->reg_writew(value, (chip)->remap_addr + AZX_REG_##reg))
#define azx_readw(chip, reg) \
	((chip)->ops->reg_readw((chip)->remap_addr + ICH6_REG_##reg))
	((chip)->ops->reg_readw((chip)->remap_addr + AZX_REG_##reg))
#define azx_writeb(chip, reg, value) \
	((chip)->ops->reg_writeb(value, (chip)->remap_addr + ICH6_REG_##reg))
	((chip)->ops->reg_writeb(value, (chip)->remap_addr + AZX_REG_##reg))
#define azx_readb(chip, reg) \
	((chip)->ops->reg_readb((chip)->remap_addr + ICH6_REG_##reg))
	((chip)->ops->reg_readb((chip)->remap_addr + AZX_REG_##reg))

#define azx_sd_writel(chip, dev, reg, value) \
	((chip)->ops->reg_writel(value, (dev)->sd_addr + ICH6_REG_##reg))
	((chip)->ops->reg_writel(value, (dev)->sd_addr + AZX_REG_##reg))
#define azx_sd_readl(chip, dev, reg) \
	((chip)->ops->reg_readl((dev)->sd_addr + ICH6_REG_##reg))
	((chip)->ops->reg_readl((dev)->sd_addr + AZX_REG_##reg))
#define azx_sd_writew(chip, dev, reg, value) \
	((chip)->ops->reg_writew(value, (dev)->sd_addr + ICH6_REG_##reg))
	((chip)->ops->reg_writew(value, (dev)->sd_addr + AZX_REG_##reg))
#define azx_sd_readw(chip, dev, reg) \
	((chip)->ops->reg_readw((dev)->sd_addr + ICH6_REG_##reg))
	((chip)->ops->reg_readw((dev)->sd_addr + AZX_REG_##reg))
#define azx_sd_writeb(chip, dev, reg, value) \
	((chip)->ops->reg_writeb(value, (dev)->sd_addr + ICH6_REG_##reg))
	((chip)->ops->reg_writeb(value, (dev)->sd_addr + AZX_REG_##reg))
#define azx_sd_readb(chip, dev, reg) \
	((chip)->ops->reg_readb((dev)->sd_addr + ICH6_REG_##reg))
	((chip)->ops->reg_readb((dev)->sd_addr + AZX_REG_##reg))

#endif /* __SOUND_HDA_PRIV_H */
Loading