diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-09-01 18:02:27 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-09-01 18:02:27 -0400 |
commit | ceeec3dc375e3b0618f16b34efc56fe093918f8b (patch) | |
tree | 2293d02721ee05131aaf1c60e4fba7e281585eec /sound/pci/hda | |
parent | fbff868db3a4cc6a89d51da9a6d49b26c29d04fb (diff) | |
parent | e3ee3b78f83688a0ae4315e8be71b2eac559904a (diff) |
/spare/repo/netdev-2.6 branch 'ieee80211'
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/Makefile | 2 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 97 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 1 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.c | 5 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 157 | ||||
-rw-r--r-- | sound/pci/hda/hda_patch.h | 3 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 4 | ||||
-rw-r--r-- | sound/pci/hda/patch_cmedia.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 9 | ||||
-rw-r--r-- | sound/pci/hda/patch_si3054.c | 300 |
10 files changed, 511 insertions, 68 deletions
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index bd8cb33c4fb4..ddfb5ff7fb8f 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | snd-hda-intel-objs := hda_intel.o | 1 | snd-hda-intel-objs := hda_intel.o |
2 | snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o patch_sigmatel.o | 2 | snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o patch_sigmatel.o patch_si3054.o |
3 | ifdef CONFIG_PROC_FS | 3 | ifdef CONFIG_PROC_FS |
4 | snd-hda-codec-objs += hda_proc.o | 4 | snd-hda-codec-objs += hda_proc.o |
5 | endif | 5 | endif |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index e2cf02387289..20f7762f7144 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -432,22 +432,26 @@ void snd_hda_get_codec_name(struct hda_codec *codec, | |||
432 | } | 432 | } |
433 | 433 | ||
434 | /* | 434 | /* |
435 | * look for an AFG node | 435 | * look for an AFG and MFG nodes |
436 | * | ||
437 | * return 0 if not found | ||
438 | */ | 436 | */ |
439 | static int look_for_afg_node(struct hda_codec *codec) | 437 | static void setup_fg_nodes(struct hda_codec *codec) |
440 | { | 438 | { |
441 | int i, total_nodes; | 439 | int i, total_nodes; |
442 | hda_nid_t nid; | 440 | hda_nid_t nid; |
443 | 441 | ||
444 | total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid); | 442 | total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid); |
445 | for (i = 0; i < total_nodes; i++, nid++) { | 443 | for (i = 0; i < total_nodes; i++, nid++) { |
446 | if ((snd_hda_param_read(codec, nid, AC_PAR_FUNCTION_TYPE) & 0xff) == | 444 | switch((snd_hda_param_read(codec, nid, AC_PAR_FUNCTION_TYPE) & 0xff)) { |
447 | AC_GRP_AUDIO_FUNCTION) | 445 | case AC_GRP_AUDIO_FUNCTION: |
448 | return nid; | 446 | codec->afg = nid; |
447 | break; | ||
448 | case AC_GRP_MODEM_FUNCTION: | ||
449 | codec->mfg = nid; | ||
450 | break; | ||
451 | default: | ||
452 | break; | ||
453 | } | ||
449 | } | 454 | } |
450 | return 0; | ||
451 | } | 455 | } |
452 | 456 | ||
453 | /* | 457 | /* |
@@ -507,10 +511,9 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
507 | codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_SUBSYSTEM_ID); | 511 | codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_SUBSYSTEM_ID); |
508 | codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_REV_ID); | 512 | codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_REV_ID); |
509 | 513 | ||
510 | /* FIXME: support for multiple AFGs? */ | 514 | setup_fg_nodes(codec); |
511 | codec->afg = look_for_afg_node(codec); | 515 | if (! codec->afg && ! codec->mfg) { |
512 | if (! codec->afg) { | 516 | snd_printdd("hda_codec: no AFG or MFG node found\n"); |
513 | snd_printdd("hda_codec: no AFG node found\n"); | ||
514 | snd_hda_codec_free(codec); | 517 | snd_hda_codec_free(codec); |
515 | return -ENODEV; | 518 | return -ENODEV; |
516 | } | 519 | } |
@@ -749,12 +752,14 @@ int snd_hda_mixer_amp_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
749 | long *valp = ucontrol->value.integer.value; | 752 | long *valp = ucontrol->value.integer.value; |
750 | int change = 0; | 753 | int change = 0; |
751 | 754 | ||
752 | if (chs & 1) | 755 | if (chs & 1) { |
753 | change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, | 756 | change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, |
754 | 0x7f, *valp); | 757 | 0x7f, *valp); |
758 | valp++; | ||
759 | } | ||
755 | if (chs & 2) | 760 | if (chs & 2) |
756 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, | 761 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, |
757 | 0x7f, valp[1]); | 762 | 0x7f, *valp); |
758 | return change; | 763 | return change; |
759 | } | 764 | } |
760 | 765 | ||
@@ -796,12 +801,15 @@ int snd_hda_mixer_amp_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
796 | long *valp = ucontrol->value.integer.value; | 801 | long *valp = ucontrol->value.integer.value; |
797 | int change = 0; | 802 | int change = 0; |
798 | 803 | ||
799 | if (chs & 1) | 804 | if (chs & 1) { |
800 | change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, | 805 | change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, |
801 | 0x80, *valp ? 0 : 0x80); | 806 | 0x80, *valp ? 0 : 0x80); |
807 | valp++; | ||
808 | } | ||
802 | if (chs & 2) | 809 | if (chs & 2) |
803 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, | 810 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, |
804 | 0x80, valp[1] ? 0 : 0x80); | 811 | 0x80, *valp ? 0 : 0x80); |
812 | |||
805 | return change; | 813 | return change; |
806 | } | 814 | } |
807 | 815 | ||
@@ -1155,8 +1163,16 @@ int snd_hda_build_controls(struct hda_bus *bus) | |||
1155 | /* | 1163 | /* |
1156 | * stream formats | 1164 | * stream formats |
1157 | */ | 1165 | */ |
1158 | static unsigned int rate_bits[][3] = { | 1166 | struct hda_rate_tbl { |
1167 | unsigned int hz; | ||
1168 | unsigned int alsa_bits; | ||
1169 | unsigned int hda_fmt; | ||
1170 | }; | ||
1171 | |||
1172 | static struct hda_rate_tbl rate_bits[] = { | ||
1159 | /* rate in Hz, ALSA rate bitmask, HDA format value */ | 1173 | /* rate in Hz, ALSA rate bitmask, HDA format value */ |
1174 | |||
1175 | /* autodetected value used in snd_hda_query_supported_pcm */ | ||
1160 | { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */ | 1176 | { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */ |
1161 | { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */ | 1177 | { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */ |
1162 | { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */ | 1178 | { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */ |
@@ -1168,7 +1184,11 @@ static unsigned int rate_bits[][3] = { | |||
1168 | { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */ | 1184 | { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */ |
1169 | { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */ | 1185 | { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */ |
1170 | { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */ | 1186 | { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */ |
1171 | { 0 } | 1187 | |
1188 | /* not autodetected value */ | ||
1189 | { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */ | ||
1190 | |||
1191 | { 0 } /* terminator */ | ||
1172 | }; | 1192 | }; |
1173 | 1193 | ||
1174 | /** | 1194 | /** |
@@ -1190,12 +1210,12 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, | |||
1190 | int i; | 1210 | int i; |
1191 | unsigned int val = 0; | 1211 | unsigned int val = 0; |
1192 | 1212 | ||
1193 | for (i = 0; rate_bits[i][0]; i++) | 1213 | for (i = 0; rate_bits[i].hz; i++) |
1194 | if (rate_bits[i][0] == rate) { | 1214 | if (rate_bits[i].hz == rate) { |
1195 | val = rate_bits[i][2]; | 1215 | val = rate_bits[i].hda_fmt; |
1196 | break; | 1216 | break; |
1197 | } | 1217 | } |
1198 | if (! rate_bits[i][0]) { | 1218 | if (! rate_bits[i].hz) { |
1199 | snd_printdd("invalid rate %d\n", rate); | 1219 | snd_printdd("invalid rate %d\n", rate); |
1200 | return 0; | 1220 | return 0; |
1201 | } | 1221 | } |
@@ -1258,9 +1278,9 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | |||
1258 | 1278 | ||
1259 | if (ratesp) { | 1279 | if (ratesp) { |
1260 | u32 rates = 0; | 1280 | u32 rates = 0; |
1261 | for (i = 0; rate_bits[i][0]; i++) { | 1281 | for (i = 0; rate_bits[i].hz; i++) { |
1262 | if (val & (1 << i)) | 1282 | if (val & (1 << i)) |
1263 | rates |= rate_bits[i][1]; | 1283 | rates |= rate_bits[i].alsa_bits; |
1264 | } | 1284 | } |
1265 | *ratesp = rates; | 1285 | *ratesp = rates; |
1266 | } | 1286 | } |
@@ -1352,13 +1372,13 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid, | |||
1352 | } | 1372 | } |
1353 | 1373 | ||
1354 | rate = format & 0xff00; | 1374 | rate = format & 0xff00; |
1355 | for (i = 0; rate_bits[i][0]; i++) | 1375 | for (i = 0; rate_bits[i].hz; i++) |
1356 | if (rate_bits[i][2] == rate) { | 1376 | if (rate_bits[i].hda_fmt == rate) { |
1357 | if (val & (1 << i)) | 1377 | if (val & (1 << i)) |
1358 | break; | 1378 | break; |
1359 | return 0; | 1379 | return 0; |
1360 | } | 1380 | } |
1361 | if (! rate_bits[i][0]) | 1381 | if (! rate_bits[i].hz) |
1362 | return 0; | 1382 | return 0; |
1363 | 1383 | ||
1364 | stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM); | 1384 | stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM); |
@@ -1541,8 +1561,11 @@ int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_c | |||
1541 | for (c = tbl; c->modelname || c->pci_subvendor; c++) { | 1561 | for (c = tbl; c->modelname || c->pci_subvendor; c++) { |
1542 | if (c->pci_subvendor == subsystem_vendor && | 1562 | if (c->pci_subvendor == subsystem_vendor && |
1543 | (! c->pci_subdevice /* all match */|| | 1563 | (! c->pci_subdevice /* all match */|| |
1544 | (c->pci_subdevice == subsystem_device))) | 1564 | (c->pci_subdevice == subsystem_device))) { |
1565 | snd_printdd(KERN_INFO "hda_codec: PCI %x:%x, codec config %d is selected\n", | ||
1566 | subsystem_vendor, subsystem_device, c->config); | ||
1545 | return c->config; | 1567 | return c->config; |
1568 | } | ||
1546 | } | 1569 | } |
1547 | } | 1570 | } |
1548 | return -1; | 1571 | return -1; |
@@ -1803,11 +1826,25 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c | |||
1803 | cfg->line_out_pins[j] = nid; | 1826 | cfg->line_out_pins[j] = nid; |
1804 | } | 1827 | } |
1805 | 1828 | ||
1806 | /* Swap surround and CLFE: the association order is front/CLFE/surr/back */ | 1829 | /* Reorder the surround channels |
1807 | if (cfg->line_outs >= 3) { | 1830 | * ALSA sequence is front/surr/clfe/side |
1831 | * HDA sequence is: | ||
1832 | * 4-ch: front/surr => OK as it is | ||
1833 | * 6-ch: front/clfe/surr | ||
1834 | * 8-ch: front/clfe/side/surr | ||
1835 | */ | ||
1836 | switch (cfg->line_outs) { | ||
1837 | case 3: | ||
1808 | nid = cfg->line_out_pins[1]; | 1838 | nid = cfg->line_out_pins[1]; |
1809 | cfg->line_out_pins[1] = cfg->line_out_pins[2]; | 1839 | cfg->line_out_pins[1] = cfg->line_out_pins[2]; |
1810 | cfg->line_out_pins[2] = nid; | 1840 | cfg->line_out_pins[2] = nid; |
1841 | break; | ||
1842 | case 4: | ||
1843 | nid = cfg->line_out_pins[1]; | ||
1844 | cfg->line_out_pins[1] = cfg->line_out_pins[3]; | ||
1845 | cfg->line_out_pins[3] = cfg->line_out_pins[2]; | ||
1846 | cfg->line_out_pins[2] = nid; | ||
1847 | break; | ||
1811 | } | 1848 | } |
1812 | 1849 | ||
1813 | return 0; | 1850 | return 0; |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index dd0d99d2ad27..63a29a8a2860 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -514,6 +514,7 @@ struct hda_codec { | |||
514 | struct list_head list; /* list point */ | 514 | struct list_head list; /* list point */ |
515 | 515 | ||
516 | hda_nid_t afg; /* AFG node id */ | 516 | hda_nid_t afg; /* AFG node id */ |
517 | hda_nid_t mfg; /* MFG node id */ | ||
517 | 518 | ||
518 | /* ids */ | 519 | /* ids */ |
519 | u32 vendor_id; | 520 | u32 vendor_id; |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 2d046abb5911..1229227af5b5 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -881,6 +881,11 @@ int snd_hda_parse_generic_codec(struct hda_codec *codec) | |||
881 | struct hda_gspec *spec; | 881 | struct hda_gspec *spec; |
882 | int err; | 882 | int err; |
883 | 883 | ||
884 | if(!codec->afg) { | ||
885 | snd_printdd("hda_generic: no generic modem yet\n"); | ||
886 | return -ENODEV; | ||
887 | } | ||
888 | |||
884 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); | 889 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); |
885 | if (spec == NULL) { | 890 | if (spec == NULL) { |
886 | printk(KERN_ERR "hda_generic: can't allocate spec\n"); | 891 | printk(KERN_ERR "hda_generic: can't allocate spec\n"); |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 288ab0764830..15107df1f490 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -71,7 +71,9 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," | |||
71 | "{Intel, ESB2}," | 71 | "{Intel, ESB2}," |
72 | "{ATI, SB450}," | 72 | "{ATI, SB450}," |
73 | "{VIA, VT8251}," | 73 | "{VIA, VT8251}," |
74 | "{VIA, VT8237A}}"); | 74 | "{VIA, VT8237A}," |
75 | "{SiS, SIS966}," | ||
76 | "{ULI, M5461}}"); | ||
75 | MODULE_DESCRIPTION("Intel HDA driver"); | 77 | MODULE_DESCRIPTION("Intel HDA driver"); |
76 | 78 | ||
77 | #define SFX "hda-intel: " | 79 | #define SFX "hda-intel: " |
@@ -141,9 +143,24 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
141 | */ | 143 | */ |
142 | 144 | ||
143 | /* max number of SDs */ | 145 | /* max number of SDs */ |
144 | #define MAX_ICH6_DEV 8 | 146 | /* ICH, ATI and VIA have 4 playback and 4 capture */ |
147 | #define ICH6_CAPTURE_INDEX 0 | ||
148 | #define ICH6_NUM_CAPTURE 4 | ||
149 | #define ICH6_PLAYBACK_INDEX 4 | ||
150 | #define ICH6_NUM_PLAYBACK 4 | ||
151 | |||
152 | /* ULI has 6 playback and 5 capture */ | ||
153 | #define ULI_CAPTURE_INDEX 0 | ||
154 | #define ULI_NUM_CAPTURE 5 | ||
155 | #define ULI_PLAYBACK_INDEX 5 | ||
156 | #define ULI_NUM_PLAYBACK 6 | ||
157 | |||
158 | /* this number is statically defined for simplicity */ | ||
159 | #define MAX_AZX_DEV 16 | ||
160 | |||
145 | /* max number of fragments - we may use more if allocating more pages for BDL */ | 161 | /* max number of fragments - we may use more if allocating more pages for BDL */ |
146 | #define AZX_MAX_FRAG (PAGE_SIZE / (MAX_ICH6_DEV * 16)) | 162 | #define BDL_SIZE PAGE_ALIGN(8192) |
163 | #define AZX_MAX_FRAG (BDL_SIZE / (MAX_AZX_DEV * 16)) | ||
147 | /* max buffer size - no h/w limit, you can increase as you like */ | 164 | /* max buffer size - no h/w limit, you can increase as you like */ |
148 | #define AZX_MAX_BUF_SIZE (1024*1024*1024) | 165 | #define AZX_MAX_BUF_SIZE (1024*1024*1024) |
149 | /* max number of PCM devics per card */ | 166 | /* max number of PCM devics per card */ |
@@ -200,7 +217,6 @@ enum { | |||
200 | }; | 217 | }; |
201 | 218 | ||
202 | /* Defines for ATI HD Audio support in SB450 south bridge */ | 219 | /* Defines for ATI HD Audio support in SB450 south bridge */ |
203 | #define ATI_SB450_HDAUDIO_PCI_DEVICE_ID 0x437b | ||
204 | #define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42 | 220 | #define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42 |
205 | #define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02 | 221 | #define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02 |
206 | 222 | ||
@@ -258,6 +274,14 @@ struct snd_azx { | |||
258 | snd_card_t *card; | 274 | snd_card_t *card; |
259 | struct pci_dev *pci; | 275 | struct pci_dev *pci; |
260 | 276 | ||
277 | /* chip type specific */ | ||
278 | int driver_type; | ||
279 | int playback_streams; | ||
280 | int playback_index_offset; | ||
281 | int capture_streams; | ||
282 | int capture_index_offset; | ||
283 | int num_streams; | ||
284 | |||
261 | /* pci resources */ | 285 | /* pci resources */ |
262 | unsigned long addr; | 286 | unsigned long addr; |
263 | void __iomem *remap_addr; | 287 | void __iomem *remap_addr; |
@@ -267,8 +291,8 @@ struct snd_azx { | |||
267 | spinlock_t reg_lock; | 291 | spinlock_t reg_lock; |
268 | struct semaphore open_mutex; | 292 | struct semaphore open_mutex; |
269 | 293 | ||
270 | /* streams */ | 294 | /* streams (x num_streams) */ |
271 | azx_dev_t azx_dev[MAX_ICH6_DEV]; | 295 | azx_dev_t *azx_dev; |
272 | 296 | ||
273 | /* PCM */ | 297 | /* PCM */ |
274 | unsigned int pcm_devs; | 298 | unsigned int pcm_devs; |
@@ -292,6 +316,23 @@ struct snd_azx { | |||
292 | unsigned int initialized: 1; | 316 | unsigned int initialized: 1; |
293 | }; | 317 | }; |
294 | 318 | ||
319 | /* driver types */ | ||
320 | enum { | ||
321 | AZX_DRIVER_ICH, | ||
322 | AZX_DRIVER_ATI, | ||
323 | AZX_DRIVER_VIA, | ||
324 | AZX_DRIVER_SIS, | ||
325 | AZX_DRIVER_ULI, | ||
326 | }; | ||
327 | |||
328 | static char *driver_short_names[] __devinitdata = { | ||
329 | [AZX_DRIVER_ICH] = "HDA Intel", | ||
330 | [AZX_DRIVER_ATI] = "HDA ATI SB", | ||
331 | [AZX_DRIVER_VIA] = "HDA VIA VT82xx", | ||
332 | [AZX_DRIVER_SIS] = "HDA SIS966", | ||
333 | [AZX_DRIVER_ULI] = "HDA ULI M5461" | ||
334 | }; | ||
335 | |||
295 | /* | 336 | /* |
296 | * macros for easy use | 337 | * macros for easy use |
297 | */ | 338 | */ |
@@ -360,6 +401,8 @@ static void azx_init_cmd_io(azx_t *chip) | |||
360 | azx_writel(chip, CORBLBASE, (u32)chip->corb.addr); | 401 | azx_writel(chip, CORBLBASE, (u32)chip->corb.addr); |
361 | azx_writel(chip, CORBUBASE, upper_32bit(chip->corb.addr)); | 402 | azx_writel(chip, CORBUBASE, upper_32bit(chip->corb.addr)); |
362 | 403 | ||
404 | /* set the corb size to 256 entries (ULI requires explicitly) */ | ||
405 | azx_writeb(chip, CORBSIZE, 0x02); | ||
363 | /* set the corb write pointer to 0 */ | 406 | /* set the corb write pointer to 0 */ |
364 | azx_writew(chip, CORBWP, 0); | 407 | azx_writew(chip, CORBWP, 0); |
365 | /* reset the corb hw read pointer */ | 408 | /* reset the corb hw read pointer */ |
@@ -373,6 +416,8 @@ static void azx_init_cmd_io(azx_t *chip) | |||
373 | azx_writel(chip, RIRBLBASE, (u32)chip->rirb.addr); | 416 | azx_writel(chip, RIRBLBASE, (u32)chip->rirb.addr); |
374 | azx_writel(chip, RIRBUBASE, upper_32bit(chip->rirb.addr)); | 417 | azx_writel(chip, RIRBUBASE, upper_32bit(chip->rirb.addr)); |
375 | 418 | ||
419 | /* set the rirb size to 256 entries (ULI requires explicitly) */ | ||
420 | azx_writeb(chip, RIRBSIZE, 0x02); | ||
376 | /* reset the rirb hw write pointer */ | 421 | /* reset the rirb hw write pointer */ |
377 | azx_writew(chip, RIRBWP, ICH6_RBRWP_CLR); | 422 | azx_writew(chip, RIRBWP, ICH6_RBRWP_CLR); |
378 | /* set N=1, get RIRB response interrupt for new entry */ | 423 | /* set N=1, get RIRB response interrupt for new entry */ |
@@ -596,7 +641,7 @@ static void azx_int_disable(azx_t *chip) | |||
596 | int i; | 641 | int i; |
597 | 642 | ||
598 | /* disable interrupts in stream descriptor */ | 643 | /* disable interrupts in stream descriptor */ |
599 | for (i = 0; i < MAX_ICH6_DEV; i++) { | 644 | for (i = 0; i < chip->num_streams; i++) { |
600 | azx_dev_t *azx_dev = &chip->azx_dev[i]; | 645 | azx_dev_t *azx_dev = &chip->azx_dev[i]; |
601 | azx_sd_writeb(azx_dev, SD_CTL, | 646 | azx_sd_writeb(azx_dev, SD_CTL, |
602 | azx_sd_readb(azx_dev, SD_CTL) & ~SD_INT_MASK); | 647 | azx_sd_readb(azx_dev, SD_CTL) & ~SD_INT_MASK); |
@@ -616,7 +661,7 @@ static void azx_int_clear(azx_t *chip) | |||
616 | int i; | 661 | int i; |
617 | 662 | ||
618 | /* clear stream status */ | 663 | /* clear stream status */ |
619 | for (i = 0; i < MAX_ICH6_DEV; i++) { | 664 | for (i = 0; i < chip->num_streams; i++) { |
620 | azx_dev_t *azx_dev = &chip->azx_dev[i]; | 665 | azx_dev_t *azx_dev = &chip->azx_dev[i]; |
621 | azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); | 666 | azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); |
622 | } | 667 | } |
@@ -686,8 +731,7 @@ static void azx_init_chip(azx_t *chip) | |||
686 | } | 731 | } |
687 | 732 | ||
688 | /* For ATI SB450 azalia HD audio, we need to enable snoop */ | 733 | /* For ATI SB450 azalia HD audio, we need to enable snoop */ |
689 | if (chip->pci->vendor == PCI_VENDOR_ID_ATI && | 734 | if (chip->driver_type == AZX_DRIVER_ATI) { |
690 | chip->pci->device == ATI_SB450_HDAUDIO_PCI_DEVICE_ID) { | ||
691 | pci_read_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, | 735 | pci_read_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, |
692 | &ati_misc_cntl2); | 736 | &ati_misc_cntl2); |
693 | pci_write_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, | 737 | pci_write_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, |
@@ -714,7 +758,7 @@ static irqreturn_t azx_interrupt(int irq, void* dev_id, struct pt_regs *regs) | |||
714 | return IRQ_NONE; | 758 | return IRQ_NONE; |
715 | } | 759 | } |
716 | 760 | ||
717 | for (i = 0; i < MAX_ICH6_DEV; i++) { | 761 | for (i = 0; i < chip->num_streams; i++) { |
718 | azx_dev = &chip->azx_dev[i]; | 762 | azx_dev = &chip->azx_dev[i]; |
719 | if (status & azx_dev->sd_int_sta_mask) { | 763 | if (status & azx_dev->sd_int_sta_mask) { |
720 | azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); | 764 | azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); |
@@ -879,9 +923,15 @@ static int __devinit azx_codec_create(azx_t *chip, const char *model) | |||
879 | /* assign a stream for the PCM */ | 923 | /* assign a stream for the PCM */ |
880 | static inline azx_dev_t *azx_assign_device(azx_t *chip, int stream) | 924 | static inline azx_dev_t *azx_assign_device(azx_t *chip, int stream) |
881 | { | 925 | { |
882 | int dev, i; | 926 | int dev, i, nums; |
883 | dev = stream == SNDRV_PCM_STREAM_PLAYBACK ? 4 : 0; | 927 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
884 | for (i = 0; i < 4; i++, dev++) | 928 | dev = chip->playback_index_offset; |
929 | nums = chip->playback_streams; | ||
930 | } else { | ||
931 | dev = chip->capture_index_offset; | ||
932 | nums = chip->capture_streams; | ||
933 | } | ||
934 | for (i = 0; i < nums; i++, dev++) | ||
885 | if (! chip->azx_dev[dev].opened) { | 935 | if (! chip->azx_dev[dev].opened) { |
886 | chip->azx_dev[dev].opened = 1; | 936 | chip->azx_dev[dev].opened = 1; |
887 | return &chip->azx_dev[dev]; | 937 | return &chip->azx_dev[dev]; |
@@ -899,8 +949,8 @@ static snd_pcm_hardware_t azx_pcm_hw = { | |||
899 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | | 949 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | |
900 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 950 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
901 | SNDRV_PCM_INFO_MMAP_VALID | | 951 | SNDRV_PCM_INFO_MMAP_VALID | |
902 | SNDRV_PCM_INFO_PAUSE | | 952 | SNDRV_PCM_INFO_PAUSE /*|*/ |
903 | SNDRV_PCM_INFO_RESUME), | 953 | /*SNDRV_PCM_INFO_RESUME*/), |
904 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 954 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
905 | .rates = SNDRV_PCM_RATE_48000, | 955 | .rates = SNDRV_PCM_RATE_48000, |
906 | .rate_min = 48000, | 956 | .rate_min = 48000, |
@@ -1049,6 +1099,7 @@ static int azx_pcm_trigger(snd_pcm_substream_t *substream, int cmd) | |||
1049 | azx_dev->running = 1; | 1099 | azx_dev->running = 1; |
1050 | break; | 1100 | break; |
1051 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 1101 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
1102 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
1052 | case SNDRV_PCM_TRIGGER_STOP: | 1103 | case SNDRV_PCM_TRIGGER_STOP: |
1053 | azx_stream_stop(chip, azx_dev); | 1104 | azx_stream_stop(chip, azx_dev); |
1054 | azx_dev->running = 0; | 1105 | azx_dev->running = 0; |
@@ -1058,6 +1109,7 @@ static int azx_pcm_trigger(snd_pcm_substream_t *substream, int cmd) | |||
1058 | } | 1109 | } |
1059 | spin_unlock(&chip->reg_lock); | 1110 | spin_unlock(&chip->reg_lock); |
1060 | if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH || | 1111 | if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH || |
1112 | cmd == SNDRV_PCM_TRIGGER_SUSPEND || | ||
1061 | cmd == SNDRV_PCM_TRIGGER_STOP) { | 1113 | cmd == SNDRV_PCM_TRIGGER_STOP) { |
1062 | int timeout = 5000; | 1114 | int timeout = 5000; |
1063 | while (azx_sd_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START && --timeout) | 1115 | while (azx_sd_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START && --timeout) |
@@ -1136,6 +1188,7 @@ static int __devinit create_codec_pcm(azx_t *chip, struct hda_codec *codec, | |||
1136 | snd_dma_pci_data(chip->pci), | 1188 | snd_dma_pci_data(chip->pci), |
1137 | 1024 * 64, 1024 * 128); | 1189 | 1024 * 64, 1024 * 128); |
1138 | chip->pcm[pcm_dev] = pcm; | 1190 | chip->pcm[pcm_dev] = pcm; |
1191 | chip->pcm_devs = pcm_dev + 1; | ||
1139 | 1192 | ||
1140 | return 0; | 1193 | return 0; |
1141 | } | 1194 | } |
@@ -1186,7 +1239,7 @@ static int __devinit azx_init_stream(azx_t *chip) | |||
1186 | /* initialize each stream (aka device) | 1239 | /* initialize each stream (aka device) |
1187 | * assign the starting bdl address to each stream (device) and initialize | 1240 | * assign the starting bdl address to each stream (device) and initialize |
1188 | */ | 1241 | */ |
1189 | for (i = 0; i < MAX_ICH6_DEV; i++) { | 1242 | for (i = 0; i < chip->num_streams; i++) { |
1190 | unsigned int off = sizeof(u32) * (i * AZX_MAX_FRAG * 4); | 1243 | unsigned int off = sizeof(u32) * (i * AZX_MAX_FRAG * 4); |
1191 | azx_dev_t *azx_dev = &chip->azx_dev[i]; | 1244 | azx_dev_t *azx_dev = &chip->azx_dev[i]; |
1192 | azx_dev->bdl = (u32 *)(chip->bdl.area + off); | 1245 | azx_dev->bdl = (u32 *)(chip->bdl.area + off); |
@@ -1245,7 +1298,7 @@ static int azx_free(azx_t *chip) | |||
1245 | if (chip->initialized) { | 1298 | if (chip->initialized) { |
1246 | int i; | 1299 | int i; |
1247 | 1300 | ||
1248 | for (i = 0; i < MAX_ICH6_DEV; i++) | 1301 | for (i = 0; i < chip->num_streams; i++) |
1249 | azx_stream_stop(chip, &chip->azx_dev[i]); | 1302 | azx_stream_stop(chip, &chip->azx_dev[i]); |
1250 | 1303 | ||
1251 | /* disable interrupts */ | 1304 | /* disable interrupts */ |
@@ -1261,10 +1314,10 @@ static int azx_free(azx_t *chip) | |||
1261 | 1314 | ||
1262 | /* wait a little for interrupts to finish */ | 1315 | /* wait a little for interrupts to finish */ |
1263 | msleep(1); | 1316 | msleep(1); |
1264 | |||
1265 | iounmap(chip->remap_addr); | ||
1266 | } | 1317 | } |
1267 | 1318 | ||
1319 | if (chip->remap_addr) | ||
1320 | iounmap(chip->remap_addr); | ||
1268 | if (chip->irq >= 0) | 1321 | if (chip->irq >= 0) |
1269 | free_irq(chip->irq, (void*)chip); | 1322 | free_irq(chip->irq, (void*)chip); |
1270 | 1323 | ||
@@ -1276,6 +1329,7 @@ static int azx_free(azx_t *chip) | |||
1276 | snd_dma_free_pages(&chip->posbuf); | 1329 | snd_dma_free_pages(&chip->posbuf); |
1277 | pci_release_regions(chip->pci); | 1330 | pci_release_regions(chip->pci); |
1278 | pci_disable_device(chip->pci); | 1331 | pci_disable_device(chip->pci); |
1332 | kfree(chip->azx_dev); | ||
1279 | kfree(chip); | 1333 | kfree(chip); |
1280 | 1334 | ||
1281 | return 0; | 1335 | return 0; |
@@ -1290,7 +1344,8 @@ static int azx_dev_free(snd_device_t *device) | |||
1290 | * constructor | 1344 | * constructor |
1291 | */ | 1345 | */ |
1292 | static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, | 1346 | static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, |
1293 | int posfix, azx_t **rchip) | 1347 | int posfix, int driver_type, |
1348 | azx_t **rchip) | ||
1294 | { | 1349 | { |
1295 | azx_t *chip; | 1350 | azx_t *chip; |
1296 | int err = 0; | 1351 | int err = 0; |
@@ -1316,9 +1371,20 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, | |||
1316 | chip->card = card; | 1371 | chip->card = card; |
1317 | chip->pci = pci; | 1372 | chip->pci = pci; |
1318 | chip->irq = -1; | 1373 | chip->irq = -1; |
1374 | chip->driver_type = driver_type; | ||
1319 | 1375 | ||
1320 | chip->position_fix = posfix; | 1376 | chip->position_fix = posfix; |
1321 | 1377 | ||
1378 | #if BITS_PER_LONG != 64 | ||
1379 | /* Fix up base address on ULI M5461 */ | ||
1380 | if (chip->driver_type == AZX_DRIVER_ULI) { | ||
1381 | u16 tmp3; | ||
1382 | pci_read_config_word(pci, 0x40, &tmp3); | ||
1383 | pci_write_config_word(pci, 0x40, tmp3 | 0x10); | ||
1384 | pci_write_config_dword(pci, PCI_BASE_ADDRESS_1, 0); | ||
1385 | } | ||
1386 | #endif | ||
1387 | |||
1322 | if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) { | 1388 | if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) { |
1323 | kfree(chip); | 1389 | kfree(chip); |
1324 | pci_disable_device(pci); | 1390 | pci_disable_device(pci); |
@@ -1344,16 +1410,37 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, | |||
1344 | pci_set_master(pci); | 1410 | pci_set_master(pci); |
1345 | synchronize_irq(chip->irq); | 1411 | synchronize_irq(chip->irq); |
1346 | 1412 | ||
1413 | switch (chip->driver_type) { | ||
1414 | case AZX_DRIVER_ULI: | ||
1415 | chip->playback_streams = ULI_NUM_PLAYBACK; | ||
1416 | chip->capture_streams = ULI_NUM_CAPTURE; | ||
1417 | chip->playback_index_offset = ULI_PLAYBACK_INDEX; | ||
1418 | chip->capture_index_offset = ULI_CAPTURE_INDEX; | ||
1419 | break; | ||
1420 | default: | ||
1421 | chip->playback_streams = ICH6_NUM_PLAYBACK; | ||
1422 | chip->capture_streams = ICH6_NUM_CAPTURE; | ||
1423 | chip->playback_index_offset = ICH6_PLAYBACK_INDEX; | ||
1424 | chip->capture_index_offset = ICH6_CAPTURE_INDEX; | ||
1425 | break; | ||
1426 | } | ||
1427 | chip->num_streams = chip->playback_streams + chip->capture_streams; | ||
1428 | chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev), GFP_KERNEL); | ||
1429 | if (! chip->azx_dev) { | ||
1430 | snd_printk(KERN_ERR "cannot malloc azx_dev\n"); | ||
1431 | goto errout; | ||
1432 | } | ||
1433 | |||
1347 | /* allocate memory for the BDL for each stream */ | 1434 | /* allocate memory for the BDL for each stream */ |
1348 | if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), | 1435 | if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), |
1349 | PAGE_SIZE, &chip->bdl)) < 0) { | 1436 | BDL_SIZE, &chip->bdl)) < 0) { |
1350 | snd_printk(KERN_ERR SFX "cannot allocate BDL\n"); | 1437 | snd_printk(KERN_ERR SFX "cannot allocate BDL\n"); |
1351 | goto errout; | 1438 | goto errout; |
1352 | } | 1439 | } |
1353 | if (chip->position_fix == POS_FIX_POSBUF) { | 1440 | if (chip->position_fix == POS_FIX_POSBUF) { |
1354 | /* allocate memory for the position buffer */ | 1441 | /* allocate memory for the position buffer */ |
1355 | if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), | 1442 | if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), |
1356 | MAX_ICH6_DEV * 8, &chip->posbuf)) < 0) { | 1443 | chip->num_streams * 8, &chip->posbuf)) < 0) { |
1357 | snd_printk(KERN_ERR SFX "cannot allocate posbuf\n"); | 1444 | snd_printk(KERN_ERR SFX "cannot allocate posbuf\n"); |
1358 | goto errout; | 1445 | goto errout; |
1359 | } | 1446 | } |
@@ -1382,6 +1469,10 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, | |||
1382 | goto errout; | 1469 | goto errout; |
1383 | } | 1470 | } |
1384 | 1471 | ||
1472 | strcpy(card->driver, "HDA-Intel"); | ||
1473 | strcpy(card->shortname, driver_short_names[chip->driver_type]); | ||
1474 | sprintf(card->longname, "%s at 0x%lx irq %i", card->shortname, chip->addr, chip->irq); | ||
1475 | |||
1385 | *rchip = chip; | 1476 | *rchip = chip; |
1386 | return 0; | 1477 | return 0; |
1387 | 1478 | ||
@@ -1410,15 +1501,12 @@ static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id * | |||
1410 | return -ENOMEM; | 1501 | return -ENOMEM; |
1411 | } | 1502 | } |
1412 | 1503 | ||
1413 | if ((err = azx_create(card, pci, position_fix[dev], &chip)) < 0) { | 1504 | if ((err = azx_create(card, pci, position_fix[dev], pci_id->driver_data, |
1505 | &chip)) < 0) { | ||
1414 | snd_card_free(card); | 1506 | snd_card_free(card); |
1415 | return err; | 1507 | return err; |
1416 | } | 1508 | } |
1417 | 1509 | ||
1418 | strcpy(card->driver, "HDA-Intel"); | ||
1419 | strcpy(card->shortname, "HDA Intel"); | ||
1420 | sprintf(card->longname, "%s at 0x%lx irq %i", card->shortname, chip->addr, chip->irq); | ||
1421 | |||
1422 | /* create codec instances */ | 1510 | /* create codec instances */ |
1423 | if ((err = azx_codec_create(chip, model[dev])) < 0) { | 1511 | if ((err = azx_codec_create(chip, model[dev])) < 0) { |
1424 | snd_card_free(card); | 1512 | snd_card_free(card); |
@@ -1459,12 +1547,13 @@ static void __devexit azx_remove(struct pci_dev *pci) | |||
1459 | 1547 | ||
1460 | /* PCI IDs */ | 1548 | /* PCI IDs */ |
1461 | static struct pci_device_id azx_ids[] = { | 1549 | static struct pci_device_id azx_ids[] = { |
1462 | { 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH6 */ | 1550 | { 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH6 */ |
1463 | { 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH7 */ | 1551 | { 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH7 */ |
1464 | { 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ESB2 */ | 1552 | { 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ESB2 */ |
1465 | { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ATI SB450 */ | 1553 | { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */ |
1466 | { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* VIA VT8251/VT8237A */ | 1554 | { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */ |
1467 | { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ALI 5461? */ | 1555 | { 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */ |
1556 | { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */ | ||
1468 | { 0, } | 1557 | { 0, } |
1469 | }; | 1558 | }; |
1470 | MODULE_DEVICE_TABLE(pci, azx_ids); | 1559 | MODULE_DEVICE_TABLE(pci, azx_ids); |
diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h index a5de684b6944..acaef3c811b8 100644 --- a/sound/pci/hda/hda_patch.h +++ b/sound/pci/hda/hda_patch.h | |||
@@ -10,11 +10,14 @@ extern struct hda_codec_preset snd_hda_preset_cmedia[]; | |||
10 | extern struct hda_codec_preset snd_hda_preset_analog[]; | 10 | extern struct hda_codec_preset snd_hda_preset_analog[]; |
11 | /* SigmaTel codecs */ | 11 | /* SigmaTel codecs */ |
12 | extern struct hda_codec_preset snd_hda_preset_sigmatel[]; | 12 | extern struct hda_codec_preset snd_hda_preset_sigmatel[]; |
13 | /* SiLabs 3054/3055 modem codecs */ | ||
14 | extern struct hda_codec_preset snd_hda_preset_si3054[]; | ||
13 | 15 | ||
14 | static const struct hda_codec_preset *hda_preset_tables[] = { | 16 | static const struct hda_codec_preset *hda_preset_tables[] = { |
15 | snd_hda_preset_realtek, | 17 | snd_hda_preset_realtek, |
16 | snd_hda_preset_cmedia, | 18 | snd_hda_preset_cmedia, |
17 | snd_hda_preset_analog, | 19 | snd_hda_preset_analog, |
18 | snd_hda_preset_sigmatel, | 20 | snd_hda_preset_sigmatel, |
21 | snd_hda_preset_si3054, | ||
19 | NULL | 22 | NULL |
20 | }; | 23 | }; |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 2fd05bb84136..bceb83a42a38 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -572,7 +572,7 @@ static snd_kcontrol_new_t ad1983_mixers[] = { | |||
572 | }, | 572 | }, |
573 | { | 573 | { |
574 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 574 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
575 | .name = "IEC958 Playback Route", | 575 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route", |
576 | .info = ad1983_spdif_route_info, | 576 | .info = ad1983_spdif_route_info, |
577 | .get = ad1983_spdif_route_get, | 577 | .get = ad1983_spdif_route_get, |
578 | .put = ad1983_spdif_route_put, | 578 | .put = ad1983_spdif_route_put, |
@@ -705,7 +705,7 @@ static snd_kcontrol_new_t ad1981_mixers[] = { | |||
705 | /* identical with AD1983 */ | 705 | /* identical with AD1983 */ |
706 | { | 706 | { |
707 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 707 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
708 | .name = "IEC958 Playback Route", | 708 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route", |
709 | .info = ad1983_spdif_route_info, | 709 | .info = ad1983_spdif_route_info, |
710 | .get = ad1983_spdif_route_get, | 710 | .get = ad1983_spdif_route_get, |
711 | .put = ad1983_spdif_route_put, | 711 | .put = ad1983_spdif_route_put, |
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c index 86f195f19eef..07fb4f5a54b3 100644 --- a/sound/pci/hda/patch_cmedia.c +++ b/sound/pci/hda/patch_cmedia.c | |||
@@ -647,6 +647,7 @@ static struct hda_board_config cmi9880_cfg_tbl[] = { | |||
647 | { .modelname = "min_fp", .config = CMI_MIN_FP }, | 647 | { .modelname = "min_fp", .config = CMI_MIN_FP }, |
648 | { .modelname = "full", .config = CMI_FULL }, | 648 | { .modelname = "full", .config = CMI_FULL }, |
649 | { .modelname = "full_dig", .config = CMI_FULL_DIG }, | 649 | { .modelname = "full_dig", .config = CMI_FULL_DIG }, |
650 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x813d, .config = CMI_FULL_DIG }, /* ASUS P5AD2 */ | ||
650 | { .modelname = "allout", .config = CMI_ALLOUT }, | 651 | { .modelname = "allout", .config = CMI_ALLOUT }, |
651 | { .modelname = "auto", .config = CMI_AUTO }, | 652 | { .modelname = "auto", .config = CMI_AUTO }, |
652 | {} /* terminator */ | 653 | {} /* terminator */ |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 9b8569900787..eeb900ab79af 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -687,6 +687,12 @@ static snd_kcontrol_new_t alc880_asus_w1v_mixer[] = { | |||
687 | { } /* end */ | 687 | { } /* end */ |
688 | }; | 688 | }; |
689 | 689 | ||
690 | /* additional mixers to alc880_asus_mixer */ | ||
691 | static snd_kcontrol_new_t alc880_pcbeep_mixer[] = { | ||
692 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
693 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
694 | { } /* end */ | ||
695 | }; | ||
690 | 696 | ||
691 | /* | 697 | /* |
692 | * build control elements | 698 | * build control elements |
@@ -1524,6 +1530,7 @@ static struct hda_board_config alc880_cfg_tbl[] = { | |||
1524 | /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */ | 1530 | /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */ |
1525 | { .modelname = "3stack-digout", .config = ALC880_3ST_DIG }, | 1531 | { .modelname = "3stack-digout", .config = ALC880_3ST_DIG }, |
1526 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG }, | 1532 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG }, |
1533 | { .pci_subvendor = 0x1025, .pci_subdevice = 0x0070, .config = ALC880_3ST_DIG }, | ||
1527 | 1534 | ||
1528 | /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/ | 1535 | /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/ |
1529 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG }, | 1536 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG }, |
@@ -1734,7 +1741,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
1734 | .input_mux = &alc880_capture_source, | 1741 | .input_mux = &alc880_capture_source, |
1735 | }, | 1742 | }, |
1736 | [ALC880_UNIWILL_DIG] = { | 1743 | [ALC880_UNIWILL_DIG] = { |
1737 | .mixers = { alc880_asus_mixer }, | 1744 | .mixers = { alc880_asus_mixer, alc880_pcbeep_mixer }, |
1738 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs }, | 1745 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs }, |
1739 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | 1746 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), |
1740 | .dac_nids = alc880_asus_dac_nids, | 1747 | .dac_nids = alc880_asus_dac_nids, |
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c new file mode 100644 index 000000000000..b0270d1b64ce --- /dev/null +++ b/sound/pci/hda/patch_si3054.c | |||
@@ -0,0 +1,300 @@ | |||
1 | /* | ||
2 | * Universal Interface for Intel High Definition Audio Codec | ||
3 | * | ||
4 | * HD audio interface patch for Silicon Labs 3054/5 modem codec | ||
5 | * | ||
6 | * Copyright (c) 2005 Sasha Khapyorsky <sashak@smlink.com> | ||
7 | * Takashi Iwai <tiwai@suse.de> | ||
8 | * | ||
9 | * | ||
10 | * This driver is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This driver is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | */ | ||
24 | |||
25 | #include <sound/driver.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/pci.h> | ||
30 | #include <sound/core.h> | ||
31 | #include "hda_codec.h" | ||
32 | #include "hda_local.h" | ||
33 | |||
34 | |||
35 | /* si3054 verbs */ | ||
36 | #define SI3054_VERB_READ_NODE 0x900 | ||
37 | #define SI3054_VERB_WRITE_NODE 0x100 | ||
38 | |||
39 | /* si3054 nodes (registers) */ | ||
40 | #define SI3054_EXTENDED_MID 2 | ||
41 | #define SI3054_LINE_RATE 3 | ||
42 | #define SI3054_LINE_LEVEL 4 | ||
43 | #define SI3054_GPIO_CFG 5 | ||
44 | #define SI3054_GPIO_POLARITY 6 | ||
45 | #define SI3054_GPIO_STICKY 7 | ||
46 | #define SI3054_GPIO_WAKEUP 8 | ||
47 | #define SI3054_GPIO_STATUS 9 | ||
48 | #define SI3054_GPIO_CONTROL 10 | ||
49 | #define SI3054_MISC_AFE 11 | ||
50 | #define SI3054_CHIPID 12 | ||
51 | #define SI3054_LINE_CFG1 13 | ||
52 | #define SI3054_LINE_STATUS 14 | ||
53 | #define SI3054_DC_TERMINATION 15 | ||
54 | #define SI3054_LINE_CONFIG 16 | ||
55 | #define SI3054_CALLPROG_ATT 17 | ||
56 | #define SI3054_SQ_CONTROL 18 | ||
57 | #define SI3054_MISC_CONTROL 19 | ||
58 | #define SI3054_RING_CTRL1 20 | ||
59 | #define SI3054_RING_CTRL2 21 | ||
60 | |||
61 | /* extended MID */ | ||
62 | #define SI3054_MEI_READY 0xf | ||
63 | |||
64 | /* line level */ | ||
65 | #define SI3054_ATAG_MASK 0x00f0 | ||
66 | #define SI3054_DTAG_MASK 0xf000 | ||
67 | |||
68 | /* GPIO bits */ | ||
69 | #define SI3054_GPIO_OH 0x0001 | ||
70 | #define SI3054_GPIO_CID 0x0002 | ||
71 | |||
72 | /* chipid and revisions */ | ||
73 | #define SI3054_CHIPID_CODEC_REV_MASK 0x000f | ||
74 | #define SI3054_CHIPID_DAA_REV_MASK 0x00f0 | ||
75 | #define SI3054_CHIPID_INTERNATIONAL 0x0100 | ||
76 | #define SI3054_CHIPID_DAA_ID 0x0f00 | ||
77 | #define SI3054_CHIPID_CODEC_ID (1<<12) | ||
78 | |||
79 | /* si3054 codec registers (nodes) access macros */ | ||
80 | #define GET_REG(codec,reg) (snd_hda_codec_read(codec,reg,0,SI3054_VERB_READ_NODE,0)) | ||
81 | #define SET_REG(codec,reg,val) (snd_hda_codec_write(codec,reg,0,SI3054_VERB_WRITE_NODE,val)) | ||
82 | |||
83 | |||
84 | struct si3054_spec { | ||
85 | unsigned international; | ||
86 | struct hda_pcm pcm; | ||
87 | }; | ||
88 | |||
89 | |||
90 | /* | ||
91 | * Modem mixer | ||
92 | */ | ||
93 | |||
94 | #define PRIVATE_VALUE(reg,mask) ((reg<<16)|(mask&0xffff)) | ||
95 | #define PRIVATE_REG(val) ((val>>16)&0xffff) | ||
96 | #define PRIVATE_MASK(val) (val&0xffff) | ||
97 | |||
98 | static int si3054_switch_info(snd_kcontrol_t *kcontrol, | ||
99 | snd_ctl_elem_info_t *uinfo) | ||
100 | { | ||
101 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
102 | uinfo->count = 1; | ||
103 | uinfo->value.integer.min = 0; | ||
104 | uinfo->value.integer.max = 1; | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static int si3054_switch_get(snd_kcontrol_t *kcontrol, | ||
109 | snd_ctl_elem_value_t *uvalue) | ||
110 | { | ||
111 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
112 | u16 reg = PRIVATE_REG(kcontrol->private_value); | ||
113 | u16 mask = PRIVATE_MASK(kcontrol->private_value); | ||
114 | uvalue->value.integer.value[0] = (GET_REG(codec, reg)) & mask ? 1 : 0 ; | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static int si3054_switch_put(snd_kcontrol_t *kcontrol, | ||
119 | snd_ctl_elem_value_t *uvalue) | ||
120 | { | ||
121 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
122 | u16 reg = PRIVATE_REG(kcontrol->private_value); | ||
123 | u16 mask = PRIVATE_MASK(kcontrol->private_value); | ||
124 | if (uvalue->value.integer.value[0]) | ||
125 | SET_REG(codec, reg, (GET_REG(codec, reg)) | mask); | ||
126 | else | ||
127 | SET_REG(codec, reg, (GET_REG(codec, reg)) & ~mask); | ||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | #define SI3054_KCONTROL(kname,reg,mask) { \ | ||
132 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
133 | .name = kname, \ | ||
134 | .info = si3054_switch_info, \ | ||
135 | .get = si3054_switch_get, \ | ||
136 | .put = si3054_switch_put, \ | ||
137 | .private_value = PRIVATE_VALUE(reg,mask), \ | ||
138 | } | ||
139 | |||
140 | |||
141 | static snd_kcontrol_new_t si3054_modem_mixer[] = { | ||
142 | SI3054_KCONTROL("Off-hook Switch", SI3054_GPIO_CONTROL, SI3054_GPIO_OH), | ||
143 | SI3054_KCONTROL("Caller ID Switch", SI3054_GPIO_CONTROL, SI3054_GPIO_CID), | ||
144 | {} | ||
145 | }; | ||
146 | |||
147 | static int si3054_build_controls(struct hda_codec *codec) | ||
148 | { | ||
149 | return snd_hda_add_new_ctls(codec, si3054_modem_mixer); | ||
150 | } | ||
151 | |||
152 | |||
153 | /* | ||
154 | * PCM callbacks | ||
155 | */ | ||
156 | |||
157 | static int si3054_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
158 | struct hda_codec *codec, | ||
159 | unsigned int stream_tag, | ||
160 | unsigned int format, | ||
161 | snd_pcm_substream_t *substream) | ||
162 | { | ||
163 | u16 val; | ||
164 | |||
165 | SET_REG(codec, SI3054_LINE_RATE, substream->runtime->rate); | ||
166 | val = GET_REG(codec, SI3054_LINE_LEVEL); | ||
167 | val &= 0xff << (8 * (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)); | ||
168 | val |= ((stream_tag & 0xf) << 4) << (8 * (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)); | ||
169 | SET_REG(codec, SI3054_LINE_LEVEL, val); | ||
170 | |||
171 | snd_hda_codec_setup_stream(codec, hinfo->nid, | ||
172 | stream_tag, 0, format); | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static int si3054_pcm_open(struct hda_pcm_stream *hinfo, | ||
177 | struct hda_codec *codec, | ||
178 | snd_pcm_substream_t *substream) | ||
179 | { | ||
180 | static unsigned int rates[] = { 8000, 9600, 16000 }; | ||
181 | static snd_pcm_hw_constraint_list_t hw_constraints_rates = { | ||
182 | .count = ARRAY_SIZE(rates), | ||
183 | .list = rates, | ||
184 | .mask = 0, | ||
185 | }; | ||
186 | substream->runtime->hw.period_bytes_min = 80; | ||
187 | return snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
188 | SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates); | ||
189 | } | ||
190 | |||
191 | |||
192 | static struct hda_pcm_stream si3054_pcm = { | ||
193 | .substreams = 1, | ||
194 | .channels_min = 1, | ||
195 | .channels_max = 1, | ||
196 | .nid = 0x1, | ||
197 | .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_KNOT, | ||
198 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
199 | .maxbps = 16, | ||
200 | .ops = { | ||
201 | .open = si3054_pcm_open, | ||
202 | .prepare = si3054_pcm_prepare, | ||
203 | }, | ||
204 | }; | ||
205 | |||
206 | |||
207 | static int si3054_build_pcms(struct hda_codec *codec) | ||
208 | { | ||
209 | struct si3054_spec *spec = codec->spec; | ||
210 | struct hda_pcm *info = &spec->pcm; | ||
211 | si3054_pcm.nid = codec->mfg; | ||
212 | codec->num_pcms = 1; | ||
213 | codec->pcm_info = info; | ||
214 | info->name = "Si3054 Modem"; | ||
215 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = si3054_pcm; | ||
216 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = si3054_pcm; | ||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | |||
221 | /* | ||
222 | * Init part | ||
223 | */ | ||
224 | |||
225 | static int si3054_init(struct hda_codec *codec) | ||
226 | { | ||
227 | struct si3054_spec *spec = codec->spec; | ||
228 | unsigned wait_count; | ||
229 | u16 val; | ||
230 | |||
231 | snd_hda_codec_write(codec, AC_NODE_ROOT, 0, AC_VERB_SET_CODEC_RESET, 0); | ||
232 | snd_hda_codec_write(codec, codec->mfg, 0, AC_VERB_SET_STREAM_FORMAT, 0); | ||
233 | SET_REG(codec, SI3054_LINE_RATE, 9600); | ||
234 | SET_REG(codec, SI3054_LINE_LEVEL, SI3054_DTAG_MASK|SI3054_ATAG_MASK); | ||
235 | SET_REG(codec, SI3054_EXTENDED_MID, 0); | ||
236 | |||
237 | wait_count = 10; | ||
238 | do { | ||
239 | msleep(2); | ||
240 | val = GET_REG(codec, SI3054_EXTENDED_MID); | ||
241 | } while ((val & SI3054_MEI_READY) != SI3054_MEI_READY && wait_count--); | ||
242 | |||
243 | if((val&SI3054_MEI_READY) != SI3054_MEI_READY) { | ||
244 | snd_printk(KERN_ERR "si3054: cannot initialize. EXT MID = %04x\n", val); | ||
245 | return -EACCES; | ||
246 | } | ||
247 | |||
248 | SET_REG(codec, SI3054_GPIO_POLARITY, 0xffff); | ||
249 | SET_REG(codec, SI3054_GPIO_CFG, 0x0); | ||
250 | SET_REG(codec, SI3054_MISC_AFE, 0); | ||
251 | SET_REG(codec, SI3054_LINE_CFG1,0x200); | ||
252 | |||
253 | if((GET_REG(codec,SI3054_LINE_STATUS) & (1<<6)) == 0) { | ||
254 | snd_printd("Link Frame Detect(FDT) is not ready (line status: %04x)\n", | ||
255 | GET_REG(codec,SI3054_LINE_STATUS)); | ||
256 | } | ||
257 | |||
258 | spec->international = GET_REG(codec, SI3054_CHIPID) & SI3054_CHIPID_INTERNATIONAL; | ||
259 | |||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | static void si3054_free(struct hda_codec *codec) | ||
264 | { | ||
265 | kfree(codec->spec); | ||
266 | } | ||
267 | |||
268 | |||
269 | /* | ||
270 | */ | ||
271 | |||
272 | static struct hda_codec_ops si3054_patch_ops = { | ||
273 | .build_controls = si3054_build_controls, | ||
274 | .build_pcms = si3054_build_pcms, | ||
275 | .init = si3054_init, | ||
276 | .free = si3054_free, | ||
277 | #ifdef CONFIG_PM | ||
278 | //.suspend = si3054_suspend, | ||
279 | .resume = si3054_init, | ||
280 | #endif | ||
281 | }; | ||
282 | |||
283 | static int patch_si3054(struct hda_codec *codec) | ||
284 | { | ||
285 | struct si3054_spec *spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); | ||
286 | if (spec == NULL) | ||
287 | return -ENOMEM; | ||
288 | codec->spec = spec; | ||
289 | codec->patch_ops = si3054_patch_ops; | ||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | /* | ||
294 | * patch entries | ||
295 | */ | ||
296 | struct hda_codec_preset snd_hda_preset_si3054[] = { | ||
297 | { .id = 0x163c3155, .name = "Si3054", .patch = patch_si3054 }, | ||
298 | {} | ||
299 | }; | ||
300 | |||