aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOndrej Zary <linux@rainbow-software.org>2006-07-31 06:51:57 -0400
committerJaroslav Kysela <perex@suse.cz>2006-09-23 04:39:46 -0400
commit1c3985580445ef9225c1ea7714d6d963f7626eeb (patch)
treeb3cbc142be479ff13593239c3db6ee132d1d167c
parentf3302a59cf6961712658db63b66ea5902c17d5e1 (diff)
[ALSA] es18xx - Add PnP BIOS support
This patch adds PnP BIOS support to es18xx driver. It allows ESS ES18xx sound chips integrated in some notebooks (such as DTK FortisPro TOP-5A) that don't appear as ISA cards (they aren't recognized by ISA PnP, only by PnP BIOS) to 'just work' automatically. Signed-off-by: Ondrej Zary <linux@rainbow-software.org> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
-rw-r--r--sound/isa/es18xx.c219
1 files changed, 157 insertions, 62 deletions
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 34998de9968c..85818200333f 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -2038,7 +2038,80 @@ MODULE_PARM_DESC(dma2, "DMA 2 # for ES18xx driver.");
2038static struct platform_device *platform_devices[SNDRV_CARDS]; 2038static struct platform_device *platform_devices[SNDRV_CARDS];
2039 2039
2040#ifdef CONFIG_PNP 2040#ifdef CONFIG_PNP
2041static int pnp_registered; 2041static int pnp_registered, pnpc_registered;
2042
2043static struct pnp_device_id snd_audiodrive_pnpbiosids[] = {
2044 { .id = "ESS1869" },
2045 { .id = "" } /* end */
2046};
2047
2048MODULE_DEVICE_TABLE(pnp, snd_audiodrive_pnpbiosids);
2049
2050/* PnP main device initialization */
2051static int __devinit snd_audiodrive_pnp_init_main(int dev, struct pnp_dev *pdev,
2052 struct pnp_resource_table *cfg)
2053{
2054 int err;
2055
2056 pnp_init_resource_table(cfg);
2057 if (port[dev] != SNDRV_AUTO_PORT)
2058 pnp_resource_change(&cfg->port_resource[0], port[dev], 16);
2059 if (fm_port[dev] != SNDRV_AUTO_PORT)
2060 pnp_resource_change(&cfg->port_resource[1], fm_port[dev], 4);
2061 if (mpu_port[dev] != SNDRV_AUTO_PORT)
2062 pnp_resource_change(&cfg->port_resource[2], mpu_port[dev], 2);
2063 if (dma1[dev] != SNDRV_AUTO_DMA)
2064 pnp_resource_change(&cfg->dma_resource[0], dma1[dev], 1);
2065 if (dma2[dev] != SNDRV_AUTO_DMA)
2066 pnp_resource_change(&cfg->dma_resource[1], dma2[dev], 1);
2067 if (irq[dev] != SNDRV_AUTO_IRQ)
2068 pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1);
2069 if (pnp_device_is_isapnp(pdev)) {
2070 err = pnp_manual_config_dev(pdev, cfg, 0);
2071 if (err < 0)
2072 snd_printk(KERN_ERR PFX "PnP manual resources are invalid, using auto config\n");
2073 }
2074 err = pnp_activate_dev(pdev);
2075 if (err < 0) {
2076 snd_printk(KERN_ERR PFX "PnP configure failure (out of resources?)\n");
2077 return -EBUSY;
2078 }
2079 /* ok. hack using Vendor-Defined Card-Level registers */
2080 /* skip csn and logdev initialization - already done in isapnp_configure */
2081 if (pnp_device_is_isapnp(pdev)) {
2082 isapnp_cfg_begin(isapnp_card_number(pdev), isapnp_csn_number(pdev));
2083 isapnp_write_byte(0x27, pnp_irq(pdev, 0)); /* Hardware Volume IRQ Number */
2084 if (mpu_port[dev] != SNDRV_AUTO_PORT)
2085 isapnp_write_byte(0x28, pnp_irq(pdev, 0)); /* MPU-401 IRQ Number */
2086 isapnp_write_byte(0x72, pnp_irq(pdev, 0)); /* second IRQ */
2087 isapnp_cfg_end();
2088 }
2089 port[dev] = pnp_port_start(pdev, 0);
2090 fm_port[dev] = pnp_port_start(pdev, 1);
2091 mpu_port[dev] = pnp_port_start(pdev, 2);
2092 dma1[dev] = pnp_dma(pdev, 0);
2093 dma2[dev] = pnp_dma(pdev, 1);
2094 irq[dev] = pnp_irq(pdev, 0);
2095 snd_printdd("PnP ES18xx: port=0x%lx, fm port=0x%lx, mpu port=0x%lx\n", port[dev], fm_port[dev], mpu_port[dev]);
2096 snd_printdd("PnP ES18xx: dma1=%i, dma2=%i, irq=%i\n", dma1[dev], dma2[dev], irq[dev]);
2097 return 0;
2098}
2099
2100static int __devinit snd_audiodrive_pnp(int dev, struct snd_audiodrive *acard,
2101 struct pnp_dev *pdev)
2102{
2103 struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
2104
2105 if (!cfg)
2106 return -ENOMEM;
2107 acard->dev = pdev;
2108 if (snd_audiodrive_pnp_init_main(dev, acard->dev, cfg) < 0) {
2109 kfree(cfg);
2110 return -EBUSY;
2111 }
2112 kfree(cfg);
2113 return 0;
2114}
2042 2115
2043static struct pnp_card_device_id snd_audiodrive_pnpids[] = { 2116static struct pnp_card_device_id snd_audiodrive_pnpids[] = {
2044 /* ESS 1868 (integrated on Compaq dual P-Pro motherboard and Genius 18PnP 3D) */ 2117 /* ESS 1868 (integrated on Compaq dual P-Pro motherboard and Genius 18PnP 3D) */
@@ -2061,13 +2134,11 @@ static struct pnp_card_device_id snd_audiodrive_pnpids[] = {
2061 2134
2062MODULE_DEVICE_TABLE(pnp_card, snd_audiodrive_pnpids); 2135MODULE_DEVICE_TABLE(pnp_card, snd_audiodrive_pnpids);
2063 2136
2064static int __devinit snd_audiodrive_pnp(int dev, struct snd_audiodrive *acard, 2137static int __devinit snd_audiodrive_pnpc(int dev, struct snd_audiodrive *acard,
2065 struct pnp_card_link *card, 2138 struct pnp_card_link *card,
2066 const struct pnp_card_device_id *id) 2139 const struct pnp_card_device_id *id)
2067{ 2140{
2068 struct pnp_dev *pdev;
2069 struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL); 2141 struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
2070 int err;
2071 2142
2072 if (!cfg) 2143 if (!cfg)
2073 return -ENOMEM; 2144 return -ENOMEM;
@@ -2082,58 +2153,16 @@ static int __devinit snd_audiodrive_pnp(int dev, struct snd_audiodrive *acard,
2082 return -EBUSY; 2153 return -EBUSY;
2083 } 2154 }
2084 /* Control port initialization */ 2155 /* Control port initialization */
2085 err = pnp_activate_dev(acard->devc); 2156 if (pnp_activate_dev(acard->devc) < 0) {
2086 if (err < 0) {
2087 snd_printk(KERN_ERR PFX "PnP control configure failure (out of resources?)\n"); 2157 snd_printk(KERN_ERR PFX "PnP control configure failure (out of resources?)\n");
2088 kfree(cfg);
2089 return -EAGAIN; 2158 return -EAGAIN;
2090 } 2159 }
2091 snd_printdd("pnp: port=0x%llx\n", 2160 snd_printdd("pnp: port=0x%llx\n",
2092 (unsigned long long)pnp_port_start(acard->devc, 0)); 2161 (unsigned long long)pnp_port_start(acard->devc, 0));
2093 /* PnP initialization */ 2162 if (snd_audiodrive_pnp_init_main(dev, acard->dev, cfg) < 0) {
2094 pdev = acard->dev;
2095 pnp_init_resource_table(cfg);
2096 if (port[dev] != SNDRV_AUTO_PORT)
2097 pnp_resource_change(&cfg->port_resource[0], port[dev], 16);
2098 if (fm_port[dev] != SNDRV_AUTO_PORT)
2099 pnp_resource_change(&cfg->port_resource[1], fm_port[dev], 4);
2100 if (mpu_port[dev] != SNDRV_AUTO_PORT)
2101 pnp_resource_change(&cfg->port_resource[2], mpu_port[dev], 2);
2102 if (dma1[dev] != SNDRV_AUTO_DMA)
2103 pnp_resource_change(&cfg->dma_resource[0], dma1[dev], 1);
2104 if (dma2[dev] != SNDRV_AUTO_DMA)
2105 pnp_resource_change(&cfg->dma_resource[1], dma2[dev], 1);
2106 if (irq[dev] != SNDRV_AUTO_IRQ)
2107 pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1);
2108 err = pnp_manual_config_dev(pdev, cfg, 0);
2109 if (err < 0)
2110 snd_printk(KERN_ERR PFX "PnP manual resources are invalid, using auto config\n");
2111 err = pnp_activate_dev(pdev);
2112 if (err < 0) {
2113 snd_printk(KERN_ERR PFX "PnP configure failure (out of resources?)\n");
2114 kfree(cfg); 2163 kfree(cfg);
2115 return -EBUSY; 2164 return -EBUSY;
2116 } 2165 }
2117 /* ok. hack using Vendor-Defined Card-Level registers */
2118 /* skip csn and logdev initialization - already done in isapnp_configure */
2119 if (pnp_device_is_isapnp(pdev)) {
2120 isapnp_cfg_begin(isapnp_card_number(pdev), isapnp_csn_number(pdev));
2121 isapnp_write_byte(0x27, pnp_irq(pdev, 0)); /* Hardware Volume IRQ Number */
2122 if (mpu_port[dev] != SNDRV_AUTO_PORT)
2123 isapnp_write_byte(0x28, pnp_irq(pdev, 0)); /* MPU-401 IRQ Number */
2124 isapnp_write_byte(0x72, pnp_irq(pdev, 0)); /* second IRQ */
2125 isapnp_cfg_end();
2126 } else {
2127 snd_printk(KERN_ERR PFX "unable to install ISA PnP hack, expect malfunction\n");
2128 }
2129 port[dev] = pnp_port_start(pdev, 0);
2130 fm_port[dev] = pnp_port_start(pdev, 1);
2131 mpu_port[dev] = pnp_port_start(pdev, 2);
2132 dma1[dev] = pnp_dma(pdev, 0);
2133 dma2[dev] = pnp_dma(pdev, 1);
2134 irq[dev] = pnp_irq(pdev, 0);
2135 snd_printdd("PnP ES18xx: port=0x%lx, fm port=0x%lx, mpu port=0x%lx\n", port[dev], fm_port[dev], mpu_port[dev]);
2136 snd_printdd("PnP ES18xx: dma1=%i, dma2=%i, irq=%i\n", dma1[dev], dma2[dev], irq[dev]);
2137 kfree(cfg); 2166 kfree(cfg);
2138 return 0; 2167 return 0;
2139} 2168}
@@ -2302,7 +2331,69 @@ static struct platform_driver snd_es18xx_nonpnp_driver = {
2302#ifdef CONFIG_PNP 2331#ifdef CONFIG_PNP
2303static unsigned int __devinitdata es18xx_pnp_devices; 2332static unsigned int __devinitdata es18xx_pnp_devices;
2304 2333
2305static int __devinit snd_audiodrive_pnp_detect(struct pnp_card_link *pcard, 2334static int __devinit snd_audiodrive_pnp_detect(struct pnp_dev *pdev,
2335 const struct pnp_device_id *id)
2336{
2337 static int dev;
2338 int err;
2339 struct snd_card *card;
2340
2341 if (pnp_device_is_isapnp(pdev))
2342 return -ENOENT; /* we have another procedure - card */
2343 for (; dev < SNDRV_CARDS; dev++) {
2344 if (enable[dev] && isapnp[dev])
2345 break;
2346 }
2347 if (dev >= SNDRV_CARDS)
2348 return -ENODEV;
2349
2350 card = snd_es18xx_card_new(dev);
2351 if (! card)
2352 return -ENOMEM;
2353 if ((err = snd_audiodrive_pnp(dev, card->private_data, pdev)) < 0) {
2354 snd_card_free(card);
2355 return err;
2356 }
2357 snd_card_set_dev(card, &pdev->dev);
2358 if ((err = snd_audiodrive_probe(card, dev)) < 0) {
2359 snd_card_free(card);
2360 return err;
2361 }
2362 pnp_set_drvdata(pdev, card);
2363 dev++;
2364 es18xx_pnp_devices++;
2365 return 0;
2366}
2367
2368static void __devexit snd_audiodrive_pnp_remove(struct pnp_dev * pdev)
2369{
2370 snd_card_free(pnp_get_drvdata(pdev));
2371 pnp_set_drvdata(pdev, NULL);
2372}
2373
2374#ifdef CONFIG_PM
2375static int snd_audiodrive_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
2376{
2377 return snd_es18xx_suspend(pnp_get_drvdata(pdev), state);
2378}
2379static int snd_audiodrive_pnp_resume(struct pnp_dev *pdev)
2380{
2381 return snd_es18xx_resume(pnp_get_drvdata(pdev));
2382}
2383#endif
2384
2385static struct pnp_driver es18xx_pnp_driver = {
2386 .name = "es18xx-pnpbios",
2387 .id_table = snd_audiodrive_pnpbiosids,
2388 .probe = snd_audiodrive_pnp_detect,
2389 .remove = __devexit_p(snd_audiodrive_pnp_remove),
2390#ifdef CONFIG_PM
2391 .suspend = snd_audiodrive_pnp_suspend,
2392 .resume = snd_audiodrive_pnp_resume,
2393#endif
2394};
2395
2396static int __devinit snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard,
2306 const struct pnp_card_device_id *pid) 2397 const struct pnp_card_device_id *pid)
2307{ 2398{
2308 static int dev; 2399 static int dev;
@@ -2320,7 +2411,7 @@ static int __devinit snd_audiodrive_pnp_detect(struct pnp_card_link *pcard,
2320 if (! card) 2411 if (! card)
2321 return -ENOMEM; 2412 return -ENOMEM;
2322 2413
2323 if ((res = snd_audiodrive_pnp(dev, card->private_data, pcard, pid)) < 0) { 2414 if ((res = snd_audiodrive_pnpc(dev, card->private_data, pcard, pid)) < 0) {
2324 snd_card_free(card); 2415 snd_card_free(card);
2325 return res; 2416 return res;
2326 } 2417 }
@@ -2336,19 +2427,19 @@ static int __devinit snd_audiodrive_pnp_detect(struct pnp_card_link *pcard,
2336 return 0; 2427 return 0;
2337} 2428}
2338 2429
2339static void __devexit snd_audiodrive_pnp_remove(struct pnp_card_link * pcard) 2430static void __devexit snd_audiodrive_pnpc_remove(struct pnp_card_link * pcard)
2340{ 2431{
2341 snd_card_free(pnp_get_card_drvdata(pcard)); 2432 snd_card_free(pnp_get_card_drvdata(pcard));
2342 pnp_set_card_drvdata(pcard, NULL); 2433 pnp_set_card_drvdata(pcard, NULL);
2343} 2434}
2344 2435
2345#ifdef CONFIG_PM 2436#ifdef CONFIG_PM
2346static int snd_audiodrive_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state) 2437static int snd_audiodrive_pnpc_suspend(struct pnp_card_link *pcard, pm_message_t state)
2347{ 2438{
2348 return snd_es18xx_suspend(pnp_get_card_drvdata(pcard), state); 2439 return snd_es18xx_suspend(pnp_get_card_drvdata(pcard), state);
2349} 2440}
2350 2441
2351static int snd_audiodrive_pnp_resume(struct pnp_card_link *pcard) 2442static int snd_audiodrive_pnpc_resume(struct pnp_card_link *pcard)
2352{ 2443{
2353 return snd_es18xx_resume(pnp_get_card_drvdata(pcard)); 2444 return snd_es18xx_resume(pnp_get_card_drvdata(pcard));
2354} 2445}
@@ -2359,11 +2450,11 @@ static struct pnp_card_driver es18xx_pnpc_driver = {
2359 .flags = PNP_DRIVER_RES_DISABLE, 2450 .flags = PNP_DRIVER_RES_DISABLE,
2360 .name = "es18xx", 2451 .name = "es18xx",
2361 .id_table = snd_audiodrive_pnpids, 2452 .id_table = snd_audiodrive_pnpids,
2362 .probe = snd_audiodrive_pnp_detect, 2453 .probe = snd_audiodrive_pnpc_detect,
2363 .remove = __devexit_p(snd_audiodrive_pnp_remove), 2454 .remove = __devexit_p(snd_audiodrive_pnpc_remove),
2364#ifdef CONFIG_PM 2455#ifdef CONFIG_PM
2365 .suspend = snd_audiodrive_pnp_suspend, 2456 .suspend = snd_audiodrive_pnpc_suspend,
2366 .resume = snd_audiodrive_pnp_resume, 2457 .resume = snd_audiodrive_pnpc_resume,
2367#endif 2458#endif
2368}; 2459};
2369#endif /* CONFIG_PNP */ 2460#endif /* CONFIG_PNP */
@@ -2373,8 +2464,10 @@ static void __init_or_module snd_es18xx_unregister_all(void)
2373 int i; 2464 int i;
2374 2465
2375#ifdef CONFIG_PNP 2466#ifdef CONFIG_PNP
2376 if (pnp_registered) 2467 if (pnpc_registered)
2377 pnp_unregister_card_driver(&es18xx_pnpc_driver); 2468 pnp_unregister_card_driver(&es18xx_pnpc_driver);
2469 if (pnp_registered)
2470 pnp_unregister_driver(&es18xx_pnp_driver);
2378#endif 2471#endif
2379 for (i = 0; i < ARRAY_SIZE(platform_devices); ++i) 2472 for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
2380 platform_device_unregister(platform_devices[i]); 2473 platform_device_unregister(platform_devices[i]);
@@ -2405,11 +2498,13 @@ static int __init alsa_card_es18xx_init(void)
2405 } 2498 }
2406 2499
2407#ifdef CONFIG_PNP 2500#ifdef CONFIG_PNP
2408 err = pnp_register_card_driver(&es18xx_pnpc_driver); 2501 err = pnp_register_driver(&es18xx_pnp_driver);
2409 if (!err) { 2502 if (!err)
2410 pnp_registered = 1; 2503 pnp_registered = 1;
2411 cards += es18xx_pnp_devices; 2504 err = pnp_register_card_driver(&es18xx_pnpc_driver);
2412 } 2505 if (!err)
2506 pnpc_registered = 1;
2507 cards += es18xx_pnp_devices;
2413#endif 2508#endif
2414 2509
2415 if(!cards) { 2510 if(!cards) {