diff options
-rw-r--r-- | sound/pci/maestro3.c | 127 |
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 | ||
782 | struct 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 | |||
782 | struct m3_list { | 788 | struct 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. */ | ||
984 | static 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; |