1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * xfi linux driver. |
4 | * |
5 | * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. |
6 | */ |
7 | |
8 | #include <linux/init.h> |
9 | #include <linux/pci.h> |
10 | #include <linux/moduleparam.h> |
11 | #include <linux/pci_ids.h> |
12 | #include <linux/module.h> |
13 | #include <sound/core.h> |
14 | #include <sound/initval.h> |
15 | #include "ctatc.h" |
16 | #include "cthardware.h" |
17 | |
18 | MODULE_AUTHOR("Creative Technology Ltd" ); |
19 | MODULE_DESCRIPTION("X-Fi driver version 1.03" ); |
20 | MODULE_LICENSE("GPL v2" ); |
21 | |
22 | static unsigned int reference_rate = 48000; |
23 | static unsigned int multiple = 2; |
24 | MODULE_PARM_DESC(reference_rate, "Reference rate (default=48000)" ); |
25 | module_param(reference_rate, uint, 0444); |
26 | MODULE_PARM_DESC(multiple, "Rate multiplier (default=2)" ); |
27 | module_param(multiple, uint, 0444); |
28 | |
29 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; |
30 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; |
31 | static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; |
32 | static unsigned int subsystem[SNDRV_CARDS]; |
33 | |
34 | module_param_array(index, int, NULL, 0444); |
35 | MODULE_PARM_DESC(index, "Index value for Creative X-Fi driver" ); |
36 | module_param_array(id, charp, NULL, 0444); |
37 | MODULE_PARM_DESC(id, "ID string for Creative X-Fi driver" ); |
38 | module_param_array(enable, bool, NULL, 0444); |
39 | MODULE_PARM_DESC(enable, "Enable Creative X-Fi driver" ); |
40 | module_param_array(subsystem, int, NULL, 0444); |
41 | MODULE_PARM_DESC(subsystem, "Override subsystem ID for Creative X-Fi driver" ); |
42 | |
43 | static const struct pci_device_id ct_pci_dev_ids[] = { |
44 | /* only X-Fi is supported, so... */ |
45 | { PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_20K1), |
46 | .driver_data = ATC20K1, |
47 | }, |
48 | { PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_20K2), |
49 | .driver_data = ATC20K2, |
50 | }, |
51 | { 0, } |
52 | }; |
53 | MODULE_DEVICE_TABLE(pci, ct_pci_dev_ids); |
54 | |
55 | static int |
56 | ct_card_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) |
57 | { |
58 | static int dev; |
59 | struct snd_card *card; |
60 | struct ct_atc *atc; |
61 | int err; |
62 | |
63 | if (dev >= SNDRV_CARDS) |
64 | return -ENODEV; |
65 | |
66 | if (!enable[dev]) { |
67 | dev++; |
68 | return -ENOENT; |
69 | } |
70 | err = snd_card_new(parent: &pci->dev, idx: index[dev], xid: id[dev], THIS_MODULE, |
71 | extra_size: 0, card_ret: &card); |
72 | if (err) |
73 | return err; |
74 | if ((reference_rate != 48000) && (reference_rate != 44100)) { |
75 | dev_err(card->dev, |
76 | "Invalid reference_rate value %u!!!\n" , |
77 | reference_rate); |
78 | dev_err(card->dev, |
79 | "The valid values for reference_rate are 48000 and 44100, Value 48000 is assumed.\n" ); |
80 | reference_rate = 48000; |
81 | } |
82 | if ((multiple != 1) && (multiple != 2) && (multiple != 4)) { |
83 | dev_err(card->dev, "Invalid multiple value %u!!!\n" , |
84 | multiple); |
85 | dev_err(card->dev, |
86 | "The valid values for multiple are 1, 2 and 4, Value 2 is assumed.\n" ); |
87 | multiple = 2; |
88 | } |
89 | err = ct_atc_create(card, pci, rsr: reference_rate, msr: multiple, |
90 | chip_type: pci_id->driver_data, subsysid: subsystem[dev], ratc: &atc); |
91 | if (err < 0) |
92 | goto error; |
93 | |
94 | card->private_data = atc; |
95 | |
96 | /* Create alsa devices supported by this card */ |
97 | err = ct_atc_create_alsa_devs(atc); |
98 | if (err < 0) |
99 | goto error; |
100 | |
101 | strcpy(p: card->driver, q: "SB-XFi" ); |
102 | strcpy(p: card->shortname, q: "Creative X-Fi" ); |
103 | snprintf(buf: card->longname, size: sizeof(card->longname), fmt: "%s %s %s" , |
104 | card->shortname, atc->chip_name, atc->model_name); |
105 | |
106 | err = snd_card_register(card); |
107 | if (err < 0) |
108 | goto error; |
109 | |
110 | pci_set_drvdata(pdev: pci, data: card); |
111 | dev++; |
112 | |
113 | return 0; |
114 | |
115 | error: |
116 | snd_card_free(card); |
117 | return err; |
118 | } |
119 | |
120 | static void ct_card_remove(struct pci_dev *pci) |
121 | { |
122 | snd_card_free(card: pci_get_drvdata(pdev: pci)); |
123 | } |
124 | |
125 | #ifdef CONFIG_PM_SLEEP |
126 | static int ct_card_suspend(struct device *dev) |
127 | { |
128 | struct snd_card *card = dev_get_drvdata(dev); |
129 | struct ct_atc *atc = card->private_data; |
130 | |
131 | return atc->suspend(atc); |
132 | } |
133 | |
134 | static int ct_card_resume(struct device *dev) |
135 | { |
136 | struct snd_card *card = dev_get_drvdata(dev); |
137 | struct ct_atc *atc = card->private_data; |
138 | |
139 | return atc->resume(atc); |
140 | } |
141 | |
142 | static SIMPLE_DEV_PM_OPS(ct_card_pm, ct_card_suspend, ct_card_resume); |
143 | #define CT_CARD_PM_OPS &ct_card_pm |
144 | #else |
145 | #define CT_CARD_PM_OPS NULL |
146 | #endif |
147 | |
148 | static struct pci_driver ct_driver = { |
149 | .name = KBUILD_MODNAME, |
150 | .id_table = ct_pci_dev_ids, |
151 | .probe = ct_card_probe, |
152 | .remove = ct_card_remove, |
153 | .driver = { |
154 | .pm = CT_CARD_PM_OPS, |
155 | }, |
156 | }; |
157 | |
158 | module_pci_driver(ct_driver); |
159 | |