162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * C-Media CMI8788 driver for Asus Xonar cards
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/pci.h>
962306a36Sopenharmony_ci#include <linux/delay.h>
1062306a36Sopenharmony_ci#include <linux/module.h>
1162306a36Sopenharmony_ci#include <sound/core.h>
1262306a36Sopenharmony_ci#include <sound/initval.h>
1362306a36Sopenharmony_ci#include <sound/pcm.h>
1462306a36Sopenharmony_ci#include "xonar.h"
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ciMODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
1762306a36Sopenharmony_ciMODULE_DESCRIPTION("Asus Virtuoso driver");
1862306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistatic int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
2162306a36Sopenharmony_cistatic char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
2262306a36Sopenharmony_cistatic bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_cimodule_param_array(index, int, NULL, 0444);
2562306a36Sopenharmony_ciMODULE_PARM_DESC(index, "card index");
2662306a36Sopenharmony_cimodule_param_array(id, charp, NULL, 0444);
2762306a36Sopenharmony_ciMODULE_PARM_DESC(id, "ID string");
2862306a36Sopenharmony_cimodule_param_array(enable, bool, NULL, 0444);
2962306a36Sopenharmony_ciMODULE_PARM_DESC(enable, "enable card");
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_cistatic const struct pci_device_id xonar_ids[] = {
3262306a36Sopenharmony_ci	{ OXYGEN_PCI_SUBID(0x1043, 0x8269) },
3362306a36Sopenharmony_ci	{ OXYGEN_PCI_SUBID(0x1043, 0x8275) },
3462306a36Sopenharmony_ci	{ OXYGEN_PCI_SUBID(0x1043, 0x82b7) },
3562306a36Sopenharmony_ci	{ OXYGEN_PCI_SUBID(0x1043, 0x8314) },
3662306a36Sopenharmony_ci	{ OXYGEN_PCI_SUBID(0x1043, 0x8327) },
3762306a36Sopenharmony_ci	{ OXYGEN_PCI_SUBID(0x1043, 0x834f) },
3862306a36Sopenharmony_ci	{ OXYGEN_PCI_SUBID(0x1043, 0x835c) },
3962306a36Sopenharmony_ci	{ OXYGEN_PCI_SUBID(0x1043, 0x835d) },
4062306a36Sopenharmony_ci	{ OXYGEN_PCI_SUBID(0x1043, 0x835e) },
4162306a36Sopenharmony_ci	{ OXYGEN_PCI_SUBID(0x1043, 0x838e) },
4262306a36Sopenharmony_ci	{ OXYGEN_PCI_SUBID(0x1043, 0x8428) },
4362306a36Sopenharmony_ci	{ OXYGEN_PCI_SUBID(0x1043, 0x8522) },
4462306a36Sopenharmony_ci	{ OXYGEN_PCI_SUBID(0x1043, 0x85f4) },
4562306a36Sopenharmony_ci	{ OXYGEN_PCI_SUBID_BROKEN_EEPROM },
4662306a36Sopenharmony_ci	{ }
4762306a36Sopenharmony_ci};
4862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, xonar_ids);
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistatic int get_xonar_model(struct oxygen *chip,
5162306a36Sopenharmony_ci			   const struct pci_device_id *id)
5262306a36Sopenharmony_ci{
5362306a36Sopenharmony_ci	if (get_xonar_pcm179x_model(chip, id) >= 0)
5462306a36Sopenharmony_ci		return 0;
5562306a36Sopenharmony_ci	if (get_xonar_cs43xx_model(chip, id) >= 0)
5662306a36Sopenharmony_ci		return 0;
5762306a36Sopenharmony_ci	if (get_xonar_wm87x6_model(chip, id) >= 0)
5862306a36Sopenharmony_ci		return 0;
5962306a36Sopenharmony_ci	return -EINVAL;
6062306a36Sopenharmony_ci}
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_cistatic int xonar_probe(struct pci_dev *pci,
6362306a36Sopenharmony_ci		       const struct pci_device_id *pci_id)
6462306a36Sopenharmony_ci{
6562306a36Sopenharmony_ci	static int dev;
6662306a36Sopenharmony_ci	int err;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	if (dev >= SNDRV_CARDS)
6962306a36Sopenharmony_ci		return -ENODEV;
7062306a36Sopenharmony_ci	if (!enable[dev]) {
7162306a36Sopenharmony_ci		++dev;
7262306a36Sopenharmony_ci		return -ENOENT;
7362306a36Sopenharmony_ci	}
7462306a36Sopenharmony_ci	err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE,
7562306a36Sopenharmony_ci			       xonar_ids, get_xonar_model);
7662306a36Sopenharmony_ci	if (err >= 0)
7762306a36Sopenharmony_ci		++dev;
7862306a36Sopenharmony_ci	return err;
7962306a36Sopenharmony_ci}
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_cistatic struct pci_driver xonar_driver = {
8262306a36Sopenharmony_ci	.name = KBUILD_MODNAME,
8362306a36Sopenharmony_ci	.id_table = xonar_ids,
8462306a36Sopenharmony_ci	.probe = xonar_probe,
8562306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP
8662306a36Sopenharmony_ci	.driver = {
8762306a36Sopenharmony_ci		.pm = &oxygen_pci_pm,
8862306a36Sopenharmony_ci	},
8962306a36Sopenharmony_ci#endif
9062306a36Sopenharmony_ci	.shutdown = oxygen_pci_shutdown,
9162306a36Sopenharmony_ci};
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cimodule_pci_driver(xonar_driver);
94