0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/init.h>
0011 #include <linux/module.h>
0012 #include <linux/slab.h>
0013 #include <sound/core.h>
0014 #include "vxpocket.h"
0015 #include <pcmcia/ciscode.h>
0016 #include <pcmcia/cisreg.h>
0017 #include <sound/initval.h>
0018 #include <sound/tlv.h>
0019
0020 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
0021 MODULE_DESCRIPTION("Digigram VXPocket");
0022 MODULE_LICENSE("GPL");
0023
0024 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
0025 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
0026 static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
0027 static int ibl[SNDRV_CARDS];
0028
0029 module_param_array(index, int, NULL, 0444);
0030 MODULE_PARM_DESC(index, "Index value for VXPocket soundcard.");
0031 module_param_array(id, charp, NULL, 0444);
0032 MODULE_PARM_DESC(id, "ID string for VXPocket soundcard.");
0033 module_param_array(enable, bool, NULL, 0444);
0034 MODULE_PARM_DESC(enable, "Enable VXPocket soundcard.");
0035 module_param_array(ibl, int, NULL, 0444);
0036 MODULE_PARM_DESC(ibl, "Capture IBL size for VXPocket soundcard.");
0037
0038
0039
0040
0041
0042 static unsigned int card_alloc;
0043
0044
0045
0046
0047 static void vxpocket_release(struct pcmcia_device *link)
0048 {
0049 free_irq(link->irq, link->priv);
0050 pcmcia_disable_device(link);
0051 }
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066 static const DECLARE_TLV_DB_SCALE(db_scale_old_vol, -11350, 50, 0);
0067
0068 static const struct snd_vx_hardware vxpocket_hw = {
0069 .name = "VXPocket",
0070 .type = VX_TYPE_VXPOCKET,
0071
0072
0073 .num_codecs = 1,
0074 .num_ins = 1,
0075 .num_outs = 1,
0076 .output_level_max = VX_ANALOG_OUT_LEVEL_MAX,
0077 .output_level_db_scale = db_scale_old_vol,
0078 };
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090 static const struct snd_vx_hardware vxp440_hw = {
0091 .name = "VXPocket440",
0092 .type = VX_TYPE_VXP440,
0093
0094
0095 .num_codecs = 2,
0096 .num_ins = 2,
0097 .num_outs = 2,
0098 .output_level_max = VX_ANALOG_OUT_LEVEL_MAX,
0099 .output_level_db_scale = db_scale_old_vol,
0100 };
0101
0102
0103
0104
0105
0106 static int snd_vxpocket_new(struct snd_card *card, int ibl,
0107 struct pcmcia_device *link,
0108 struct snd_vxpocket **chip_ret)
0109 {
0110 struct vx_core *chip;
0111 struct snd_vxpocket *vxp;
0112
0113 chip = snd_vx_create(card, &vxpocket_hw, &snd_vxpocket_ops,
0114 sizeof(struct snd_vxpocket) - sizeof(struct vx_core));
0115 if (!chip)
0116 return -ENOMEM;
0117
0118 chip->ibl.size = ibl;
0119
0120 vxp = to_vxpocket(chip);
0121
0122 vxp->p_dev = link;
0123 link->priv = chip;
0124
0125 link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
0126 link->resource[0]->end = 16;
0127
0128 link->config_flags |= CONF_ENABLE_IRQ;
0129 link->config_index = 1;
0130 link->config_regs = PRESENT_OPTION;
0131
0132 *chip_ret = vxp;
0133 return 0;
0134 }
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148 static int snd_vxpocket_assign_resources(struct vx_core *chip, int port, int irq)
0149 {
0150 int err;
0151 struct snd_card *card = chip->card;
0152 struct snd_vxpocket *vxp = to_vxpocket(chip);
0153
0154 snd_printdd(KERN_DEBUG "vxpocket assign resources: port = 0x%x, irq = %d\n", port, irq);
0155 vxp->port = port;
0156
0157 sprintf(card->shortname, "Digigram %s", card->driver);
0158 sprintf(card->longname, "%s at 0x%x, irq %i",
0159 card->shortname, port, irq);
0160
0161 chip->irq = irq;
0162 card->sync_irq = chip->irq;
0163
0164 err = snd_vx_setup_firmware(chip);
0165 if (err < 0)
0166 return err;
0167
0168 return 0;
0169 }
0170
0171
0172
0173
0174
0175
0176 static int vxpocket_config(struct pcmcia_device *link)
0177 {
0178 struct vx_core *chip = link->priv;
0179 int ret;
0180
0181 snd_printdd(KERN_DEBUG "vxpocket_config called\n");
0182
0183
0184 if (!strcmp(link->prod_id[1], "VX-POCKET")) {
0185 snd_printdd("VX-pocket is detected\n");
0186 } else {
0187 snd_printdd("VX-pocket 440 is detected\n");
0188
0189 chip->hw = &vxp440_hw;
0190 chip->type = vxp440_hw.type;
0191 strcpy(chip->card->driver, vxp440_hw.name);
0192 }
0193
0194 ret = pcmcia_request_io(link);
0195 if (ret)
0196 goto failed_preirq;
0197
0198 ret = request_threaded_irq(link->irq, snd_vx_irq_handler,
0199 snd_vx_threaded_irq_handler,
0200 IRQF_SHARED, link->devname, link->priv);
0201 if (ret)
0202 goto failed_preirq;
0203
0204 ret = pcmcia_enable_device(link);
0205 if (ret)
0206 goto failed;
0207
0208 chip->dev = &link->dev;
0209
0210 if (snd_vxpocket_assign_resources(chip, link->resource[0]->start,
0211 link->irq) < 0)
0212 goto failed;
0213
0214 return 0;
0215
0216 failed:
0217 free_irq(link->irq, link->priv);
0218 failed_preirq:
0219 pcmcia_disable_device(link);
0220 return -ENODEV;
0221 }
0222
0223 #ifdef CONFIG_PM
0224
0225 static int vxp_suspend(struct pcmcia_device *link)
0226 {
0227 struct vx_core *chip = link->priv;
0228
0229 snd_printdd(KERN_DEBUG "SUSPEND\n");
0230 if (chip) {
0231 snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n");
0232 snd_vx_suspend(chip);
0233 }
0234
0235 return 0;
0236 }
0237
0238 static int vxp_resume(struct pcmcia_device *link)
0239 {
0240 struct vx_core *chip = link->priv;
0241
0242 snd_printdd(KERN_DEBUG "RESUME\n");
0243 if (pcmcia_dev_present(link)) {
0244
0245 if (chip) {
0246 snd_printdd(KERN_DEBUG "calling snd_vx_resume\n");
0247 snd_vx_resume(chip);
0248 }
0249 }
0250 snd_printdd(KERN_DEBUG "resume done!\n");
0251
0252 return 0;
0253 }
0254
0255 #endif
0256
0257
0258
0259
0260 static int vxpocket_probe(struct pcmcia_device *p_dev)
0261 {
0262 struct snd_card *card;
0263 struct snd_vxpocket *vxp;
0264 int i, err;
0265
0266
0267 for (i = 0; i < SNDRV_CARDS; i++) {
0268 if (!(card_alloc & (1 << i)))
0269 break;
0270 }
0271 if (i >= SNDRV_CARDS) {
0272 snd_printk(KERN_ERR "vxpocket: too many cards found\n");
0273 return -EINVAL;
0274 }
0275 if (! enable[i])
0276 return -ENODEV;
0277
0278
0279 err = snd_card_new(&p_dev->dev, index[i], id[i], THIS_MODULE,
0280 0, &card);
0281 if (err < 0) {
0282 snd_printk(KERN_ERR "vxpocket: cannot create a card instance\n");
0283 return err;
0284 }
0285
0286 err = snd_vxpocket_new(card, ibl[i], p_dev, &vxp);
0287 if (err < 0) {
0288 snd_card_free(card);
0289 return err;
0290 }
0291 card->private_data = vxp;
0292
0293 vxp->index = i;
0294 card_alloc |= 1 << i;
0295
0296 vxp->p_dev = p_dev;
0297
0298 return vxpocket_config(p_dev);
0299 }
0300
0301 static void vxpocket_detach(struct pcmcia_device *link)
0302 {
0303 struct snd_vxpocket *vxp;
0304 struct vx_core *chip;
0305
0306 if (! link)
0307 return;
0308
0309 vxp = link->priv;
0310 chip = (struct vx_core *)vxp;
0311 card_alloc &= ~(1 << vxp->index);
0312
0313 chip->chip_status |= VX_STAT_IS_STALE;
0314 snd_card_disconnect(chip->card);
0315 vxpocket_release(link);
0316 snd_card_free_when_closed(chip->card);
0317 }
0318
0319
0320
0321
0322
0323 static const struct pcmcia_device_id vxp_ids[] = {
0324 PCMCIA_DEVICE_MANF_CARD(0x01f1, 0x0100),
0325 PCMCIA_DEVICE_NULL
0326 };
0327 MODULE_DEVICE_TABLE(pcmcia, vxp_ids);
0328
0329 static struct pcmcia_driver vxp_cs_driver = {
0330 .owner = THIS_MODULE,
0331 .name = "snd-vxpocket",
0332 .probe = vxpocket_probe,
0333 .remove = vxpocket_detach,
0334 .id_table = vxp_ids,
0335 #ifdef CONFIG_PM
0336 .suspend = vxp_suspend,
0337 .resume = vxp_resume,
0338 #endif
0339 };
0340 module_pcmcia_driver(vxp_cs_driver);