162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Driver for PowerMac AWACS 462306a36Sopenharmony_ci * Copyright (c) 2001 by Takashi Iwai <tiwai@suse.de> 562306a36Sopenharmony_ci * based on dmasound.c. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/init.h> 962306a36Sopenharmony_ci#include <linux/err.h> 1062306a36Sopenharmony_ci#include <linux/platform_device.h> 1162306a36Sopenharmony_ci#include <linux/module.h> 1262306a36Sopenharmony_ci#include <sound/core.h> 1362306a36Sopenharmony_ci#include <sound/initval.h> 1462306a36Sopenharmony_ci#include "pmac.h" 1562306a36Sopenharmony_ci#include "awacs.h" 1662306a36Sopenharmony_ci#include "burgundy.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define CHIP_NAME "PMac" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ciMODULE_DESCRIPTION("PowerMac"); 2162306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ 2462306a36Sopenharmony_cistatic char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ 2562306a36Sopenharmony_cistatic bool enable_beep = 1; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cimodule_param(index, int, 0444); 2862306a36Sopenharmony_ciMODULE_PARM_DESC(index, "Index value for " CHIP_NAME " soundchip."); 2962306a36Sopenharmony_cimodule_param(id, charp, 0444); 3062306a36Sopenharmony_ciMODULE_PARM_DESC(id, "ID string for " CHIP_NAME " soundchip."); 3162306a36Sopenharmony_cimodule_param(enable_beep, bool, 0444); 3262306a36Sopenharmony_ciMODULE_PARM_DESC(enable_beep, "Enable beep using PCM."); 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic struct platform_device *device; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci/* 3862306a36Sopenharmony_ci */ 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistatic int snd_pmac_probe(struct platform_device *devptr) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci struct snd_card *card; 4362306a36Sopenharmony_ci struct snd_pmac *chip; 4462306a36Sopenharmony_ci char *name_ext; 4562306a36Sopenharmony_ci int err; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci err = snd_card_new(&devptr->dev, index, id, THIS_MODULE, 0, &card); 4862306a36Sopenharmony_ci if (err < 0) 4962306a36Sopenharmony_ci return err; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci err = snd_pmac_new(card, &chip); 5262306a36Sopenharmony_ci if (err < 0) 5362306a36Sopenharmony_ci goto __error; 5462306a36Sopenharmony_ci card->private_data = chip; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci switch (chip->model) { 5762306a36Sopenharmony_ci case PMAC_BURGUNDY: 5862306a36Sopenharmony_ci strcpy(card->driver, "PMac Burgundy"); 5962306a36Sopenharmony_ci strcpy(card->shortname, "PowerMac Burgundy"); 6062306a36Sopenharmony_ci sprintf(card->longname, "%s (Dev %d) Sub-frame %d", 6162306a36Sopenharmony_ci card->shortname, chip->device_id, chip->subframe); 6262306a36Sopenharmony_ci err = snd_pmac_burgundy_init(chip); 6362306a36Sopenharmony_ci if (err < 0) 6462306a36Sopenharmony_ci goto __error; 6562306a36Sopenharmony_ci break; 6662306a36Sopenharmony_ci case PMAC_DACA: 6762306a36Sopenharmony_ci strcpy(card->driver, "PMac DACA"); 6862306a36Sopenharmony_ci strcpy(card->shortname, "PowerMac DACA"); 6962306a36Sopenharmony_ci sprintf(card->longname, "%s (Dev %d) Sub-frame %d", 7062306a36Sopenharmony_ci card->shortname, chip->device_id, chip->subframe); 7162306a36Sopenharmony_ci err = snd_pmac_daca_init(chip); 7262306a36Sopenharmony_ci if (err < 0) 7362306a36Sopenharmony_ci goto __error; 7462306a36Sopenharmony_ci break; 7562306a36Sopenharmony_ci case PMAC_TUMBLER: 7662306a36Sopenharmony_ci case PMAC_SNAPPER: 7762306a36Sopenharmony_ci name_ext = chip->model == PMAC_TUMBLER ? "Tumbler" : "Snapper"; 7862306a36Sopenharmony_ci sprintf(card->driver, "PMac %s", name_ext); 7962306a36Sopenharmony_ci sprintf(card->shortname, "PowerMac %s", name_ext); 8062306a36Sopenharmony_ci sprintf(card->longname, "%s (Dev %d) Sub-frame %d", 8162306a36Sopenharmony_ci card->shortname, chip->device_id, chip->subframe); 8262306a36Sopenharmony_ci err = snd_pmac_tumbler_init(chip); 8362306a36Sopenharmony_ci if (err < 0) 8462306a36Sopenharmony_ci goto __error; 8562306a36Sopenharmony_ci err = snd_pmac_tumbler_post_init(); 8662306a36Sopenharmony_ci if (err < 0) 8762306a36Sopenharmony_ci goto __error; 8862306a36Sopenharmony_ci break; 8962306a36Sopenharmony_ci case PMAC_AWACS: 9062306a36Sopenharmony_ci case PMAC_SCREAMER: 9162306a36Sopenharmony_ci name_ext = chip->model == PMAC_SCREAMER ? "Screamer" : "AWACS"; 9262306a36Sopenharmony_ci sprintf(card->driver, "PMac %s", name_ext); 9362306a36Sopenharmony_ci sprintf(card->shortname, "PowerMac %s", name_ext); 9462306a36Sopenharmony_ci if (chip->is_pbook_3400) 9562306a36Sopenharmony_ci name_ext = " [PB3400]"; 9662306a36Sopenharmony_ci else if (chip->is_pbook_G3) 9762306a36Sopenharmony_ci name_ext = " [PBG3]"; 9862306a36Sopenharmony_ci else 9962306a36Sopenharmony_ci name_ext = ""; 10062306a36Sopenharmony_ci sprintf(card->longname, "%s%s Rev %d", 10162306a36Sopenharmony_ci card->shortname, name_ext, chip->revision); 10262306a36Sopenharmony_ci err = snd_pmac_awacs_init(chip); 10362306a36Sopenharmony_ci if (err < 0) 10462306a36Sopenharmony_ci goto __error; 10562306a36Sopenharmony_ci break; 10662306a36Sopenharmony_ci default: 10762306a36Sopenharmony_ci snd_printk(KERN_ERR "unsupported hardware %d\n", chip->model); 10862306a36Sopenharmony_ci err = -EINVAL; 10962306a36Sopenharmony_ci goto __error; 11062306a36Sopenharmony_ci } 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci err = snd_pmac_pcm_new(chip); 11362306a36Sopenharmony_ci if (err < 0) 11462306a36Sopenharmony_ci goto __error; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci chip->initialized = 1; 11762306a36Sopenharmony_ci if (enable_beep) 11862306a36Sopenharmony_ci snd_pmac_attach_beep(chip); 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci err = snd_card_register(card); 12162306a36Sopenharmony_ci if (err < 0) 12262306a36Sopenharmony_ci goto __error; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci platform_set_drvdata(devptr, card); 12562306a36Sopenharmony_ci return 0; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci__error: 12862306a36Sopenharmony_ci snd_card_free(card); 12962306a36Sopenharmony_ci return err; 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic void snd_pmac_remove(struct platform_device *devptr) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci snd_card_free(platform_get_drvdata(devptr)); 13662306a36Sopenharmony_ci} 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 13962306a36Sopenharmony_cistatic int snd_pmac_driver_suspend(struct device *dev) 14062306a36Sopenharmony_ci{ 14162306a36Sopenharmony_ci struct snd_card *card = dev_get_drvdata(dev); 14262306a36Sopenharmony_ci snd_pmac_suspend(card->private_data); 14362306a36Sopenharmony_ci return 0; 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistatic int snd_pmac_driver_resume(struct device *dev) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci struct snd_card *card = dev_get_drvdata(dev); 14962306a36Sopenharmony_ci snd_pmac_resume(card->private_data); 15062306a36Sopenharmony_ci return 0; 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(snd_pmac_pm, snd_pmac_driver_suspend, snd_pmac_driver_resume); 15462306a36Sopenharmony_ci#define SND_PMAC_PM_OPS &snd_pmac_pm 15562306a36Sopenharmony_ci#else 15662306a36Sopenharmony_ci#define SND_PMAC_PM_OPS NULL 15762306a36Sopenharmony_ci#endif 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci#define SND_PMAC_DRIVER "snd_powermac" 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_cistatic struct platform_driver snd_pmac_driver = { 16262306a36Sopenharmony_ci .probe = snd_pmac_probe, 16362306a36Sopenharmony_ci .remove_new = snd_pmac_remove, 16462306a36Sopenharmony_ci .driver = { 16562306a36Sopenharmony_ci .name = SND_PMAC_DRIVER, 16662306a36Sopenharmony_ci .pm = SND_PMAC_PM_OPS, 16762306a36Sopenharmony_ci }, 16862306a36Sopenharmony_ci}; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cistatic int __init alsa_card_pmac_init(void) 17162306a36Sopenharmony_ci{ 17262306a36Sopenharmony_ci int err; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci err = platform_driver_register(&snd_pmac_driver); 17562306a36Sopenharmony_ci if (err < 0) 17662306a36Sopenharmony_ci return err; 17762306a36Sopenharmony_ci device = platform_device_register_simple(SND_PMAC_DRIVER, -1, NULL, 0); 17862306a36Sopenharmony_ci return 0; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistatic void __exit alsa_card_pmac_exit(void) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci if (!IS_ERR(device)) 18562306a36Sopenharmony_ci platform_device_unregister(device); 18662306a36Sopenharmony_ci platform_driver_unregister(&snd_pmac_driver); 18762306a36Sopenharmony_ci} 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cimodule_init(alsa_card_pmac_init) 19062306a36Sopenharmony_cimodule_exit(alsa_card_pmac_exit) 191