Loading Documentation/sound/alsa/HD-Audio-Models.txt +6 −0 Original line number Diff line number Diff line Loading @@ -114,6 +114,11 @@ ALC662/663/272 samsung-nc10 Samsung NC10 mini notebook auto auto-config reading BIOS (default) ALC680 ====== base Base model (ASUS NX90) auto auto-config reading BIOS (default) ALC882/883/885/888/889 ====================== 3stack-dig 3-jack with SPDIF I/O Loading Loading @@ -282,6 +287,7 @@ Conexant 5051 hp HP Spartan laptop hp-dv6736 HP dv6736 hp-f700 HP Compaq Presario F700 ideapad Lenovo IdeaPad laptop lenovo-x200 Lenovo X200 laptop toshiba Toshiba Satellite M300 Loading sound/pci/hda/hda_codec.c +55 −32 Original line number Diff line number Diff line Loading @@ -396,15 +396,18 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, } for (n = prev_nid + 1; n <= val; n++) { if (conns >= max_conns) { snd_printk(KERN_ERR "Too many connections\n"); snd_printk(KERN_ERR "hda_codec: " "Too many connections %d for NID 0x%x\n", conns, nid); return -EINVAL; } conn_list[conns++] = n; } } else { if (conns >= max_conns) { snd_printk(KERN_ERR "Too many connections\n"); snd_printk(KERN_ERR "hda_codec: " "Too many connections %d for NID 0x%x\n", conns, nid); return -EINVAL; } conn_list[conns++] = val; Loading Loading @@ -1565,6 +1568,17 @@ void snd_hda_codec_resume_amp(struct hda_codec *codec) EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp); #endif /* SND_HDA_NEEDS_RESUME */ static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir, unsigned int ofs) { u32 caps = query_amp_caps(codec, nid, dir); /* get num steps */ caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; if (ofs < caps) caps -= ofs; return caps; } /** * snd_hda_mixer_amp_volume_info - Info callback for a standard AMP mixer * Loading @@ -1579,23 +1593,17 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, u8 chs = get_amp_channels(kcontrol); int dir = get_amp_direction(kcontrol); unsigned int ofs = get_amp_offset(kcontrol); u32 caps; caps = query_amp_caps(codec, nid, dir); /* num steps */ caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; if (!caps) { uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = chs == 3 ? 2 : 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = get_amp_max_value(codec, nid, dir, ofs); if (!uinfo->value.integer.max) { printk(KERN_WARNING "hda_codec: " "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid, kcontrol->id.name); return -EINVAL; } if (ofs < caps) caps -= ofs; uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = chs == 3 ? 2 : 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = caps; return 0; } EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info); Loading @@ -1620,8 +1628,14 @@ update_amp_value(struct hda_codec *codec, hda_nid_t nid, int ch, int dir, int idx, unsigned int ofs, unsigned int val) { unsigned int maxval; if (val > 0) val += ofs; /* ofs = 0: raw max value */ maxval = get_amp_max_value(codec, nid, dir, 0); if (val > maxval) val = maxval; return snd_hda_codec_amp_update(codec, nid, ch, dir, idx, HDA_AMP_VOLMASK, val); } Loading Loading @@ -2999,26 +3013,31 @@ struct hda_rate_tbl { unsigned int hda_fmt; }; /* rate = base * mult / div */ #define HDA_RATE(base, mult, div) \ (AC_FMT_BASE_##base##K | (((mult) - 1) << AC_FMT_MULT_SHIFT) | \ (((div) - 1) << AC_FMT_DIV_SHIFT)) static struct hda_rate_tbl rate_bits[] = { /* rate in Hz, ALSA rate bitmask, HDA format value */ /* autodetected value used in snd_hda_query_supported_pcm */ { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */ { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */ { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */ { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */ { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */ { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */ { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */ { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */ { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */ { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */ { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */ { 8000, SNDRV_PCM_RATE_8000, HDA_RATE(48, 1, 6) }, { 11025, SNDRV_PCM_RATE_11025, HDA_RATE(44, 1, 4) }, { 16000, SNDRV_PCM_RATE_16000, HDA_RATE(48, 1, 3) }, { 22050, SNDRV_PCM_RATE_22050, HDA_RATE(44, 1, 2) }, { 32000, SNDRV_PCM_RATE_32000, HDA_RATE(48, 2, 3) }, { 44100, SNDRV_PCM_RATE_44100, HDA_RATE(44, 1, 1) }, { 48000, SNDRV_PCM_RATE_48000, HDA_RATE(48, 1, 1) }, { 88200, SNDRV_PCM_RATE_88200, HDA_RATE(44, 2, 1) }, { 96000, SNDRV_PCM_RATE_96000, HDA_RATE(48, 2, 1) }, { 176400, SNDRV_PCM_RATE_176400, HDA_RATE(44, 4, 1) }, { 192000, SNDRV_PCM_RATE_192000, HDA_RATE(48, 4, 1) }, #define AC_PAR_PCM_RATE_BITS 11 /* up to bits 10, 384kHZ isn't supported properly */ /* not autodetected value */ { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */ { 9600, SNDRV_PCM_RATE_KNOT, HDA_RATE(48, 1, 5) }, { 0 } /* terminator */ }; Loading @@ -3037,7 +3056,8 @@ static struct hda_rate_tbl rate_bits[] = { unsigned int snd_hda_calc_stream_format(unsigned int rate, unsigned int channels, unsigned int format, unsigned int maxbps) unsigned int maxbps, unsigned short spdif_ctls) { int i; unsigned int val = 0; Loading @@ -3060,20 +3080,20 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, switch (snd_pcm_format_width(format)) { case 8: val |= 0x00; val |= AC_FMT_BITS_8; break; case 16: val |= 0x10; val |= AC_FMT_BITS_16; break; case 20: case 24: case 32: if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE) val |= 0x40; val |= AC_FMT_BITS_32; else if (maxbps >= 24) val |= 0x30; val |= AC_FMT_BITS_24; else val |= 0x20; val |= AC_FMT_BITS_20; break; default: snd_printdd("invalid format width %d\n", Loading @@ -3081,6 +3101,9 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, return 0; } if (spdif_ctls & AC_DIG1_NONAUDIO) val |= AC_FMT_TYPE_NON_PCM; return val; } EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format); Loading sound/pci/hda/hda_codec.h +26 −1 Original line number Diff line number Diff line Loading @@ -224,6 +224,27 @@ enum { /* Input converter SDI select */ #define AC_SDI_SELECT (0xf<<0) /* stream format id */ #define AC_FMT_CHAN_SHIFT 0 #define AC_FMT_CHAN_MASK (0x0f << 0) #define AC_FMT_BITS_SHIFT 4 #define AC_FMT_BITS_MASK (7 << 4) #define AC_FMT_BITS_8 (0 << 4) #define AC_FMT_BITS_16 (1 << 4) #define AC_FMT_BITS_20 (2 << 4) #define AC_FMT_BITS_24 (3 << 4) #define AC_FMT_BITS_32 (4 << 4) #define AC_FMT_DIV_SHIFT 8 #define AC_FMT_DIV_MASK (7 << 8) #define AC_FMT_MULT_SHIFT 11 #define AC_FMT_MULT_MASK (7 << 11) #define AC_FMT_BASE_SHIFT 14 #define AC_FMT_BASE_48K (0 << 14) #define AC_FMT_BASE_44K (1 << 14) #define AC_FMT_TYPE_SHIFT 15 #define AC_FMT_TYPE_PCM (0 << 15) #define AC_FMT_TYPE_NON_PCM (1 << 15) /* Unsolicited response control */ #define AC_UNSOL_TAG (0x3f<<0) #define AC_UNSOL_ENABLED (1<<7) Loading Loading @@ -364,6 +385,9 @@ enum { #define AC_DIG2_CC (0x7f<<0) /* Pin widget control - 8bit */ #define AC_PINCTL_EPT (0x3<<0) #define AC_PINCTL_EPT_NATIVE 0 #define AC_PINCTL_EPT_HBR 3 #define AC_PINCTL_VREFEN (0x7<<0) #define AC_PINCTL_VREF_HIZ 0 /* Hi-Z */ #define AC_PINCTL_VREF_50 1 /* 50% */ Loading Loading @@ -928,7 +952,8 @@ void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid); unsigned int snd_hda_calc_stream_format(unsigned int rate, unsigned int channels, unsigned int format, unsigned int maxbps); unsigned int maxbps, unsigned short spdif_ctls); int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid, unsigned int format); Loading sound/pci/hda/hda_hwdep.c +3 −1 Original line number Diff line number Diff line Loading @@ -649,7 +649,9 @@ static void parse_codec_mode(char *buf, struct hda_bus *bus, *codecp = NULL; if (sscanf(buf, "%i %i %i", &vendorid, &subid, &caddr) == 3) { list_for_each_entry(codec, &bus->codec_list, list) { if (codec->addr == caddr) { if (codec->vendor_id == vendorid && codec->subsystem_id == subid && codec->addr == caddr) { *codecp = codec; break; } Loading sound/pci/hda/hda_intel.c +3 −2 Original line number Diff line number Diff line Loading @@ -1653,7 +1653,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) format_val = snd_hda_calc_stream_format(runtime->rate, runtime->channels, runtime->format, hinfo->maxbps); hinfo->maxbps, apcm->codec->spdif_ctls); if (!format_val) { snd_printk(KERN_ERR SFX "invalid format_val, rate=%d, ch=%d, format=%d\n", Loading Loading @@ -1960,7 +1961,7 @@ static void azx_irq_pending_work(struct work_struct *work) spin_unlock_irq(&chip->reg_lock); if (!pending) return; cond_resched(); msleep(1); } } Loading Loading
Documentation/sound/alsa/HD-Audio-Models.txt +6 −0 Original line number Diff line number Diff line Loading @@ -114,6 +114,11 @@ ALC662/663/272 samsung-nc10 Samsung NC10 mini notebook auto auto-config reading BIOS (default) ALC680 ====== base Base model (ASUS NX90) auto auto-config reading BIOS (default) ALC882/883/885/888/889 ====================== 3stack-dig 3-jack with SPDIF I/O Loading Loading @@ -282,6 +287,7 @@ Conexant 5051 hp HP Spartan laptop hp-dv6736 HP dv6736 hp-f700 HP Compaq Presario F700 ideapad Lenovo IdeaPad laptop lenovo-x200 Lenovo X200 laptop toshiba Toshiba Satellite M300 Loading
sound/pci/hda/hda_codec.c +55 −32 Original line number Diff line number Diff line Loading @@ -396,15 +396,18 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, } for (n = prev_nid + 1; n <= val; n++) { if (conns >= max_conns) { snd_printk(KERN_ERR "Too many connections\n"); snd_printk(KERN_ERR "hda_codec: " "Too many connections %d for NID 0x%x\n", conns, nid); return -EINVAL; } conn_list[conns++] = n; } } else { if (conns >= max_conns) { snd_printk(KERN_ERR "Too many connections\n"); snd_printk(KERN_ERR "hda_codec: " "Too many connections %d for NID 0x%x\n", conns, nid); return -EINVAL; } conn_list[conns++] = val; Loading Loading @@ -1565,6 +1568,17 @@ void snd_hda_codec_resume_amp(struct hda_codec *codec) EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp); #endif /* SND_HDA_NEEDS_RESUME */ static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir, unsigned int ofs) { u32 caps = query_amp_caps(codec, nid, dir); /* get num steps */ caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; if (ofs < caps) caps -= ofs; return caps; } /** * snd_hda_mixer_amp_volume_info - Info callback for a standard AMP mixer * Loading @@ -1579,23 +1593,17 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, u8 chs = get_amp_channels(kcontrol); int dir = get_amp_direction(kcontrol); unsigned int ofs = get_amp_offset(kcontrol); u32 caps; caps = query_amp_caps(codec, nid, dir); /* num steps */ caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; if (!caps) { uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = chs == 3 ? 2 : 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = get_amp_max_value(codec, nid, dir, ofs); if (!uinfo->value.integer.max) { printk(KERN_WARNING "hda_codec: " "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid, kcontrol->id.name); return -EINVAL; } if (ofs < caps) caps -= ofs; uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = chs == 3 ? 2 : 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = caps; return 0; } EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info); Loading @@ -1620,8 +1628,14 @@ update_amp_value(struct hda_codec *codec, hda_nid_t nid, int ch, int dir, int idx, unsigned int ofs, unsigned int val) { unsigned int maxval; if (val > 0) val += ofs; /* ofs = 0: raw max value */ maxval = get_amp_max_value(codec, nid, dir, 0); if (val > maxval) val = maxval; return snd_hda_codec_amp_update(codec, nid, ch, dir, idx, HDA_AMP_VOLMASK, val); } Loading Loading @@ -2999,26 +3013,31 @@ struct hda_rate_tbl { unsigned int hda_fmt; }; /* rate = base * mult / div */ #define HDA_RATE(base, mult, div) \ (AC_FMT_BASE_##base##K | (((mult) - 1) << AC_FMT_MULT_SHIFT) | \ (((div) - 1) << AC_FMT_DIV_SHIFT)) static struct hda_rate_tbl rate_bits[] = { /* rate in Hz, ALSA rate bitmask, HDA format value */ /* autodetected value used in snd_hda_query_supported_pcm */ { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */ { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */ { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */ { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */ { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */ { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */ { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */ { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */ { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */ { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */ { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */ { 8000, SNDRV_PCM_RATE_8000, HDA_RATE(48, 1, 6) }, { 11025, SNDRV_PCM_RATE_11025, HDA_RATE(44, 1, 4) }, { 16000, SNDRV_PCM_RATE_16000, HDA_RATE(48, 1, 3) }, { 22050, SNDRV_PCM_RATE_22050, HDA_RATE(44, 1, 2) }, { 32000, SNDRV_PCM_RATE_32000, HDA_RATE(48, 2, 3) }, { 44100, SNDRV_PCM_RATE_44100, HDA_RATE(44, 1, 1) }, { 48000, SNDRV_PCM_RATE_48000, HDA_RATE(48, 1, 1) }, { 88200, SNDRV_PCM_RATE_88200, HDA_RATE(44, 2, 1) }, { 96000, SNDRV_PCM_RATE_96000, HDA_RATE(48, 2, 1) }, { 176400, SNDRV_PCM_RATE_176400, HDA_RATE(44, 4, 1) }, { 192000, SNDRV_PCM_RATE_192000, HDA_RATE(48, 4, 1) }, #define AC_PAR_PCM_RATE_BITS 11 /* up to bits 10, 384kHZ isn't supported properly */ /* not autodetected value */ { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */ { 9600, SNDRV_PCM_RATE_KNOT, HDA_RATE(48, 1, 5) }, { 0 } /* terminator */ }; Loading @@ -3037,7 +3056,8 @@ static struct hda_rate_tbl rate_bits[] = { unsigned int snd_hda_calc_stream_format(unsigned int rate, unsigned int channels, unsigned int format, unsigned int maxbps) unsigned int maxbps, unsigned short spdif_ctls) { int i; unsigned int val = 0; Loading @@ -3060,20 +3080,20 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, switch (snd_pcm_format_width(format)) { case 8: val |= 0x00; val |= AC_FMT_BITS_8; break; case 16: val |= 0x10; val |= AC_FMT_BITS_16; break; case 20: case 24: case 32: if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE) val |= 0x40; val |= AC_FMT_BITS_32; else if (maxbps >= 24) val |= 0x30; val |= AC_FMT_BITS_24; else val |= 0x20; val |= AC_FMT_BITS_20; break; default: snd_printdd("invalid format width %d\n", Loading @@ -3081,6 +3101,9 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, return 0; } if (spdif_ctls & AC_DIG1_NONAUDIO) val |= AC_FMT_TYPE_NON_PCM; return val; } EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format); Loading
sound/pci/hda/hda_codec.h +26 −1 Original line number Diff line number Diff line Loading @@ -224,6 +224,27 @@ enum { /* Input converter SDI select */ #define AC_SDI_SELECT (0xf<<0) /* stream format id */ #define AC_FMT_CHAN_SHIFT 0 #define AC_FMT_CHAN_MASK (0x0f << 0) #define AC_FMT_BITS_SHIFT 4 #define AC_FMT_BITS_MASK (7 << 4) #define AC_FMT_BITS_8 (0 << 4) #define AC_FMT_BITS_16 (1 << 4) #define AC_FMT_BITS_20 (2 << 4) #define AC_FMT_BITS_24 (3 << 4) #define AC_FMT_BITS_32 (4 << 4) #define AC_FMT_DIV_SHIFT 8 #define AC_FMT_DIV_MASK (7 << 8) #define AC_FMT_MULT_SHIFT 11 #define AC_FMT_MULT_MASK (7 << 11) #define AC_FMT_BASE_SHIFT 14 #define AC_FMT_BASE_48K (0 << 14) #define AC_FMT_BASE_44K (1 << 14) #define AC_FMT_TYPE_SHIFT 15 #define AC_FMT_TYPE_PCM (0 << 15) #define AC_FMT_TYPE_NON_PCM (1 << 15) /* Unsolicited response control */ #define AC_UNSOL_TAG (0x3f<<0) #define AC_UNSOL_ENABLED (1<<7) Loading Loading @@ -364,6 +385,9 @@ enum { #define AC_DIG2_CC (0x7f<<0) /* Pin widget control - 8bit */ #define AC_PINCTL_EPT (0x3<<0) #define AC_PINCTL_EPT_NATIVE 0 #define AC_PINCTL_EPT_HBR 3 #define AC_PINCTL_VREFEN (0x7<<0) #define AC_PINCTL_VREF_HIZ 0 /* Hi-Z */ #define AC_PINCTL_VREF_50 1 /* 50% */ Loading Loading @@ -928,7 +952,8 @@ void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid); unsigned int snd_hda_calc_stream_format(unsigned int rate, unsigned int channels, unsigned int format, unsigned int maxbps); unsigned int maxbps, unsigned short spdif_ctls); int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid, unsigned int format); Loading
sound/pci/hda/hda_hwdep.c +3 −1 Original line number Diff line number Diff line Loading @@ -649,7 +649,9 @@ static void parse_codec_mode(char *buf, struct hda_bus *bus, *codecp = NULL; if (sscanf(buf, "%i %i %i", &vendorid, &subid, &caddr) == 3) { list_for_each_entry(codec, &bus->codec_list, list) { if (codec->addr == caddr) { if (codec->vendor_id == vendorid && codec->subsystem_id == subid && codec->addr == caddr) { *codecp = codec; break; } Loading
sound/pci/hda/hda_intel.c +3 −2 Original line number Diff line number Diff line Loading @@ -1653,7 +1653,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) format_val = snd_hda_calc_stream_format(runtime->rate, runtime->channels, runtime->format, hinfo->maxbps); hinfo->maxbps, apcm->codec->spdif_ctls); if (!format_val) { snd_printk(KERN_ERR SFX "invalid format_val, rate=%d, ch=%d, format=%d\n", Loading Loading @@ -1960,7 +1961,7 @@ static void azx_irq_pending_work(struct work_struct *work) spin_unlock_irq(&chip->reg_lock); if (!pending) return; cond_resched(); msleep(1); } } Loading