X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Fpci%2Fhda%2Fhda_intel.c;h=0ff38cbe7471276eef0a41e07fc95eb4746b0955;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=9dd541df60d2ad15de39a605a4869356ccae5974;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 9dd541df6..0ff38cbe7 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include "hda_codec.h" @@ -54,7 +53,6 @@ static char *id = SNDRV_DEFAULT_STR1; 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."); @@ -66,8 +64,6 @@ module_param(position_fix, int, 0444); 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 */ @@ -81,7 +77,6 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," "{Intel, ESB2}," "{Intel, ICH8}," "{ATI, SB450}," - "{ATI, SB600}," "{VIA, VT8251}," "{VIA, VT8237A}," "{SiS, SIS966}," @@ -239,6 +234,12 @@ enum { #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 + /* */ @@ -251,6 +252,7 @@ struct azx_dev { unsigned int fragsize; /* size of each period in bytes */ unsigned int frags; /* number for period in the play buffer */ unsigned int fifo_size; /* FIFO size */ + unsigned int last_pos; /* last updated period position */ void __iomem *sd_addr; /* stream descriptor pointer */ @@ -261,11 +263,10 @@ struct azx_dev { unsigned int format_val; /* format value to be set in the controller and the codec */ unsigned char stream_tag; /* assigned stream */ unsigned char index; /* stream index */ - /* for sanity check of position buffer */ - unsigned int period_intr; unsigned int opened: 1; unsigned int running: 1; + unsigned int period_updating: 1; }; /* CORB/RIRB */ @@ -299,7 +300,7 @@ struct azx { /* locks */ spinlock_t reg_lock; - struct mutex open_mutex; + struct semaphore open_mutex; /* streams (x num_streams) */ struct azx_dev *azx_dev; @@ -324,7 +325,6 @@ struct azx { /* flags */ int position_fix; unsigned int initialized: 1; - unsigned int single_cmd: 1; }; /* driver types */ @@ -388,6 +388,7 @@ static char *driver_short_names[] __devinitdata = { * Interface for HD codec */ +#ifdef USE_CORB_RIRB /* * CORB / RIRB interface */ @@ -435,7 +436,11 @@ static void azx_init_cmd_io(struct azx *chip) /* 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; } @@ -447,8 +452,8 @@ static void azx_free_cmd_io(struct azx *chip) } /* send a command */ -static int azx_corb_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, - unsigned int verb, unsigned int para) +static int azx_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; unsigned int wp; @@ -504,21 +509,18 @@ static void azx_update_rirb(struct azx *chip) } /* receive a response */ -static unsigned int azx_rirb_get_response(struct hda_codec *codec) +static unsigned int azx_get_response(struct hda_codec *codec) { struct azx *chip = codec->bus->private_data; int timeout = 50; while (chip->rirb.cmds) { if (! --timeout) { - snd_printk(KERN_ERR - "hda_intel: azx_get_response timeout, " - "switching to single_cmd mode...\n"); + if (printk_ratelimit()) + snd_printk(KERN_ERR + "azx_get_response timeout\n"); chip->rirb.rp = azx_readb(chip, RIRBWP); chip->rirb.cmds = 0; - /* switch to single_cmd mode */ - chip->single_cmd = 1; - azx_free_cmd_io(chip); return -1; } msleep(1); @@ -526,6 +528,7 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec) return chip->rirb.res; /* the last value */ } +#else /* * Use the single immediate command instead of CORB/RIRB for simplicity * @@ -536,10 +539,13 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec) * 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_single_send_cmd(struct hda_codec *codec, hda_nid_t nid, - int direct, unsigned int verb, - unsigned int para) +static int azx_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; @@ -567,7 +573,7 @@ static int azx_single_send_cmd(struct hda_codec *codec, hda_nid_t nid, } /* receive a response */ -static unsigned int azx_single_get_response(struct hda_codec *codec) +static unsigned int azx_get_response(struct hda_codec *codec) { struct azx *chip = codec->bus->private_data; int timeout = 50; @@ -582,35 +588,9 @@ static unsigned int azx_single_get_response(struct hda_codec *codec) return (unsigned int)-1; } -/* - * The below are the main callbacks from hda_codec. - * - * They are just the skeleton to call sub-callbacks according to the - * current setting of chip->single_cmd. - */ - -/* send a command */ -static int azx_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; - if (chip->single_cmd) - return azx_single_send_cmd(codec, nid, direct, verb, para); - else - return azx_corb_send_cmd(codec, nid, direct, verb, para); -} - -/* get a response */ -static unsigned int azx_get_response(struct hda_codec *codec) -{ - struct azx *chip = codec->bus->private_data; - if (chip->single_cmd) - return azx_single_get_response(codec); - else - return azx_rirb_get_response(codec); -} +#define azx_update_rirb(chip) +#endif /* USE_CORB_RIRB */ /* reset codec link */ static int azx_reset(struct azx *chip) @@ -757,8 +737,7 @@ static void azx_init_chip(struct azx *chip) azx_int_enable(chip); /* initialize the codec command I/O */ - if (! chip->single_cmd) - azx_init_cmd_io(chip); + azx_init_cmd_io(chip); /* program the position buffer */ azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); @@ -805,10 +784,11 @@ static irqreturn_t azx_interrupt(int irq, void* dev_id, struct pt_regs *regs) if (status & azx_dev->sd_int_sta_mask) { azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); if (azx_dev->substream && azx_dev->running) { - azx_dev->period_intr++; + azx_dev->period_updating = 1; spin_unlock(&chip->reg_lock); snd_pcm_period_elapsed(azx_dev->substream); spin_lock(&chip->reg_lock); + azx_dev->period_updating = 0; } } } @@ -816,7 +796,7 @@ static irqreturn_t azx_interrupt(int irq, void* dev_id, struct pt_regs *regs) /* clear rirb int */ status = azx_readb(chip, RIRBSTS); if (status & RIRB_INT_MASK) { - if (! chip->single_cmd && (status & RIRB_INT_RESPONSE)) + if (status & RIRB_INT_RESPONSE) azx_update_rirb(chip); azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); } @@ -1022,10 +1002,10 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) unsigned long flags; int err; - mutex_lock(&chip->open_mutex); + down(&chip->open_mutex); azx_dev = azx_assign_device(chip, substream->stream); if (azx_dev == NULL) { - mutex_unlock(&chip->open_mutex); + up(&chip->open_mutex); return -EBUSY; } runtime->hw = azx_pcm_hw; @@ -1037,7 +1017,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); if ((err = hinfo->ops.open(hinfo, apcm->codec, substream)) < 0) { azx_release_device(azx_dev); - mutex_unlock(&chip->open_mutex); + up(&chip->open_mutex); return err; } spin_lock_irqsave(&chip->reg_lock, flags); @@ -1046,7 +1026,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) spin_unlock_irqrestore(&chip->reg_lock, flags); runtime->private_data = azx_dev; - mutex_unlock(&chip->open_mutex); + up(&chip->open_mutex); return 0; } @@ -1058,14 +1038,14 @@ static int azx_pcm_close(struct snd_pcm_substream *substream) struct azx_dev *azx_dev = get_azx_dev(substream); unsigned long flags; - mutex_lock(&chip->open_mutex); + down(&chip->open_mutex); spin_lock_irqsave(&chip->reg_lock, flags); azx_dev->substream = NULL; azx_dev->running = 0; spin_unlock_irqrestore(&chip->reg_lock, flags); azx_release_device(azx_dev); hinfo->ops.close(hinfo, apcm->codec, substream); - mutex_unlock(&chip->open_mutex); + up(&chip->open_mutex); return 0; } @@ -1119,6 +1099,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; else azx_dev->fifo_size = 0; + azx_dev->last_pos = 0; return hinfo->ops.prepare(hinfo, apcm->codec, azx_dev->stream_tag, azx_dev->format_val, substream); @@ -1166,20 +1147,10 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) struct azx_dev *azx_dev = get_azx_dev(substream); unsigned int pos; - if (chip->position_fix == POS_FIX_POSBUF || - chip->position_fix == POS_FIX_AUTO) { + if (chip->position_fix == POS_FIX_POSBUF) { /* use the position buffer */ pos = *azx_dev->posbuf; - if (chip->position_fix == POS_FIX_AUTO && - azx_dev->period_intr == 1 && ! pos) { - printk(KERN_WARNING - "hda-intel: Invalid position buffer, " - "using LPIB read method instead.\n"); - chip->position_fix = POS_FIX_NONE; - goto read_lpib; - } } else { - read_lpib: /* read LPIB */ pos = azx_sd_readl(azx_dev, SD_LPIB); if (chip->position_fix == POS_FIX_FIFO) @@ -1444,14 +1415,13 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, } spin_lock_init(&chip->reg_lock); - mutex_init(&chip->open_mutex); + init_MUTEX(&chip->open_mutex); chip->card = card; chip->pci = pci; chip->irq = -1; chip->driver_type = driver_type; - chip->position_fix = position_fix; - chip->single_cmd = single_cmd; + chip->position_fix = position_fix ? position_fix : POS_FIX_POSBUF; #if BITS_PER_LONG != 64 /* Fix up base address on ULI M5461 */ @@ -1522,9 +1492,8 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, goto errout; } /* allocate CORB/RIRB */ - if (! chip->single_cmd) - if ((err = azx_alloc_cmd_io(chip)) < 0) - goto errout; + if ((err = azx_alloc_cmd_io(chip)) < 0) + goto errout; /* initialize streams */ azx_init_stream(chip); @@ -1614,13 +1583,12 @@ static void __devexit azx_remove(struct pci_dev *pci) } /* PCI IDs */ -static struct pci_device_id azx_ids[] __devinitdata = { +static struct pci_device_id azx_ids[] = { { 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH6 */ { 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH7 */ { 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ESB2 */ { 0x8086, 0x284b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH8 */ { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */ - { 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */ { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */ { 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */ { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */