Commit 84526820 authored by Takashi Iwai's avatar Takashi Iwai

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

parents e8750940 fb1d8ac2
...@@ -17,8 +17,6 @@ ...@@ -17,8 +17,6 @@
#include "hda_local.h" #include "hda_local.h"
#include "hda_auto_parser.h" #include "hda_auto_parser.h"
#define SFX "hda_codec: "
/* /*
* Helper for automatic pin configuration * Helper for automatic pin configuration
*/ */
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/reboot.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/initval.h> #include <sound/initval.h>
#include "hda_priv.h" #include "hda_priv.h"
...@@ -152,11 +153,11 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) ...@@ -152,11 +153,11 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
upper_32_bits(azx_dev->bdl.addr)); upper_32_bits(azx_dev->bdl.addr));
/* enable the position buffer */ /* enable the position buffer */
if (chip->position_fix[0] != POS_FIX_LPIB || if (chip->get_position[0] != azx_get_pos_lpib ||
chip->position_fix[1] != POS_FIX_LPIB) { chip->get_position[1] != azx_get_pos_lpib) {
if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) if (!(azx_readl(chip, DPLBASE) & AZX_DPLBASE_ENABLE))
azx_writel(chip, DPLBASE, 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 */ /* 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) ...@@ -673,125 +674,40 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
return 0; return 0;
} }
/* get the current DMA position with correction on VIA chips */ unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev)
static unsigned int azx_via_get_position(struct azx *chip,
struct azx_dev *azx_dev)
{ {
unsigned int link_pos, mini_pos, bound_pos; return azx_sd_readl(chip, azx_dev, SD_LPIB);
unsigned int mod_link_pos, mod_dma_pos, mod_mini_pos; }
unsigned int fifo_size; EXPORT_SYMBOL_GPL(azx_get_pos_lpib);
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;
}
/* Calculate real DMA position we want */ unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev)
return bound_pos + mod_dma_pos; {
return le32_to_cpu(*azx_dev->posbuf);
} }
EXPORT_SYMBOL_GPL(azx_get_pos_posbuf);
unsigned int azx_get_position(struct azx *chip, unsigned int azx_get_position(struct azx *chip,
struct azx_dev *azx_dev, struct azx_dev *azx_dev)
bool with_check)
{ {
struct snd_pcm_substream *substream = azx_dev->substream; struct snd_pcm_substream *substream = azx_dev->substream;
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
unsigned int pos; unsigned int pos;
int stream = substream->stream; int stream = substream->stream;
struct hda_pcm_stream *hinfo = apcm->hinfo[stream];
int delay = 0; int delay = 0;
switch (chip->position_fix[stream]) { if (chip->get_position[stream])
case POS_FIX_LPIB: pos = chip->get_position[stream](chip, azx_dev);
/* read LPIB */ else /* use the position buffer as default */
pos = azx_sd_readl(chip, azx_dev, SD_LPIB); pos = azx_get_pos_posbuf(chip, azx_dev);
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 (pos >= azx_dev->bufsize) if (pos >= azx_dev->bufsize)
pos = 0; 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) { 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) if (hinfo->ops.get_delay)
delay += hinfo->ops.get_delay(hinfo, apcm->codec, delay += hinfo->ops.get_delay(hinfo, apcm->codec,
substream); substream);
...@@ -809,7 +725,7 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *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 *chip = apcm->chip;
struct azx_dev *azx_dev = get_azx_dev(substream); struct azx_dev *azx_dev = get_azx_dev(substream);
return bytes_to_frames(substream->runtime, 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, static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream,
...@@ -1059,10 +975,10 @@ static void azx_init_cmd_io(struct azx *chip) ...@@ -1059,10 +975,10 @@ static void azx_init_cmd_io(struct azx *chip)
azx_writew(chip, CORBWP, 0); azx_writew(chip, CORBWP, 0);
/* reset the corb hw read pointer */ /* 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)) { if (!(chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR)) {
for (timeout = 1000; timeout > 0; timeout--) { 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; break;
udelay(1); udelay(1);
} }
...@@ -1082,7 +998,7 @@ static void azx_init_cmd_io(struct azx *chip) ...@@ -1082,7 +998,7 @@ static void azx_init_cmd_io(struct azx *chip)
} }
/* enable corb dma */ /* enable corb dma */
azx_writeb(chip, CORBCTL, ICH6_CORBCTL_RUN); azx_writeb(chip, CORBCTL, AZX_CORBCTL_RUN);
/* RIRB set up */ /* RIRB set up */
chip->rirb.addr = chip->rb.addr + 2048; chip->rirb.addr = chip->rb.addr + 2048;
...@@ -1095,14 +1011,14 @@ static void azx_init_cmd_io(struct azx *chip) ...@@ -1095,14 +1011,14 @@ static void azx_init_cmd_io(struct azx *chip)
/* set the rirb size to 256 entries (ULI requires explicitly) */ /* set the rirb size to 256 entries (ULI requires explicitly) */
azx_writeb(chip, RIRBSIZE, 0x02); azx_writeb(chip, RIRBSIZE, 0x02);
/* reset the rirb hw write pointer */ /* 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 */ /* set N=1, get RIRB response interrupt for new entry */
if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND)
azx_writew(chip, RINTCNT, 0xc0); azx_writew(chip, RINTCNT, 0xc0);
else else
azx_writew(chip, RINTCNT, 1); azx_writew(chip, RINTCNT, 1);
/* enable rirb dma and response irq */ /* 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); spin_unlock_irq(&chip->reg_lock);
} }
EXPORT_SYMBOL_GPL(azx_init_cmd_io); EXPORT_SYMBOL_GPL(azx_init_cmd_io);
...@@ -1146,7 +1062,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val) ...@@ -1146,7 +1062,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
return -EIO; return -EIO;
} }
wp++; wp++;
wp %= ICH6_MAX_CORB_ENTRIES; wp %= AZX_MAX_CORB_ENTRIES;
rp = azx_readw(chip, CORBRP); rp = azx_readw(chip, CORBRP);
if (wp == rp) { if (wp == rp) {
...@@ -1164,7 +1080,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val) ...@@ -1164,7 +1080,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
return 0; 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 */ /* retrieve RIRB entry - called from interrupt handler */
static void azx_update_rirb(struct azx *chip) static void azx_update_rirb(struct azx *chip)
...@@ -1185,7 +1101,7 @@ 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) { while (chip->rirb.rp != wp) {
chip->rirb.rp++; 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 */ rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */
res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]); res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]);
...@@ -1196,8 +1112,7 @@ static void azx_update_rirb(struct azx *chip) ...@@ -1196,8 +1112,7 @@ static void azx_update_rirb(struct azx *chip)
res, res_ex, res, res_ex,
chip->rirb.rp, wp); chip->rirb.rp, wp);
snd_BUG(); snd_BUG();
} } else if (res_ex & AZX_RIRB_EX_UNSOL_EV)
else if (res_ex & ICH6_RIRB_EX_UNSOL_EV)
snd_hda_queue_unsol_event(chip->bus, res, res_ex); snd_hda_queue_unsol_event(chip->bus, res, res_ex);
else if (chip->rirb.cmds[addr]) { else if (chip->rirb.cmds[addr]) {
chip->rirb.res[addr] = res; chip->rirb.res[addr] = res;
...@@ -1305,7 +1220,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, ...@@ -1305,7 +1220,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
/* release CORB/RIRB */ /* release CORB/RIRB */
azx_free_cmd_io(chip); azx_free_cmd_io(chip);
/* disable unsolicited responses */ /* 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; return -1;
} }
...@@ -1326,7 +1241,7 @@ static int azx_single_wait_for_response(struct azx *chip, unsigned int addr) ...@@ -1326,7 +1241,7 @@ static int azx_single_wait_for_response(struct azx *chip, unsigned int addr)
while (timeout--) { while (timeout--) {
/* check IRV busy bit */ /* 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 */ /* reuse rirb.res as the response return value */
chip->rirb.res[addr] = azx_readl(chip, IR); chip->rirb.res[addr] = azx_readl(chip, IR);
return 0; return 0;
...@@ -1350,13 +1265,13 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val) ...@@ -1350,13 +1265,13 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
bus->rirb_error = 0; bus->rirb_error = 0;
while (timeout--) { while (timeout--) {
/* check ICB busy bit */ /* check ICB busy bit */
if (!((azx_readw(chip, IRS) & ICH6_IRS_BUSY))) { if (!((azx_readw(chip, IRS) & AZX_IRS_BUSY))) {
/* Clear IRV valid bit */ /* Clear IRV valid bit */
azx_writew(chip, IRS, azx_readw(chip, IRS) | azx_writew(chip, IRS, azx_readw(chip, IRS) |
ICH6_IRS_VALID); AZX_IRS_VALID);
azx_writel(chip, IC, val); azx_writel(chip, IC, val);
azx_writew(chip, IRS, azx_readw(chip, IRS) | azx_writew(chip, IRS, azx_readw(chip, IRS) |
ICH6_IRS_BUSY); AZX_IRS_BUSY);
return azx_single_wait_for_response(chip, addr); return azx_single_wait_for_response(chip, addr);
} }
udelay(1); udelay(1);
...@@ -1585,10 +1500,10 @@ void azx_enter_link_reset(struct azx *chip) ...@@ -1585,10 +1500,10 @@ void azx_enter_link_reset(struct azx *chip)
unsigned long timeout; unsigned long timeout;
/* reset controller */ /* 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); 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)) time_before(jiffies, timeout))
usleep_range(500, 1000); usleep_range(500, 1000);
} }
...@@ -1599,7 +1514,7 @@ static void azx_exit_link_reset(struct azx *chip) ...@@ -1599,7 +1514,7 @@ static void azx_exit_link_reset(struct azx *chip)
{ {
unsigned long timeout; 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); timeout = jiffies + msecs_to_jiffies(100);
while (!azx_readb(chip, GCTL) && while (!azx_readb(chip, GCTL) &&
...@@ -1640,7 +1555,7 @@ static int azx_reset(struct azx *chip, bool full_reset) ...@@ -1640,7 +1555,7 @@ static int azx_reset(struct azx *chip, bool full_reset)
/* Accept unsolicited responses */ /* Accept unsolicited responses */
if (!chip->single_cmd) if (!chip->single_cmd)
azx_writel(chip, GCTL, azx_readl(chip, GCTL) | azx_writel(chip, GCTL, azx_readl(chip, GCTL) |
ICH6_GCTL_UNSOL); AZX_GCTL_UNSOL);
/* detect codecs */ /* detect codecs */
if (!chip->codec_mask) { if (!chip->codec_mask) {
...@@ -1657,7 +1572,7 @@ static void azx_int_enable(struct azx *chip) ...@@ -1657,7 +1572,7 @@ static void azx_int_enable(struct azx *chip)
{ {
/* enable controller CIE and GIE */ /* enable controller CIE and GIE */
azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) | 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 */ /* disable interrupts */
...@@ -1678,7 +1593,7 @@ static void azx_int_disable(struct azx *chip) ...@@ -1678,7 +1593,7 @@ static void azx_int_disable(struct azx *chip)
/* disable controller CIE and GIE */ /* disable controller CIE and GIE */
azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) & 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 */ /* clear interrupts */
...@@ -1699,7 +1614,7 @@ static void azx_int_clear(struct azx *chip) ...@@ -1699,7 +1614,7 @@ static void azx_int_clear(struct azx *chip)
azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
/* clear int status */ /* 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) ...@@ -2031,5 +1946,30 @@ int azx_init_stream(struct azx *chip)
} }
EXPORT_SYMBOL_GPL(azx_init_stream); 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_LICENSE("GPL");
MODULE_DESCRIPTION("Common HDA driver funcitons"); MODULE_DESCRIPTION("Common HDA driver funcitons");
...@@ -25,9 +25,9 @@ static inline struct azx_dev *get_azx_dev(struct snd_pcm_substream *substream) ...@@ -25,9 +25,9 @@ static inline struct azx_dev *get_azx_dev(struct snd_pcm_substream *substream)
{ {
return substream->runtime->private_data; return substream->runtime->private_data;
} }
unsigned int azx_get_position(struct azx *chip, unsigned int azx_get_position(struct azx *chip, struct azx_dev *azx_dev);
struct azx_dev *azx_dev, unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev);
bool with_check); unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev);
/* Stream control. */ /* Stream control. */
void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev); void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev);
...@@ -50,4 +50,7 @@ int azx_codec_configure(struct azx *chip); ...@@ -50,4 +50,7 @@ int azx_codec_configure(struct azx *chip);
int azx_mixer_create(struct azx *chip); int azx_mixer_create(struct azx *chip);
int azx_init_stream(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 */ #endif /* __SOUND_HDA_CONTROLLER_H */
...@@ -44,7 +44,6 @@ ...@@ -44,7 +44,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/reboot.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/clocksource.h> #include <linux/clocksource.h>
...@@ -66,6 +65,52 @@ ...@@ -66,6 +65,52 @@
#include "hda_controller.h" #include "hda_controller.h"
#include "hda_priv.h" #include "hda_priv.h"
/* 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
/* 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
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
...@@ -294,8 +339,8 @@ static char *driver_short_names[] = { ...@@ -294,8 +339,8 @@ static char *driver_short_names[] = {
* Clock) to 24MHz BCLK: BCLK = CDCLK * M / N * Clock) to 24MHz BCLK: BCLK = CDCLK * M / N
* The values will be lost when the display power well is disabled. * The values will be lost when the display power well is disabled.
*/ */
#define ICH6_REG_EM4 0x100c #define AZX_REG_EM4 0x100c
#define ICH6_REG_EM5 0x1010 #define AZX_REG_EM5 0x1010
struct hda_intel { struct hda_intel {
struct azx chip; struct azx chip;
...@@ -303,8 +348,28 @@ struct hda_intel { ...@@ -303,8 +348,28 @@ struct hda_intel {
/* HSW/BDW display HDA controller to restore BCLK from CDCLK */ /* HSW/BDW display HDA controller to restore BCLK from CDCLK */
unsigned int bclk_m; unsigned int bclk_m;
unsigned int bclk_n; unsigned int bclk_n;
};
/* for pending irqs */
struct work_struct irq_pending_work;
/* sync probing */
struct completion probe_wait;
struct work_struct probe_work;
/* card list (for power_save trigger) */
struct list_head list;
/* extra flags */
unsigned int irq_pending_warned:1;
/* VGA-switcheroo setup */
unsigned int use_vga_switcheroo:1;
unsigned int vga_switcheroo_registered:1;
unsigned int init_failed:1; /* delayed init failed */
/* secondary power domain for hdmi audio under vga device */
struct dev_pm_domain hdmi_pm_domain;
};
#ifdef CONFIG_X86 #ifdef CONFIG_X86
static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on) static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on)
...@@ -386,7 +451,7 @@ static void azx_init_pci(struct azx *chip) ...@@ -386,7 +451,7 @@ static void azx_init_pci(struct azx *chip)
*/ */
if (!(chip->driver_caps & AZX_DCAPS_NO_TCSEL)) { if (!(chip->driver_caps & AZX_DCAPS_NO_TCSEL)) {
dev_dbg(chip->card->dev, "Clearing TCSEL\n"); dev_dbg(chip->card->dev, "Clearing TCSEL\n");
update_pci_byte(chip->pci, ICH6_PCIREG_TCSEL, 0x07, 0); update_pci_byte(chip->pci, AZX_PCIREG_TCSEL, 0x07, 0);
} }
/* For ATI SB450/600/700/800/900 and AMD Hudson azalia HD audio, /* For ATI SB450/600/700/800/900 and AMD Hudson azalia HD audio,
...@@ -434,11 +499,44 @@ static void azx_init_pci(struct azx *chip) ...@@ -434,11 +499,44 @@ static void azx_init_pci(struct azx *chip)
} }
} }
/* calculate runtime delay from LPIB */
static int azx_get_delay_from_lpib(struct azx *chip, struct azx_dev *azx_dev,
unsigned int pos)
{
struct snd_pcm_substream *substream = azx_dev->substream;
int stream = substream->stream;
unsigned int lpib_pos = azx_get_pos_lpib(chip, azx_dev);
int delay;
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;
chip->get_delay[stream] = NULL;
}
return bytes_to_frames(substream->runtime, delay);
}
static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev); static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev);
/* called from IRQ */ /* called from IRQ */
static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev)
{ {
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
int ok; int ok;
ok = azx_position_ok(chip, azx_dev); ok = azx_position_ok(chip, azx_dev);
...@@ -448,7 +546,7 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) ...@@ -448,7 +546,7 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev)
} else if (ok == 0 && chip->bus && chip->bus->workq) { } else if (ok == 0 && chip->bus && chip->bus->workq) {
/* bogus IRQ, process it later */ /* bogus IRQ, process it later */
azx_dev->irq_pending = 1; azx_dev->irq_pending = 1;
queue_work(chip->bus->workq, &chip->irq_pending_work); queue_work(chip->bus->workq, &hda->irq_pending_work);
} }
return 0; return 0;
} }
...@@ -464,6 +562,8 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) ...@@ -464,6 +562,8 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev)
*/ */
static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
{ {
struct snd_pcm_substream *substream = azx_dev->substream;
int stream = substream->stream;
u32 wallclk; u32 wallclk;
unsigned int pos; unsigned int pos;
...@@ -471,7 +571,25 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) ...@@ -471,7 +571,25 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
if (wallclk < (azx_dev->period_wallclk * 2) / 3) if (wallclk < (azx_dev->period_wallclk * 2) / 3)
return -1; /* bogus (too early) interrupt */ return -1; /* bogus (too early) interrupt */
pos = azx_get_position(chip, azx_dev, true); 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 || pos == (u32)-1) {
dev_info(chip->card->dev,
"Invalid position buffer, using LPIB read method instead.\n");
chip->get_position[stream] = azx_get_pos_lpib;
pos = azx_get_pos_lpib(chip, azx_dev);
chip->get_delay[stream] = NULL;
} else {
chip->get_position[stream] = azx_get_pos_posbuf;
if (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)
chip->get_delay[stream] = azx_get_delay_from_lpib;
}
}
if (pos >= azx_dev->bufsize)
pos = 0;
if (WARN_ONCE(!azx_dev->period_bytes, if (WARN_ONCE(!azx_dev->period_bytes,
"hda-intel: zero azx_dev->period_bytes")) "hda-intel: zero azx_dev->period_bytes"))
...@@ -489,14 +607,15 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) ...@@ -489,14 +607,15 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
*/ */
static void azx_irq_pending_work(struct work_struct *work) static void azx_irq_pending_work(struct work_struct *work)
{ {
struct azx *chip = container_of(work, struct azx, irq_pending_work); struct hda_intel *hda = container_of(work, struct hda_intel, irq_pending_work);
struct azx *chip = &hda->chip;
int i, pending, ok; int i, pending, ok;
if (!chip->irq_pending_warned) { if (!hda->irq_pending_warned) {
dev_info(chip->card->dev, dev_info(chip->card->dev,
"IRQ timing workaround is activated for card #%d. Suggest a bigger bdl_pos_adj.\n", "IRQ timing workaround is activated for card #%d. Suggest a bigger bdl_pos_adj.\n",
chip->card->number); chip->card->number);
chip->irq_pending_warned = 1; hda->irq_pending_warned = 1;
} }
for (;;) { for (;;) {
...@@ -554,27 +673,86 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect) ...@@ -554,27 +673,86 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect)
return 0; 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 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;
}
/* Calculate real DMA position we want */
return bound_pos + mod_dma_pos;
}
#ifdef CONFIG_PM #ifdef CONFIG_PM
static DEFINE_MUTEX(card_list_lock); static DEFINE_MUTEX(card_list_lock);
static LIST_HEAD(card_list); static LIST_HEAD(card_list);
static void azx_add_card_list(struct azx *chip) static void azx_add_card_list(struct azx *chip)
{ {
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
mutex_lock(&card_list_lock); mutex_lock(&card_list_lock);
list_add(&chip->list, &card_list); list_add(&hda->list, &card_list);
mutex_unlock(&card_list_lock); mutex_unlock(&card_list_lock);
} }
static void azx_del_card_list(struct azx *chip) static void azx_del_card_list(struct azx *chip)
{ {
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
mutex_lock(&card_list_lock); mutex_lock(&card_list_lock);
list_del_init(&chip->list); list_del_init(&hda->list);
mutex_unlock(&card_list_lock); mutex_unlock(&card_list_lock);
} }
/* trigger power-save check at writing parameter */ /* trigger power-save check at writing parameter */
static int param_set_xint(const char *val, const struct kernel_param *kp) static int param_set_xint(const char *val, const struct kernel_param *kp)
{ {
struct hda_intel *hda;
struct azx *chip; struct azx *chip;
struct hda_codec *c; struct hda_codec *c;
int prev = power_save; int prev = power_save;
...@@ -584,7 +762,8 @@ static int param_set_xint(const char *val, const struct kernel_param *kp) ...@@ -584,7 +762,8 @@ static int param_set_xint(const char *val, const struct kernel_param *kp)
return ret; return ret;
mutex_lock(&card_list_lock); mutex_lock(&card_list_lock);
list_for_each_entry(chip, &card_list, list) { list_for_each_entry(hda, &card_list, list) {
chip = &hda->chip;
if (!chip->bus || chip->disabled) if (!chip->bus || chip->disabled)
continue; continue;
list_for_each_entry(c, &chip->bus->codec_list, list) list_for_each_entry(c, &chip->bus->codec_list, list)
...@@ -789,29 +968,6 @@ static const struct dev_pm_ops azx_pm = { ...@@ -789,29 +968,6 @@ static const struct dev_pm_ops azx_pm = {
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
/*
* 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;
}
static void azx_notifier_register(struct azx *chip)
{
chip->reboot_notifier.notifier_call = azx_halt;
register_reboot_notifier(&chip->reboot_notifier);
}
static void azx_notifier_unregister(struct azx *chip)
{
if (chip->reboot_notifier.notifier_call)
unregister_reboot_notifier(&chip->reboot_notifier);
}
static int azx_probe_continue(struct azx *chip); static int azx_probe_continue(struct azx *chip);
#ifdef SUPPORT_VGA_SWITCHEROO #ifdef SUPPORT_VGA_SWITCHEROO
...@@ -822,10 +978,11 @@ static void azx_vs_set_state(struct pci_dev *pci, ...@@ -822,10 +978,11 @@ static void azx_vs_set_state(struct pci_dev *pci,
{ {
struct snd_card *card = pci_get_drvdata(pci); struct snd_card *card = pci_get_drvdata(pci);
struct azx *chip = card->private_data; struct azx *chip = card->private_data;
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
bool disabled; bool disabled;
wait_for_completion(&chip->probe_wait); wait_for_completion(&hda->probe_wait);
if (chip->init_failed) if (hda->init_failed)
return; return;
disabled = (state == VGA_SWITCHEROO_OFF); disabled = (state == VGA_SWITCHEROO_OFF);
...@@ -839,7 +996,7 @@ static void azx_vs_set_state(struct pci_dev *pci, ...@@ -839,7 +996,7 @@ static void azx_vs_set_state(struct pci_dev *pci,
"Start delayed initialization\n"); "Start delayed initialization\n");
if (azx_probe_continue(chip) < 0) { if (azx_probe_continue(chip) < 0) {
dev_err(chip->card->dev, "initialization error\n"); dev_err(chip->card->dev, "initialization error\n");
chip->init_failed = true; hda->init_failed = true;
} }
} }
} else { } else {
...@@ -869,9 +1026,10 @@ static bool azx_vs_can_switch(struct pci_dev *pci) ...@@ -869,9 +1026,10 @@ static bool azx_vs_can_switch(struct pci_dev *pci)
{ {
struct snd_card *card = pci_get_drvdata(pci); struct snd_card *card = pci_get_drvdata(pci);
struct azx *chip = card->private_data; struct azx *chip = card->private_data;
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
wait_for_completion(&chip->probe_wait); wait_for_completion(&hda->probe_wait);
if (chip->init_failed) if (hda->init_failed)
return false; return false;
if (chip->disabled || !chip->bus) if (chip->disabled || !chip->bus)
return true; return true;
...@@ -883,11 +1041,12 @@ static bool azx_vs_can_switch(struct pci_dev *pci) ...@@ -883,11 +1041,12 @@ static bool azx_vs_can_switch(struct pci_dev *pci)
static void init_vga_switcheroo(struct azx *chip) static void init_vga_switcheroo(struct azx *chip)
{ {
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
struct pci_dev *p = get_bound_vga(chip->pci); struct pci_dev *p = get_bound_vga(chip->pci);
if (p) { if (p) {
dev_info(chip->card->dev, dev_info(chip->card->dev,
"Handle VGA-switcheroo audio client\n"); "Handle VGA-switcheroo audio client\n");
chip->use_vga_switcheroo = 1; hda->use_vga_switcheroo = 1;
pci_dev_put(p); pci_dev_put(p);
} }
} }
...@@ -899,9 +1058,10 @@ static const struct vga_switcheroo_client_ops azx_vs_ops = { ...@@ -899,9 +1058,10 @@ static const struct vga_switcheroo_client_ops azx_vs_ops = {
static int register_vga_switcheroo(struct azx *chip) static int register_vga_switcheroo(struct azx *chip)
{ {
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
int err; int err;
if (!chip->use_vga_switcheroo) if (!hda->use_vga_switcheroo)
return 0; return 0;
/* FIXME: currently only handling DIS controller /* FIXME: currently only handling DIS controller
* is there any machine with two switchable HDMI audio controllers? * is there any machine with two switchable HDMI audio controllers?
...@@ -911,11 +1071,11 @@ static int register_vga_switcheroo(struct azx *chip) ...@@ -911,11 +1071,11 @@ static int register_vga_switcheroo(struct azx *chip)
chip->bus != NULL); chip->bus != NULL);
if (err < 0) if (err < 0)
return err; return err;
chip->vga_switcheroo_registered = 1; hda->vga_switcheroo_registered = 1;
/* register as an optimus hdmi audio power domain */ /* register as an optimus hdmi audio power domain */
vga_switcheroo_init_domain_pm_optimus_hdmi_audio(chip->card->dev, vga_switcheroo_init_domain_pm_optimus_hdmi_audio(chip->card->dev,
&chip->hdmi_pm_domain); &hda->hdmi_pm_domain);
return 0; return 0;
} }
#else #else
...@@ -931,7 +1091,6 @@ static int azx_free(struct azx *chip) ...@@ -931,7 +1091,6 @@ static int azx_free(struct azx *chip)
{ {
struct pci_dev *pci = chip->pci; struct pci_dev *pci = chip->pci;
struct hda_intel *hda = container_of(chip, struct hda_intel, chip); struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
int i; int i;
if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME)
...@@ -942,13 +1101,13 @@ static int azx_free(struct azx *chip) ...@@ -942,13 +1101,13 @@ static int azx_free(struct azx *chip)
azx_notifier_unregister(chip); azx_notifier_unregister(chip);
chip->init_failed = 1; /* to be sure */ hda->init_failed = 1; /* to be sure */
complete_all(&chip->probe_wait); complete_all(&hda->probe_wait);
if (use_vga_switcheroo(chip)) { if (use_vga_switcheroo(hda)) {
if (chip->disabled && chip->bus) if (chip->disabled && chip->bus)
snd_hda_unlock_devices(chip->bus); snd_hda_unlock_devices(chip->bus);
if (chip->vga_switcheroo_registered) if (hda->vga_switcheroo_registered)
vga_switcheroo_unregister_client(chip->pci); vga_switcheroo_unregister_client(chip->pci);
} }
...@@ -1084,6 +1243,30 @@ static int check_position_fix(struct azx *chip, int fix) ...@@ -1084,6 +1243,30 @@ static int check_position_fix(struct azx *chip, int fix)
return POS_FIX_AUTO; return POS_FIX_AUTO;
} }
static void assign_position_fix(struct azx *chip, int fix)
{
static azx_get_pos_callback_t callbacks[] = {
[POS_FIX_AUTO] = NULL,
[POS_FIX_LPIB] = azx_get_pos_lpib,
[POS_FIX_POSBUF] = azx_get_pos_posbuf,
[POS_FIX_VIACOMBO] = azx_via_get_position,
[POS_FIX_COMBO] = azx_get_pos_lpib,
};
chip->get_position[0] = chip->get_position[1] = callbacks[fix];
/* combo mode uses LPIB only for playback */
if (fix == POS_FIX_COMBO)
chip->get_position[1] = NULL;
if (fix == POS_FIX_POSBUF &&
(chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) {
chip->get_delay[0] = chip->get_delay[1] =
azx_get_delay_from_lpib;
}
}
/* /*
* black-lists for probe_mask * black-lists for probe_mask
*/ */
...@@ -1209,7 +1392,8 @@ static void azx_check_snoop_available(struct azx *chip) ...@@ -1209,7 +1392,8 @@ static void azx_check_snoop_available(struct azx *chip)
static void azx_probe_work(struct work_struct *work) static void azx_probe_work(struct work_struct *work)
{ {
azx_probe_continue(container_of(work, struct azx, probe_work)); struct hda_intel *hda = container_of(work, struct hda_intel, probe_work);
azx_probe_continue(&hda->chip);
} }
/* /*
...@@ -1252,19 +1436,13 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, ...@@ -1252,19 +1436,13 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
check_msi(chip); check_msi(chip);
chip->dev_index = dev; chip->dev_index = dev;
chip->jackpoll_ms = jackpoll_ms; chip->jackpoll_ms = jackpoll_ms;
INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work);
INIT_LIST_HEAD(&chip->pcm_list); INIT_LIST_HEAD(&chip->pcm_list);
INIT_LIST_HEAD(&chip->list); INIT_WORK(&hda->irq_pending_work, azx_irq_pending_work);
INIT_LIST_HEAD(&hda->list);
init_vga_switcheroo(chip); init_vga_switcheroo(chip);
init_completion(&chip->probe_wait); init_completion(&hda->probe_wait);
chip->position_fix[0] = chip->position_fix[1] = assign_position_fix(chip, check_position_fix(chip, position_fix[dev]));
check_position_fix(chip, position_fix[dev]);
/* combo mode uses LPIB for playback */
if (chip->position_fix[0] == POS_FIX_COMBO) {
chip->position_fix[0] = POS_FIX_LPIB;
chip->position_fix[1] = POS_FIX_AUTO;
}
check_probe_mask(chip, dev); check_probe_mask(chip, dev);
...@@ -1293,7 +1471,7 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, ...@@ -1293,7 +1471,7 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
} }
/* continue probing in work context as may trigger request module */ /* continue probing in work context as may trigger request module */
INIT_WORK(&chip->probe_work, azx_probe_work); INIT_WORK(&hda->probe_work, azx_probe_work);
*rchip = chip; *rchip = chip;
...@@ -1351,7 +1529,7 @@ static int azx_first_init(struct azx *chip) ...@@ -1351,7 +1529,7 @@ static int azx_first_init(struct azx *chip)
NULL); NULL);
if (p_smbus) { if (p_smbus) {
if (p_smbus->revision < 0x30) if (p_smbus->revision < 0x30)
gcap &= ~ICH6_GCAP_64OK; gcap &= ~AZX_GCAP_64OK;
pci_dev_put(p_smbus); pci_dev_put(p_smbus);
} }
} }
...@@ -1359,7 +1537,7 @@ static int azx_first_init(struct azx *chip) ...@@ -1359,7 +1537,7 @@ static int azx_first_init(struct azx *chip)
/* disable 64bit DMA address on some devices */ /* disable 64bit DMA address on some devices */
if (chip->driver_caps & AZX_DCAPS_NO_64BIT) { if (chip->driver_caps & AZX_DCAPS_NO_64BIT) {
dev_dbg(card->dev, "Disabling 64bit DMA\n"); dev_dbg(card->dev, "Disabling 64bit DMA\n");
gcap &= ~ICH6_GCAP_64OK; gcap &= ~AZX_GCAP_64OK;
} }
/* disable buffer size rounding to 128-byte multiples if supported */ /* disable buffer size rounding to 128-byte multiples if supported */
...@@ -1375,7 +1553,7 @@ static int azx_first_init(struct azx *chip) ...@@ -1375,7 +1553,7 @@ static int azx_first_init(struct azx *chip)
} }
/* allow 64bit DMA address if supported by H/W */ /* allow 64bit DMA address if supported by H/W */
if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64))) if ((gcap & AZX_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64)); pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64));
else { else {
pci_set_dma_mask(pci, DMA_BIT_MASK(32)); pci_set_dma_mask(pci, DMA_BIT_MASK(32));
...@@ -1615,6 +1793,7 @@ static int azx_probe(struct pci_dev *pci, ...@@ -1615,6 +1793,7 @@ static int azx_probe(struct pci_dev *pci,
{ {
static int dev; static int dev;
struct snd_card *card; struct snd_card *card;
struct hda_intel *hda;
struct azx *chip; struct azx *chip;
bool schedule_probe; bool schedule_probe;
int err; int err;
...@@ -1638,6 +1817,7 @@ static int azx_probe(struct pci_dev *pci, ...@@ -1638,6 +1817,7 @@ static int azx_probe(struct pci_dev *pci,
if (err < 0) if (err < 0)
goto out_free; goto out_free;
card->private_data = chip; card->private_data = chip;
hda = container_of(chip, struct hda_intel, chip);
pci_set_drvdata(pci, card); pci_set_drvdata(pci, card);
...@@ -1674,11 +1854,11 @@ static int azx_probe(struct pci_dev *pci, ...@@ -1674,11 +1854,11 @@ static int azx_probe(struct pci_dev *pci,
#endif #endif
if (schedule_probe) if (schedule_probe)
schedule_work(&chip->probe_work); schedule_work(&hda->probe_work);
dev++; dev++;
if (chip->disabled) if (chip->disabled)
complete_all(&chip->probe_wait); complete_all(&hda->probe_wait);
return 0; return 0;
out_free: out_free:
...@@ -1694,6 +1874,7 @@ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = { ...@@ -1694,6 +1874,7 @@ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = {
static int azx_probe_continue(struct azx *chip) static int azx_probe_continue(struct azx *chip)
{ {
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
struct pci_dev *pci = chip->pci; struct pci_dev *pci = chip->pci;
int dev = chip->dev_index; int dev = chip->dev_index;
int err; int err;
...@@ -1767,13 +1948,13 @@ static int azx_probe_continue(struct azx *chip) ...@@ -1767,13 +1948,13 @@ static int azx_probe_continue(struct azx *chip)
power_down_all_codecs(chip); power_down_all_codecs(chip);
azx_notifier_register(chip); azx_notifier_register(chip);
azx_add_card_list(chip); azx_add_card_list(chip);
if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) || chip->use_vga_switcheroo) if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) || hda->use_vga_switcheroo)
pm_runtime_put_noidle(&pci->dev); pm_runtime_put_noidle(&pci->dev);
out_free: out_free:
if (err < 0) if (err < 0)
chip->init_failed = 1; hda->init_failed = 1;
complete_all(&chip->probe_wait); complete_all(&hda->probe_wait);
return err; return err;
} }
......
...@@ -22,107 +22,87 @@ ...@@ -22,107 +22,87 @@
/* /*
* registers * registers
*/ */
#define ICH6_REG_GCAP 0x00 #define AZX_REG_GCAP 0x00
#define ICH6_GCAP_64OK (1 << 0) /* 64bit address support */ #define AZX_GCAP_64OK (1 << 0) /* 64bit address support */
#define ICH6_GCAP_NSDO (3 << 1) /* # of serial data out signals */ #define AZX_GCAP_NSDO (3 << 1) /* # of serial data out signals */
#define ICH6_GCAP_BSS (31 << 3) /* # of bidirectional streams */ #define AZX_GCAP_BSS (31 << 3) /* # of bidirectional streams */
#define ICH6_GCAP_ISS (15 << 8) /* # of input streams */ #define AZX_GCAP_ISS (15 << 8) /* # of input streams */
#define ICH6_GCAP_OSS (15 << 12) /* # of output streams */ #define AZX_GCAP_OSS (15 << 12) /* # of output streams */
#define ICH6_REG_VMIN 0x02 #define AZX_REG_VMIN 0x02
#define ICH6_REG_VMAJ 0x03 #define AZX_REG_VMAJ 0x03
#define ICH6_REG_OUTPAY 0x04 #define AZX_REG_OUTPAY 0x04
#define ICH6_REG_INPAY 0x06 #define AZX_REG_INPAY 0x06
#define ICH6_REG_GCTL 0x08 #define AZX_REG_GCTL 0x08
#define ICH6_GCTL_RESET (1 << 0) /* controller reset */ #define AZX_GCTL_RESET (1 << 0) /* controller reset */
#define ICH6_GCTL_FCNTRL (1 << 1) /* flush control */ #define AZX_GCTL_FCNTRL (1 << 1) /* flush control */
#define ICH6_GCTL_UNSOL (1 << 8) /* accept unsol. response enable */ #define AZX_GCTL_UNSOL (1 << 8) /* accept unsol. response enable */
#define ICH6_REG_WAKEEN 0x0c #define AZX_REG_WAKEEN 0x0c
#define ICH6_REG_STATESTS 0x0e #define AZX_REG_STATESTS 0x0e
#define ICH6_REG_GSTS 0x10 #define AZX_REG_GSTS 0x10
#define ICH6_GSTS_FSTS (1 << 1) /* flush status */ #define AZX_GSTS_FSTS (1 << 1) /* flush status */
#define ICH6_REG_INTCTL 0x20 #define AZX_REG_INTCTL 0x20
#define ICH6_REG_INTSTS 0x24 #define AZX_REG_INTSTS 0x24
#define ICH6_REG_WALLCLK 0x30 /* 24Mhz source */ #define AZX_REG_WALLCLK 0x30 /* 24Mhz source */
#define ICH6_REG_OLD_SSYNC 0x34 /* SSYNC for old ICH */ #define AZX_REG_OLD_SSYNC 0x34 /* SSYNC for old ICH */
#define ICH6_REG_SSYNC 0x38 #define AZX_REG_SSYNC 0x38
#define ICH6_REG_CORBLBASE 0x40 #define AZX_REG_CORBLBASE 0x40
#define ICH6_REG_CORBUBASE 0x44 #define AZX_REG_CORBUBASE 0x44
#define ICH6_REG_CORBWP 0x48 #define AZX_REG_CORBWP 0x48
#define ICH6_REG_CORBRP 0x4a #define AZX_REG_CORBRP 0x4a
#define ICH6_CORBRP_RST (1 << 15) /* read pointer reset */ #define AZX_CORBRP_RST (1 << 15) /* read pointer reset */
#define ICH6_REG_CORBCTL 0x4c #define AZX_REG_CORBCTL 0x4c
#define ICH6_CORBCTL_RUN (1 << 1) /* enable DMA */ #define AZX_CORBCTL_RUN (1 << 1) /* enable DMA */
#define ICH6_CORBCTL_CMEIE (1 << 0) /* enable memory error irq */ #define AZX_CORBCTL_CMEIE (1 << 0) /* enable memory error irq */
#define ICH6_REG_CORBSTS 0x4d #define AZX_REG_CORBSTS 0x4d
#define ICH6_CORBSTS_CMEI (1 << 0) /* memory error indication */ #define AZX_CORBSTS_CMEI (1 << 0) /* memory error indication */
#define ICH6_REG_CORBSIZE 0x4e #define AZX_REG_CORBSIZE 0x4e
#define ICH6_REG_RIRBLBASE 0x50 #define AZX_REG_RIRBLBASE 0x50
#define ICH6_REG_RIRBUBASE 0x54 #define AZX_REG_RIRBUBASE 0x54
#define ICH6_REG_RIRBWP 0x58 #define AZX_REG_RIRBWP 0x58
#define ICH6_RIRBWP_RST (1 << 15) /* write pointer reset */ #define AZX_RIRBWP_RST (1 << 15) /* write pointer reset */
#define ICH6_REG_RINTCNT 0x5a #define AZX_REG_RINTCNT 0x5a
#define ICH6_REG_RIRBCTL 0x5c #define AZX_REG_RIRBCTL 0x5c
#define ICH6_RBCTL_IRQ_EN (1 << 0) /* enable IRQ */ #define AZX_RBCTL_IRQ_EN (1 << 0) /* enable IRQ */
#define ICH6_RBCTL_DMA_EN (1 << 1) /* enable DMA */ #define AZX_RBCTL_DMA_EN (1 << 1) /* enable DMA */
#define ICH6_RBCTL_OVERRUN_EN (1 << 2) /* enable overrun irq */ #define AZX_RBCTL_OVERRUN_EN (1 << 2) /* enable overrun irq */
#define ICH6_REG_RIRBSTS 0x5d #define AZX_REG_RIRBSTS 0x5d
#define ICH6_RBSTS_IRQ (1 << 0) /* response irq */ #define AZX_RBSTS_IRQ (1 << 0) /* response irq */
#define ICH6_RBSTS_OVERRUN (1 << 2) /* overrun irq */ #define AZX_RBSTS_OVERRUN (1 << 2) /* overrun irq */
#define ICH6_REG_RIRBSIZE 0x5e #define AZX_REG_RIRBSIZE 0x5e
#define ICH6_REG_IC 0x60 #define AZX_REG_IC 0x60
#define ICH6_REG_IR 0x64 #define AZX_REG_IR 0x64
#define ICH6_REG_IRS 0x68 #define AZX_REG_IRS 0x68
#define ICH6_IRS_VALID (1<<1) #define AZX_IRS_VALID (1<<1)
#define ICH6_IRS_BUSY (1<<0) #define AZX_IRS_BUSY (1<<0)
#define ICH6_REG_DPLBASE 0x70 #define AZX_REG_DPLBASE 0x70
#define ICH6_REG_DPUBASE 0x74 #define AZX_REG_DPUBASE 0x74
#define ICH6_DPLBASE_ENABLE 0x1 /* Enable position buffer */ #define AZX_DPLBASE_ENABLE 0x1 /* Enable position buffer */
/* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ /* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
/* stream register offsets from stream base */ /* stream register offsets from stream base */
#define ICH6_REG_SD_CTL 0x00 #define AZX_REG_SD_CTL 0x00
#define ICH6_REG_SD_STS 0x03 #define AZX_REG_SD_STS 0x03
#define ICH6_REG_SD_LPIB 0x04 #define AZX_REG_SD_LPIB 0x04
#define ICH6_REG_SD_CBL 0x08 #define AZX_REG_SD_CBL 0x08
#define ICH6_REG_SD_LVI 0x0c #define AZX_REG_SD_LVI 0x0c
#define ICH6_REG_SD_FIFOW 0x0e #define AZX_REG_SD_FIFOW 0x0e
#define ICH6_REG_SD_FIFOSIZE 0x10 #define AZX_REG_SD_FIFOSIZE 0x10
#define ICH6_REG_SD_FORMAT 0x12 #define AZX_REG_SD_FORMAT 0x12
#define ICH6_REG_SD_BDLPL 0x18 #define AZX_REG_SD_BDLPL 0x18
#define ICH6_REG_SD_BDLPU 0x1c #define AZX_REG_SD_BDLPU 0x1c
/* PCI space */ /* PCI space */
#define ICH6_PCIREG_TCSEL 0x44 #define AZX_PCIREG_TCSEL 0x44
/* /*
* other constants * 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 */ /* max number of fragments - we may use more if allocating more pages for BDL */
#define BDL_SIZE 4096 #define BDL_SIZE 4096
#define AZX_MAX_BDL_ENTRIES (BDL_SIZE / 16) #define AZX_MAX_BDL_ENTRIES (BDL_SIZE / 16)
...@@ -160,13 +140,13 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; ...@@ -160,13 +140,13 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define SD_STS_FIFO_READY 0x20 /* FIFO ready */ #define SD_STS_FIFO_READY 0x20 /* FIFO ready */
/* INTCTL and INTSTS */ /* INTCTL and INTSTS */
#define ICH6_INT_ALL_STREAM 0xff /* all stream interrupts */ #define AZX_INT_ALL_STREAM 0xff /* all stream interrupts */
#define ICH6_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ #define AZX_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */
#define ICH6_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ #define AZX_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */
/* below are so far hardcoded - should read registers in future */ /* below are so far hardcoded - should read registers in future */
#define ICH6_MAX_CORB_ENTRIES 256 #define AZX_MAX_CORB_ENTRIES 256
#define ICH6_MAX_RIRB_ENTRIES 256 #define AZX_MAX_RIRB_ENTRIES 256
/* driver quirks (capabilities) */ /* driver quirks (capabilities) */
/* bits 0-7 are used for indicating driver type */ /* bits 0-7 are used for indicating driver type */
...@@ -191,35 +171,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; ...@@ -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_I915_POWERWELL (1 << 27) /* HSW i915 powerwell support */
#define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28) /* CORBRP clears itself after reset */ #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 */ /* HD Audio class code */
#define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403 #define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403
...@@ -324,6 +275,9 @@ struct azx_pcm { ...@@ -324,6 +275,9 @@ struct azx_pcm {
struct list_head list; 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 azx {
struct snd_card *card; struct snd_card *card;
struct pci_dev *pci; struct pci_dev *pci;
...@@ -342,6 +296,10 @@ struct azx { ...@@ -342,6 +296,10 @@ struct azx {
/* Register interaction. */ /* Register interaction. */
const struct hda_controller_ops *ops; 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 */ /* pci resources */
unsigned long addr; unsigned long addr;
void __iomem *remap_addr; void __iomem *remap_addr;
...@@ -350,7 +308,6 @@ struct azx { ...@@ -350,7 +308,6 @@ struct azx {
/* locks */ /* locks */
spinlock_t reg_lock; spinlock_t reg_lock;
struct mutex open_mutex; /* Prevents concurrent open/close operations */ struct mutex open_mutex; /* Prevents concurrent open/close operations */
struct completion probe_wait;
/* streams (x num_streams) */ /* streams (x num_streams) */
struct azx_dev *azx_dev; struct azx_dev *azx_dev;
...@@ -377,7 +334,6 @@ struct azx { ...@@ -377,7 +334,6 @@ struct azx {
#endif #endif
/* flags */ /* flags */
int position_fix[2]; /* for both playback/capture streams */
const int *bdl_pos_adj; const int *bdl_pos_adj;
int poll_count; int poll_count;
unsigned int running:1; unsigned int running:1;
...@@ -385,46 +341,23 @@ struct azx { ...@@ -385,46 +341,23 @@ struct azx {
unsigned int single_cmd:1; unsigned int single_cmd:1;
unsigned int polling_mode:1; unsigned int polling_mode:1;
unsigned int msi:1; unsigned int msi:1;
unsigned int irq_pending_warned:1;
unsigned int probing:1; /* codec probing phase */ unsigned int probing:1; /* codec probing phase */
unsigned int snoop:1; unsigned int snoop:1;
unsigned int align_buffer_size:1; unsigned int align_buffer_size:1;
unsigned int region_requested: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 */ unsigned int disabled:1; /* disabled by VGA-switcher */
/* for debugging */ /* for debugging */
unsigned int last_cmd[AZX_MAX_CODECS]; 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) */ /* reboot notifier (for mysterious hangup problem at power-down) */
struct notifier_block reboot_notifier; struct notifier_block reboot_notifier;
/* card list (for power_save trigger) */
struct list_head list;
#ifdef CONFIG_SND_HDA_DSP_LOADER #ifdef CONFIG_SND_HDA_DSP_LOADER
struct azx_dev saved_azx_dev; struct azx_dev saved_azx_dev;
#endif #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 #ifdef CONFIG_X86
#define azx_snoop(chip) ((chip)->snoop) #define azx_snoop(chip) ((chip)->snoop)
#else #else
...@@ -436,29 +369,29 @@ struct azx { ...@@ -436,29 +369,29 @@ struct azx {
*/ */
#define azx_writel(chip, reg, value) \ #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) \ #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) \ #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) \ #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) \ #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) \ #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) \ #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) \ #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) \ #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) \ #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) \ #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) \ #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 */ #endif /* __SOUND_HDA_PRIV_H */
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/reboot.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/time.h> #include <linux/time.h>
...@@ -294,30 +293,6 @@ static const struct dev_pm_ops hda_tegra_pm = { ...@@ -294,30 +293,6 @@ static const struct dev_pm_ops hda_tegra_pm = {
SET_SYSTEM_SLEEP_PM_OPS(hda_tegra_suspend, hda_tegra_resume) SET_SYSTEM_SLEEP_PM_OPS(hda_tegra_suspend, hda_tegra_resume)
}; };
/*
* reboot notifier for hang-up problem at power-down
*/
static int hda_tegra_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;
}
static void hda_tegra_notifier_register(struct azx *chip)
{
chip->reboot_notifier.notifier_call = hda_tegra_halt;
register_reboot_notifier(&chip->reboot_notifier);
}
static void hda_tegra_notifier_unregister(struct azx *chip)
{
if (chip->reboot_notifier.notifier_call)
unregister_reboot_notifier(&chip->reboot_notifier);
}
/* /*
* destructor * destructor
*/ */
...@@ -326,7 +301,7 @@ static int hda_tegra_dev_free(struct snd_device *device) ...@@ -326,7 +301,7 @@ static int hda_tegra_dev_free(struct snd_device *device)
int i; int i;
struct azx *chip = device->device_data; struct azx *chip = device->device_data;
hda_tegra_notifier_unregister(chip); azx_notifier_unregister(chip);
if (chip->initialized) { if (chip->initialized) {
for (i = 0; i < chip->num_streams; i++) for (i = 0; i < chip->num_streams; i++)
...@@ -480,8 +455,6 @@ static int hda_tegra_create(struct snd_card *card, ...@@ -480,8 +455,6 @@ static int hda_tegra_create(struct snd_card *card,
INIT_LIST_HEAD(&chip->pcm_list); INIT_LIST_HEAD(&chip->pcm_list);
INIT_LIST_HEAD(&chip->list); INIT_LIST_HEAD(&chip->list);
chip->position_fix[0] = POS_FIX_AUTO;
chip->position_fix[1] = POS_FIX_AUTO;
chip->codec_probe_mask = -1; chip->codec_probe_mask = -1;
chip->single_cmd = false; chip->single_cmd = false;
...@@ -559,7 +532,7 @@ static int hda_tegra_probe(struct platform_device *pdev) ...@@ -559,7 +532,7 @@ static int hda_tegra_probe(struct platform_device *pdev)
chip->running = 1; chip->running = 1;
power_down_all_codecs(chip); power_down_all_codecs(chip);
hda_tegra_notifier_register(chip); azx_notifier_register(chip);
return 0; return 0;
......
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