model - force the model name
position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)
+ single_cmd - Use single immediate commands to communicate with
+ codecs (for debugging only)
This module supports one card and autoprobe.
(Usually SD_LPLIB register is more accurate than the
position buffer.)
+ NB: If you get many "azx_get_response timeout" messages at
+ loading, it's likely a problem of interrupts (e.g. ACPI irq
+ routing). Try to boot with options like "pci=noacpi". Also, you
+ can try "single_cmd=1" module option. This will switch the
+ communication method between HDA controller and codecs to the
+ single immediate commands instead of CORB/RIRB. Basically, the
+ single command mode is provided only for BIOS, and you won't get
+ unsolicited events, too. But, at least, this works independently
+ from the irq. Remember this is a last resort, and should be
+ avoided as much as possible...
+
The power-management is supported.
Module snd-hdsp
static char *model;
static int position_fix;
static int probe_mask = -1;
+static int single_cmd;
module_param(index, int, 0444);
MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size).");
module_param(probe_mask, int, 0444);
MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1).");
+module_param(single_cmd, bool, 0444);
+MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs (for debugging only).");
/* just for backward compatibility */
#define NVIDIA_HDA_TRANSREG_ADDR 0x4e
#define NVIDIA_HDA_ENABLE_COHBITS 0x0f
-/*
- * Use CORB/RIRB for communication from/to codecs.
- * This is the way recommended by Intel (see below).
- */
-#define USE_CORB_RIRB
-
/*
*/
/* flags */
int position_fix;
unsigned int initialized: 1;
+ unsigned int single_cmd: 1;
};
/* driver types */
* Interface for HD codec
*/
-#ifdef USE_CORB_RIRB
/*
* CORB / RIRB interface
*/
/* set N=1, get RIRB response interrupt for new entry */
azx_writew(chip, RINTCNT, 1);
/* enable rirb dma and response irq */
-#ifdef USE_CORB_RIRB
azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN);
-#else
- azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN);
-#endif
chip->rirb.rp = chip->rirb.cmds = 0;
}
return chip->rirb.res; /* the last value */
}
-#else
/*
* Use the single immediate command instead of CORB/RIRB for simplicity
*
* I left the codes, however, for debugging/testing purposes.
*/
-#define azx_alloc_cmd_io(chip) 0
-#define azx_init_cmd_io(chip)
-#define azx_free_cmd_io(chip)
-
/* send a command */
-static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
- unsigned int verb, unsigned int para)
+static int azx_single_send_cmd(struct hda_codec *codec, hda_nid_t nid,
+ int direct, unsigned int verb,
+ unsigned int para)
{
struct azx *chip = codec->bus->private_data;
u32 val;
}
/* receive a response */
-static unsigned int azx_get_response(struct hda_codec *codec)
+static unsigned int azx_single_get_response(struct hda_codec *codec)
{
struct azx *chip = codec->bus->private_data;
int timeout = 50;
return (unsigned int)-1;
}
-#define azx_update_rirb(chip)
-
-#endif /* USE_CORB_RIRB */
-
/* reset codec link */
static int azx_reset(struct azx *chip)
{
azx_int_enable(chip);
/* initialize the codec command I/O */
- azx_init_cmd_io(chip);
+ if (! chip->single_cmd)
+ azx_init_cmd_io(chip);
/* program the position buffer */
azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
/* clear rirb int */
status = azx_readb(chip, RIRBSTS);
if (status & RIRB_INT_MASK) {
- if (status & RIRB_INT_RESPONSE)
+ if (! chip->single_cmd && (status & RIRB_INT_RESPONSE))
azx_update_rirb(chip);
azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
}
bus_temp.private_data = chip;
bus_temp.modelname = model;
bus_temp.pci = chip->pci;
- bus_temp.ops.command = azx_send_cmd;
- bus_temp.ops.get_response = azx_get_response;
+ if (chip->single_cmd) {
+ bus_temp.ops.command = azx_single_send_cmd;
+ bus_temp.ops.get_response = azx_single_get_response;
+ } else {
+ bus_temp.ops.command = azx_send_cmd;
+ bus_temp.ops.get_response = azx_get_response;
+ }
if ((err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus)) < 0)
return err;
for (i = 0; i < chip->pcm_devs; i++)
snd_pcm_suspend_all(chip->pcm[i]);
snd_hda_suspend(chip->bus, state);
- azx_free_cmd_io(chip);
+ if (! chip->single_cmd)
+ azx_free_cmd_io(chip);
pci_disable_device(pci);
pci_save_state(pci);
return 0;
azx_int_clear(chip);
/* disable CORB/RIRB */
- azx_free_cmd_io(chip);
+ if (! chip->single_cmd)
+ azx_free_cmd_io(chip);
/* disable position buffer */
azx_writel(chip, DPLBASE, 0);
chip->driver_type = driver_type;
chip->position_fix = position_fix ? position_fix : POS_FIX_POSBUF;
+ chip->single_cmd = single_cmd;
#if BITS_PER_LONG != 64
/* Fix up base address on ULI M5461 */
goto errout;
}
/* allocate CORB/RIRB */
- if ((err = azx_alloc_cmd_io(chip)) < 0)
- goto errout;
+ if (! chip->single_cmd)
+ if ((err = azx_alloc_cmd_io(chip)) < 0)
+ goto errout;
/* initialize streams */
azx_init_stream(chip);