1 /* 2 * Driver for Sound Core PDAudioCF soundcard 3 * 4 * Copyright (c) 2003 by Jaroslav Kysela <perex@suse.cz> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21 #include <sound/driver.h> 22 #include <sound/core.h> 23 #include <linux/slab.h> 24 #include <linux/moduleparam.h> 25 #include <pcmcia/ciscode.h> 26 #include <pcmcia/cisreg.h> 27 #include "pdaudiocf.h" 28 #include <sound/initval.h> 29 #include <linux/init.h> 30 31 /* 32 */ 33 34 #define CARD_NAME "PDAudio-CF" 35 36 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); 37 MODULE_DESCRIPTION("Sound Core " CARD_NAME); 38 MODULE_LICENSE("GPL"); 39 MODULE_SUPPORTED_DEVICE("{{Sound Core," CARD_NAME "}}"); 40 41 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 42 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 43 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */ 44 45 module_param_array(index, int, NULL, 0444); 46 MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); 47 module_param_array(id, charp, NULL, 0444); 48 MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); 49 module_param_array(enable, bool, NULL, 0444); 50 MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); 51 52 /* 53 */ 54 55 static struct snd_card *card_list[SNDRV_CARDS]; 56 57 /* 58 * prototypes 59 */ 60 static void pdacf_config(dev_link_t *link); 61 static void snd_pdacf_detach(struct pcmcia_device *p_dev); 62 63 static void pdacf_release(dev_link_t *link) 64 { 65 if (link->state & DEV_CONFIG) { 66 /* release cs resources */ 67 pcmcia_release_configuration(link->handle); 68 pcmcia_release_io(link->handle, &link->io); 69 pcmcia_release_irq(link->handle, &link->irq); 70 link->state &= ~DEV_CONFIG; 71 } 72 } 73 74 /* 75 * destructor 76 */ 77 static int snd_pdacf_free(struct snd_pdacf *pdacf) 78 { 79 dev_link_t *link = &pdacf->link; 80 81 pdacf_release(link); 82 83 card_list[pdacf->index] = NULL; 84 pdacf->card = NULL; 85 86 kfree(pdacf); 87 return 0; 88 } 89 90 static int snd_pdacf_dev_free(struct snd_device *device) 91 { 92 struct snd_pdacf *chip = device->device_data; 93 return snd_pdacf_free(chip); 94 } 95 96 /* 97 * snd_pdacf_attach - attach callback for cs 98 */ 99 static int snd_pdacf_attach(struct pcmcia_device *p_dev) 100 { 101 int i; 102 dev_link_t *link; /* Info for cardmgr */ 103 struct snd_pdacf *pdacf; 104 struct snd_card *card; 105 static struct snd_device_ops ops = { 106 .dev_free = snd_pdacf_dev_free, 107 }; 108 109 snd_printdd(KERN_DEBUG "pdacf_attach called\n"); 110 /* find an empty slot from the card list */ 111 for (i = 0; i < SNDRV_CARDS; i++) { 112 if (! card_list[i]) 113 break; 114 } 115 if (i >= SNDRV_CARDS) { 116 snd_printk(KERN_ERR "pdacf: too many cards found\n"); 117 return -EINVAL; 118 } 119 if (! enable[i]) 120 return -ENODEV; /* disabled explicitly */ 121 122 /* ok, create a card instance */ 123 card = snd_card_new(index[i], id[i], THIS_MODULE, 0); 124 if (card == NULL) { 125 snd_printk(KERN_ERR "pdacf: cannot create a card instance\n"); 126 return -ENOMEM; 127 } 128 129 pdacf = snd_pdacf_create(card); 130 if (! pdacf) 131 return -EIO; 132 133 if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, pdacf, &ops) < 0) { 134 kfree(pdacf); 135 snd_card_free(card); 136 return -ENODEV; 137 } 138 139 pdacf->index = i; 140 card_list[i] = card; 141 142 link = &pdacf->link; 143 link->priv = pdacf; 144 145 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; 146 link->io.NumPorts1 = 16; 147 148 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT | IRQ_FORCED_PULSE; 149 // link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; 150 151 link->irq.IRQInfo1 = 0 /* | IRQ_LEVEL_ID */; 152 link->irq.Handler = pdacf_interrupt; 153 link->irq.Instance = pdacf; 154 link->conf.Attributes = CONF_ENABLE_IRQ; 155 link->conf.IntType = INT_MEMORY_AND_IO; 156 link->conf.ConfigIndex = 1; 157 link->conf.Present = PRESENT_OPTION; 158 159 /* Chain drivers */ 160 link->next = NULL; 161 162 link->handle = p_dev; 163 pdacf_config(link); 164 165 return 0; 166 } 167 168 169 /** 170 * snd_pdacf_assign_resources - initialize the hardware and card instance. 171 * @port: i/o port for the card 172 * @irq: irq number for the card 173 * 174 * this function assigns the specified port and irq, boot the card, 175 * create pcm and control instances, and initialize the rest hardware. 176 * 177 * returns 0 if successful, or a negative error code. 178 */ 179 static int snd_pdacf_assign_resources(struct snd_pdacf *pdacf, int port, int irq) 180 { 181 int err; 182 struct snd_card *card = pdacf->card; 183 184 snd_printdd(KERN_DEBUG "pdacf assign resources: port = 0x%x, irq = %d\n", port, irq); 185 pdacf->port = port; 186 pdacf->irq = irq; 187 pdacf->chip_status |= PDAUDIOCF_STAT_IS_CONFIGURED; 188 189 err = snd_pdacf_ak4117_create(pdacf); 190 if (err < 0) 191 return err; 192 193 strcpy(card->driver, "PDAudio-CF"); 194 sprintf(card->shortname, "Core Sound %s", card->driver); 195 sprintf(card->longname, "%s at 0x%x, irq %i", 196 card->shortname, port, irq); 197 198 err = snd_pdacf_pcm_new(pdacf); 199 if (err < 0) 200 return err; 201 202 if ((err = snd_card_register(card)) < 0) 203 return err; 204 205 return 0; 206 } 207 208 209 /* 210 * snd_pdacf_detach - detach callback for cs 211 */ 212 static void snd_pdacf_detach(struct pcmcia_device *p_dev) 213 { 214 dev_link_t *link = dev_to_instance(p_dev); 215 struct snd_pdacf *chip = link->priv; 216 217 snd_printdd(KERN_DEBUG "pdacf_detach called\n"); 218 219 if (chip->chip_status & PDAUDIOCF_STAT_IS_CONFIGURED) 220 snd_pdacf_powerdown(chip); 221 chip->chip_status |= PDAUDIOCF_STAT_IS_STALE; /* to be sure */ 222 snd_card_disconnect(chip->card); 223 snd_card_free_in_thread(chip->card); 224 } 225 226 /* 227 * configuration callback 228 */ 229 230 #define CS_CHECK(fn, ret) \ 231 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) 232 233 static void pdacf_config(dev_link_t *link) 234 { 235 client_handle_t handle = link->handle; 236 struct snd_pdacf *pdacf = link->priv; 237 tuple_t tuple; 238 cisparse_t *parse = NULL; 239 config_info_t conf; 240 u_short buf[32]; 241 int last_fn, last_ret; 242 243 snd_printdd(KERN_DEBUG "pdacf_config called\n"); 244 parse = kmalloc(sizeof(*parse), GFP_KERNEL); 245 if (! parse) { 246 snd_printk(KERN_ERR "pdacf_config: cannot allocate\n"); 247 return; 248 } 249 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 250 tuple.Attributes = 0; 251 tuple.TupleData = (cisdata_t *)buf; 252 tuple.TupleDataMax = sizeof(buf); 253 tuple.TupleOffset = 0; 254 tuple.DesiredTuple = CISTPL_CONFIG; 255 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); 256 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); 257 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse)); 258 link->conf.ConfigBase = parse->config.base; 259 link->conf.ConfigIndex = 0x5; 260 kfree(parse); 261 262 CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); 263 link->conf.Vcc = conf.Vcc; 264 265 /* Configure card */ 266 link->state |= DEV_CONFIG; 267 268 CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io)); 269 CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); 270 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); 271 272 if (snd_pdacf_assign_resources(pdacf, link->io.BasePort1, link->irq.AssignedIRQ) < 0) 273 goto failed; 274 275 link->dev = &pdacf->node; 276 link->state &= ~DEV_CONFIG_PENDING; 277 return; 278 279 cs_failed: 280 cs_error(link->handle, last_fn, last_ret); 281 failed: 282 pcmcia_release_configuration(link->handle); 283 pcmcia_release_io(link->handle, &link->io); 284 pcmcia_release_irq(link->handle, &link->irq); 285 } 286 287 #ifdef CONFIG_PM 288 289 static int pdacf_suspend(struct pcmcia_device *dev) 290 { 291 dev_link_t *link = dev_to_instance(dev); 292 struct snd_pdacf *chip = link->priv; 293 294 snd_printdd(KERN_DEBUG "SUSPEND\n"); 295 link->state |= DEV_SUSPEND; 296 if (chip) { 297 snd_printdd(KERN_DEBUG "snd_pdacf_suspend calling\n"); 298 snd_pdacf_suspend(chip, PMSG_SUSPEND); 299 } 300 301 snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n"); 302 if (link->state & DEV_CONFIG) 303 pcmcia_release_configuration(link->handle); 304 305 return 0; 306 } 307 308 static int pdacf_resume(struct pcmcia_device *dev) 309 { 310 dev_link_t *link = dev_to_instance(dev); 311 struct snd_pdacf *chip = link->priv; 312 313 snd_printdd(KERN_DEBUG "RESUME\n"); 314 link->state &= ~DEV_SUSPEND; 315 316 snd_printdd(KERN_DEBUG "CARD_RESET\n"); 317 if (DEV_OK(link)) { 318 snd_printdd(KERN_DEBUG "requestconfig...\n"); 319 pcmcia_request_configuration(link->handle, &link->conf); 320 if (chip) { 321 snd_printdd(KERN_DEBUG "calling snd_pdacf_resume\n"); 322 snd_pdacf_resume(chip); 323 } 324 } 325 snd_printdd(KERN_DEBUG "resume done!\n"); 326 327 return 0; 328 } 329 330 #endif 331 332 /* 333 * Module entry points 334 */ 335 static struct pcmcia_device_id snd_pdacf_ids[] = { 336 PCMCIA_DEVICE_MANF_CARD(0x015d, 0x4c45), 337 PCMCIA_DEVICE_NULL 338 }; 339 MODULE_DEVICE_TABLE(pcmcia, snd_pdacf_ids); 340 341 static struct pcmcia_driver pdacf_cs_driver = { 342 .owner = THIS_MODULE, 343 .drv = { 344 .name = "snd-pdaudiocf", 345 }, 346 .probe = snd_pdacf_attach, 347 .remove = snd_pdacf_detach, 348 .id_table = snd_pdacf_ids, 349 #ifdef CONFIG_PM 350 .suspend = pdacf_suspend, 351 .resume = pdacf_resume, 352 #endif 353 354 }; 355 356 static int __init init_pdacf(void) 357 { 358 return pcmcia_register_driver(&pdacf_cs_driver); 359 } 360 361 static void __exit exit_pdacf(void) 362 { 363 pcmcia_unregister_driver(&pdacf_cs_driver); 364 } 365 366 module_init(init_pdacf); 367 module_exit(exit_pdacf); 368