X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=sound%2Fpci%2Fmaestro3.c;h=93dfedcaed866d35f24b925471b5a854c54a8ae1;hb=0678accd2da33873455ef8d41d847bd550727159;hp=1928e06b6d82939fab3a687c1d3dea69f39da794;hpb=1465887cfe79889273e3fd3aaf862e7ec3ee244f;p=linux-2.6-omap-h63xx.git diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 1928e06b6d8..93dfedcaed8 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,7 @@ #include #include #include +#include MODULE_AUTHOR("Zach Brown , Takashi Iwai "); MODULE_DESCRIPTION("ESS Maestro3 PCI"); @@ -57,6 +59,10 @@ MODULE_SUPPORTED_DEVICE("{{ESS,Maestro3 PCI}," "{ESS,Allegro PCI}," "{ESS,Allegro-1 PCI}," "{ESS,Canyon3D-2/LE PCI}}"); +#ifndef CONFIG_SND_MAESTRO3_FIRMWARE_IN_KERNEL +MODULE_FIRMWARE("ess/maestro3_assp_kernel.fw"); +MODULE_FIRMWARE("ess/maestro3_assp_minisrc.fw"); +#endif static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ @@ -726,7 +732,6 @@ MODULE_PARM_DESC(amp_gpio, "GPIO pin number for external amp. (default = -1)"); #define MINISRC_IN_BUFFER_SIZE ( 0x50 * 2 ) #define MINISRC_OUT_BUFFER_SIZE ( 0x50 * 2 * 2) -#define MINISRC_OUT_BUFFER_SIZE ( 0x50 * 2 * 2) #define MINISRC_TMP_BUFFER_SIZE ( 112 + ( MINISRC_BIQUAD_STAGE * 3 + 4 ) * 2 * 2 ) #define MINISRC_BIQUAD_STAGE 2 #define MINISRC_COEF_LOC 0x175 @@ -768,21 +773,6 @@ MODULE_PARM_DESC(amp_gpio, "GPIO pin number for external amp. (default = -1)"); /* */ -/* quirk lists */ -struct m3_quirk { - const char *name; /* device name */ - u16 vendor, device; /* subsystem ids */ - int amp_gpio; /* gpio pin # for external amp, -1 = default */ - int irda_workaround; /* non-zero if avoid to touch 0x10 on GPIO_DIRECTION - (e.g. for IrDA on Dell Inspirons) */ -}; - -struct m3_hv_quirk { - u16 vendor, device, subsystem_vendor, subsystem_device; - u32 config; /* ALLEGRO_CONFIG hardware volume bits */ - int is_omnibook; /* Do HP OmniBook GPIO magic? */ -}; - struct m3_list { int curlen; int mem_addr; @@ -830,8 +820,6 @@ struct snd_m3 { struct snd_pcm *pcm; struct pci_dev *pci; - const struct m3_quirk *quirk; - const struct m3_hv_quirk *hv_quirk; int dacs_active; int timer_users; @@ -845,7 +833,11 @@ struct snd_m3 { u8 reset_state; int external_amp; - int amp_gpio; + int amp_gpio; /* gpio pin # for external amp, -1 = default */ + unsigned int hv_config; /* hardware-volume config bits */ + unsigned irda_workaround :1; /* avoid to touch 0x10 on GPIO_DIRECTION + (e.g. for IrDA on Dell Inspirons) */ + unsigned is_omnibook :1; /* Do HP OmniBook GPIO magic? */ /* midi */ struct snd_rawmidi *rmidi; @@ -864,12 +856,15 @@ struct snd_m3 { #ifdef CONFIG_PM u16 *suspend_mem; #endif + + const struct firmware *assp_kernel_image; + const struct firmware *assp_minisrc_image; }; /* * pci ids */ -static struct pci_device_id snd_m3_ids[] __devinitdata = { +static struct pci_device_id snd_m3_ids[] = { {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO_1, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO, PCI_ANY_ID, PCI_ANY_ID, @@ -891,127 +886,104 @@ static struct pci_device_id snd_m3_ids[] __devinitdata = { MODULE_DEVICE_TABLE(pci, snd_m3_ids); -static const struct m3_quirk m3_quirk_list[] = { - /* panasonic CF-28 "toughbook" */ - { - .name = "Panasonic CF-28", - .vendor = 0x10f7, - .device = 0x833e, - .amp_gpio = 0x0d, - }, - /* panasonic CF-72 "toughbook" */ - { - .name = "Panasonic CF-72", - .vendor = 0x10f7, - .device = 0x833d, - .amp_gpio = 0x0d, - }, - /* Dell Inspiron 4000 */ - { - .name = "Dell Inspiron 4000", - .vendor = 0x1028, - .device = 0x00b0, - .amp_gpio = -1, - .irda_workaround = 1, - }, - /* Dell Inspiron 8000 */ - { - .name = "Dell Inspiron 8000", - .vendor = 0x1028, - .device = 0x00a4, - .amp_gpio = -1, - .irda_workaround = 1, - }, - /* Dell Inspiron 8100 */ - { - .name = "Dell Inspiron 8100", - .vendor = 0x1028, - .device = 0x00e6, - .amp_gpio = -1, - .irda_workaround = 1, - }, - /* NEC LM800J/7 */ - { - .name = "NEC LM800J/7", - .vendor = 0x1033, - .device = 0x80f1, - .amp_gpio = 0x03, - }, - /* LEGEND ZhaoYang 3100CF */ - { - .name = "LEGEND ZhaoYang 3100CF", - .vendor = 0x1509, - .device = 0x1740, - .amp_gpio = 0x03, - }, - /* END */ - { NULL } +static struct snd_pci_quirk m3_amp_quirk_list[] __devinitdata = { + SND_PCI_QUIRK(0x10f7, 0x833e, "Panasonic CF-28", 0x0d), + SND_PCI_QUIRK(0x10f7, 0x833d, "Panasonic CF-72", 0x0d), + SND_PCI_QUIRK(0x1033, 0x80f1, "NEC LM800J/7", 0x03), + SND_PCI_QUIRK(0x1509, 0x1740, "LEGEND ZhaoYang 3100CF", 0x03), + { } /* END */ }; -/* These values came from the Windows driver. */ -static const struct m3_hv_quirk m3_hv_quirk_list[] = { +static struct snd_pci_quirk m3_irda_quirk_list[] __devinitdata = { + SND_PCI_QUIRK(0x1028, 0x00b0, "Dell Inspiron 4000", 1), + SND_PCI_QUIRK(0x1028, 0x00a4, "Dell Inspiron 8000", 1), + SND_PCI_QUIRK(0x1028, 0x00e6, "Dell Inspiron 8100", 1), + { } /* END */ +}; + +/* hardware volume quirks */ +static struct snd_pci_quirk m3_hv_quirk_list[] __devinitdata = { /* Allegro chips */ - { 0x125D, 0x1988, 0x0E11, 0x002E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x0E11, 0x0094, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x0E11, 0xB112, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x0E11, 0xB114, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x103C, 0x0012, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x103C, 0x0018, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x103C, 0x001C, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x103C, 0x001D, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x103C, 0x001E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x107B, 0x3350, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x10F7, 0x8338, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x10F7, 0x833C, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x10F7, 0x833D, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x10F7, 0x833E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x10F7, 0x833F, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x13BD, 0x1018, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x13BD, 0x1019, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x13BD, 0x101A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x14FF, 0x0F03, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x14FF, 0x0F04, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x14FF, 0x0F05, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x156D, 0xB400, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x156D, 0xB795, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x156D, 0xB797, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x156D, 0xC700, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x1033, 0x80F1, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x1988, 0x103C, 0x001A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, /* HP OmniBook 6100 */ - { 0x125D, 0x1988, 0x107B, 0x340A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x1988, 0x107B, 0x3450, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x1988, 0x109F, 0x3134, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x1988, 0x109F, 0x3161, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x1988, 0x144D, 0x3280, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x1988, 0x144D, 0x3281, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x1988, 0x144D, 0xC002, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x1988, 0x144D, 0xC003, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x1988, 0x1509, 0x1740, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x1988, 0x1610, 0x0010, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x1988, 0x1042, 0x1042, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1988, 0x107B, 0x9500, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1988, 0x14FF, 0x0F06, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1988, 0x1558, 0x8586, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1988, 0x161F, 0x2011, HV_CTRL_ENABLE, 0 }, + SND_PCI_QUIRK(0x0E11, 0x002E, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x0E11, 0x0094, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x0E11, 0xB112, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x0E11, 0xB114, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x103C, 0x0012, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x103C, 0x0018, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x103C, 0x001C, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x103C, 0x001D, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x103C, 0x001E, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x107B, 0x3350, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x10F7, 0x8338, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x10F7, 0x833C, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x10F7, 0x833D, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x10F7, 0x833E, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x10F7, 0x833F, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x13BD, 0x1018, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x13BD, 0x1019, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x13BD, 0x101A, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x14FF, 0x0F03, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x14FF, 0x0F04, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x14FF, 0x0F05, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x156D, 0xB400, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x156D, 0xB795, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x156D, 0xB797, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x156D, 0xC700, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), + SND_PCI_QUIRK(0x1033, 0x80F1, NULL, + HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), + SND_PCI_QUIRK(0x103C, 0x001A, NULL, /* HP OmniBook 6100 */ + HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), + SND_PCI_QUIRK(0x107B, 0x340A, NULL, + HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), + SND_PCI_QUIRK(0x107B, 0x3450, NULL, + HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), + SND_PCI_QUIRK(0x109F, 0x3134, NULL, + HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), + SND_PCI_QUIRK(0x109F, 0x3161, NULL, + HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), + SND_PCI_QUIRK(0x144D, 0x3280, NULL, + HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), + SND_PCI_QUIRK(0x144D, 0x3281, NULL, + HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), + SND_PCI_QUIRK(0x144D, 0xC002, NULL, + HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), + SND_PCI_QUIRK(0x144D, 0xC003, NULL, + HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), + SND_PCI_QUIRK(0x1509, 0x1740, NULL, + HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), + SND_PCI_QUIRK(0x1610, 0x0010, NULL, + HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), + SND_PCI_QUIRK(0x1042, 0x1042, NULL, HV_CTRL_ENABLE), + SND_PCI_QUIRK(0x107B, 0x9500, NULL, HV_CTRL_ENABLE), + SND_PCI_QUIRK(0x14FF, 0x0F06, NULL, HV_CTRL_ENABLE), + SND_PCI_QUIRK(0x1558, 0x8586, NULL, HV_CTRL_ENABLE), + SND_PCI_QUIRK(0x161F, 0x2011, NULL, HV_CTRL_ENABLE), /* Maestro3 chips */ - { 0x125D, 0x1998, 0x103C, 0x000E, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1998, 0x103C, 0x0010, HV_CTRL_ENABLE, 1 }, /* HP OmniBook 6000 */ - { 0x125D, 0x1998, 0x103C, 0x0011, HV_CTRL_ENABLE, 1 }, /* HP OmniBook 500 */ - { 0x125D, 0x1998, 0x103C, 0x001B, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1998, 0x104D, 0x80A6, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1998, 0x104D, 0x80AA, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1998, 0x107B, 0x5300, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1998, 0x110A, 0x1998, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1998, 0x13BD, 0x1015, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1998, 0x13BD, 0x101C, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1998, 0x13BD, 0x1802, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1998, 0x1599, 0x0715, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1998, 0x5643, 0x5643, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x199A, 0x144D, 0x3260, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x199A, 0x144D, 0x3261, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x199A, 0x144D, 0xC000, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x199A, 0x144D, 0xC001, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 }, - { 0 } + SND_PCI_QUIRK(0x103C, 0x000E, NULL, HV_CTRL_ENABLE), + SND_PCI_QUIRK(0x103C, 0x0010, NULL, HV_CTRL_ENABLE), + SND_PCI_QUIRK(0x103C, 0x0011, NULL, HV_CTRL_ENABLE), + SND_PCI_QUIRK(0x103C, 0x001B, NULL, HV_CTRL_ENABLE), + SND_PCI_QUIRK(0x104D, 0x80A6, NULL, HV_CTRL_ENABLE), + SND_PCI_QUIRK(0x104D, 0x80AA, NULL, HV_CTRL_ENABLE), + SND_PCI_QUIRK(0x107B, 0x5300, NULL, HV_CTRL_ENABLE), + SND_PCI_QUIRK(0x110A, 0x1998, NULL, HV_CTRL_ENABLE), + SND_PCI_QUIRK(0x13BD, 0x1015, NULL, HV_CTRL_ENABLE), + SND_PCI_QUIRK(0x13BD, 0x101C, NULL, HV_CTRL_ENABLE), + SND_PCI_QUIRK(0x13BD, 0x1802, NULL, HV_CTRL_ENABLE), + SND_PCI_QUIRK(0x1599, 0x0715, NULL, HV_CTRL_ENABLE), + SND_PCI_QUIRK(0x5643, 0x5643, NULL, HV_CTRL_ENABLE), + SND_PCI_QUIRK(0x144D, 0x3260, NULL, HV_CTRL_ENABLE | REDUCED_DEBOUNCE), + SND_PCI_QUIRK(0x144D, 0x3261, NULL, HV_CTRL_ENABLE | REDUCED_DEBOUNCE), + SND_PCI_QUIRK(0x144D, 0xC000, NULL, HV_CTRL_ENABLE | REDUCED_DEBOUNCE), + SND_PCI_QUIRK(0x144D, 0xC001, NULL, HV_CTRL_ENABLE | REDUCED_DEBOUNCE), + { } /* END */ +}; + +/* HP Omnibook quirks */ +static struct snd_pci_quirk m3_omnibook_quirk_list[] __devinitdata = { + SND_PCI_QUIRK_ID(0x103c, 0x0010), /* HP OmniBook 6000 */ + SND_PCI_QUIRK_ID(0x103c, 0x0011), /* HP OmniBook 500 */ + { } /* END */ }; /* @@ -1685,8 +1657,7 @@ static void snd_m3_update_hw_volume(unsigned long private_data) spin_unlock_irqrestore(&chip->ac97_lock, flags); } -static irqreturn_t -snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t snd_m3_interrupt(int irq, void *dev_id) { struct snd_m3 *chip = dev_id; u8 status; @@ -1849,7 +1820,6 @@ snd_m3_playback_open(struct snd_pcm_substream *subs) return err; runtime->hw = snd_m3_playback; - snd_pcm_set_sync(subs); return 0; } @@ -1874,7 +1844,6 @@ snd_m3_capture_open(struct snd_pcm_substream *subs) return err; runtime->hw = snd_m3_capture; - snd_pcm_set_sync(subs); return 0; } @@ -2051,7 +2020,7 @@ static void snd_m3_ac97_reset(struct snd_m3 *chip) for (i = 0; i < 5; i++) { dir = inw(io + GPIO_DIRECTION); - if (! chip->quirk || ! chip->quirk->irda_workaround) + if (!chip->irda_workaround) dir |= 0x10; /* assuming pci bus master? */ snd_m3_remote_codec_config(io, 0); @@ -2133,11 +2102,13 @@ static int __devinit snd_m3_mixer(struct snd_m3 *chip) } +#ifdef CONFIG_SND_MAESTRO3_FIRMWARE_IN_KERNEL + /* * DSP Code images */ -static const u16 assp_kernel_image[] __devinitdata = { +static const u16 assp_kernel_image[] = { 0x7980, 0x0030, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x00FB, 0x7980, 0x00DD, 0x7980, 0x03B4, 0x7980, 0x0332, 0x7980, 0x0287, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x031A, 0x7980, 0x03B4, 0x7980, 0x022F, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x03B4, @@ -2224,7 +2195,7 @@ static const u16 assp_kernel_image[] __devinitdata = { * Mini sample rate converter code image * that is to be loaded at 0x400 on the DSP. */ -static const u16 assp_minisrc_image[] __devinitdata = { +static const u16 assp_minisrc_image[] = { 0xBF80, 0x101E, 0x906E, 0x006E, 0x8B88, 0x6980, 0xEF88, 0x906F, 0x0D6F, 0x6900, 0xEB08, 0x0412, 0xBC20, 0x696E, 0xB801, 0x906E, 0x7980, 0x0403, 0xB90E, 0x8807, 0xBE43, 0xBF01, 0xBE47, 0xBE41, @@ -2261,20 +2232,47 @@ static const u16 assp_minisrc_image[] __devinitdata = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, }; +static const struct firmware assp_kernel = { + .data = (u8 *)assp_kernel_image, + .size = sizeof assp_kernel_image +}; +static const struct firmware assp_minisrc = { + .data = (u8 *)assp_minisrc_image, + .size = sizeof assp_minisrc_image +}; + +#else /* CONFIG_SND_MAESTRO3_FIRMWARE_IN_KERNEL */ + +#ifdef __LITTLE_ENDIAN +static inline void snd_m3_convert_from_le(const struct firmware *fw) { } +#else +static void snd_m3_convert_from_le(const struct firmware *fw) +{ + int i; + u16 *data = (u16 *)fw->data; + + for (i = 0; i < fw->size / 2; ++i) + le16_to_cpus(&data[i]); +} +#endif + +#endif /* CONFIG_SND_MAESTRO3_FIRMWARE_IN_KERNEL */ + /* * initialize ASSP */ #define MINISRC_LPF_LEN 10 -static const u16 minisrc_lpf[MINISRC_LPF_LEN] __devinitdata = { +static const u16 minisrc_lpf[MINISRC_LPF_LEN] = { 0X0743, 0X1104, 0X0A4C, 0XF88D, 0X242C, 0X1023, 0X1AA9, 0X0B60, 0XEFDD, 0X186F }; -static void __devinit snd_m3_assp_init(struct snd_m3 *chip) +static void snd_m3_assp_init(struct snd_m3 *chip) { unsigned int i; + u16 *data; /* zero kernel data */ for (i = 0; i < (REV_B_DATA_MEMORY_UNIT_LENGTH * NUM_UNITS_KERNEL_DATA) / 2; i++) @@ -2292,10 +2290,10 @@ static void __devinit snd_m3_assp_init(struct snd_m3 *chip) KDATA_DMA_XFER0); /* write kernel into code memory.. */ - for (i = 0 ; i < ARRAY_SIZE(assp_kernel_image); i++) { + data = (u16 *)chip->assp_kernel_image->data; + for (i = 0 ; i * 2 < chip->assp_kernel_image->size; i++) { snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, - REV_B_CODE_MEMORY_BEGIN + i, - assp_kernel_image[i]); + REV_B_CODE_MEMORY_BEGIN + i, data[i]); } /* @@ -2304,10 +2302,10 @@ static void __devinit snd_m3_assp_init(struct snd_m3 *chip) * drop it there. It seems that the minisrc doesn't * need vectors, so we won't bother with them.. */ - for (i = 0; i < ARRAY_SIZE(assp_minisrc_image); i++) { + data = (u16 *)chip->assp_minisrc_image->data; + for (i = 0; i * 2 < chip->assp_minisrc_image->size; i++) { snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, - 0x400 + i, - assp_minisrc_image[i]); + 0x400 + i, data[i]); } /* @@ -2378,7 +2376,7 @@ static int __devinit snd_m3_assp_client_init(struct snd_m3 *chip, struct m3_dma * shifted list address is aligned. * list address = (mem address >> 1) >> 7; */ - data_bytes = (data_bytes + 255) & ~255; + data_bytes = ALIGN(data_bytes, 256); address = 0x1100 + ((data_bytes/2) * index); if ((address + (data_bytes/2)) >= 0x1c00) { @@ -2445,7 +2443,7 @@ snd_m3_chip_init(struct snd_m3 *chip) DISABLE_LEGACY); pci_write_config_word(pcidev, PCI_LEGACY_AUDIO_CTRL, w); - if (chip->hv_quirk && chip->hv_quirk->is_omnibook) { + if (chip->is_omnibook) { /* * Volume buttons on some HP OmniBook laptops don't work * correctly. This makes them work for the most part. @@ -2462,8 +2460,7 @@ snd_m3_chip_init(struct snd_m3 *chip) } pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n); n &= ~(HV_CTRL_ENABLE | REDUCED_DEBOUNCE | HV_BUTTON_FROM_GD); - if (chip->hv_quirk) - n |= chip->hv_quirk->config; + n |= chip->hv_config; /* For some reason we must always use reduced debounce. */ n |= REDUCED_DEBOUNCE; n |= PM_CTRL_ENABLE | CLK_DIV_BY_49 | USE_PCI_TIMING; @@ -2511,7 +2508,7 @@ snd_m3_enable_ints(struct snd_m3 *chip) /* TODO: MPU401 not supported yet */ val = ASSP_INT_ENABLE /*| MPU401_INT_ENABLE*/; - if (chip->hv_quirk && (chip->hv_quirk->config & HV_CTRL_ENABLE)) + if (chip->hv_config & HV_CTRL_ENABLE) val |= HV_INT_ENABLE; outw(val, io + HOST_INT_CTRL); outb(inb(io + ASSP_CONTROL_C) | ASSP_HOST_INT_ENABLE, @@ -2554,6 +2551,11 @@ static int snd_m3_free(struct snd_m3 *chip) if (chip->iobase) pci_release_regions(chip->pci); +#ifndef CONFIG_SND_MAESTRO3_FIRMWARE_IN_KERNEL + release_firmware(chip->assp_kernel_image); + release_firmware(chip->assp_minisrc_image); +#endif + pci_disable_device(chip->pci); kfree(chip); return 0; @@ -2590,12 +2592,9 @@ static int m3_suspend(struct pci_dev *pci, pm_message_t state) chip->suspend_mem[index++] = snd_m3_assp_read(chip, MEMTYPE_INTERNAL_DATA, i); - /* power down apci registers */ - snd_m3_outw(chip, 0xffff, 0x54); - snd_m3_outw(chip, 0xffff, 0x56); - pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -2608,8 +2607,14 @@ static int m3_resume(struct pci_dev *pci) if (chip->suspend_mem == NULL) return 0; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "maestor3: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); /* first lets just bring everything back. .*/ @@ -2663,8 +2668,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, { struct snd_m3 *chip; int i, err; - const struct m3_quirk *quirk; - const struct m3_hv_quirk *hv_quirk; + const struct snd_pci_quirk *quirk; static struct snd_device_ops ops = { .dev_free = snd_m3_dev_free, }; @@ -2704,34 +2708,32 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, chip->pci = pci; chip->irq = -1; - for (quirk = m3_quirk_list; quirk->vendor; quirk++) { - if (pci->subsystem_vendor == quirk->vendor && - pci->subsystem_device == quirk->device) { - printk(KERN_INFO "maestro3: enabled hack for '%s'\n", quirk->name); - chip->quirk = quirk; - break; - } - } - - for (hv_quirk = m3_hv_quirk_list; hv_quirk->vendor; hv_quirk++) { - if (pci->vendor == hv_quirk->vendor && - pci->device == hv_quirk->device && - pci->subsystem_vendor == hv_quirk->subsystem_vendor && - pci->subsystem_device == hv_quirk->subsystem_device) { - chip->hv_quirk = hv_quirk; - break; - } - } - chip->external_amp = enable_amp; if (amp_gpio >= 0 && amp_gpio <= 0x0f) chip->amp_gpio = amp_gpio; - else if (chip->quirk && chip->quirk->amp_gpio >= 0) - chip->amp_gpio = chip->quirk->amp_gpio; - else if (chip->allegro_flag) - chip->amp_gpio = GPO_EXT_AMP_ALLEGRO; - else /* presumably this is for all 'maestro3's.. */ - chip->amp_gpio = GPO_EXT_AMP_M3; + else { + quirk = snd_pci_quirk_lookup(pci, m3_amp_quirk_list); + if (quirk) { + snd_printdd(KERN_INFO "maestro3: set amp-gpio " + "for '%s'\n", quirk->name); + chip->amp_gpio = quirk->value; + } else if (chip->allegro_flag) + chip->amp_gpio = GPO_EXT_AMP_ALLEGRO; + else /* presumably this is for all 'maestro3's.. */ + chip->amp_gpio = GPO_EXT_AMP_M3; + } + + quirk = snd_pci_quirk_lookup(pci, m3_irda_quirk_list); + if (quirk) { + snd_printdd(KERN_INFO "maestro3: enabled irda workaround " + "for '%s'\n", quirk->name); + chip->irda_workaround = 1; + } + quirk = snd_pci_quirk_lookup(pci, m3_hv_quirk_list); + if (quirk) + chip->hv_config = quirk->value; + if (snd_pci_quirk_lookup(pci, m3_omnibook_quirk_list)) + chip->is_omnibook = 1; chip->num_substreams = NR_DSPS; chip->substreams = kcalloc(chip->num_substreams, sizeof(struct m3_dma), @@ -2742,6 +2744,30 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, return -ENOMEM; } +#ifdef CONFIG_SND_MAESTRO3_FIRMWARE_IN_KERNEL + chip->assp_kernel_image = &assp_kernel; +#else + err = request_firmware(&chip->assp_kernel_image, + "ess/maestro3_assp_kernel.fw", &pci->dev); + if (err < 0) { + snd_m3_free(chip); + return err; + } else + snd_m3_convert_from_le(chip->assp_kernel_image); +#endif + +#ifdef CONFIG_SND_MAESTRO3_FIRMWARE_IN_KERNEL + chip->assp_minisrc_image = &assp_minisrc; +#else + err = request_firmware(&chip->assp_minisrc_image, + "ess/maestro3_assp_minisrc.fw", &pci->dev); + if (err < 0) { + snd_m3_free(chip); + return err; + } else + snd_m3_convert_from_le(chip->assp_minisrc_image); +#endif + if ((err = pci_request_regions(pci, card->driver)) < 0) { snd_m3_free(chip); return err; @@ -2760,7 +2786,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip); - if (request_irq(pci->irq, snd_m3_interrupt, SA_INTERRUPT|SA_SHIRQ, + if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED, card->driver, chip)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_m3_free(chip); @@ -2861,7 +2887,8 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) #if 0 /* TODO: not supported yet */ /* TODO enable MIDI IRQ and I/O */ err = snd_mpu401_uart_new(chip->card, 0, MPU401_HW_MPU401, - chip->iobase + MPU401_DATA_PORT, 1, + chip->iobase + MPU401_DATA_PORT, + MPU401_INFO_INTEGRATED, chip->irq, 0, &chip->rmidi); if (err < 0) printk(KERN_WARNING "maestro3: no MIDI support.\n");