Loading Documentation/sound/alsa/HD-Audio.txt +3 −1 Original line number Original line Diff line number Diff line Loading @@ -204,7 +204,6 @@ generic parser regardless of the codec. Usually the codec-specific parser is much better than the generic parser (as now). Thus this parser is much better than the generic parser (as now). Thus this option is more about the debugging purpose. option is more about the debugging purpose. Speaker and Headphone Output Speaker and Headphone Output ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ One of the most frequent (and obvious) bugs with HD-audio is the One of the most frequent (and obvious) bugs with HD-audio is the Loading Loading @@ -600,6 +599,9 @@ probing, the proc file is available, so you can get the raw codec information before modified by the driver. Of course, the driver information before modified by the driver. Of course, the driver isn't usable with `probe_only=1`. But you can continue the isn't usable with `probe_only=1`. But you can continue the configuration via hwdep sysfs file if hda-reconfig option is enabled. configuration via hwdep sysfs file if hda-reconfig option is enabled. Using `probe_only` mask 2 skips the reset of HDA codecs (use `probe_only=3` as module option). The hwdep interface can be used to determine the BIOS codec initialization. hda-verb hda-verb Loading sound/pci/hda/Kconfig +1 −0 Original line number Original line Diff line number Diff line Loading @@ -145,6 +145,7 @@ config SND_HDA_CODEC_NVHDMI config SND_HDA_CODEC_INTELHDMI config SND_HDA_CODEC_INTELHDMI bool "Build INTEL HDMI HD-audio codec support" bool "Build INTEL HDMI HD-audio codec support" select SND_DYNAMIC_MINORS default y default y help help Say Y here to include INTEL HDMI HD-audio codec support in Say Y here to include INTEL HDMI HD-audio codec support in Loading sound/pci/hda/hda_codec.c +63 −13 Original line number Original line Diff line number Diff line Loading @@ -1209,8 +1209,7 @@ static void free_hda_cache(struct hda_cache_rec *cache) } } /* query the hash. allocate an entry if not found. */ /* query the hash. allocate an entry if not found. */ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, static struct hda_cache_head *get_hash(struct hda_cache_rec *cache, u32 key) u32 key) { { u16 idx = key % (u16)ARRAY_SIZE(cache->hash); u16 idx = key % (u16)ARRAY_SIZE(cache->hash); u16 cur = cache->hash[idx]; u16 cur = cache->hash[idx]; Loading @@ -1222,7 +1221,16 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, return info; return info; cur = info->next; cur = info->next; } } return NULL; } /* query the hash. allocate an entry if not found. */ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, u32 key) { struct hda_cache_head *info = get_hash(cache, key); if (!info) { u16 idx, cur; /* add a new hash entry */ /* add a new hash entry */ info = snd_array_new(&cache->buf); info = snd_array_new(&cache->buf); if (!info) if (!info) Loading @@ -1230,9 +1238,10 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, cur = snd_array_index(&cache->buf, info); cur = snd_array_index(&cache->buf, info); info->key = key; info->key = key; info->val = 0; info->val = 0; idx = key % (u16)ARRAY_SIZE(cache->hash); info->next = cache->hash[idx]; info->next = cache->hash[idx]; cache->hash[idx] = cur; cache->hash[idx] = cur; } return info; return info; } } Loading Loading @@ -1461,6 +1470,8 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx)); info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx)); if (!info) if (!info) return 0; return 0; if (snd_BUG_ON(mask & ~0xff)) mask &= 0xff; val &= mask; val &= mask; val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask; val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask; if (info->vol[ch] == val) if (info->vol[ch] == val) Loading @@ -1486,6 +1497,9 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, int direction, int idx, int mask, int val) int direction, int idx, int mask, int val) { { int ch, ret = 0; int ch, ret = 0; if (snd_BUG_ON(mask & ~0xff)) mask &= 0xff; for (ch = 0; ch < 2; ch++) for (ch = 0; ch < 2; ch++) ret |= snd_hda_codec_amp_update(codec, nid, ch, direction, ret |= snd_hda_codec_amp_update(codec, nid, ch, direction, idx, mask, val); idx, mask, val); Loading Loading @@ -2716,6 +2730,41 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, } } EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache); EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache); /** * snd_hda_codec_update_cache - check cache and write the cmd only when needed * @codec: the HDA codec * @nid: NID to send the command * @direct: direct flag * @verb: the verb to send * @parm: the parameter for the verb * * This function works like snd_hda_codec_write_cache(), but it doesn't send * command if the parameter is already identical with the cached value. * If not, it sends the command and refreshes the cache. * * Returns 0 if successful, or a negative error code. */ int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid, int direct, unsigned int verb, unsigned int parm) { struct hda_cache_head *c; u32 key; /* parm may contain the verb stuff for get/set amp */ verb = verb | (parm >> 8); parm &= 0xff; key = build_cmd_cache_key(nid, verb); mutex_lock(&codec->bus->cmd_mutex); c = get_hash(&codec->cmd_cache, key); if (c && c->val == parm) { mutex_unlock(&codec->bus->cmd_mutex); return 0; } mutex_unlock(&codec->bus->cmd_mutex); return snd_hda_codec_write_cache(codec, nid, direct, verb, parm); } EXPORT_SYMBOL_HDA(snd_hda_codec_update_cache); /** /** * snd_hda_codec_resume_cache - Resume the all commands from the cache * snd_hda_codec_resume_cache - Resume the all commands from the cache * @codec: HD-audio codec * @codec: HD-audio codec Loading Loading @@ -4218,7 +4267,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, break; break; case AC_JACK_MIC_IN: { case AC_JACK_MIC_IN: { int preferred, alt; int preferred, alt; if (loc == AC_JACK_LOC_FRONT) { if (loc == AC_JACK_LOC_FRONT || (loc & 0x30) == AC_JACK_LOC_INTERNAL) { preferred = AUTO_PIN_FRONT_MIC; preferred = AUTO_PIN_FRONT_MIC; alt = AUTO_PIN_MIC; alt = AUTO_PIN_MIC; } else { } else { Loading sound/pci/hda/hda_codec.h +3 −0 Original line number Original line Diff line number Diff line Loading @@ -885,9 +885,12 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, int direct, unsigned int verb, unsigned int parm); int direct, unsigned int verb, unsigned int parm); void snd_hda_sequence_write_cache(struct hda_codec *codec, void snd_hda_sequence_write_cache(struct hda_codec *codec, const struct hda_verb *seq); const struct hda_verb *seq); int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid, int direct, unsigned int verb, unsigned int parm); void snd_hda_codec_resume_cache(struct hda_codec *codec); void snd_hda_codec_resume_cache(struct hda_codec *codec); #else #else #define snd_hda_codec_write_cache snd_hda_codec_write #define snd_hda_codec_write_cache snd_hda_codec_write #define snd_hda_codec_update_cache snd_hda_codec_write #define snd_hda_sequence_write_cache snd_hda_sequence_write #define snd_hda_sequence_write_cache snd_hda_sequence_write #endif #endif Loading sound/pci/hda/hda_intel.c +63 −46 Original line number Original line Diff line number Diff line Loading @@ -84,7 +84,7 @@ module_param_array(bdl_pos_adj, int, NULL, 0644); MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); module_param_array(probe_mask, int, NULL, 0444); module_param_array(probe_mask, int, NULL, 0444); MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); module_param_array(probe_only, bool, NULL, 0444); module_param_array(probe_only, int, NULL, 0444); MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization."); MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization."); module_param(single_cmd, bool, 0444); module_param(single_cmd, bool, 0444); MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs " MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs " Loading Loading @@ -174,7 +174,7 @@ MODULE_DESCRIPTION("Intel HDA driver"); #define ICH6_GSTS_FSTS (1 << 1) /* flush status */ #define ICH6_GSTS_FSTS (1 << 1) /* flush status */ #define ICH6_REG_INTCTL 0x20 #define ICH6_REG_INTCTL 0x20 #define ICH6_REG_INTSTS 0x24 #define ICH6_REG_INTSTS 0x24 #define ICH6_REG_WALCLK 0x30 #define ICH6_REG_WALLCLK 0x30 /* 24Mhz source */ #define ICH6_REG_SYNC 0x34 #define ICH6_REG_SYNC 0x34 #define ICH6_REG_CORBLBASE 0x40 #define ICH6_REG_CORBLBASE 0x40 #define ICH6_REG_CORBUBASE 0x44 #define ICH6_REG_CORBUBASE 0x44 Loading Loading @@ -340,8 +340,8 @@ struct azx_dev { unsigned int period_bytes; /* size of the period in bytes */ unsigned int period_bytes; /* size of the period in bytes */ unsigned int frags; /* number for period in the play buffer */ unsigned int frags; /* number for period in the play buffer */ unsigned int fifo_size; /* FIFO size */ unsigned int fifo_size; /* FIFO size */ unsigned long start_jiffies; /* start + minimum jiffies */ unsigned long start_wallclk; /* start + minimum wallclk */ unsigned long min_jiffies; /* minimum jiffies before position is valid */ unsigned long period_wallclk; /* wallclk for period */ void __iomem *sd_addr; /* stream descriptor pointer */ void __iomem *sd_addr; /* stream descriptor pointer */ Loading @@ -361,7 +361,6 @@ struct azx_dev { unsigned int opened :1; unsigned int opened :1; unsigned int running :1; unsigned int running :1; unsigned int irq_pending :1; unsigned int irq_pending :1; unsigned int start_flag: 1; /* stream full start flag */ /* /* * For VIA: * For VIA: * A flag to ensure DMA position is 0 * A flag to ensure DMA position is 0 Loading Loading @@ -425,7 +424,7 @@ struct azx { struct snd_dma_buffer posbuf; struct snd_dma_buffer posbuf; /* flags */ /* flags */ int position_fix; int position_fix[2]; /* for both playback/capture streams */ int poll_count; int poll_count; unsigned int running :1; unsigned int running :1; unsigned int initialized :1; unsigned int initialized :1; Loading Loading @@ -858,10 +857,13 @@ static void azx_power_notify(struct hda_bus *bus); #endif #endif /* reset codec link */ /* reset codec link */ static int azx_reset(struct azx *chip) static int azx_reset(struct azx *chip, int full_reset) { { int count; int count; if (!full_reset) goto __skip; /* clear STATESTS */ /* clear STATESTS */ azx_writeb(chip, STATESTS, STATESTS_INT_MASK); azx_writeb(chip, STATESTS, STATESTS_INT_MASK); Loading @@ -887,6 +889,7 @@ static int azx_reset(struct azx *chip) /* Brent Chartrand said to wait >= 540us for codecs to initialize */ /* Brent Chartrand said to wait >= 540us for codecs to initialize */ msleep(1); msleep(1); __skip: /* check to see if controller is ready */ /* check to see if controller is ready */ if (!azx_readb(chip, GCTL)) { if (!azx_readb(chip, GCTL)) { snd_printd(SFX "azx_reset: controller not ready!\n"); snd_printd(SFX "azx_reset: controller not ready!\n"); Loading Loading @@ -998,13 +1001,13 @@ static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev) /* /* * reset and start the controller registers * reset and start the controller registers */ */ static void azx_init_chip(struct azx *chip) static void azx_init_chip(struct azx *chip, int full_reset) { { if (chip->initialized) if (chip->initialized) return; return; /* reset controller */ /* reset controller */ azx_reset(chip); azx_reset(chip, full_reset); /* initialize interrupts */ /* initialize interrupts */ azx_int_clear(chip); azx_int_clear(chip); Loading Loading @@ -1302,8 +1305,10 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr)); azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr)); /* enable the position buffer */ /* enable the position buffer */ if (chip->position_fix == POS_FIX_POSBUF || if (chip->position_fix[0] == POS_FIX_POSBUF || chip->position_fix == POS_FIX_AUTO || chip->position_fix[0] == POS_FIX_AUTO || chip->position_fix[1] == POS_FIX_POSBUF || chip->position_fix[1] == POS_FIX_AUTO || chip->via_dmapos_patch) { chip->via_dmapos_patch) { if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) azx_writel(chip, DPLBASE, azx_writel(chip, DPLBASE, Loading Loading @@ -1348,7 +1353,7 @@ static void azx_bus_reset(struct hda_bus *bus) bus->in_reset = 1; bus->in_reset = 1; azx_stop_chip(chip); azx_stop_chip(chip); azx_init_chip(chip); azx_init_chip(chip, 1); #ifdef CONFIG_PM #ifdef CONFIG_PM if (chip->initialized) { if (chip->initialized) { int i; int i; Loading Loading @@ -1422,7 +1427,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model) * get back to the sanity state. * get back to the sanity state. */ */ azx_stop_chip(chip); azx_stop_chip(chip); azx_init_chip(chip); azx_init_chip(chip, 1); } } } } } } Loading Loading @@ -1670,8 +1675,9 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) return err; return err; } } azx_dev->min_jiffies = (runtime->period_size * HZ) / /* wallclk has 24Mhz clock source */ (runtime->rate * 2); azx_dev->period_wallclk = (((runtime->period_size * 24000) / runtime->rate) * 1000); azx_setup_controller(chip, azx_dev); azx_setup_controller(chip, azx_dev); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; Loading Loading @@ -1725,14 +1731,15 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) if (s->pcm->card != substream->pcm->card) if (s->pcm->card != substream->pcm->card) continue; continue; azx_dev = get_azx_dev(s); azx_dev = get_azx_dev(s); if (rstart) { if (start) { azx_dev->start_flag = 1; azx_dev->start_wallclk = azx_readl(chip, WALLCLK); azx_dev->start_jiffies = jiffies + azx_dev->min_jiffies; if (!rstart) } azx_dev->start_wallclk -= if (start) azx_dev->period_wallclk; azx_stream_start(chip, azx_dev); azx_stream_start(chip, azx_dev); else } else { azx_stream_stop(chip, azx_dev); azx_stream_stop(chip, azx_dev); } azx_dev->running = start; azx_dev->running = start; } } spin_unlock(&chip->reg_lock); spin_unlock(&chip->reg_lock); Loading Loading @@ -1843,14 +1850,17 @@ static unsigned int azx_get_position(struct azx *chip, if (chip->via_dmapos_patch) if (chip->via_dmapos_patch) pos = azx_via_get_position(chip, azx_dev); pos = azx_via_get_position(chip, azx_dev); else if (chip->position_fix == POS_FIX_POSBUF || else { chip->position_fix == POS_FIX_AUTO) { int stream = azx_dev->substream->stream; if (chip->position_fix[stream] == POS_FIX_POSBUF || chip->position_fix[stream] == POS_FIX_AUTO) { /* use the position buffer */ /* use the position buffer */ pos = le32_to_cpu(*azx_dev->posbuf); pos = le32_to_cpu(*azx_dev->posbuf); } else { } else { /* read LPIB */ /* read LPIB */ pos = azx_sd_readl(azx_dev, SD_LPIB); pos = azx_sd_readl(azx_dev, SD_LPIB); } } } if (pos >= azx_dev->bufsize) if (pos >= azx_dev->bufsize) pos = 0; pos = 0; return pos; return pos; Loading @@ -1876,32 +1886,35 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) */ */ 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) { { u32 wallclk; unsigned int pos; unsigned int pos; int stream; if (azx_dev->start_flag && wallclk = azx_readl(chip, WALLCLK) - azx_dev->start_wallclk; time_before_eq(jiffies, azx_dev->start_jiffies)) if (wallclk < (azx_dev->period_wallclk * 2) / 3) return -1; /* bogus (too early) interrupt */ return -1; /* bogus (too early) interrupt */ azx_dev->start_flag = 0; stream = azx_dev->substream->stream; pos = azx_get_position(chip, azx_dev); pos = azx_get_position(chip, azx_dev); if (chip->position_fix == POS_FIX_AUTO) { if (chip->position_fix[stream] == POS_FIX_AUTO) { if (!pos) { if (!pos) { printk(KERN_WARNING printk(KERN_WARNING "hda-intel: Invalid position buffer, " "hda-intel: Invalid position buffer, " "using LPIB read method instead.\n"); "using LPIB read method instead.\n"); chip->position_fix = POS_FIX_LPIB; chip->position_fix[stream] = POS_FIX_LPIB; pos = azx_get_position(chip, azx_dev); pos = azx_get_position(chip, azx_dev); } else } else chip->position_fix = POS_FIX_POSBUF; chip->position_fix[stream] = POS_FIX_POSBUF; } } if (!bdl_pos_adj[chip->dev_index]) return 1; /* no delayed ack */ 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")) return 0; /* this shouldn't happen! */ return -1; /* this shouldn't happen! */ if (pos % azx_dev->period_bytes > azx_dev->period_bytes / 2) if (wallclk <= azx_dev->period_wallclk && return 0; /* NG - it's below the period boundary */ pos % azx_dev->period_bytes > azx_dev->period_bytes / 2) /* NG - it's below the first next period boundary */ return bdl_pos_adj[chip->dev_index] ? 0 : -1; azx_dev->start_wallclk = wallclk; return 1; /* OK, it's fine */ return 1; /* OK, it's fine */ } } Loading @@ -1911,7 +1924,7 @@ 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 azx *chip = container_of(work, struct azx, irq_pending_work); int i, pending; int i, pending, ok; if (!chip->irq_pending_warned) { if (!chip->irq_pending_warned) { printk(KERN_WARNING printk(KERN_WARNING Loading @@ -1930,11 +1943,14 @@ static void azx_irq_pending_work(struct work_struct *work) !azx_dev->substream || !azx_dev->substream || !azx_dev->running) !azx_dev->running) continue; continue; if (azx_position_ok(chip, azx_dev)) { ok = azx_position_ok(chip, azx_dev); if (ok > 0) { azx_dev->irq_pending = 0; azx_dev->irq_pending = 0; spin_unlock(&chip->reg_lock); spin_unlock(&chip->reg_lock); snd_pcm_period_elapsed(azx_dev->substream); snd_pcm_period_elapsed(azx_dev->substream); spin_lock(&chip->reg_lock); spin_lock(&chip->reg_lock); } else if (ok < 0) { pending = 0; /* too early */ } else } else pending++; pending++; } } Loading Loading @@ -2112,7 +2128,7 @@ static void azx_power_notify(struct hda_bus *bus) } } } } if (power_on) if (power_on) azx_init_chip(chip); azx_init_chip(chip, 1); else if (chip->running && power_save_controller && else if (chip->running && power_save_controller && !bus->power_keep_link_on) !bus->power_keep_link_on) azx_stop_chip(chip); azx_stop_chip(chip); Loading Loading @@ -2182,7 +2198,7 @@ static int azx_resume(struct pci_dev *pci) azx_init_pci(chip); azx_init_pci(chip); if (snd_hda_codecs_inuse(chip->bus)) if (snd_hda_codecs_inuse(chip->bus)) azx_init_chip(chip); azx_init_chip(chip, 1); snd_hda_resume(chip->bus); snd_hda_resume(chip->bus); snd_power_change_state(card, SNDRV_CTL_POWER_D0); snd_power_change_state(card, SNDRV_CTL_POWER_D0); Loading Loading @@ -2431,7 +2447,8 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, chip->dev_index = dev; chip->dev_index = dev; INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work); INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work); chip->position_fix = check_position_fix(chip, position_fix[dev]); chip->position_fix[0] = chip->position_fix[1] = check_position_fix(chip, position_fix[dev]); check_probe_mask(chip, dev); check_probe_mask(chip, dev); chip->single_cmd = single_cmd; chip->single_cmd = single_cmd; Loading Loading @@ -2577,7 +2594,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, /* initialize chip */ /* initialize chip */ azx_init_pci(chip); azx_init_pci(chip); azx_init_chip(chip); azx_init_chip(chip, (probe_only[dev] & 2) == 0); /* codec detection */ /* codec detection */ if (!chip->codec_mask) { if (!chip->codec_mask) { Loading Loading @@ -2666,7 +2683,7 @@ static int __devinit azx_probe(struct pci_dev *pci, goto out_free; goto out_free; } } #endif #endif if (!probe_only[dev]) { if ((probe_only[dev] & 1) == 0) { err = azx_codec_configure(chip); err = azx_codec_configure(chip); if (err < 0) if (err < 0) goto out_free; goto out_free; Loading Loading
Documentation/sound/alsa/HD-Audio.txt +3 −1 Original line number Original line Diff line number Diff line Loading @@ -204,7 +204,6 @@ generic parser regardless of the codec. Usually the codec-specific parser is much better than the generic parser (as now). Thus this parser is much better than the generic parser (as now). Thus this option is more about the debugging purpose. option is more about the debugging purpose. Speaker and Headphone Output Speaker and Headphone Output ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ One of the most frequent (and obvious) bugs with HD-audio is the One of the most frequent (and obvious) bugs with HD-audio is the Loading Loading @@ -600,6 +599,9 @@ probing, the proc file is available, so you can get the raw codec information before modified by the driver. Of course, the driver information before modified by the driver. Of course, the driver isn't usable with `probe_only=1`. But you can continue the isn't usable with `probe_only=1`. But you can continue the configuration via hwdep sysfs file if hda-reconfig option is enabled. configuration via hwdep sysfs file if hda-reconfig option is enabled. Using `probe_only` mask 2 skips the reset of HDA codecs (use `probe_only=3` as module option). The hwdep interface can be used to determine the BIOS codec initialization. hda-verb hda-verb Loading
sound/pci/hda/Kconfig +1 −0 Original line number Original line Diff line number Diff line Loading @@ -145,6 +145,7 @@ config SND_HDA_CODEC_NVHDMI config SND_HDA_CODEC_INTELHDMI config SND_HDA_CODEC_INTELHDMI bool "Build INTEL HDMI HD-audio codec support" bool "Build INTEL HDMI HD-audio codec support" select SND_DYNAMIC_MINORS default y default y help help Say Y here to include INTEL HDMI HD-audio codec support in Say Y here to include INTEL HDMI HD-audio codec support in Loading
sound/pci/hda/hda_codec.c +63 −13 Original line number Original line Diff line number Diff line Loading @@ -1209,8 +1209,7 @@ static void free_hda_cache(struct hda_cache_rec *cache) } } /* query the hash. allocate an entry if not found. */ /* query the hash. allocate an entry if not found. */ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, static struct hda_cache_head *get_hash(struct hda_cache_rec *cache, u32 key) u32 key) { { u16 idx = key % (u16)ARRAY_SIZE(cache->hash); u16 idx = key % (u16)ARRAY_SIZE(cache->hash); u16 cur = cache->hash[idx]; u16 cur = cache->hash[idx]; Loading @@ -1222,7 +1221,16 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, return info; return info; cur = info->next; cur = info->next; } } return NULL; } /* query the hash. allocate an entry if not found. */ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, u32 key) { struct hda_cache_head *info = get_hash(cache, key); if (!info) { u16 idx, cur; /* add a new hash entry */ /* add a new hash entry */ info = snd_array_new(&cache->buf); info = snd_array_new(&cache->buf); if (!info) if (!info) Loading @@ -1230,9 +1238,10 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, cur = snd_array_index(&cache->buf, info); cur = snd_array_index(&cache->buf, info); info->key = key; info->key = key; info->val = 0; info->val = 0; idx = key % (u16)ARRAY_SIZE(cache->hash); info->next = cache->hash[idx]; info->next = cache->hash[idx]; cache->hash[idx] = cur; cache->hash[idx] = cur; } return info; return info; } } Loading Loading @@ -1461,6 +1470,8 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx)); info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx)); if (!info) if (!info) return 0; return 0; if (snd_BUG_ON(mask & ~0xff)) mask &= 0xff; val &= mask; val &= mask; val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask; val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask; if (info->vol[ch] == val) if (info->vol[ch] == val) Loading @@ -1486,6 +1497,9 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, int direction, int idx, int mask, int val) int direction, int idx, int mask, int val) { { int ch, ret = 0; int ch, ret = 0; if (snd_BUG_ON(mask & ~0xff)) mask &= 0xff; for (ch = 0; ch < 2; ch++) for (ch = 0; ch < 2; ch++) ret |= snd_hda_codec_amp_update(codec, nid, ch, direction, ret |= snd_hda_codec_amp_update(codec, nid, ch, direction, idx, mask, val); idx, mask, val); Loading Loading @@ -2716,6 +2730,41 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, } } EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache); EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache); /** * snd_hda_codec_update_cache - check cache and write the cmd only when needed * @codec: the HDA codec * @nid: NID to send the command * @direct: direct flag * @verb: the verb to send * @parm: the parameter for the verb * * This function works like snd_hda_codec_write_cache(), but it doesn't send * command if the parameter is already identical with the cached value. * If not, it sends the command and refreshes the cache. * * Returns 0 if successful, or a negative error code. */ int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid, int direct, unsigned int verb, unsigned int parm) { struct hda_cache_head *c; u32 key; /* parm may contain the verb stuff for get/set amp */ verb = verb | (parm >> 8); parm &= 0xff; key = build_cmd_cache_key(nid, verb); mutex_lock(&codec->bus->cmd_mutex); c = get_hash(&codec->cmd_cache, key); if (c && c->val == parm) { mutex_unlock(&codec->bus->cmd_mutex); return 0; } mutex_unlock(&codec->bus->cmd_mutex); return snd_hda_codec_write_cache(codec, nid, direct, verb, parm); } EXPORT_SYMBOL_HDA(snd_hda_codec_update_cache); /** /** * snd_hda_codec_resume_cache - Resume the all commands from the cache * snd_hda_codec_resume_cache - Resume the all commands from the cache * @codec: HD-audio codec * @codec: HD-audio codec Loading Loading @@ -4218,7 +4267,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, break; break; case AC_JACK_MIC_IN: { case AC_JACK_MIC_IN: { int preferred, alt; int preferred, alt; if (loc == AC_JACK_LOC_FRONT) { if (loc == AC_JACK_LOC_FRONT || (loc & 0x30) == AC_JACK_LOC_INTERNAL) { preferred = AUTO_PIN_FRONT_MIC; preferred = AUTO_PIN_FRONT_MIC; alt = AUTO_PIN_MIC; alt = AUTO_PIN_MIC; } else { } else { Loading
sound/pci/hda/hda_codec.h +3 −0 Original line number Original line Diff line number Diff line Loading @@ -885,9 +885,12 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, int direct, unsigned int verb, unsigned int parm); int direct, unsigned int verb, unsigned int parm); void snd_hda_sequence_write_cache(struct hda_codec *codec, void snd_hda_sequence_write_cache(struct hda_codec *codec, const struct hda_verb *seq); const struct hda_verb *seq); int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid, int direct, unsigned int verb, unsigned int parm); void snd_hda_codec_resume_cache(struct hda_codec *codec); void snd_hda_codec_resume_cache(struct hda_codec *codec); #else #else #define snd_hda_codec_write_cache snd_hda_codec_write #define snd_hda_codec_write_cache snd_hda_codec_write #define snd_hda_codec_update_cache snd_hda_codec_write #define snd_hda_sequence_write_cache snd_hda_sequence_write #define snd_hda_sequence_write_cache snd_hda_sequence_write #endif #endif Loading
sound/pci/hda/hda_intel.c +63 −46 Original line number Original line Diff line number Diff line Loading @@ -84,7 +84,7 @@ module_param_array(bdl_pos_adj, int, NULL, 0644); MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); module_param_array(probe_mask, int, NULL, 0444); module_param_array(probe_mask, int, NULL, 0444); MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); module_param_array(probe_only, bool, NULL, 0444); module_param_array(probe_only, int, NULL, 0444); MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization."); MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization."); module_param(single_cmd, bool, 0444); module_param(single_cmd, bool, 0444); MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs " MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs " Loading Loading @@ -174,7 +174,7 @@ MODULE_DESCRIPTION("Intel HDA driver"); #define ICH6_GSTS_FSTS (1 << 1) /* flush status */ #define ICH6_GSTS_FSTS (1 << 1) /* flush status */ #define ICH6_REG_INTCTL 0x20 #define ICH6_REG_INTCTL 0x20 #define ICH6_REG_INTSTS 0x24 #define ICH6_REG_INTSTS 0x24 #define ICH6_REG_WALCLK 0x30 #define ICH6_REG_WALLCLK 0x30 /* 24Mhz source */ #define ICH6_REG_SYNC 0x34 #define ICH6_REG_SYNC 0x34 #define ICH6_REG_CORBLBASE 0x40 #define ICH6_REG_CORBLBASE 0x40 #define ICH6_REG_CORBUBASE 0x44 #define ICH6_REG_CORBUBASE 0x44 Loading Loading @@ -340,8 +340,8 @@ struct azx_dev { unsigned int period_bytes; /* size of the period in bytes */ unsigned int period_bytes; /* size of the period in bytes */ unsigned int frags; /* number for period in the play buffer */ unsigned int frags; /* number for period in the play buffer */ unsigned int fifo_size; /* FIFO size */ unsigned int fifo_size; /* FIFO size */ unsigned long start_jiffies; /* start + minimum jiffies */ unsigned long start_wallclk; /* start + minimum wallclk */ unsigned long min_jiffies; /* minimum jiffies before position is valid */ unsigned long period_wallclk; /* wallclk for period */ void __iomem *sd_addr; /* stream descriptor pointer */ void __iomem *sd_addr; /* stream descriptor pointer */ Loading @@ -361,7 +361,6 @@ struct azx_dev { unsigned int opened :1; unsigned int opened :1; unsigned int running :1; unsigned int running :1; unsigned int irq_pending :1; unsigned int irq_pending :1; unsigned int start_flag: 1; /* stream full start flag */ /* /* * For VIA: * For VIA: * A flag to ensure DMA position is 0 * A flag to ensure DMA position is 0 Loading Loading @@ -425,7 +424,7 @@ struct azx { struct snd_dma_buffer posbuf; struct snd_dma_buffer posbuf; /* flags */ /* flags */ int position_fix; int position_fix[2]; /* for both playback/capture streams */ int poll_count; int poll_count; unsigned int running :1; unsigned int running :1; unsigned int initialized :1; unsigned int initialized :1; Loading Loading @@ -858,10 +857,13 @@ static void azx_power_notify(struct hda_bus *bus); #endif #endif /* reset codec link */ /* reset codec link */ static int azx_reset(struct azx *chip) static int azx_reset(struct azx *chip, int full_reset) { { int count; int count; if (!full_reset) goto __skip; /* clear STATESTS */ /* clear STATESTS */ azx_writeb(chip, STATESTS, STATESTS_INT_MASK); azx_writeb(chip, STATESTS, STATESTS_INT_MASK); Loading @@ -887,6 +889,7 @@ static int azx_reset(struct azx *chip) /* Brent Chartrand said to wait >= 540us for codecs to initialize */ /* Brent Chartrand said to wait >= 540us for codecs to initialize */ msleep(1); msleep(1); __skip: /* check to see if controller is ready */ /* check to see if controller is ready */ if (!azx_readb(chip, GCTL)) { if (!azx_readb(chip, GCTL)) { snd_printd(SFX "azx_reset: controller not ready!\n"); snd_printd(SFX "azx_reset: controller not ready!\n"); Loading Loading @@ -998,13 +1001,13 @@ static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev) /* /* * reset and start the controller registers * reset and start the controller registers */ */ static void azx_init_chip(struct azx *chip) static void azx_init_chip(struct azx *chip, int full_reset) { { if (chip->initialized) if (chip->initialized) return; return; /* reset controller */ /* reset controller */ azx_reset(chip); azx_reset(chip, full_reset); /* initialize interrupts */ /* initialize interrupts */ azx_int_clear(chip); azx_int_clear(chip); Loading Loading @@ -1302,8 +1305,10 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr)); azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr)); /* enable the position buffer */ /* enable the position buffer */ if (chip->position_fix == POS_FIX_POSBUF || if (chip->position_fix[0] == POS_FIX_POSBUF || chip->position_fix == POS_FIX_AUTO || chip->position_fix[0] == POS_FIX_AUTO || chip->position_fix[1] == POS_FIX_POSBUF || chip->position_fix[1] == POS_FIX_AUTO || chip->via_dmapos_patch) { chip->via_dmapos_patch) { if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) azx_writel(chip, DPLBASE, azx_writel(chip, DPLBASE, Loading Loading @@ -1348,7 +1353,7 @@ static void azx_bus_reset(struct hda_bus *bus) bus->in_reset = 1; bus->in_reset = 1; azx_stop_chip(chip); azx_stop_chip(chip); azx_init_chip(chip); azx_init_chip(chip, 1); #ifdef CONFIG_PM #ifdef CONFIG_PM if (chip->initialized) { if (chip->initialized) { int i; int i; Loading Loading @@ -1422,7 +1427,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model) * get back to the sanity state. * get back to the sanity state. */ */ azx_stop_chip(chip); azx_stop_chip(chip); azx_init_chip(chip); azx_init_chip(chip, 1); } } } } } } Loading Loading @@ -1670,8 +1675,9 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) return err; return err; } } azx_dev->min_jiffies = (runtime->period_size * HZ) / /* wallclk has 24Mhz clock source */ (runtime->rate * 2); azx_dev->period_wallclk = (((runtime->period_size * 24000) / runtime->rate) * 1000); azx_setup_controller(chip, azx_dev); azx_setup_controller(chip, azx_dev); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; Loading Loading @@ -1725,14 +1731,15 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) if (s->pcm->card != substream->pcm->card) if (s->pcm->card != substream->pcm->card) continue; continue; azx_dev = get_azx_dev(s); azx_dev = get_azx_dev(s); if (rstart) { if (start) { azx_dev->start_flag = 1; azx_dev->start_wallclk = azx_readl(chip, WALLCLK); azx_dev->start_jiffies = jiffies + azx_dev->min_jiffies; if (!rstart) } azx_dev->start_wallclk -= if (start) azx_dev->period_wallclk; azx_stream_start(chip, azx_dev); azx_stream_start(chip, azx_dev); else } else { azx_stream_stop(chip, azx_dev); azx_stream_stop(chip, azx_dev); } azx_dev->running = start; azx_dev->running = start; } } spin_unlock(&chip->reg_lock); spin_unlock(&chip->reg_lock); Loading Loading @@ -1843,14 +1850,17 @@ static unsigned int azx_get_position(struct azx *chip, if (chip->via_dmapos_patch) if (chip->via_dmapos_patch) pos = azx_via_get_position(chip, azx_dev); pos = azx_via_get_position(chip, azx_dev); else if (chip->position_fix == POS_FIX_POSBUF || else { chip->position_fix == POS_FIX_AUTO) { int stream = azx_dev->substream->stream; if (chip->position_fix[stream] == POS_FIX_POSBUF || chip->position_fix[stream] == POS_FIX_AUTO) { /* use the position buffer */ /* use the position buffer */ pos = le32_to_cpu(*azx_dev->posbuf); pos = le32_to_cpu(*azx_dev->posbuf); } else { } else { /* read LPIB */ /* read LPIB */ pos = azx_sd_readl(azx_dev, SD_LPIB); pos = azx_sd_readl(azx_dev, SD_LPIB); } } } if (pos >= azx_dev->bufsize) if (pos >= azx_dev->bufsize) pos = 0; pos = 0; return pos; return pos; Loading @@ -1876,32 +1886,35 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) */ */ 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) { { u32 wallclk; unsigned int pos; unsigned int pos; int stream; if (azx_dev->start_flag && wallclk = azx_readl(chip, WALLCLK) - azx_dev->start_wallclk; time_before_eq(jiffies, azx_dev->start_jiffies)) if (wallclk < (azx_dev->period_wallclk * 2) / 3) return -1; /* bogus (too early) interrupt */ return -1; /* bogus (too early) interrupt */ azx_dev->start_flag = 0; stream = azx_dev->substream->stream; pos = azx_get_position(chip, azx_dev); pos = azx_get_position(chip, azx_dev); if (chip->position_fix == POS_FIX_AUTO) { if (chip->position_fix[stream] == POS_FIX_AUTO) { if (!pos) { if (!pos) { printk(KERN_WARNING printk(KERN_WARNING "hda-intel: Invalid position buffer, " "hda-intel: Invalid position buffer, " "using LPIB read method instead.\n"); "using LPIB read method instead.\n"); chip->position_fix = POS_FIX_LPIB; chip->position_fix[stream] = POS_FIX_LPIB; pos = azx_get_position(chip, azx_dev); pos = azx_get_position(chip, azx_dev); } else } else chip->position_fix = POS_FIX_POSBUF; chip->position_fix[stream] = POS_FIX_POSBUF; } } if (!bdl_pos_adj[chip->dev_index]) return 1; /* no delayed ack */ 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")) return 0; /* this shouldn't happen! */ return -1; /* this shouldn't happen! */ if (pos % azx_dev->period_bytes > azx_dev->period_bytes / 2) if (wallclk <= azx_dev->period_wallclk && return 0; /* NG - it's below the period boundary */ pos % azx_dev->period_bytes > azx_dev->period_bytes / 2) /* NG - it's below the first next period boundary */ return bdl_pos_adj[chip->dev_index] ? 0 : -1; azx_dev->start_wallclk = wallclk; return 1; /* OK, it's fine */ return 1; /* OK, it's fine */ } } Loading @@ -1911,7 +1924,7 @@ 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 azx *chip = container_of(work, struct azx, irq_pending_work); int i, pending; int i, pending, ok; if (!chip->irq_pending_warned) { if (!chip->irq_pending_warned) { printk(KERN_WARNING printk(KERN_WARNING Loading @@ -1930,11 +1943,14 @@ static void azx_irq_pending_work(struct work_struct *work) !azx_dev->substream || !azx_dev->substream || !azx_dev->running) !azx_dev->running) continue; continue; if (azx_position_ok(chip, azx_dev)) { ok = azx_position_ok(chip, azx_dev); if (ok > 0) { azx_dev->irq_pending = 0; azx_dev->irq_pending = 0; spin_unlock(&chip->reg_lock); spin_unlock(&chip->reg_lock); snd_pcm_period_elapsed(azx_dev->substream); snd_pcm_period_elapsed(azx_dev->substream); spin_lock(&chip->reg_lock); spin_lock(&chip->reg_lock); } else if (ok < 0) { pending = 0; /* too early */ } else } else pending++; pending++; } } Loading Loading @@ -2112,7 +2128,7 @@ static void azx_power_notify(struct hda_bus *bus) } } } } if (power_on) if (power_on) azx_init_chip(chip); azx_init_chip(chip, 1); else if (chip->running && power_save_controller && else if (chip->running && power_save_controller && !bus->power_keep_link_on) !bus->power_keep_link_on) azx_stop_chip(chip); azx_stop_chip(chip); Loading Loading @@ -2182,7 +2198,7 @@ static int azx_resume(struct pci_dev *pci) azx_init_pci(chip); azx_init_pci(chip); if (snd_hda_codecs_inuse(chip->bus)) if (snd_hda_codecs_inuse(chip->bus)) azx_init_chip(chip); azx_init_chip(chip, 1); snd_hda_resume(chip->bus); snd_hda_resume(chip->bus); snd_power_change_state(card, SNDRV_CTL_POWER_D0); snd_power_change_state(card, SNDRV_CTL_POWER_D0); Loading Loading @@ -2431,7 +2447,8 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, chip->dev_index = dev; chip->dev_index = dev; INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work); INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work); chip->position_fix = check_position_fix(chip, position_fix[dev]); chip->position_fix[0] = chip->position_fix[1] = check_position_fix(chip, position_fix[dev]); check_probe_mask(chip, dev); check_probe_mask(chip, dev); chip->single_cmd = single_cmd; chip->single_cmd = single_cmd; Loading Loading @@ -2577,7 +2594,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, /* initialize chip */ /* initialize chip */ azx_init_pci(chip); azx_init_pci(chip); azx_init_chip(chip); azx_init_chip(chip, (probe_only[dev] & 2) == 0); /* codec detection */ /* codec detection */ if (!chip->codec_mask) { if (!chip->codec_mask) { Loading Loading @@ -2666,7 +2683,7 @@ static int __devinit azx_probe(struct pci_dev *pci, goto out_free; goto out_free; } } #endif #endif if (!probe_only[dev]) { if ((probe_only[dev] & 1) == 0) { err = azx_codec_configure(chip); err = azx_codec_configure(chip); if (err < 0) if (err < 0) goto out_free; goto out_free; Loading