aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/pci/maestro3.c127
1 files changed, 106 insertions, 21 deletions
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 3690ea05b042..096f15132853 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -779,6 +779,12 @@ struct m3_quirk {
779 (e.g. for IrDA on Dell Inspirons) */ 779 (e.g. for IrDA on Dell Inspirons) */
780}; 780};
781 781
782struct m3_hv_quirk {
783 u16 vendor, device, subsystem_vendor, subsystem_device;
784 u32 config; /* ALLEGRO_CONFIG hardware volume bits */
785 int is_omnibook; /* Do HP OmniBook GPIO magic? */
786};
787
782struct m3_list { 788struct m3_list {
783 int curlen; 789 int curlen;
784 int mem_addr; 790 int mem_addr;
@@ -828,6 +834,7 @@ struct snd_m3 {
828 834
829 struct pci_dev *pci; 835 struct pci_dev *pci;
830 struct m3_quirk *quirk; 836 struct m3_quirk *quirk;
837 struct m3_hv_quirk *hv_quirk;
831 838
832 int dacs_active; 839 int dacs_active;
833 int timer_users; 840 int timer_users;
@@ -856,7 +863,7 @@ struct snd_m3 {
856 snd_kcontrol_t *master_switch; 863 snd_kcontrol_t *master_switch;
857 snd_kcontrol_t *master_volume; 864 snd_kcontrol_t *master_volume;
858 struct tasklet_struct hwvol_tq; 865 struct tasklet_struct hwvol_tq;
859 866
860#ifdef CONFIG_PM 867#ifdef CONFIG_PM
861 u16 *suspend_mem; 868 u16 *suspend_mem;
862#endif 869#endif
@@ -973,6 +980,71 @@ static struct m3_quirk m3_quirk_list[] = {
973 { NULL } 980 { NULL }
974}; 981};
975 982
983/* These values came from the Windows driver. */
984static struct m3_hv_quirk m3_hv_quirk_list[] = {
985 /* Allegro chips */
986 { 0x125D, 0x1988, 0x0E11, 0x002E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
987 { 0x125D, 0x1988, 0x0E11, 0x0094, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
988 { 0x125D, 0x1988, 0x0E11, 0xB112, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
989 { 0x125D, 0x1988, 0x0E11, 0xB114, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
990 { 0x125D, 0x1988, 0x103C, 0x0012, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
991 { 0x125D, 0x1988, 0x103C, 0x0018, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
992 { 0x125D, 0x1988, 0x103C, 0x001C, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
993 { 0x125D, 0x1988, 0x103C, 0x001D, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
994 { 0x125D, 0x1988, 0x103C, 0x001E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
995 { 0x125D, 0x1988, 0x107B, 0x3350, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
996 { 0x125D, 0x1988, 0x10F7, 0x8338, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
997 { 0x125D, 0x1988, 0x10F7, 0x833C, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
998 { 0x125D, 0x1988, 0x10F7, 0x833D, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
999 { 0x125D, 0x1988, 0x10F7, 0x833E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
1000 { 0x125D, 0x1988, 0x10F7, 0x833F, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
1001 { 0x125D, 0x1988, 0x13BD, 0x1018, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
1002 { 0x125D, 0x1988, 0x13BD, 0x1019, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
1003 { 0x125D, 0x1988, 0x13BD, 0x101A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
1004 { 0x125D, 0x1988, 0x14FF, 0x0F03, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
1005 { 0x125D, 0x1988, 0x14FF, 0x0F04, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
1006 { 0x125D, 0x1988, 0x14FF, 0x0F05, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
1007 { 0x125D, 0x1988, 0x156D, 0xB400, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
1008 { 0x125D, 0x1988, 0x156D, 0xB795, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
1009 { 0x125D, 0x1988, 0x156D, 0xB797, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
1010 { 0x125D, 0x1988, 0x156D, 0xC700, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
1011 { 0x125D, 0x1988, 0x1033, 0x80F1, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
1012 { 0x125D, 0x1988, 0x103C, 0x001A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, /* HP OmniBook 6100 */
1013 { 0x125D, 0x1988, 0x107B, 0x340A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
1014 { 0x125D, 0x1988, 0x107B, 0x3450, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
1015 { 0x125D, 0x1988, 0x109F, 0x3134, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
1016 { 0x125D, 0x1988, 0x109F, 0x3161, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
1017 { 0x125D, 0x1988, 0x144D, 0x3280, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
1018 { 0x125D, 0x1988, 0x144D, 0x3281, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
1019 { 0x125D, 0x1988, 0x144D, 0xC002, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
1020 { 0x125D, 0x1988, 0x144D, 0xC003, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
1021 { 0x125D, 0x1988, 0x1509, 0x1740, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
1022 { 0x125D, 0x1988, 0x1610, 0x0010, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
1023 { 0x125D, 0x1988, 0x1042, 0x1042, HV_CTRL_ENABLE, 0 },
1024 { 0x125D, 0x1988, 0x107B, 0x9500, HV_CTRL_ENABLE, 0 },
1025 { 0x125D, 0x1988, 0x14FF, 0x0F06, HV_CTRL_ENABLE, 0 },
1026 { 0x125D, 0x1988, 0x1558, 0x8586, HV_CTRL_ENABLE, 0 },
1027 { 0x125D, 0x1988, 0x161F, 0x2011, HV_CTRL_ENABLE, 0 },
1028 /* Maestro3 chips */
1029 { 0x125D, 0x1998, 0x103C, 0x000E, HV_CTRL_ENABLE, 0 },
1030 { 0x125D, 0x1998, 0x103C, 0x0010, HV_CTRL_ENABLE, 1 }, /* HP OmniBook 6000 */
1031 { 0x125D, 0x1998, 0x103C, 0x0011, HV_CTRL_ENABLE, 1 }, /* HP OmniBook 500 */
1032 { 0x125D, 0x1998, 0x103C, 0x001B, HV_CTRL_ENABLE, 0 },
1033 { 0x125D, 0x1998, 0x104D, 0x80A6, HV_CTRL_ENABLE, 0 },
1034 { 0x125D, 0x1998, 0x104D, 0x80AA, HV_CTRL_ENABLE, 0 },
1035 { 0x125D, 0x1998, 0x107B, 0x5300, HV_CTRL_ENABLE, 0 },
1036 { 0x125D, 0x1998, 0x110A, 0x1998, HV_CTRL_ENABLE, 0 },
1037 { 0x125D, 0x1998, 0x13BD, 0x1015, HV_CTRL_ENABLE, 0 },
1038 { 0x125D, 0x1998, 0x13BD, 0x101C, HV_CTRL_ENABLE, 0 },
1039 { 0x125D, 0x1998, 0x13BD, 0x1802, HV_CTRL_ENABLE, 0 },
1040 { 0x125D, 0x1998, 0x1599, 0x0715, HV_CTRL_ENABLE, 0 },
1041 { 0x125D, 0x1998, 0x5643, 0x5643, HV_CTRL_ENABLE, 0 },
1042 { 0x125D, 0x199A, 0x144D, 0x3260, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
1043 { 0x125D, 0x199A, 0x144D, 0x3261, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
1044 { 0x125D, 0x199A, 0x144D, 0xC000, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
1045 { 0x125D, 0x199A, 0x144D, 0xC001, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
1046 { 0 }
1047};
976 1048
977/* 1049/*
978 * lowlevel functions 1050 * lowlevel functions
@@ -2392,21 +2464,27 @@ snd_m3_chip_init(m3_t *chip)
2392 DISABLE_LEGACY); 2464 DISABLE_LEGACY);
2393 pci_write_config_word(pcidev, PCI_LEGACY_AUDIO_CTRL, w); 2465 pci_write_config_word(pcidev, PCI_LEGACY_AUDIO_CTRL, w);
2394 2466
2395 /* 2467 if (chip->hv_quirk && chip->hv_quirk->is_omnibook) {
2396 * Volume buttons on some HP OmniBook laptops (500 and 6000 at least) 2468 /*
2397 * don't work correctly. This makes them work for the most part. 2469 * Volume buttons on some HP OmniBook laptops don't work
2398 * Volume up and down buttons on the laptop side work perfectly. 2470 * correctly. This makes them work for the most part.
2399 * Fn+cursor_up (volme up) works, Fn+cursor_down (volume down) doesn't, 2471 *
2400 * Fn+F8 (mute) works acts as volume up. 2472 * Volume up and down buttons on the laptop side work.
2401 */ 2473 * Fn+cursor_up (volme up) works.
2402 outw(~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_MASK); 2474 * Fn+cursor_down (volume down) doesn't work.
2403 outw(inw(io + GPIO_DIRECTION) & ~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DIRECTION); 2475 * Fn+F7 (mute) works acts as volume up.
2404 outw((GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DATA); 2476 */
2405 outw(0xffff, io + GPIO_MASK); 2477 outw(~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_MASK);
2406 2478 outw(inw(io + GPIO_DIRECTION) & ~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DIRECTION);
2479 outw((GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DATA);
2480 outw(0xffff, io + GPIO_MASK);
2481 }
2407 pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n); 2482 pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n);
2408 n &= ~HV_BUTTON_FROM_GD; 2483 n &= ~(HV_CTRL_ENABLE | REDUCED_DEBOUNCE | HV_BUTTON_FROM_GD);
2409 n |= HV_CTRL_ENABLE | REDUCED_DEBOUNCE; 2484 if (chip->hv_quirk)
2485 n |= chip->hv_quirk->config;
2486 /* For some reason we must always use reduced debounce. */
2487 n |= REDUCED_DEBOUNCE;
2410 n |= PM_CTRL_ENABLE | CLK_DIV_BY_49 | USE_PCI_TIMING; 2488 n |= PM_CTRL_ENABLE | CLK_DIV_BY_49 | USE_PCI_TIMING;
2411 pci_write_config_dword(pcidev, PCI_ALLEGRO_CONFIG, n); 2489 pci_write_config_dword(pcidev, PCI_ALLEGRO_CONFIG, n);
2412 2490
@@ -2594,7 +2672,7 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
2594 m3_t *chip; 2672 m3_t *chip;
2595 int i, err; 2673 int i, err;
2596 struct m3_quirk *quirk; 2674 struct m3_quirk *quirk;
2597 u16 subsystem_vendor, subsystem_device; 2675 struct m3_hv_quirk *hv_quirk;
2598 static snd_device_ops_t ops = { 2676 static snd_device_ops_t ops = {
2599 .dev_free = snd_m3_dev_free, 2677 .dev_free = snd_m3_dev_free,
2600 }; 2678 };
@@ -2632,18 +2710,25 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
2632 chip->pci = pci; 2710 chip->pci = pci;
2633 chip->irq = -1; 2711 chip->irq = -1;
2634 2712
2635 pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
2636 pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device);
2637
2638 for (quirk = m3_quirk_list; quirk->vendor; quirk++) { 2713 for (quirk = m3_quirk_list; quirk->vendor; quirk++) {
2639 if (subsystem_vendor == quirk->vendor && 2714 if (pci->subsystem_vendor == quirk->vendor &&
2640 subsystem_device == quirk->device) { 2715 pci->subsystem_device == quirk->device) {
2641 printk(KERN_INFO "maestro3: enabled hack for '%s'\n", quirk->name); 2716 printk(KERN_INFO "maestro3: enabled hack for '%s'\n", quirk->name);
2642 chip->quirk = quirk; 2717 chip->quirk = quirk;
2643 break; 2718 break;
2644 } 2719 }
2645 } 2720 }
2646 2721
2722 for (hv_quirk = m3_hv_quirk_list; hv_quirk->vendor; hv_quirk++) {
2723 if (pci->vendor == hv_quirk->vendor &&
2724 pci->device == hv_quirk->device &&
2725 pci->subsystem_vendor == hv_quirk->subsystem_vendor &&
2726 pci->subsystem_device == hv_quirk->subsystem_device) {
2727 chip->hv_quirk = hv_quirk;
2728 break;
2729 }
2730 }
2731
2647 chip->external_amp = enable_amp; 2732 chip->external_amp = enable_amp;
2648 if (amp_gpio >= 0 && amp_gpio <= 0x0f) 2733 if (amp_gpio >= 0 && amp_gpio <= 0x0f)
2649 chip->amp_gpio = amp_gpio; 2734 chip->amp_gpio = amp_gpio;