treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156
[linux-block.git] / sound / isa / cs423x / cs4231.c
CommitLineData
1a59d1b8 1// SPDX-License-Identifier: GPL-2.0-or-later
1da177e4
LT
2/*
3 * Generic driver for CS4231 chips
c1017a4c 4 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
1da177e4
LT
5 * Originally the CS4232/CS4232A driver, modified for use on CS4231 by
6 * Tugrul Galatali <galatalt@stuy.edu>
1da177e4
LT
7 */
8
1da177e4 9#include <linux/init.h>
8b913757 10#include <linux/err.h>
d63898c9 11#include <linux/isa.h>
1da177e4
LT
12#include <linux/time.h>
13#include <linux/wait.h>
65a77217 14#include <linux/module.h>
1da177e4 15#include <sound/core.h>
61ef19d7 16#include <sound/wss.h>
1da177e4
LT
17#include <sound/mpu401.h>
18#include <sound/initval.h>
19
d63898c9
RH
20#define CRD_NAME "Generic CS4231"
21#define DEV_NAME "cs4231"
22
23MODULE_DESCRIPTION(CRD_NAME);
c1017a4c 24MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
1da177e4
LT
25MODULE_LICENSE("GPL");
26MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4231}}");
27
28static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
29static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
a67ff6a5 30static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
1da177e4
LT
31static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
32static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
33static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,11,12,15 */
34static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 9,11,12,15 */
35static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
36static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
37
38module_param_array(index, int, NULL, 0444);
d63898c9 39MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
1da177e4 40module_param_array(id, charp, NULL, 0444);
d63898c9 41MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
1da177e4 42module_param_array(enable, bool, NULL, 0444);
d63898c9 43MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
e992ef57 44module_param_hw_array(port, long, ioport, NULL, 0444);
d63898c9 45MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
e992ef57 46module_param_hw_array(mpu_port, long, ioport, NULL, 0444);
d63898c9 47MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver.");
e992ef57 48module_param_hw_array(irq, int, irq, NULL, 0444);
d63898c9 49MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
e992ef57 50module_param_hw_array(mpu_irq, int, irq, NULL, 0444);
d63898c9 51MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver.");
e992ef57 52module_param_hw_array(dma1, int, dma, NULL, 0444);
d63898c9 53MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver.");
e992ef57 54module_param_hw_array(dma2, int, dma, NULL, 0444);
d63898c9 55MODULE_PARM_DESC(dma2, "DMA2 # for " CRD_NAME " driver.");
1da177e4 56
1bff292e 57static int snd_cs4231_match(struct device *dev, unsigned int n)
d63898c9
RH
58{
59 if (!enable[n])
60 return 0;
f7a9275d 61
d63898c9 62 if (port[n] == SNDRV_AUTO_PORT) {
0418ff0c 63 dev_err(dev, "please specify port\n");
d63898c9
RH
64 return 0;
65 }
66 if (irq[n] == SNDRV_AUTO_IRQ) {
0418ff0c 67 dev_err(dev, "please specify irq\n");
d63898c9
RH
68 return 0;
69 }
70 if (dma1[n] == SNDRV_AUTO_DMA) {
0418ff0c 71 dev_err(dev, "please specify dma1\n");
d63898c9
RH
72 return 0;
73 }
74 return 1;
75}
1da177e4 76
1bff292e 77static int snd_cs4231_probe(struct device *dev, unsigned int n)
1da177e4 78{
ba2375a4 79 struct snd_card *card;
7779f75f 80 struct snd_wss *chip;
d63898c9 81 int error;
1da177e4 82
4323cc4d 83 error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
c95eadd2
TI
84 if (error < 0)
85 return error;
d63898c9 86
7779f75f
KH
87 error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], dma2[n],
88 WSS_HW_DETECT, 0, &chip);
d63898c9
RH
89 if (error < 0)
90 goto out;
91
8b913757 92 card->private_data = chip;
1da177e4 93
fa60c065 94 error = snd_wss_pcm(chip, 0);
d63898c9
RH
95 if (error < 0)
96 goto out;
1da177e4 97
6d8b04de
AB
98 strlcpy(card->driver, "CS4231", sizeof(card->driver));
99 strlcpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
100
101 if (dma2[n] < 0)
102 snprintf(card->longname, sizeof(card->longname),
103 "%s at 0x%lx, irq %d, dma %d",
104 chip->pcm->name, chip->port, irq[n], dma1[n]);
105 else
106 snprintf(card->longname, sizeof(card->longname),
107 "%s at 0x%lx, irq %d, dma %d&%d",
108 chip->pcm->name, chip->port, irq[n], dma1[n], dma2[n]);
d63898c9 109
7779f75f 110 error = snd_wss_mixer(chip);
d63898c9
RH
111 if (error < 0)
112 goto out;
113
fa60c065 114 error = snd_wss_timer(chip, 0);
d63898c9
RH
115 if (error < 0)
116 goto out;
117
118 if (mpu_port[n] > 0 && mpu_port[n] != SNDRV_AUTO_PORT) {
119 if (mpu_irq[n] == SNDRV_AUTO_IRQ)
120 mpu_irq[n] = -1;
1da177e4 121 if (snd_mpu401_uart_new(card, 0, MPU401_HW_CS4232,
d63898c9 122 mpu_port[n], 0, mpu_irq[n],
1da177e4 123 NULL) < 0)
0418ff0c 124 dev_warn(dev, "MPU401 not detected\n");
1da177e4 125 }
43bcd973 126
d63898c9
RH
127 error = snd_card_register(card);
128 if (error < 0)
129 goto out;
8b913757 130
d63898c9 131 dev_set_drvdata(dev, card);
1da177e4 132 return 0;
43bcd973 133
d63898c9
RH
134out: snd_card_free(card);
135 return error;
1da177e4
LT
136}
137
1bff292e 138static int snd_cs4231_remove(struct device *dev, unsigned int n)
8b913757 139{
d63898c9 140 snd_card_free(dev_get_drvdata(dev));
8b913757
TI
141 return 0;
142}
143
144#ifdef CONFIG_PM
d63898c9 145static int snd_cs4231_suspend(struct device *dev, unsigned int n, pm_message_t state)
1da177e4 146{
d63898c9 147 struct snd_card *card = dev_get_drvdata(dev);
7779f75f 148 struct snd_wss *chip = card->private_data;
d63898c9 149
8b913757 150 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
8b913757
TI
151 chip->suspend(chip);
152 return 0;
153}
1da177e4 154
d63898c9 155static int snd_cs4231_resume(struct device *dev, unsigned int n)
8b913757 156{
d63898c9 157 struct snd_card *card = dev_get_drvdata(dev);
7779f75f 158 struct snd_wss *chip = card->private_data;
d63898c9 159
8b913757
TI
160 chip->resume(chip);
161 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
162 return 0;
163}
164#endif
165
d63898c9
RH
166static struct isa_driver snd_cs4231_driver = {
167 .match = snd_cs4231_match,
8b913757 168 .probe = snd_cs4231_probe,
1bff292e 169 .remove = snd_cs4231_remove,
8b913757
TI
170#ifdef CONFIG_PM
171 .suspend = snd_cs4231_suspend,
172 .resume = snd_cs4231_resume,
173#endif
174 .driver = {
d63898c9
RH
175 .name = DEV_NAME
176 }
8b913757
TI
177};
178
ec5c0896 179module_isa_driver(snd_cs4231_driver, SNDRV_CARDS);