diff options
Diffstat (limited to 'sound/sparc')
| -rw-r--r-- | sound/sparc/Kconfig | 17 | ||||
| -rw-r--r-- | sound/sparc/amd7930.c | 152 | ||||
| -rw-r--r-- | sound/sparc/cs4231.c | 1105 | ||||
| -rw-r--r-- | sound/sparc/dbri.c | 700 |
4 files changed, 874 insertions, 1100 deletions
diff --git a/sound/sparc/Kconfig b/sound/sparc/Kconfig index 079e22af074..d75deba5617 100644 --- a/sound/sparc/Kconfig +++ b/sound/sparc/Kconfig @@ -1,11 +1,17 @@ # ALSA Sparc drivers -menu "ALSA Sparc devices" - depends on SND!=n && SPARC +menuconfig SND_SPARC + bool "Sparc sound devices" + depends on SPARC + default y + help + Support for sound devices specific to Sun SPARC architectures. + +if SND_SPARC config SND_SUN_AMD7930 tristate "Sun AMD7930" - depends on SBUS && SND + depends on SBUS select SND_PCM help Say Y here to include support for AMD7930 sound device on Sun. @@ -15,7 +21,6 @@ config SND_SUN_AMD7930 config SND_SUN_CS4231 tristate "Sun CS4231" - depends on SND select SND_PCM help Say Y here to include support for CS4231 sound device on Sun. @@ -25,7 +30,7 @@ config SND_SUN_CS4231 config SND_SUN_DBRI tristate "Sun DBRI" - depends on SND && SBUS + depends on SBUS select SND_PCM help Say Y here to include support for DBRI sound device on Sun. @@ -33,4 +38,4 @@ config SND_SUN_DBRI To compile this driver as a module, choose M here: the module will be called snd-sun-dbri. -endmenu +endif # SND_SPARC diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index be0bd503f01..4a85e143347 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c @@ -1,6 +1,6 @@ /* * Driver for AMD7930 sound chips found on Sparcs. - * Copyright (C) 2002 David S. Miller <davem@redhat.com> + * Copyright (C) 2002, 2008 David S. Miller <davem@davemloft.net> * * Based entirely upon drivers/sbus/audio/amd7930.c which is: * Copyright (C) 1996,1997 Thomas K. Dyas (tdyas@eden.rutgers.edu) @@ -35,8 +35,9 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/moduleparam.h> +#include <linux/of.h> +#include <linux/of_device.h> -#include <sound/driver.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/info.h> @@ -45,12 +46,11 @@ #include <asm/io.h> #include <asm/irq.h> -#include <asm/sbus.h> #include <asm/prom.h> static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ +static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for Sun AMD7930 soundcard."); @@ -336,8 +336,8 @@ struct snd_amd7930 { int pgain; int mgain; + struct platform_device *op; unsigned int irq; - unsigned int regs_size; struct snd_amd7930 *next; }; @@ -491,7 +491,7 @@ static void __amd7930_update_map(struct snd_amd7930 *amd) __amd7930_write_map(amd); } -static irqreturn_t snd_amd7930_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t snd_amd7930_interrupt(int irq, void *dev_id) { struct snd_amd7930 *amd = dev_id; unsigned int elapsed; @@ -755,7 +755,7 @@ static struct snd_pcm_ops snd_amd7930_capture_ops = { .pointer = snd_amd7930_capture_pointer, }; -static int __devinit snd_amd7930_pcm(struct snd_amd7930 *amd) +static int snd_amd7930_pcm(struct snd_amd7930 *amd) { struct snd_pcm *pcm; int err; @@ -766,7 +766,6 @@ static int __devinit snd_amd7930_pcm(struct snd_amd7930 *amd) /* playback count */ 1, /* capture count */ 1, &pcm)) < 0) return err; - snd_assert(pcm != NULL, return -EINVAL); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_amd7930_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_amd7930_capture_ops); @@ -789,13 +788,6 @@ static int __devinit snd_amd7930_pcm(struct snd_amd7930 *amd) static int snd_amd7930_info_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo) { - int type = kctl->private_value; - - snd_assert(type == VOLUME_MONITOR || - type == VOLUME_CAPTURE || - type == VOLUME_PLAYBACK, return -EINVAL); - (void) type; - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; uinfo->value.integer.min = 0; @@ -810,10 +802,6 @@ static int snd_amd7930_get_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem int type = kctl->private_value; int *swval; - snd_assert(type == VOLUME_MONITOR || - type == VOLUME_CAPTURE || - type == VOLUME_PLAYBACK, return -EINVAL); - switch (type) { case VOLUME_MONITOR: swval = &amd->mgain; @@ -825,7 +813,7 @@ static int snd_amd7930_get_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem default: swval = &amd->pgain; break; - }; + } ucontrol->value.integer.value[0] = *swval; @@ -839,10 +827,6 @@ static int snd_amd7930_put_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem int type = kctl->private_value; int *swval, change; - snd_assert(type == VOLUME_MONITOR || - type == VOLUME_CAPTURE || - type == VOLUME_PLAYBACK, return -EINVAL); - switch (type) { case VOLUME_MONITOR: swval = &amd->mgain; @@ -854,12 +838,12 @@ static int snd_amd7930_put_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem default: swval = &amd->pgain; break; - }; + } spin_lock_irqsave(&amd->lock, flags); if (*swval != ucontrol->value.integer.value[0]) { - *swval = ucontrol->value.integer.value[0]; + *swval = ucontrol->value.integer.value[0] & 0xff; __amd7930_update_map(amd); change = 1; } else @@ -870,7 +854,7 @@ static int snd_amd7930_put_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem return change; } -static struct snd_kcontrol_new amd7930_controls[] __devinitdata = { +static struct snd_kcontrol_new amd7930_controls[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Monitor Volume", @@ -900,12 +884,13 @@ static struct snd_kcontrol_new amd7930_controls[] __devinitdata = { }, }; -static int __devinit snd_amd7930_mixer(struct snd_amd7930 *amd) +static int snd_amd7930_mixer(struct snd_amd7930 *amd) { struct snd_card *card; int idx, err; - snd_assert(amd != NULL && amd->card != NULL, return -EINVAL); + if (snd_BUG_ON(!amd || !amd->card)) + return -EINVAL; card = amd->card; strcpy(card->mixername, card->shortname); @@ -921,13 +906,16 @@ static int __devinit snd_amd7930_mixer(struct snd_amd7930 *amd) static int snd_amd7930_free(struct snd_amd7930 *amd) { + struct platform_device *op = amd->op; + amd7930_idle(amd); if (amd->irq) free_irq(amd->irq, amd); if (amd->regs) - sbus_iounmap(amd->regs, amd->regs_size); + of_iounmap(&op->resource[0], amd->regs, + resource_size(&op->resource[0])); kfree(amd); @@ -945,14 +933,13 @@ static struct snd_device_ops snd_amd7930_dev_ops = { .dev_free = snd_amd7930_dev_free, }; -static int __devinit snd_amd7930_create(struct snd_card *card, - struct resource *rp, - unsigned int reg_size, - int irq, int dev, - struct snd_amd7930 **ramd) +static int snd_amd7930_create(struct snd_card *card, + struct platform_device *op, + int irq, int dev, + struct snd_amd7930 **ramd) { - unsigned long flags; struct snd_amd7930 *amd; + unsigned long flags; int err; *ramd = NULL; @@ -962,19 +949,21 @@ static int __devinit snd_amd7930_create(struct snd_card *card, spin_lock_init(&amd->lock); amd->card = card; - amd->regs_size = reg_size; + amd->op = op; - amd->regs = sbus_ioremap(rp, 0, amd->regs_size, "amd7930"); + amd->regs = of_ioremap(&op->resource[0], 0, + resource_size(&op->resource[0]), "amd7930"); if (!amd->regs) { - snd_printk("amd7930-%d: Unable to map chip registers.\n", dev); + snd_printk(KERN_ERR + "amd7930-%d: Unable to map chip registers.\n", dev); return -EIO; } amd7930_idle(amd); if (request_irq(irq, snd_amd7930_interrupt, - IRQF_DISABLED | IRQF_SHARED, "amd7930", amd)) { - snd_printk("amd7930-%d: Unable to grab IRQ %d\n", + IRQF_SHARED, "amd7930", amd)) { + snd_printk(KERN_ERR "amd7930-%d: Unable to grab IRQ %d\n", dev, irq); snd_amd7930_free(amd); return -EBUSY; @@ -1013,12 +1002,15 @@ static int __devinit snd_amd7930_create(struct snd_card *card, return 0; } -static int __devinit amd7930_attach_common(struct resource *rp, int irq) +static int amd7930_sbus_probe(struct platform_device *op) { + struct resource *rp = &op->resource[0]; static int dev_num; struct snd_card *card; struct snd_amd7930 *amd; - int err; + int err, irq; + + irq = op->archdata.irqs[0]; if (dev_num >= SNDRV_CARDS) return -ENODEV; @@ -1027,9 +1019,10 @@ static int __devinit amd7930_attach_common(struct resource *rp, int irq) return -ENOENT; } - card = snd_card_new(index[dev_num], id[dev_num], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_new(&op->dev, index[dev_num], id[dev_num], + THIS_MODULE, 0, &card); + if (err < 0) + return err; strcpy(card->driver, "AMD7930"); strcpy(card->shortname, "Sun AMD7930"); @@ -1039,8 +1032,7 @@ static int __devinit amd7930_attach_common(struct resource *rp, int irq) (unsigned long long)rp->start, irq); - if ((err = snd_amd7930_create(card, rp, - (rp->end - rp->start) + 1, + if ((err = snd_amd7930_create(card, op, irq, dev_num, &amd)) < 0) goto out_err; @@ -1065,71 +1057,25 @@ out_err: return err; } -static int __devinit amd7930_obio_attach(struct device_node *dp) -{ - struct linux_prom_registers *regs; - struct linux_prom_irqs *irqp; - struct resource res, *rp; - int len; - - irqp = of_get_property(dp, "intr", &len); - if (!irqp) { - snd_printk("%s: Firmware node lacks IRQ property.\n", - dp->full_name); - return -ENODEV; - } - - regs = of_get_property(dp, "reg", &len); - if (!regs) { - snd_printk("%s: Firmware node lacks register property.\n", - dp->full_name); - return -ENODEV; - } - - rp = &res; - rp->start = regs->phys_addr; - rp->end = rp->start + regs->reg_size - 1; - rp->flags = IORESOURCE_IO | (regs->which_io & 0xff); - - return amd7930_attach_common(rp, irqp->pri); -} - -static int __devinit amd7930_sbus_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct sbus_dev *sdev = to_sbus_device(&dev->dev); - - return amd7930_attach_common(&sdev->resource[0], sdev->irqs[0]); -} - -static struct of_device_id amd7930_match[] = { +static const struct of_device_id amd7930_match[] = { { .name = "audio", }, {}, }; -static struct of_platform_driver amd7930_sbus_driver = { - .name = "audio", - .match_table = amd7930_match, +static struct platform_driver amd7930_sbus_driver = { + .driver = { + .name = "audio", + .owner = THIS_MODULE, + .of_match_table = amd7930_match, + }, .probe = amd7930_sbus_probe, }; static int __init amd7930_init(void) { - struct device_node *dp; - - /* Try to find the sun4c "audio" node first. */ - dp = of_find_node_by_path("/"); - dp = dp->child; - while (dp) { - if (!strcmp(dp->name, "audio")) - amd7930_obio_attach(dp); - - dp = dp->sibling; - } - - /* Probe each SBUS for amd7930 chips. */ - return of_register_driver(&amd7930_sbus_driver, &sbus_bus_type); + return platform_driver_register(&amd7930_sbus_driver); } static void __exit amd7930_exit(void) @@ -1146,7 +1092,7 @@ static void __exit amd7930_exit(void) amd7930_list = NULL; - of_unregister_driver(&amd7930_sbus_driver); + platform_driver_unregister(&amd7930_sbus_driver); } module_init(amd7930_init); diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 9a06c3bd694..4e91bcaa366 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -1,22 +1,24 @@ /* * Driver for CS4231 sound chips found on Sparcs. - * Copyright (C) 2002 David S. Miller <davem@redhat.com> + * Copyright (C) 2002, 2008 David S. Miller <davem@davemloft.net> * * Based entirely upon drivers/sbus/audio/cs4231.c which is: - * Copyright (C) 1996, 1997, 1998, 1998 Derrick J Brashear (shadow@andrew.cmu.edu) + * Copyright (C) 1996, 1997, 1998 Derrick J Brashear (shadow@andrew.cmu.edu) * and also sound/isa/cs423x/cs4231_lib.c which is: - * Copyright (c) by Jaroslav Kysela <perex@suse.cz> + * Copyright (c) by Jaroslav Kysela <perex@perex.cz> */ #include <linux/module.h> #include <linux/kernel.h> -#include <linux/slab.h> #include <linux/delay.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/moduleparam.h> +#include <linux/irq.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/of_device.h> -#include <sound/driver.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/info.h> @@ -25,29 +27,20 @@ #include <sound/initval.h> #include <sound/pcm_params.h> -#include <asm/io.h> -#include <asm/irq.h> - #ifdef CONFIG_SBUS #define SBUS_SUPPORT #endif -#ifdef SBUS_SUPPORT -#include <asm/sbus.h> -#endif - #if defined(CONFIG_PCI) && defined(CONFIG_SPARC64) #define EBUS_SUPPORT -#endif - -#ifdef EBUS_SUPPORT #include <linux/pci.h> -#include <asm/ebus.h> +#include <asm/ebus_dma.h> #endif static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ +/* Enable this card */ +static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for Sun CS4231 soundcard."); @@ -62,20 +55,20 @@ MODULE_SUPPORTED_DEVICE("{{Sun,CS4231}}"); #ifdef SBUS_SUPPORT struct sbus_dma_info { - spinlock_t lock; - int dir; - void __iomem *regs; + spinlock_t lock; /* DMA access lock */ + int dir; + void __iomem *regs; }; #endif struct snd_cs4231; struct cs4231_dma_control { - void (*prepare)(struct cs4231_dma_control *dma_cont, int dir); - void (*enable)(struct cs4231_dma_control *dma_cont, int on); - int (*request)(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len); - unsigned int (*address)(struct cs4231_dma_control *dma_cont); - void (*reset)(struct snd_cs4231 *chip); - void (*preallocate)(struct snd_cs4231 *chip, struct snd_pcm *pcm); + void (*prepare)(struct cs4231_dma_control *dma_cont, + int dir); + void (*enable)(struct cs4231_dma_control *dma_cont, int on); + int (*request)(struct cs4231_dma_control *dma_cont, + dma_addr_t bus_addr, size_t len); + unsigned int (*address)(struct cs4231_dma_control *dma_cont); #ifdef EBUS_SUPPORT struct ebus_dma_info ebus_info; #endif @@ -85,7 +78,7 @@ struct cs4231_dma_control { }; struct snd_cs4231 { - spinlock_t lock; + spinlock_t lock; /* registers access lock */ void __iomem *port; struct cs4231_dma_control p_dma; @@ -109,157 +102,30 @@ struct snd_cs4231 { #define CS4231_MODE_PLAY 0x0001 #define CS4231_MODE_RECORD 0x0002 #define CS4231_MODE_TIMER 0x0004 -#define CS4231_MODE_OPEN (CS4231_MODE_PLAY|CS4231_MODE_RECORD|CS4231_MODE_TIMER) +#define CS4231_MODE_OPEN (CS4231_MODE_PLAY | CS4231_MODE_RECORD | \ + CS4231_MODE_TIMER) unsigned char image[32]; /* registers image */ int mce_bit; int calibrate_mute; - struct mutex mce_mutex; - struct mutex open_mutex; + struct mutex mce_mutex; /* mutex for mce register */ + struct mutex open_mutex; /* mutex for ALSA open/close */ - union { -#ifdef SBUS_SUPPORT - struct sbus_dev *sdev; -#endif -#ifdef EBUS_SUPPORT - struct pci_dev *pdev; -#endif - } dev_u; + struct platform_device *op; unsigned int irq[2]; unsigned int regs_size; struct snd_cs4231 *next; }; -static struct snd_cs4231 *cs4231_list; - /* Eventually we can use sound/isa/cs423x/cs4231_lib.c directly, but for * now.... -DaveM */ /* IO ports */ - -#define CS4231P(chip, x) ((chip)->port + c_d_c_CS4231##x) +#include <sound/cs4231-regs.h> /* XXX offsets are different than PC ISA chips... */ -#define c_d_c_CS4231REGSEL 0x0 -#define c_d_c_CS4231REG 0x4 -#define c_d_c_CS4231STATUS 0x8 -#define c_d_c_CS4231PIO 0xc - -/* codec registers */ - -#define CS4231_LEFT_INPUT 0x00 /* left input control */ -#define CS4231_RIGHT_INPUT 0x01 /* right input control */ -#define CS4231_AUX1_LEFT_INPUT 0x02 /* left AUX1 input control */ -#define CS4231_AUX1_RIGHT_INPUT 0x03 /* right AUX1 input control */ -#define CS4231_AUX2_LEFT_INPUT 0x04 /* left AUX2 input control */ -#define CS4231_AUX2_RIGHT_INPUT 0x05 /* right AUX2 input control */ -#define CS4231_LEFT_OUTPUT 0x06 /* left output control register */ -#define CS4231_RIGHT_OUTPUT 0x07 /* right output control register */ -#define CS4231_PLAYBK_FORMAT 0x08 /* clock and data format - playback - bits 7-0 MCE */ -#define CS4231_IFACE_CTRL 0x09 /* interface control - bits 7-2 MCE */ -#define CS4231_PIN_CTRL 0x0a /* pin control */ -#define CS4231_TEST_INIT 0x0b /* test and initialization */ -#define CS4231_MISC_INFO 0x0c /* miscellaneaous information */ -#define CS4231_LOOPBACK 0x0d /* loopback control */ -#define CS4231_PLY_UPR_CNT 0x0e /* playback upper base count */ -#define CS4231_PLY_LWR_CNT 0x0f /* playback lower base count */ -#define CS4231_ALT_FEATURE_1 0x10 /* alternate #1 feature enable */ -#define CS4231_ALT_FEATURE_2 0x11 /* alternate #2 feature enable */ -#define CS4231_LEFT_LINE_IN 0x12 /* left line input control */ -#define CS4231_RIGHT_LINE_IN 0x13 /* right line input control */ -#define CS4231_TIMER_LOW 0x14 /* timer low byte */ -#define CS4231_TIMER_HIGH 0x15 /* timer high byte */ -#define CS4231_LEFT_MIC_INPUT 0x16 /* left MIC input control register (InterWave only) */ -#define CS4231_RIGHT_MIC_INPUT 0x17 /* right MIC input control register (InterWave only) */ -#define CS4236_EXT_REG 0x17 /* extended register access */ -#define CS4231_IRQ_STATUS 0x18 /* irq status register */ -#define CS4231_LINE_LEFT_OUTPUT 0x19 /* left line output control register (InterWave only) */ -#define CS4231_VERSION 0x19 /* CS4231(A) - version values */ -#define CS4231_MONO_CTRL 0x1a /* mono input/output control */ -#define CS4231_LINE_RIGHT_OUTPUT 0x1b /* right line output control register (InterWave only) */ -#define CS4235_LEFT_MASTER 0x1b /* left master output control */ -#define CS4231_REC_FORMAT 0x1c /* clock and data format - record - bits 7-0 MCE */ -#define CS4231_PLY_VAR_FREQ 0x1d /* playback variable frequency */ -#define CS4235_RIGHT_MASTER 0x1d /* right master output control */ -#define CS4231_REC_UPR_CNT 0x1e /* record upper count */ -#define CS4231_REC_LWR_CNT 0x1f /* record lower count */ - -/* definitions for codec register select port - CODECP( REGSEL ) */ - -#define CS4231_INIT 0x80 /* CODEC is initializing */ -#define CS4231_MCE 0x40 /* mode change enable */ -#define CS4231_TRD 0x20 /* transfer request disable */ - -/* definitions for codec status register - CODECP( STATUS ) */ - -#define CS4231_GLOBALIRQ 0x01 /* IRQ is active */ - -/* definitions for codec irq status - CS4231_IRQ_STATUS */ - -#define CS4231_PLAYBACK_IRQ 0x10 -#define CS4231_RECORD_IRQ 0x20 -#define CS4231_TIMER_IRQ 0x40 -#define CS4231_ALL_IRQS 0x70 -#define CS4231_REC_UNDERRUN 0x08 -#define CS4231_REC_OVERRUN 0x04 -#define CS4231_PLY_OVERRUN 0x02 -#define CS4231_PLY_UNDERRUN 0x01 - -/* definitions for CS4231_LEFT_INPUT and CS4231_RIGHT_INPUT registers */ - -#define CS4231_ENABLE_MIC_GAIN 0x20 - -#define CS4231_MIXS_LINE 0x00 -#define CS4231_MIXS_AUX1 0x40 -#define CS4231_MIXS_MIC 0x80 -#define CS4231_MIXS_ALL 0xc0 - -/* definitions for clock and data format register - CS4231_PLAYBK_FORMAT */ - -#define CS4231_LINEAR_8 0x00 /* 8-bit unsigned data */ -#define CS4231_ALAW_8 0x60 /* 8-bit A-law companded */ -#define CS4231_ULAW_8 0x20 /* 8-bit U-law companded */ -#define CS4231_LINEAR_16 0x40 /* 16-bit twos complement data - little endian */ -#define CS4231_LINEAR_16_BIG 0xc0 /* 16-bit twos complement data - big endian */ -#define CS4231_ADPCM_16 0xa0 /* 16-bit ADPCM */ -#define CS4231_STEREO 0x10 /* stereo mode */ -/* bits 3-1 define frequency divisor */ -#define CS4231_XTAL1 0x00 /* 24.576 crystal */ -#define CS4231_XTAL2 0x01 /* 16.9344 crystal */ - -/* definitions for interface control register - CS4231_IFACE_CTRL */ - -#define CS4231_RECORD_PIO 0x80 /* record PIO enable */ -#define CS4231_PLAYBACK_PIO 0x40 /* playback PIO enable */ -#define CS4231_CALIB_MODE 0x18 /* calibration mode bits */ -#define CS4231_AUTOCALIB 0x08 /* auto calibrate */ -#define CS4231_SINGLE_DMA 0x04 /* use single DMA channel */ -#define CS4231_RECORD_ENABLE 0x02 /* record enable */ -#define CS4231_PLAYBACK_ENABLE 0x01 /* playback enable */ - -/* definitions for pin control register - CS4231_PIN_CTRL */ - -#define CS4231_IRQ_ENABLE 0x02 /* enable IRQ */ -#define CS4231_XCTL1 0x40 /* external control #1 */ -#define CS4231_XCTL0 0x80 /* external control #0 */ - -/* definitions for test and init register - CS4231_TEST_INIT */ - -#define CS4231_CALIB_IN_PROGRESS 0x20 /* auto calibrate in progress */ -#define CS4231_DMA_REQUEST 0x10 /* DMA request in progress */ - -/* definitions for misc control register - CS4231_MISC_INFO */ - -#define CS4231_MODE2 0x40 /* MODE 2 */ -#define CS4231_IW_MODE3 0x6c /* MODE 3 - InterWave enhanced mode */ -#define CS4231_4236_MODE3 0xe0 /* MODE 3 - CS4236+ enhanced mode */ - -/* definitions for alternate feature 1 register - CS4231_ALT_FEATURE_1 */ - -#define CS4231_DACZ 0x01 /* zero DAC when underrun */ -#define CS4231_TIMER_ENABLE 0x40 /* codec timer enable */ -#define CS4231_OLB 0x80 /* output level bit */ +#define CS4231U(chip, x) ((chip)->port + ((c_d_c_CS4231##x) << 2)) /* SBUS DMA register defines. */ @@ -340,7 +206,7 @@ static unsigned int rates[14] = { }; static struct snd_pcm_hw_constraint_list hw_constraints_rates = { - .count = 14, + .count = ARRAY_SIZE(rates), .list = rates, }; @@ -389,117 +255,82 @@ static unsigned char snd_cs4231_original_image[32] = static u8 __cs4231_readb(struct snd_cs4231 *cp, void __iomem *reg_addr) { -#ifdef EBUS_SUPPORT - if (cp->flags & CS4231_FLAG_EBUS) { + if (cp->flags & CS4231_FLAG_EBUS) return readb(reg_addr); - } else { -#endif -#ifdef SBUS_SUPPORT + else return sbus_readb(reg_addr); -#endif -#ifdef EBUS_SUPPORT - } -#endif } -static void __cs4231_writeb(struct snd_cs4231 *cp, u8 val, void __iomem *reg_addr) +static void __cs4231_writeb(struct snd_cs4231 *cp, u8 val, + void __iomem *reg_addr) { -#ifdef EBUS_SUPPORT - if (cp->flags & CS4231_FLAG_EBUS) { + if (cp->flags & CS4231_FLAG_EBUS) return writeb(val, reg_addr); - } else { -#endif -#ifdef SBUS_SUPPORT + else return sbus_writeb(val, reg_addr); -#endif -#ifdef EBUS_SUPPORT - } -#endif } /* * Basic I/O functions */ -static void snd_cs4231_outm(struct snd_cs4231 *chip, unsigned char reg, - unsigned char mask, unsigned char value) +static void snd_cs4231_ready(struct snd_cs4231 *chip) { int timeout; - unsigned char tmp; - for (timeout = 250; - timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); - timeout--) - udelay(100); -#ifdef CONFIG_SND_DEBUG - if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) - snd_printdd("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); -#endif - if (chip->calibrate_mute) { - chip->image[reg] &= mask; - chip->image[reg] |= value; - } else { - __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); - mb(); - tmp = (chip->image[reg] & mask) | value; - __cs4231_writeb(chip, tmp, CS4231P(chip, REG)); - chip->image[reg] = tmp; - mb(); + for (timeout = 250; timeout > 0; timeout--) { + int val = __cs4231_readb(chip, CS4231U(chip, REGSEL)); + if ((val & CS4231_INIT) == 0) + break; + udelay(100); } } -static void snd_cs4231_dout(struct snd_cs4231 *chip, unsigned char reg, unsigned char value) +static void snd_cs4231_dout(struct snd_cs4231 *chip, unsigned char reg, + unsigned char value) { - int timeout; - - for (timeout = 250; - timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); - timeout--) - udelay(100); + snd_cs4231_ready(chip); #ifdef CONFIG_SND_DEBUG - if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) - snd_printdd("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); + if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) + snd_printdd("out: auto calibration time out - reg = 0x%x, " + "value = 0x%x\n", + reg, value); #endif - __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); - __cs4231_writeb(chip, value, CS4231P(chip, REG)); + __cs4231_writeb(chip, chip->mce_bit | reg, CS4231U(chip, REGSEL)); + wmb(); + __cs4231_writeb(chip, value, CS4231U(chip, REG)); mb(); } -static void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char value) +static inline void snd_cs4231_outm(struct snd_cs4231 *chip, unsigned char reg, + unsigned char mask, unsigned char value) { - int timeout; + unsigned char tmp = (chip->image[reg] & mask) | value; - for (timeout = 250; - timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); - timeout--) - udelay(100); -#ifdef CONFIG_SND_DEBUG - if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) - snd_printdd("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); -#endif - __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); - __cs4231_writeb(chip, value, CS4231P(chip, REG)); + chip->image[reg] = tmp; + if (!chip->calibrate_mute) + snd_cs4231_dout(chip, reg, tmp); +} + +static void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, + unsigned char value) +{ + snd_cs4231_dout(chip, reg, value); chip->image[reg] = value; mb(); } static unsigned char snd_cs4231_in(struct snd_cs4231 *chip, unsigned char reg) { - int timeout; - unsigned char ret; - - for (timeout = 250; - timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); - timeout--) - udelay(100); + snd_cs4231_ready(chip); #ifdef CONFIG_SND_DEBUG - if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) - snd_printdd("in: auto calibration time out - reg = 0x%x\n", reg); + if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) + snd_printdd("in: auto calibration time out - reg = 0x%x\n", + reg); #endif - __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); + __cs4231_writeb(chip, chip->mce_bit | reg, CS4231U(chip, REGSEL)); mb(); - ret = __cs4231_readb(chip, CS4231P(chip, REG)); - return ret; + return __cs4231_readb(chip, CS4231U(chip, REG)); } /* @@ -510,15 +341,17 @@ static void snd_cs4231_busy_wait(struct snd_cs4231 *chip) { int timeout; - /* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */ + /* looks like this sequence is proper for CS4231A chip (GUS MAX) */ for (timeout = 5; timeout > 0; timeout--) - __cs4231_readb(chip, CS4231P(chip, REGSEL)); + __cs4231_readb(chip, CS4231U(chip, REGSEL)); /* end of cleanup sequence */ - for (timeout = 500; - timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); - timeout--) - udelay(1000); + for (timeout = 500; timeout > 0; timeout--) { + int val = __cs4231_readb(chip, CS4231U(chip, REGSEL)); + if ((val & CS4231_INIT) == 0) + break; + msleep(1); + } } static void snd_cs4231_mce_up(struct snd_cs4231 *chip) @@ -527,77 +360,63 @@ static void snd_cs4231_mce_up(struct snd_cs4231 *chip) int timeout; spin_lock_irqsave(&chip->lock, flags); - for (timeout = 250; timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); timeout--) - udelay(100); + snd_cs4231_ready(chip); #ifdef CONFIG_SND_DEBUG - if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) + if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) snd_printdd("mce_up - auto calibration time out (0)\n"); #endif chip->mce_bit |= CS4231_MCE; - timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL)); + timeout = __cs4231_readb(chip, CS4231U(chip, REGSEL)); if (timeout == 0x80) - snd_printdd("mce_up [%p]: serious init problem - codec still busy\n", chip->port); + snd_printdd("mce_up [%p]: serious init problem - " + "codec still busy\n", + chip->port); if (!(timeout & CS4231_MCE)) - __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL)); + __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), + CS4231U(chip, REGSEL)); spin_unlock_irqrestore(&chip->lock, flags); } static void snd_cs4231_mce_down(struct snd_cs4231 *chip) { - unsigned long flags; - int timeout; + unsigned long flags, timeout; + int reg; - spin_lock_irqsave(&chip->lock, flags); snd_cs4231_busy_wait(chip); + spin_lock_irqsave(&chip->lock, flags); #ifdef CONFIG_SND_DEBUG - if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) - snd_printdd("mce_down [%p] - auto calibration time out (0)\n", CS4231P(chip, REGSEL)); + if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) + snd_printdd("mce_down [%p] - auto calibration time out (0)\n", + CS4231U(chip, REGSEL)); #endif chip->mce_bit &= ~CS4231_MCE; - timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL)); - __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL)); - if (timeout == 0x80) - snd_printdd("mce_down [%p]: serious init problem - codec still busy\n", chip->port); - if ((timeout & CS4231_MCE) == 0) { + reg = __cs4231_readb(chip, CS4231U(chip, REGSEL)); + __cs4231_writeb(chip, chip->mce_bit | (reg & 0x1f), + CS4231U(chip, REGSEL)); + if (reg == 0x80) + snd_printdd("mce_down [%p]: serious init problem " + "- codec still busy\n", chip->port); + if ((reg & CS4231_MCE) == 0) { spin_unlock_irqrestore(&chip->lock, flags); return; } - snd_cs4231_busy_wait(chip); - /* calibration process */ - - for (timeout = 500; timeout > 0 && (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) == 0; timeout--) - udelay(100); - if ((snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) == 0) { - snd_printd("cs4231_mce_down - auto calibration time out (1)\n"); + /* + * Wait for auto-calibration (AC) process to finish, i.e. ACI to go low. + */ + timeout = jiffies + msecs_to_jiffies(250); + do { spin_unlock_irqrestore(&chip->lock, flags); - return; - } - - /* in 10ms increments, check condition, up to 250ms */ - timeout = 25; - while (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) { - spin_unlock_irqrestore(&chip->lock, flags); - if (--timeout < 0) { - snd_printk("mce_down - auto calibration time out (2)\n"); - return; - } - msleep(10); - spin_lock_irqsave(&chip->lock, flags); - } - - /* in 10ms increments, check condition, up to 100ms */ - timeout = 10; - while (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) { - spin_unlock_irqrestore(&chip->lock, flags); - if (--timeout < 0) { - snd_printk("mce_down - auto calibration time out (3)\n"); - return; - } - msleep(10); + msleep(1); spin_lock_irqsave(&chip->lock, flags); - } + reg = snd_cs4231_in(chip, CS4231_TEST_INIT); + reg &= CS4231_CALIB_IN_PROGRESS; + } while (reg && time_before(jiffies, timeout)); spin_unlock_irqrestore(&chip->lock, flags); + + if (reg) + snd_printk(KERN_ERR + "mce_down - auto calibration time out (2)\n"); } static void snd_cs4231_advance_dma(struct cs4231_dma_control *dma_cont, @@ -610,9 +429,11 @@ static void snd_cs4231_advance_dma(struct cs4231_dma_control *dma_cont, unsigned int period_size = snd_pcm_lib_period_bytes(substream); unsigned int offset = period_size * (*periods_sent); - BUG_ON(period_size >= (1 << 24)); + if (WARN_ON(period_size >= (1 << 24))) + return; - if (dma_cont->request(dma_cont, runtime->dma_addr + offset, period_size)) + if (dma_cont->request(dma_cont, + runtime->dma_addr + offset, period_size)) return; (*periods_sent) = ((*periods_sent) + 1) % runtime->periods; } @@ -661,11 +482,9 @@ static int snd_cs4231_trigger(struct snd_pcm_substream *substream, int cmd) { unsigned int what = 0; struct snd_pcm_substream *s; - struct list_head *pos; unsigned long flags; - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { if (s == chip->playback_substream) { what |= CS4231_PLAYBACK_ENABLE; snd_pcm_trigger_done(s, substream); @@ -707,21 +526,32 @@ static unsigned char snd_cs4231_get_rate(unsigned int rate) for (i = 0; i < 14; i++) if (rate == rates[i]) return freq_bits[i]; - // snd_BUG(); + return freq_bits[13]; } -static unsigned char snd_cs4231_get_format(struct snd_cs4231 *chip, int format, int channels) +static unsigned char snd_cs4231_get_format(struct snd_cs4231 *chip, int format, + int channels) { unsigned char rformat; rformat = CS4231_LINEAR_8; switch (format) { - case SNDRV_PCM_FORMAT_MU_LAW: rformat = CS4231_ULAW_8; break; - case SNDRV_PCM_FORMAT_A_LAW: rformat = CS4231_ALAW_8; break; - case SNDRV_PCM_FORMAT_S16_LE: rformat = CS4231_LINEAR_16; break; - case SNDRV_PCM_FORMAT_S16_BE: rformat = CS4231_LINEAR_16_BIG; break; - case SNDRV_PCM_FORMAT_IMA_ADPCM: rformat = CS4231_ADPCM_16; break; + case SNDRV_PCM_FORMAT_MU_LAW: + rformat = CS4231_ULAW_8; + break; + case SNDRV_PCM_FORMAT_A_LAW: + rformat = CS4231_ALAW_8; + break; + case SNDRV_PCM_FORMAT_S16_LE: + rformat = CS4231_LINEAR_16; + break; + case SNDRV_PCM_FORMAT_S16_BE: + rformat = CS4231_LINEAR_16_BIG; + break; + case SNDRV_PCM_FORMAT_IMA_ADPCM: + rformat = CS4231_ADPCM_16; + break; } if (channels > 1) rformat |= CS4231_STEREO; @@ -768,7 +598,8 @@ static void snd_cs4231_calibrate_mute(struct snd_cs4231 *chip, int mute) spin_unlock_irqrestore(&chip->lock, flags); } -static void snd_cs4231_playback_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params, +static void snd_cs4231_playback_format(struct snd_cs4231 *chip, + struct snd_pcm_hw_params *params, unsigned char pdfr) { unsigned long flags; @@ -791,8 +622,9 @@ static void snd_cs4231_playback_format(struct snd_cs4231 *chip, struct snd_pcm_h mutex_unlock(&chip->mce_mutex); } -static void snd_cs4231_capture_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params, - unsigned char cdfr) +static void snd_cs4231_capture_format(struct snd_cs4231 *chip, + struct snd_pcm_hw_params *params, + unsigned char cdfr) { unsigned long flags; @@ -849,7 +681,8 @@ static int snd_cs4231_timer_start(struct snd_timer *timer) chip->image[CS4231_TIMER_LOW] = (unsigned char) ticks); snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1] | CS4231_TIMER_ENABLE); + chip->image[CS4231_ALT_FEATURE_1] | + CS4231_TIMER_ENABLE); } spin_unlock_irqrestore(&chip->lock, flags); @@ -862,14 +695,15 @@ static int snd_cs4231_timer_stop(struct snd_timer *timer) struct snd_cs4231 *chip = snd_timer_chip(timer); spin_lock_irqsave(&chip->lock, flags); + chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE; snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE); + chip->image[CS4231_ALT_FEATURE_1]); spin_unlock_irqrestore(&chip->lock, flags); return 0; } -static void __init snd_cs4231_init(struct snd_cs4231 *chip) +static void snd_cs4231_init(struct snd_cs4231 *chip) { unsigned long flags; @@ -880,8 +714,10 @@ static void __init snd_cs4231_init(struct snd_cs4231 *chip) #endif snd_cs4231_mce_up(chip); spin_lock_irqsave(&chip->lock, flags); - chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO | - CS4231_RECORD_ENABLE | CS4231_RECORD_PIO | + chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | + CS4231_PLAYBACK_PIO | + CS4231_RECORD_ENABLE | + CS4231_RECORD_PIO | CS4231_CALIB_MODE); chip->image[CS4231_IFACE_CTRL] |= CS4231_AUTOCALIB; snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); @@ -894,21 +730,25 @@ static void __init snd_cs4231_init(struct snd_cs4231 *chip) snd_cs4231_mce_up(chip); spin_lock_irqsave(&chip->lock, flags); - snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]); + snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, + chip->image[CS4231_ALT_FEATURE_1]); spin_unlock_irqrestore(&chip->lock, flags); snd_cs4231_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printdd("init: (3) - afei = 0x%x\n", chip->image[CS4231_ALT_FEATURE_1]); + snd_printdd("init: (3) - afei = 0x%x\n", + chip->image[CS4231_ALT_FEATURE_1]); #endif spin_lock_irqsave(&chip->lock, flags); - snd_cs4231_out(chip, CS4231_ALT_FEATURE_2, chip->image[CS4231_ALT_FEATURE_2]); + snd_cs4231_out(chip, CS4231_ALT_FEATURE_2, + chip->image[CS4231_ALT_FEATURE_2]); spin_unlock_irqrestore(&chip->lock, flags); snd_cs4231_mce_up(chip); spin_lock_irqsave(&chip->lock, flags); - snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT]); + snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, + chip->image[CS4231_PLAYBK_FORMAT]); spin_unlock_irqrestore(&chip->lock, flags); snd_cs4231_mce_down(chip); @@ -947,8 +787,8 @@ static int snd_cs4231_open(struct snd_cs4231 *chip, unsigned int mode) CS4231_RECORD_IRQ | CS4231_TIMER_IRQ); snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0); - __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */ - __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */ + __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */ + __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */ snd_cs4231_out(chip, CS4231_IRQ_STATUS, CS4231_PLAYBACK_IRQ | CS4231_RECORD_IRQ | @@ -977,8 +817,8 @@ static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode) /* disable IRQ */ spin_lock_irqsave(&chip->lock, flags); snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0); - __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */ - __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */ + __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */ + __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */ /* now disable record & playback */ @@ -991,7 +831,8 @@ static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode) chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO | CS4231_RECORD_ENABLE | CS4231_RECORD_PIO); - snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); + snd_cs4231_out(chip, CS4231_IFACE_CTRL, + chip->image[CS4231_IFACE_CTRL]); spin_unlock_irqrestore(&chip->lock, flags); snd_cs4231_mce_down(chip); spin_lock_irqsave(&chip->lock, flags); @@ -999,8 +840,8 @@ static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode) /* clear IRQ again */ snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0); - __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */ - __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */ + __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */ + __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */ spin_unlock_irqrestore(&chip->lock, flags); snd_cs4231_calibrate_mute(chip, 0); @@ -1020,15 +861,14 @@ static int snd_cs4231_timer_open(struct snd_timer *timer) return 0; } -static int snd_cs4231_timer_close(struct snd_timer * timer) +static int snd_cs4231_timer_close(struct snd_timer *timer) { struct snd_cs4231 *chip = snd_timer_chip(timer); snd_cs4231_close(chip, CS4231_MODE_TIMER); return 0; } -static struct snd_timer_hardware snd_cs4231_timer_table = -{ +static struct snd_timer_hardware snd_cs4231_timer_table = { .flags = SNDRV_TIMER_HW_AUTO, .resolution = 9945, .ticks = 65535, @@ -1050,8 +890,9 @@ static int snd_cs4231_playback_hw_params(struct snd_pcm_substream *substream, unsigned char new_pdfr; int err; - if ((err = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params))) < 0) + err = snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); + if (err < 0) return err; new_pdfr = snd_cs4231_get_format(chip, params_format(hw_params), params_channels(hw_params)) | @@ -1061,28 +902,29 @@ static int snd_cs4231_playback_hw_params(struct snd_pcm_substream *substream, return 0; } -static int snd_cs4231_playback_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - static int snd_cs4231_playback_prepare(struct snd_pcm_substream *substream) { struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; unsigned long flags; + int ret = 0; spin_lock_irqsave(&chip->lock, flags); chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO); - BUG_ON(runtime->period_size > 0xffff + 1); + if (WARN_ON(runtime->period_size > 0xffff + 1)) { + ret = -EINVAL; + goto out; + } chip->p_periods_sent = 0; + +out: spin_unlock_irqrestore(&chip->lock, flags); - return 0; + return ret; } static int snd_cs4231_capture_hw_params(struct snd_pcm_substream *substream, @@ -1092,8 +934,9 @@ static int snd_cs4231_capture_hw_params(struct snd_pcm_substream *substream, unsigned char new_cdfr; int err; - if ((err = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params))) < 0) + err = snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); + if (err < 0) return err; new_cdfr = snd_cs4231_get_format(chip, params_format(hw_params), params_channels(hw_params)) | @@ -1103,11 +946,6 @@ static int snd_cs4231_capture_hw_params(struct snd_pcm_substream *substream, return 0; } -static int snd_cs4231_capture_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - static int snd_cs4231_capture_prepare(struct snd_pcm_substream *substream) { struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); @@ -1133,7 +971,8 @@ static void snd_cs4231_overrange(struct snd_cs4231 *chip) res = snd_cs4231_in(chip, CS4231_TEST_INIT); spin_unlock_irqrestore(&chip->lock, flags); - if (res & (0x08 | 0x02)) /* detect overrange only above 0dB; may be user selectable? */ + /* detect overrange only above 0dB; may be user selectable? */ + if (res & (0x08 | 0x02)) chip->capture_substream->runtime->overrange++; } @@ -1155,51 +994,50 @@ static void snd_cs4231_capture_callback(struct snd_cs4231 *chip) } } -static snd_pcm_uframes_t snd_cs4231_playback_pointer(struct snd_pcm_substream *substream) +static snd_pcm_uframes_t snd_cs4231_playback_pointer( + struct snd_pcm_substream *substream) { struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); struct cs4231_dma_control *dma_cont = &chip->p_dma; size_t ptr; - + if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) return 0; ptr = dma_cont->address(dma_cont); if (ptr != 0) ptr -= substream->runtime->dma_addr; - + return bytes_to_frames(substream->runtime, ptr); } -static snd_pcm_uframes_t snd_cs4231_capture_pointer(struct snd_pcm_substream *substream) +static snd_pcm_uframes_t snd_cs4231_capture_pointer( + struct snd_pcm_substream *substream) { struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); struct cs4231_dma_control *dma_cont = &chip->c_dma; size_t ptr; - + if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE)) return 0; ptr = dma_cont->address(dma_cont); if (ptr != 0) ptr -= substream->runtime->dma_addr; - + return bytes_to_frames(substream->runtime, ptr); } -/* - - */ - -static int __init snd_cs4231_probe(struct snd_cs4231 *chip) +static int snd_cs4231_probe(struct snd_cs4231 *chip) { unsigned long flags; - int i, id, vers; + int i; + int id = 0; + int vers = 0; unsigned char *ptr; - id = vers = 0; for (i = 0; i < 50; i++) { mb(); - if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) - udelay(2000); + if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) + msleep(2); else { spin_lock_irqsave(&chip->lock, flags); snd_cs4231_out(chip, CS4231_MISC_INFO, CS4231_MODE2); @@ -1216,12 +1054,9 @@ static int __init snd_cs4231_probe(struct snd_cs4231 *chip) spin_lock_irqsave(&chip->lock, flags); - - /* Reset DMA engine (sbus only). */ - chip->p_dma.reset(chip); - - __cs4231_readb(chip, CS4231P(chip, STATUS)); /* clear any pendings IRQ */ - __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); + /* clear any pendings IRQ */ + __cs4231_readb(chip, CS4231U(chip, STATUS)); + __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); mb(); spin_unlock_irqrestore(&chip->lock, flags); @@ -1254,42 +1089,50 @@ static int __init snd_cs4231_probe(struct snd_cs4231 *chip) return 0; /* all things are ok.. */ } -static struct snd_pcm_hardware snd_cs4231_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START), - .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | - SNDRV_PCM_FMTBIT_IMA_ADPCM | - SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S16_BE), - .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000, +static struct snd_pcm_hardware snd_cs4231_playback = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_SYNC_START, + .formats = SNDRV_PCM_FMTBIT_MU_LAW | + SNDRV_PCM_FMTBIT_A_LAW | + SNDRV_PCM_FMTBIT_IMA_ADPCM | + SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S16_BE, + .rates = SNDRV_PCM_RATE_KNOT | + SNDRV_PCM_RATE_8000_48000, .rate_min = 5510, .rate_max = 48000, .channels_min = 1, .channels_max = 2, - .buffer_bytes_max = (32*1024), - .period_bytes_min = 4096, - .period_bytes_max = (32*1024), + .buffer_bytes_max = 32 * 1024, + .period_bytes_min = 64, + .period_bytes_max = 32 * 1024, .periods_min = 1, .periods_max = 1024, }; -static struct snd_pcm_hardware snd_cs4231_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START), - .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | - SNDRV_PCM_FMTBIT_IMA_ADPCM | - SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S16_BE), - .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000, +static struct snd_pcm_hardware snd_cs4231_capture = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_SYNC_START, + .formats = SNDRV_PCM_FMTBIT_MU_LAW | + SNDRV_PCM_FMTBIT_A_LAW | + SNDRV_PCM_FMTBIT_IMA_ADPCM | + SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S16_BE, + .rates = SNDRV_PCM_RATE_KNOT | + SNDRV_PCM_RATE_8000_48000, .rate_min = 5510, .rate_max = 48000, .channels_min = 1, .channels_max = 2, - .buffer_bytes_max = (32*1024), - .period_bytes_min = 4096, - .period_bytes_max = (32*1024), + .buffer_bytes_max = 32 * 1024, + .period_bytes_min = 64, + .period_bytes_max = 32 * 1024, .periods_min = 1, .periods_max = 1024, }; @@ -1302,7 +1145,8 @@ static int snd_cs4231_playback_open(struct snd_pcm_substream *substream) runtime->hw = snd_cs4231_playback; - if ((err = snd_cs4231_open(chip, CS4231_MODE_PLAY)) < 0) { + err = snd_cs4231_open(chip, CS4231_MODE_PLAY); + if (err < 0) { snd_free_pages(runtime->dma_area, runtime->dma_bytes); return err; } @@ -1322,7 +1166,8 @@ static int snd_cs4231_capture_open(struct snd_pcm_substream *substream) runtime->hw = snd_cs4231_capture; - if ((err = snd_cs4231_open(chip, CS4231_MODE_RECORD)) < 0) { + err = snd_cs4231_open(chip, CS4231_MODE_RECORD); + if (err < 0) { snd_free_pages(runtime->dma_area, runtime->dma_bytes); return err; } @@ -1363,7 +1208,7 @@ static struct snd_pcm_ops snd_cs4231_playback_ops = { .close = snd_cs4231_playback_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_cs4231_playback_hw_params, - .hw_free = snd_cs4231_playback_hw_free, + .hw_free = snd_pcm_lib_free_pages, .prepare = snd_cs4231_playback_prepare, .trigger = snd_cs4231_trigger, .pointer = snd_cs4231_playback_pointer, @@ -1374,37 +1219,44 @@ static struct snd_pcm_ops snd_cs4231_capture_ops = { .close = snd_cs4231_capture_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_cs4231_capture_hw_params, - .hw_free = snd_cs4231_capture_hw_free, + .hw_free = snd_pcm_lib_free_pages, .prepare = snd_cs4231_capture_prepare, .trigger = snd_cs4231_trigger, .pointer = snd_cs4231_capture_pointer, }; -static int __init snd_cs4231_pcm(struct snd_cs4231 *chip) +static int snd_cs4231_pcm(struct snd_card *card) { + struct snd_cs4231 *chip = card->private_data; struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(chip->card, "CS4231", 0, 1, 1, &pcm)) < 0) + err = snd_pcm_new(card, "CS4231", 0, 1, 1, &pcm); + if (err < 0) return err; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs4231_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cs4231_capture_ops); - + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, + &snd_cs4231_playback_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, + &snd_cs4231_capture_ops); + /* global setup */ pcm->private_data = chip; pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; strcpy(pcm->name, "CS4231"); - chip->p_dma.preallocate(chip, pcm); + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, + &chip->op->dev, + 64 * 1024, 128 * 1024); chip->pcm = pcm; return 0; } -static int __init snd_cs4231_timer(struct snd_cs4231 *chip) +static int snd_cs4231_timer(struct snd_card *card) { + struct snd_cs4231 *chip = card->private_data; struct snd_timer *timer; struct snd_timer_id tid; int err; @@ -1412,10 +1264,11 @@ static int __init snd_cs4231_timer(struct snd_cs4231 *chip) /* Timer initialization */ tid.dev_class = SNDRV_TIMER_CLASS_CARD; tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; - tid.card = chip->card->number; + tid.card = card->number; tid.device = 0; tid.subdevice = 0; - if ((err = snd_timer_new(chip->card, "CS4231", &tid, &timer)) < 0) + err = snd_timer_new(card, "CS4231", &tid, &timer); + if (err < 0) return err; strcpy(timer->name, "CS4231"); timer->private_data = chip; @@ -1424,7 +1277,7 @@ static int __init snd_cs4231_timer(struct snd_cs4231 *chip) return 0; } - + /* * MIXER part */ @@ -1435,15 +1288,14 @@ static int snd_cs4231_info_mux(struct snd_kcontrol *kcontrol, static char *texts[4] = { "Line", "CD", "Mic", "Mix" }; - struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); - snd_assert(chip->card != NULL, return -EINVAL); uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 2; uinfo->value.enumerated.items = 4; if (uinfo->value.enumerated.item > 3) uinfo->value.enumerated.item = 3; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); + strcpy(uinfo->value.enumerated.name, + texts[uinfo->value.enumerated.item]); return 0; } @@ -1453,7 +1305,7 @@ static int snd_cs4231_get_mux(struct snd_kcontrol *kcontrol, { struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; - + spin_lock_irqsave(&chip->lock, flags); ucontrol->value.enumerated.item[0] = (chip->image[CS4231_LEFT_INPUT] & CS4231_MIXS_ALL) >> 6; @@ -1471,7 +1323,7 @@ static int snd_cs4231_put_mux(struct snd_kcontrol *kcontrol, unsigned long flags; unsigned short left, right; int change; - + if (ucontrol->value.enumerated.item[0] > 3 || ucontrol->value.enumerated.item[1] > 3) return -EINVAL; @@ -1483,7 +1335,7 @@ static int snd_cs4231_put_mux(struct snd_kcontrol *kcontrol, left = (chip->image[CS4231_LEFT_INPUT] & ~CS4231_MIXS_ALL) | left; right = (chip->image[CS4231_RIGHT_INPUT] & ~CS4231_MIXS_ALL) | right; change = left != chip->image[CS4231_LEFT_INPUT] || - right != chip->image[CS4231_RIGHT_INPUT]; + right != chip->image[CS4231_RIGHT_INPUT]; snd_cs4231_out(chip, CS4231_LEFT_INPUT, left); snd_cs4231_out(chip, CS4231_RIGHT_INPUT, right); @@ -1515,7 +1367,7 @@ static int snd_cs4231_get_single(struct snd_kcontrol *kcontrol, int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 0xff; - + spin_lock_irqsave(&chip->lock, flags); ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask; @@ -1540,7 +1392,7 @@ static int snd_cs4231_put_single(struct snd_kcontrol *kcontrol, int invert = (kcontrol->private_value >> 24) & 0xff; int change; unsigned short val; - + val = (ucontrol->value.integer.value[0] & mask); if (invert) val = mask - val; @@ -1582,11 +1434,13 @@ static int snd_cs4231_get_double(struct snd_kcontrol *kcontrol, int shift_right = (kcontrol->private_value >> 19) & 0x07; int mask = (kcontrol->private_value >> 24) & 0xff; int invert = (kcontrol->private_value >> 22) & 1; - + spin_lock_irqsave(&chip->lock, flags); - ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask; - ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask; + ucontrol->value.integer.value[0] = + (chip->image[left_reg] >> shift_left) & mask; + ucontrol->value.integer.value[1] = + (chip->image[right_reg] >> shift_right) & mask; spin_unlock_irqrestore(&chip->lock, flags); @@ -1613,7 +1467,7 @@ static int snd_cs4231_put_double(struct snd_kcontrol *kcontrol, int invert = (kcontrol->private_value >> 22) & 1; int change; unsigned short val1, val2; - + val1 = ucontrol->value.integer.value[0] & mask; val2 = ucontrol->value.integer.value[1] & mask; if (invert) { @@ -1627,7 +1481,8 @@ static int snd_cs4231_put_double(struct snd_kcontrol *kcontrol, val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1; val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2; - change = val1 != chip->image[left_reg] || val2 != chip->image[right_reg]; + change = val1 != chip->image[left_reg]; + change |= val2 != chip->image[right_reg]; snd_cs4231_out(chip, left_reg, val1); snd_cs4231_out(chip, right_reg, val2); @@ -1637,31 +1492,42 @@ static int snd_cs4231_put_double(struct snd_kcontrol *kcontrol, } #define CS4231_SINGLE(xname, xindex, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_cs4231_info_single, \ - .get = snd_cs4231_get_single, .put = snd_cs4231_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } - -#define CS4231_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_cs4231_info_double, \ - .get = snd_cs4231_get_double, .put = snd_cs4231_put_double, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } - -static struct snd_kcontrol_new snd_cs4231_controls[] __initdata = { -CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), -CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), -CS4231_DOUBLE("Line Playback Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), -CS4231_DOUBLE("Line Playback Volume", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), -CS4231_DOUBLE("Aux Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), -CS4231_DOUBLE("Aux Playback Volume", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1), -CS4231_DOUBLE("Aux Playback Switch", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), -CS4231_DOUBLE("Aux Playback Volume", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .index = (xindex), \ + .info = snd_cs4231_info_single, \ + .get = snd_cs4231_get_single, .put = snd_cs4231_put_single, \ + .private_value = (reg) | ((shift) << 8) | ((mask) << 16) | ((invert) << 24) } + +#define CS4231_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, \ + shift_right, mask, invert) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .index = (xindex), \ + .info = snd_cs4231_info_double, \ + .get = snd_cs4231_get_double, .put = snd_cs4231_put_double, \ + .private_value = (left_reg) | ((right_reg) << 8) | ((shift_left) << 16) | \ + ((shift_right) << 19) | ((mask) << 24) | ((invert) << 22) } + +static struct snd_kcontrol_new snd_cs4231_controls[] = { +CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, + CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), +CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, + CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), +CS4231_DOUBLE("Line Playback Switch", 0, CS4231_LEFT_LINE_IN, + CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), +CS4231_DOUBLE("Line Playback Volume", 0, CS4231_LEFT_LINE_IN, + CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), +CS4231_DOUBLE("Aux Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, + CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), +CS4231_DOUBLE("Aux Playback Volume", 0, CS4231_AUX1_LEFT_INPUT, + CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1), +CS4231_DOUBLE("Aux Playback Switch", 1, CS4231_AUX2_LEFT_INPUT, + CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), +CS4231_DOUBLE("Aux Playback Volume", 1, CS4231_AUX2_LEFT_INPUT, + CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), CS4231_SINGLE("Mono Playback Switch", 0, CS4231_MONO_CTRL, 7, 1, 1), CS4231_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1), CS4231_SINGLE("Mono Output Playback Switch", 0, CS4231_MONO_CTRL, 6, 1, 1), CS4231_SINGLE("Mono Output Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0), -CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0), +CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, + 15, 0), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Source", @@ -1669,29 +1535,29 @@ CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, .get = snd_cs4231_get_mux, .put = snd_cs4231_put_mux, }, -CS4231_DOUBLE("Mic Boost", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0), +CS4231_DOUBLE("Mic Boost", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, + 1, 0), CS4231_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0), CS4231_SINGLE("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1), /* SPARC specific uses of XCTL{0,1} general purpose outputs. */ CS4231_SINGLE("Line Out Switch", 0, CS4231_PIN_CTRL, 6, 1, 1), CS4231_SINGLE("Headphone Out Switch", 0, CS4231_PIN_CTRL, 7, 1, 1) }; - -static int __init snd_cs4231_mixer(struct snd_cs4231 *chip) + +static int snd_cs4231_mixer(struct snd_card *card) { - struct snd_card *card; + struct snd_cs4231 *chip = card->private_data; int err, idx; - snd_assert(chip != NULL && chip->pcm != NULL, return -EINVAL); - - card = chip->card; + if (snd_BUG_ON(!chip || !chip->pcm)) + return -EINVAL; strcpy(card->mixername, chip->pcm->name); for (idx = 0; idx < ARRAY_SIZE(snd_cs4231_controls); idx++) { - if ((err = snd_ctl_add(card, - snd_ctl_new1(&snd_cs4231_controls[idx], - chip))) < 0) + err = snd_ctl_add(card, + snd_ctl_new1(&snd_cs4231_controls[idx], chip)); + if (err < 0) return err; } return 0; @@ -1699,9 +1565,12 @@ static int __init snd_cs4231_mixer(struct snd_cs4231 *chip) static int dev; -static int __init cs4231_attach_begin(struct snd_card **rcard) +static int cs4231_attach_begin(struct platform_device *op, + struct snd_card **rcard) { struct snd_card *card; + struct snd_cs4231 *chip; + int err; *rcard = NULL; @@ -1713,35 +1582,43 @@ static int __init cs4231_attach_begin(struct snd_card **rcard) return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_new(&op->dev, index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_cs4231), &card); + if (err < 0) + return err; strcpy(card->driver, "CS4231"); strcpy(card->shortname, "Sun CS4231"); + chip = card->private_data; + chip->card = card; + *rcard = card; return 0; } -static int __init cs4231_attach_finish(struct snd_card *card, struct snd_cs4231 *chip) +static int cs4231_attach_finish(struct snd_card *card) { + struct snd_cs4231 *chip = card->private_data; int err; - if ((err = snd_cs4231_pcm(chip)) < 0) + err = snd_cs4231_pcm(card); + if (err < 0) goto out_err; - if ((err = snd_cs4231_mixer(chip)) < 0) + err = snd_cs4231_mixer(card); + if (err < 0) goto out_err; - if ((err = snd_cs4231_timer(chip)) < 0) + err = snd_cs4231_timer(card); + if (err < 0) goto out_err; - if ((err = snd_card_register(card)) < 0) + err = snd_card_register(card); + if (err < 0) goto out_err; - chip->next = cs4231_list; - cs4231_list = chip; + dev_set_drvdata(&chip->op->dev, chip); dev++; return 0; @@ -1753,7 +1630,7 @@ out_err: #ifdef SBUS_SUPPORT -static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id) { unsigned long flags; unsigned char status; @@ -1761,7 +1638,7 @@ static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_re struct snd_cs4231 *chip = dev_id; /*This is IRQ is not raised by the cs4231*/ - if (!(__cs4231_readb(chip, CS4231P(chip, STATUS)) & CS4231_GLOBALIRQ)) + if (!(__cs4231_readb(chip, CS4231U(chip, STATUS)) & CS4231_GLOBALIRQ)) return IRQ_NONE; /* ACK the APC interrupt. */ @@ -1769,24 +1646,24 @@ static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_re sbus_writel(csr, chip->port + APCCSR); - if ((csr & APC_PDMA_READY) && - (csr & APC_PLAY_INT) && + if ((csr & APC_PDMA_READY) && + (csr & APC_PLAY_INT) && (csr & APC_XINT_PNVA) && !(csr & APC_XINT_EMPT)) snd_cs4231_play_callback(chip); - if ((csr & APC_CDMA_READY) && - (csr & APC_CAPT_INT) && + if ((csr & APC_CDMA_READY) && + (csr & APC_CAPT_INT) && (csr & APC_XINT_CNVA) && !(csr & APC_XINT_EMPT)) snd_cs4231_capture_callback(chip); - + status = snd_cs4231_in(chip, CS4231_IRQ_STATUS); if (status & CS4231_TIMER_IRQ) { if (chip->timer) snd_timer_interrupt(chip->timer, chip->timer->sticks); - } + } if ((status & CS4231_RECORD_IRQ) && (csr & APC_CDMA_READY)) snd_cs4231_overrange(chip); @@ -1796,34 +1673,34 @@ static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_re snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0); spin_unlock_irqrestore(&chip->lock, flags); - return 0; + return IRQ_HANDLED; } /* * SBUS DMA routines */ -static int sbus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len) +static int sbus_dma_request(struct cs4231_dma_control *dma_cont, + dma_addr_t bus_addr, size_t len) { unsigned long flags; u32 test, csr; int err; struct sbus_dma_info *base = &dma_cont->sbus_info; - + if (len >= (1 << 24)) return -EINVAL; spin_lock_irqsave(&base->lock, flags); csr = sbus_readl(base->regs + APCCSR); err = -EINVAL; test = APC_CDMA_READY; - if ( base->dir == APC_PLAY ) + if (base->dir == APC_PLAY) test = APC_PDMA_READY; if (!(csr & test)) goto out; err = -EBUSY; - csr = sbus_readl(base->regs + APCCSR); test = APC_XINT_CNVA; - if ( base->dir == APC_PLAY ) + if (base->dir == APC_PLAY) test = APC_XINT_PNVA; if (!(csr & test)) goto out; @@ -1846,7 +1723,7 @@ static void sbus_dma_prepare(struct cs4231_dma_control *dma_cont, int d) test = APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA | APC_XINT_PLAY | APC_XINT_PEMP | APC_XINT_GENL | APC_XINT_PENA; - if ( base->dir == APC_RECORD ) + if (base->dir == APC_RECORD) test = APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA | APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL; csr |= test; @@ -1862,32 +1739,30 @@ static void sbus_dma_enable(struct cs4231_dma_control *dma_cont, int on) spin_lock_irqsave(&base->lock, flags); if (!on) { - if (base->dir == APC_PLAY) { - sbus_writel(0, base->regs + base->dir + APCNVA); - sbus_writel(1, base->regs + base->dir + APCC); + sbus_writel(0, base->regs + base->dir + APCNC); + sbus_writel(0, base->regs + base->dir + APCNVA); + if (base->dir == APC_PLAY) { + sbus_writel(0, base->regs + base->dir + APCC); + sbus_writel(0, base->regs + base->dir + APCVA); } - else - { - sbus_writel(0, base->regs + base->dir + APCNC); - sbus_writel(0, base->regs + base->dir + APCVA); - } - } - udelay(600); + + udelay(1200); + } csr = sbus_readl(base->regs + APCCSR); shift = 0; - if ( base->dir == APC_PLAY ) + if (base->dir == APC_PLAY) shift = 1; if (on) csr &= ~(APC_CPAUSE << shift); else - csr |= (APC_CPAUSE << shift); + csr |= (APC_CPAUSE << shift); sbus_writel(csr, base->regs + APCCSR); if (on) csr |= (APC_CDMA_READY << shift); else csr &= ~(APC_CDMA_READY << shift); sbus_writel(csr, base->regs + APCCSR); - + spin_unlock_irqrestore(&base->lock, flags); } @@ -1895,31 +1770,7 @@ static unsigned int sbus_dma_addr(struct cs4231_dma_control *dma_cont) { struct sbus_dma_info *base = &dma_cont->sbus_info; - return sbus_readl(base->regs + base->dir + APCVA); -} - -static void sbus_dma_reset(struct snd_cs4231 *chip) -{ - sbus_writel(APC_CHIP_RESET, chip->port + APCCSR); - sbus_writel(0x00, chip->port + APCCSR); - sbus_writel(sbus_readl(chip->port + APCCSR) | APC_CDC_RESET, - chip->port + APCCSR); - - udelay(20); - - sbus_writel(sbus_readl(chip->port + APCCSR) & ~APC_CDC_RESET, - chip->port + APCCSR); - sbus_writel(sbus_readl(chip->port + APCCSR) | (APC_XINT_ENA | - APC_XINT_PENA | - APC_XINT_CENA), - chip->port + APCCSR); -} - -static void sbus_dma_preallocate(struct snd_cs4231 *chip, struct snd_pcm *pcm) -{ - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_SBUS, - snd_dma_sbus_data(chip->dev_u.sdev), - 64*1024, 128*1024); + return sbus_readl(base->regs + base->dir + APCVA); } /* @@ -1928,13 +1779,13 @@ static void sbus_dma_preallocate(struct snd_cs4231 *chip, struct snd_pcm *pcm) static int snd_cs4231_sbus_free(struct snd_cs4231 *chip) { + struct platform_device *op = chip->op; + if (chip->irq[0]) free_irq(chip->irq[0], chip); if (chip->port) - sbus_iounmap(chip->port, chip->regs_size); - - kfree(chip); + of_iounmap(&op->resource[0], chip->port, chip->regs_size); return 0; } @@ -1950,32 +1801,25 @@ static struct snd_device_ops snd_cs4231_sbus_dev_ops = { .dev_free = snd_cs4231_sbus_dev_free, }; -static int __init snd_cs4231_sbus_create(struct snd_card *card, - struct sbus_dev *sdev, - int dev, - struct snd_cs4231 **rchip) +static int snd_cs4231_sbus_create(struct snd_card *card, + struct platform_device *op, + int dev) { - struct snd_cs4231 *chip; + struct snd_cs4231 *chip = card->private_data; int err; - *rchip = NULL; - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - spin_lock_init(&chip->lock); spin_lock_init(&chip->c_dma.sbus_info.lock); spin_lock_init(&chip->p_dma.sbus_info.lock); mutex_init(&chip->mce_mutex); mutex_init(&chip->open_mutex); - chip->card = card; - chip->dev_u.sdev = sdev; - chip->regs_size = sdev->reg_addrs[0].reg_size; + chip->op = op; + chip->regs_size = resource_size(&op->resource[0]); memcpy(&chip->image, &snd_cs4231_original_image, sizeof(snd_cs4231_original_image)); - chip->port = sbus_ioremap(&sdev->resource[0], 0, - chip->regs_size, "cs4231"); + chip->port = of_ioremap(&op->resource[0], 0, + chip->regs_size, "cs4231"); if (!chip->port) { snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev); return -EIO; @@ -1990,24 +1834,20 @@ static int __init snd_cs4231_sbus_create(struct snd_card *card, chip->p_dma.enable = sbus_dma_enable; chip->p_dma.request = sbus_dma_request; chip->p_dma.address = sbus_dma_addr; - chip->p_dma.reset = sbus_dma_reset; - chip->p_dma.preallocate = sbus_dma_preallocate; chip->c_dma.prepare = sbus_dma_prepare; chip->c_dma.enable = sbus_dma_enable; chip->c_dma.request = sbus_dma_request; chip->c_dma.address = sbus_dma_addr; - chip->c_dma.reset = sbus_dma_reset; - chip->c_dma.preallocate = sbus_dma_preallocate; - if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt, + if (request_irq(op->archdata.irqs[0], snd_cs4231_sbus_interrupt, IRQF_SHARED, "cs4231", chip)) { snd_printdd("cs4231-%d: Unable to grab SBUS IRQ %d\n", - dev, sdev->irqs[0]); + dev, op->archdata.irqs[0]); snd_cs4231_sbus_free(chip); return -EBUSY; } - chip->irq[0] = sdev->irqs[0]; + chip->irq[0] = op->archdata.irqs[0]; if (snd_cs4231_probe(chip) < 0) { snd_cs4231_sbus_free(chip); @@ -2021,18 +1861,16 @@ static int __init snd_cs4231_sbus_create(struct snd_card *card, return err; } - *rchip = chip; return 0; } -static int __init cs4231_sbus_attach(struct sbus_dev *sdev) +static int cs4231_sbus_probe(struct platform_device *op) { - struct resource *rp = &sdev->resource[0]; - struct snd_cs4231 *cp; + struct resource *rp = &op->resource[0]; struct snd_card *card; int err; - err = cs4231_attach_begin(&card); + err = cs4231_attach_begin(op, &card); if (err) return err; @@ -2040,27 +1878,30 @@ static int __init cs4231_sbus_attach(struct sbus_dev *sdev) card->shortname, rp->flags & 0xffL, (unsigned long long)rp->start, - sdev->irqs[0]); + op->archdata.irqs[0]); - if ((err = snd_cs4231_sbus_create(card, sdev, dev, &cp)) < 0) { + err = snd_cs4231_sbus_create(card, op, dev); + if (err < 0) { snd_card_free(card); return err; } - return cs4231_attach_finish(card, cp); + return cs4231_attach_finish(card); } #endif #ifdef EBUS_SUPPORT -static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event, void *cookie) +static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event, + void *cookie) { struct snd_cs4231 *chip = cookie; - + snd_cs4231_play_callback(chip); } -static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event, void *cookie) +static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, + int event, void *cookie) { struct snd_cs4231 *chip = cookie; @@ -2071,7 +1912,8 @@ static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event, * EBUS DMA wrappers */ -static int _ebus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len) +static int _ebus_dma_request(struct cs4231_dma_control *dma_cont, + dma_addr_t bus_addr, size_t len) { return ebus_dma_request(&dma_cont->ebus_info, bus_addr, len); } @@ -2091,37 +1933,25 @@ static unsigned int _ebus_dma_addr(struct cs4231_dma_control *dma_cont) return ebus_dma_addr(&dma_cont->ebus_info); } -static void _ebus_dma_reset(struct snd_cs4231 *chip) -{ - return; -} - -static void _ebus_dma_preallocate(struct snd_cs4231 *chip, struct snd_pcm *pcm) -{ - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->dev_u.pdev), - 64*1024, 128*1024); -} - /* * Init and exit routines */ static int snd_cs4231_ebus_free(struct snd_cs4231 *chip) { + struct platform_device *op = chip->op; + if (chip->c_dma.ebus_info.regs) { ebus_dma_unregister(&chip->c_dma.ebus_info); - iounmap(chip->c_dma.ebus_info.regs); + of_iounmap(&op->resource[2], chip->c_dma.ebus_info.regs, 0x10); } if (chip->p_dma.ebus_info.regs) { ebus_dma_unregister(&chip->p_dma.ebus_info); - iounmap(chip->p_dma.ebus_info.regs); + of_iounmap(&op->resource[1], chip->p_dma.ebus_info.regs, 0x10); } if (chip->port) - iounmap(chip->port); - - kfree(chip); + of_iounmap(&op->resource[0], chip->port, 0x10); return 0; } @@ -2137,58 +1967,50 @@ static struct snd_device_ops snd_cs4231_ebus_dev_ops = { .dev_free = snd_cs4231_ebus_dev_free, }; -static int __init snd_cs4231_ebus_create(struct snd_card *card, - struct linux_ebus_device *edev, - int dev, - struct snd_cs4231 **rchip) +static int snd_cs4231_ebus_create(struct snd_card *card, + struct platform_device *op, + int dev) { - struct snd_cs4231 *chip; + struct snd_cs4231 *chip = card->private_data; int err; - *rchip = NULL; - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - spin_lock_init(&chip->lock); spin_lock_init(&chip->c_dma.ebus_info.lock); spin_lock_init(&chip->p_dma.ebus_info.lock); mutex_init(&chip->mce_mutex); mutex_init(&chip->open_mutex); chip->flags |= CS4231_FLAG_EBUS; - chip->card = card; - chip->dev_u.pdev = edev->bus->self; + chip->op = op; memcpy(&chip->image, &snd_cs4231_original_image, sizeof(snd_cs4231_original_image)); strcpy(chip->c_dma.ebus_info.name, "cs4231(capture)"); chip->c_dma.ebus_info.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER; chip->c_dma.ebus_info.callback = snd_cs4231_ebus_capture_callback; chip->c_dma.ebus_info.client_cookie = chip; - chip->c_dma.ebus_info.irq = edev->irqs[0]; + chip->c_dma.ebus_info.irq = op->archdata.irqs[0]; strcpy(chip->p_dma.ebus_info.name, "cs4231(play)"); chip->p_dma.ebus_info.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER; chip->p_dma.ebus_info.callback = snd_cs4231_ebus_play_callback; chip->p_dma.ebus_info.client_cookie = chip; - chip->p_dma.ebus_info.irq = edev->irqs[1]; + chip->p_dma.ebus_info.irq = op->archdata.irqs[1]; chip->p_dma.prepare = _ebus_dma_prepare; chip->p_dma.enable = _ebus_dma_enable; chip->p_dma.request = _ebus_dma_request; chip->p_dma.address = _ebus_dma_addr; - chip->p_dma.reset = _ebus_dma_reset; - chip->p_dma.preallocate = _ebus_dma_preallocate; chip->c_dma.prepare = _ebus_dma_prepare; chip->c_dma.enable = _ebus_dma_enable; chip->c_dma.request = _ebus_dma_request; chip->c_dma.address = _ebus_dma_addr; - chip->c_dma.reset = _ebus_dma_reset; - chip->c_dma.preallocate = _ebus_dma_preallocate; - chip->port = ioremap(edev->resource[0].start, 0x10); - chip->p_dma.ebus_info.regs = ioremap(edev->resource[1].start, 0x10); - chip->c_dma.ebus_info.regs = ioremap(edev->resource[2].start, 0x10); - if (!chip->port || !chip->p_dma.ebus_info.regs || !chip->c_dma.ebus_info.regs) { + chip->port = of_ioremap(&op->resource[0], 0, 0x10, "cs4231"); + chip->p_dma.ebus_info.regs = + of_ioremap(&op->resource[1], 0, 0x10, "cs4231_pdma"); + chip->c_dma.ebus_info.regs = + of_ioremap(&op->resource[2], 0, 0x10, "cs4231_cdma"); + if (!chip->port || !chip->p_dma.ebus_info.regs || + !chip->c_dma.ebus_info.regs) { snd_cs4231_ebus_free(chip); snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev); return -EIO; @@ -2196,18 +2018,21 @@ static int __init snd_cs4231_ebus_create(struct snd_card *card, if (ebus_dma_register(&chip->c_dma.ebus_info)) { snd_cs4231_ebus_free(chip); - snd_printdd("cs4231-%d: Unable to register EBUS capture DMA\n", dev); + snd_printdd("cs4231-%d: Unable to register EBUS capture DMA\n", + dev); return -EBUSY; } if (ebus_dma_irq_enable(&chip->c_dma.ebus_info, 1)) { snd_cs4231_ebus_free(chip); - snd_printdd("cs4231-%d: Unable to enable EBUS capture IRQ\n", dev); + snd_printdd("cs4231-%d: Unable to enable EBUS capture IRQ\n", + dev); return -EBUSY; } if (ebus_dma_register(&chip->p_dma.ebus_info)) { snd_cs4231_ebus_free(chip); - snd_printdd("cs4231-%d: Unable to register EBUS play DMA\n", dev); + snd_printdd("cs4231-%d: Unable to register EBUS play DMA\n", + dev); return -EBUSY; } if (ebus_dma_irq_enable(&chip->p_dma.ebus_info, 1)) { @@ -2228,97 +2053,77 @@ static int __init snd_cs4231_ebus_create(struct snd_card *card, return err; } - *rchip = chip; return 0; } -static int __init cs4231_ebus_attach(struct linux_ebus_device *edev) +static int cs4231_ebus_probe(struct platform_device *op) { struct snd_card *card; - struct snd_cs4231 *chip; int err; - err = cs4231_attach_begin(&card); + err = cs4231_attach_begin(op, &card); if (err) return err; - sprintf(card->longname, "%s at 0x%lx, irq %d", + sprintf(card->longname, "%s at 0x%llx, irq %d", card->shortname, - edev->resource[0].start, - edev->irqs[0]); + op->resource[0].start, + op->archdata.irqs[0]); - if ((err = snd_cs4231_ebus_create(card, edev, dev, &chip)) < 0) { + err = snd_cs4231_ebus_create(card, op, dev); + if (err < 0) { snd_card_free(card); return err; } - return cs4231_attach_finish(card, chip); + return cs4231_attach_finish(card); } #endif -static int __init cs4231_init(void) +static int cs4231_probe(struct platform_device *op) { -#ifdef SBUS_SUPPORT - struct sbus_bus *sbus; - struct sbus_dev *sdev; -#endif #ifdef EBUS_SUPPORT - struct linux_ebus *ebus; - struct linux_ebus_device *edev; + if (!strcmp(op->dev.of_node->parent->name, "ebus")) + return cs4231_ebus_probe(op); #endif - int found; - - found = 0; - #ifdef SBUS_SUPPORT - for_all_sbusdev(sdev, sbus) { - if (!strcmp(sdev->prom_name, "SUNW,CS4231")) { - if (cs4231_sbus_attach(sdev) == 0) - found++; - } - } -#endif -#ifdef EBUS_SUPPORT - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - int match = 0; - - if (!strcmp(edev->prom_node->name, "SUNW,CS4231")) { - match = 1; - } else if (!strcmp(edev->prom_node->name, "audio")) { - char *compat; - - compat = of_get_property(edev->prom_node, - "compatible", NULL); - if (compat && !strcmp(compat, "SUNW,CS4231")) - match = 1; - } - - if (match && - cs4231_ebus_attach(edev) == 0) - found++; - } - } + if (!strcmp(op->dev.of_node->parent->name, "sbus") || + !strcmp(op->dev.of_node->parent->name, "sbi")) + return cs4231_sbus_probe(op); #endif - - - return (found > 0) ? 0 : -EIO; + return -ENODEV; } -static void __exit cs4231_exit(void) +static int cs4231_remove(struct platform_device *op) { - struct snd_cs4231 *p = cs4231_list; + struct snd_cs4231 *chip = dev_get_drvdata(&op->dev); - while (p != NULL) { - struct snd_cs4231 *next = p->next; + snd_card_free(chip->card); - snd_card_free(p->card); + return 0; +} - p = next; - } +static const struct of_device_id cs4231_match[] = { + { + .name = "SUNW,CS4231", + }, + { + .name = "audio", + .compatible = "SUNW,CS4231", + }, + {}, +}; - cs4231_list = NULL; -} +MODULE_DEVICE_TABLE(of, cs4231_match); + +static struct platform_driver cs4231_driver = { + .driver = { + .name = "audio", + .owner = THIS_MODULE, + .of_match_table = cs4231_match, + }, + .probe = cs4231_probe, + .remove = cs4231_remove, +}; -module_init(cs4231_init); -module_exit(cs4231_exit); +module_platform_driver(cs4231_driver); diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index 8016541ec16..be1b1aa96b7 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -8,18 +8,18 @@ * Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de) * Copyright (C) 1998, 1999 Brent Baccala (baccala@freesoft.org) * - * This is the lowlevel driver for the DBRI & MMCODEC duo used for ISDN & AUDIO - * on Sun SPARCstation 10, 20, LX and Voyager models. + * This is the low level driver for the DBRI & MMCODEC duo used for ISDN & AUDIO + * on Sun SPARCStation 10, 20, LX and Voyager models. * * - DBRI: AT&T T5900FX Dual Basic Rates ISDN Interface. It is a 32 channel * data time multiplexer with ISDN support (aka T7259) * Interfaces: SBus,ISDN NT & TE, CHI, 4 bits parallel. * CHI: (spelled ki) Concentration Highway Interface (AT&T or Intel bus ?). * Documentation: - * - "STP 4000SBus Dual Basic Rate ISDN (DBRI) Tranceiver" from + * - "STP 4000SBus Dual Basic Rate ISDN (DBRI) Transceiver" from * Sparc Technology Business (courtesy of Sun Support) * - Data sheet of the T7903, a newer but very similar ISA bus equivalent - * available from the Lucent (formarly AT&T microelectronics) home + * available from the Lucent (formerly AT&T microelectronics) home * page. * - http://www.freesoft.org/Linux/DBRI/ * - MMCODEC: Crystal Semiconductor CS4215 16 bit Multimedia Audio Codec @@ -27,21 +27,21 @@ * Documentation: from the Crystal Semiconductor home page. * * The DBRI is a 32 pipe machine, each pipe can transfer some bits between - * memory and a serial device (long pipes, nr 0-15) or between two serial - * devices (short pipes, nr 16-31), or simply send a fixed data to a serial + * memory and a serial device (long pipes, no. 0-15) or between two serial + * devices (short pipes, no. 16-31), or simply send a fixed data to a serial * device (short pipes). - * A timeslot defines the bit-offset and nr of bits read from a serial device. + * A timeslot defines the bit-offset and no. of bits read from a serial device. * The timeslots are linked to 6 circular lists, one for each direction for * each serial device (NT,TE,CHI). A timeslot is associated to 1 or 2 pipes * (the second one is a monitor/tee pipe, valid only for serial input). * * The mmcodec is connected via the CHI bus and needs the data & some - * parameters (volume, output selection) timemultiplexed in 8 byte + * parameters (volume, output selection) time multiplexed in 8 byte * chunks. It also has a control mode, which serves for audio format setting. * * Looking at the CS4215 data sheet it is easy to set up 2 or 4 codecs on - * the same CHI bus, so I thought perhaps it is possible to use the onboard - * & the speakerbox codec simultanously, giving 2 (not very independent :-) + * the same CHI bus, so I thought perhaps it is possible to use the on-board + * & the speakerbox codec simultaneously, giving 2 (not very independent :-) * audio devices. But the SUN HW group decided against it, at least on my * LX the speakerbox connector has at least 1 pin missing and 1 wrongly * connected. @@ -53,9 +53,12 @@ * other DBRI low-level stuff */ -#include <sound/driver.h> #include <linux/interrupt.h> #include <linux/delay.h> +#include <linux/irq.h> +#include <linux/io.h> +#include <linux/dma-mapping.h> +#include <linux/gfp.h> #include <sound/core.h> #include <sound/pcm.h> @@ -64,10 +67,10 @@ #include <sound/control.h> #include <sound/initval.h> -#include <asm/irq.h> -#include <asm/io.h> -#include <asm/sbus.h> -#include <asm/atomic.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/atomic.h> +#include <linux/module.h> MODULE_AUTHOR("Rudolf Koenig, Brent Baccala and Martin Habets"); MODULE_DESCRIPTION("Sun DBRI"); @@ -76,7 +79,8 @@ MODULE_SUPPORTED_DEVICE("{{Sun,DBRI}}"); static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ +/* Enable this card */ +static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for Sun DBRI soundcard."); @@ -104,7 +108,7 @@ static char *cmds[] = { "SSP", "CHI", "NT", "TE", "CDEC", "TEST", "CDM", "RESRV" }; -#define dprintk(a, x...) if(dbri_debug & a) printk(KERN_DEBUG x) +#define dprintk(a, x...) if (dbri_debug & a) printk(KERN_DEBUG x) #else #define dprintk(a, x...) do { } while (0) @@ -131,7 +135,7 @@ struct cs4215 { }; /* - * Control mode first + * Control mode first */ /* Time Slot 1, Status register */ @@ -219,7 +223,7 @@ static struct { /* Time Slot 7, Input Setting */ #define CS4215_LG(v) v /* Left Gain Setting 0xf: 22.5 dB */ #define CS4215_IS (1<<4) /* Input Select: 1=Microphone, 0=Line */ -#define CS4215_OVR (1<<5) /* 1: Overrange condition occurred */ +#define CS4215_OVR (1<<5) /* 1: Over range condition occurred */ #define CS4215_PIO0 (1<<6) /* Parallel I/O 0 */ #define CS4215_PIO1 (1<<7) @@ -232,12 +236,12 @@ static struct { ****************************************************************************/ /* DBRI main registers */ -#define REG0 0x00UL /* Status and Control */ -#define REG1 0x04UL /* Mode and Interrupt */ -#define REG2 0x08UL /* Parallel IO */ -#define REG3 0x0cUL /* Test */ -#define REG8 0x20UL /* Command Queue Pointer */ -#define REG9 0x24UL /* Interrupt Queue Pointer */ +#define REG0 0x00 /* Status and Control */ +#define REG1 0x04 /* Mode and Interrupt */ +#define REG2 0x08 /* Parallel IO */ +#define REG3 0x0c /* Test */ +#define REG8 0x20 /* Command Queue Pointer */ +#define REG9 0x24 /* Interrupt Queue Pointer */ #define DBRI_NO_CMDS 64 #define DBRI_INT_BLK 64 @@ -285,7 +289,7 @@ struct dbri_pipe { /* Per stream (playback or record) information */ struct dbri_streaminfo { struct snd_pcm_substream *substream; - u32 dvma_buffer; /* Device view of Alsa DMA buffer */ + u32 dvma_buffer; /* Device view of ALSA DMA buffer */ int size; /* Size of DMA buffer */ size_t offset; /* offset in user buffer */ int pipe; /* Data pipe used */ @@ -295,10 +299,8 @@ struct dbri_streaminfo { /* This structure holds the information for both chips (DBRI & CS4215) */ struct snd_dbri { - struct snd_card *card; /* ALSA card */ - int regs_size, irq; /* Needed for unload */ - struct sbus_dev *sdev; /* SBUS device info */ + struct platform_device *op; /* OF device info */ spinlock_t lock; struct dbri_dma *dma; /* Pointer to our DMA block */ @@ -317,8 +319,6 @@ struct snd_dbri { struct cs4215 mm; /* mmcodec special info */ /* per stream (playback/record) info */ struct dbri_streaminfo stream_info[DBRI_NO_STREAMS]; - - struct snd_dbri *next; }; #define DBRI_MAX_VOLUME 63 /* Output volume */ @@ -341,11 +341,11 @@ struct snd_dbri { /* DBRI Reg1 - Mode and Interrupt Register - defines. (Page 18) */ #define D_LITTLE_END (1<<8) /* Byte Order */ #define D_BIG_END (0<<8) /* Byte Order */ -#define D_MRR (1<<4) /* Multiple Error Ack on SBus (readonly) */ -#define D_MLE (1<<3) /* Multiple Late Error on SBus (readonly) */ -#define D_LBG (1<<2) /* Lost Bus Grant on SBus (readonly) */ -#define D_MBE (1<<1) /* Burst Error on SBus (readonly) */ -#define D_IR (1<<0) /* Interrupt Indicator (readonly) */ +#define D_MRR (1<<4) /* Multiple Error Ack on SBus (read only) */ +#define D_MLE (1<<3) /* Multiple Late Error on SBus (read only) */ +#define D_LBG (1<<2) /* Lost Bus Grant on SBus (read only) */ +#define D_MBE (1<<1) /* Burst Error on SBus (read only) */ +#define D_IR (1<<0) /* Interrupt Indicator (read only) */ /* DBRI Reg2 - Parallel IO Register - defines. (Page 18) */ #define D_ENPIO3 (1<<7) /* Enable Pin 3 */ @@ -376,11 +376,11 @@ struct snd_dbri { #define D_CDM 0xe /* CHI Data mode command */ /* Special bits for some commands */ -#define D_PIPE(v) ((v)<<0) /* Pipe Nr: 0-15 long, 16-21 short */ +#define D_PIPE(v) ((v)<<0) /* Pipe No.: 0-15 long, 16-21 short */ /* Setup Data Pipe */ /* IRM */ -#define D_SDP_2SAME (1<<18) /* Report 2nd time in a row value rcvd */ +#define D_SDP_2SAME (1<<18) /* Report 2nd time in a row value received */ #define D_SDP_CHANGE (2<<18) /* Report any changes */ #define D_SDP_EVERY (3<<18) /* Report any changes */ #define D_SDP_EOL (1<<17) /* EOL interrupt enable */ @@ -419,7 +419,7 @@ struct snd_dbri { #define D_TS_NONCONTIG (3<<10) /* Non contiguous mode */ #define D_TS_ANCHOR (7<<10) /* Starting short pipes */ #define D_TS_MON(v) ((v)<<5) /* Monitor Pipe */ -#define D_TS_NEXT(v) ((v)<<0) /* Pipe Nr: 0-15 long, 16-21 short */ +#define D_TS_NEXT(v) ((v)<<0) /* Pipe no.: 0-15 long, 16-21 short */ /* Concentration Highway Interface Modes */ #define D_CHI_CHICM(v) ((v)<<16) /* Clock mode */ @@ -435,7 +435,7 @@ struct snd_dbri { #define D_NT_NBF (1<<16) /* Number of bad frames to loose framing */ #define D_NT_IRM_IMM (1<<15) /* Interrupt Report & Mask: Immediate */ #define D_NT_IRM_EN (1<<14) /* Interrupt Report & Mask: Enable */ -#define D_NT_ISNT (1<<13) /* Configfure interface as NT */ +#define D_NT_ISNT (1<<13) /* Configure interface as NT */ #define D_NT_FT (1<<12) /* Fixed Timing */ #define D_NT_EZ (1<<11) /* Echo Channel is Zeros */ #define D_NT_IFA (1<<10) /* Inhibit Final Activation */ @@ -455,7 +455,7 @@ struct snd_dbri { #define D_TEST_RAM(v) ((v)<<16) /* RAM Pointer */ #define D_TEST_SIZE(v) ((v)<<11) /* */ #define D_TEST_ROMONOFF 0x5 /* Toggle ROM opcode monitor on/off */ -#define D_TEST_PROC 0x6 /* MicroProcessor test */ +#define D_TEST_PROC 0x6 /* Microprocessor test */ #define D_TEST_SER 0x7 /* Serial-Controller test */ #define D_TEST_RAMREAD 0x8 /* Copy from Ram to system memory */ #define D_TEST_RAMWRITE 0x9 /* Copy into Ram from system memory */ @@ -464,12 +464,12 @@ struct snd_dbri { #define D_TEST_DUMP 0xe /* ROM Dump */ /* CHI Data Mode */ -#define D_CDM_THI (1<<8) /* Transmit Data on CHIDR Pin */ -#define D_CDM_RHI (1<<7) /* Receive Data on CHIDX Pin */ -#define D_CDM_RCE (1<<6) /* Receive on Rising Edge of CHICK */ -#define D_CDM_XCE (1<<2) /* Transmit Data on Rising Edge of CHICK */ -#define D_CDM_XEN (1<<1) /* Transmit Highway Enable */ -#define D_CDM_REN (1<<0) /* Receive Highway Enable */ +#define D_CDM_THI (1 << 8) /* Transmit Data on CHIDR Pin */ +#define D_CDM_RHI (1 << 7) /* Receive Data on CHIDX Pin */ +#define D_CDM_RCE (1 << 6) /* Receive on Rising Edge of CHICK */ +#define D_CDM_XCE (1 << 2) /* Transmit Data on Rising Edge of CHICK */ +#define D_CDM_XEN (1 << 1) /* Transmit Highway Enable */ +#define D_CDM_REN (1 << 0) /* Receive Highway Enable */ /* The Interrupts */ #define D_INTR_BRDY 1 /* Buffer Ready for processing */ @@ -493,9 +493,9 @@ struct snd_dbri { #define D_INTR_CHI 36 #define D_INTR_CMD 38 -#define D_INTR_GETCHAN(v) (((v)>>24) & 0x3f) -#define D_INTR_GETCODE(v) (((v)>>20) & 0xf) -#define D_INTR_GETCMD(v) (((v)>>16) & 0xf) +#define D_INTR_GETCHAN(v) (((v) >> 24) & 0x3f) +#define D_INTR_GETCODE(v) (((v) >> 20) & 0xf) +#define D_INTR_GETCMD(v) (((v) >> 16) & 0xf) #define D_INTR_GETVAL(v) ((v) & 0xffff) #define D_INTR_GETRVAL(v) ((v) & 0xfffff) @@ -533,43 +533,42 @@ struct snd_dbri { #define D_P_31 31 /* */ /* Transmit descriptor defines */ -#define DBRI_TD_F (1<<31) /* End of Frame */ -#define DBRI_TD_D (1<<30) /* Do not append CRC */ -#define DBRI_TD_CNT(v) ((v)<<16) /* Number of valid bytes in the buffer */ -#define DBRI_TD_B (1<<15) /* Final interrupt */ -#define DBRI_TD_M (1<<14) /* Marker interrupt */ -#define DBRI_TD_I (1<<13) /* Transmit Idle Characters */ -#define DBRI_TD_FCNT(v) (v) /* Flag Count */ -#define DBRI_TD_UNR (1<<3) /* Underrun: transmitter is out of data */ -#define DBRI_TD_ABT (1<<2) /* Abort: frame aborted */ -#define DBRI_TD_TBC (1<<0) /* Transmit buffer Complete */ -#define DBRI_TD_STATUS(v) ((v)&0xff) /* Transmit status */ - /* Maximum buffer size per TD: almost 8Kb */ +#define DBRI_TD_F (1 << 31) /* End of Frame */ +#define DBRI_TD_D (1 << 30) /* Do not append CRC */ +#define DBRI_TD_CNT(v) ((v) << 16) /* Number of valid bytes in the buffer */ +#define DBRI_TD_B (1 << 15) /* Final interrupt */ +#define DBRI_TD_M (1 << 14) /* Marker interrupt */ +#define DBRI_TD_I (1 << 13) /* Transmit Idle Characters */ +#define DBRI_TD_FCNT(v) (v) /* Flag Count */ +#define DBRI_TD_UNR (1 << 3) /* Underrun: transmitter is out of data */ +#define DBRI_TD_ABT (1 << 2) /* Abort: frame aborted */ +#define DBRI_TD_TBC (1 << 0) /* Transmit buffer Complete */ +#define DBRI_TD_STATUS(v) ((v) & 0xff) /* Transmit status */ + /* Maximum buffer size per TD: almost 8KB */ #define DBRI_TD_MAXCNT ((1 << 13) - 4) /* Receive descriptor defines */ -#define DBRI_RD_F (1<<31) /* End of Frame */ -#define DBRI_RD_C (1<<30) /* Completed buffer */ -#define DBRI_RD_B (1<<15) /* Final interrupt */ -#define DBRI_RD_M (1<<14) /* Marker interrupt */ -#define DBRI_RD_BCNT(v) (v) /* Buffer size */ -#define DBRI_RD_CRC (1<<7) /* 0: CRC is correct */ -#define DBRI_RD_BBC (1<<6) /* 1: Bad Byte received */ -#define DBRI_RD_ABT (1<<5) /* Abort: frame aborted */ -#define DBRI_RD_OVRN (1<<3) /* Overrun: data lost */ -#define DBRI_RD_STATUS(v) ((v)&0xff) /* Receive status */ -#define DBRI_RD_CNT(v) (((v)>>16)&0x1fff) /* Valid bytes in the buffer */ +#define DBRI_RD_F (1 << 31) /* End of Frame */ +#define DBRI_RD_C (1 << 30) /* Completed buffer */ +#define DBRI_RD_B (1 << 15) /* Final interrupt */ +#define DBRI_RD_M (1 << 14) /* Marker interrupt */ +#define DBRI_RD_BCNT(v) (v) /* Buffer size */ +#define DBRI_RD_CRC (1 << 7) /* 0: CRC is correct */ +#define DBRI_RD_BBC (1 << 6) /* 1: Bad Byte received */ +#define DBRI_RD_ABT (1 << 5) /* Abort: frame aborted */ +#define DBRI_RD_OVRN (1 << 3) /* Overrun: data lost */ +#define DBRI_RD_STATUS(v) ((v) & 0xff) /* Receive status */ +#define DBRI_RD_CNT(v) (((v) >> 16) & 0x1fff) /* Valid bytes in the buffer */ /* stream_info[] access */ /* Translate the ALSA direction into the array index */ #define DBRI_STREAMNO(substream) \ - (substream->stream == \ - SNDRV_PCM_STREAM_PLAYBACK? DBRI_PLAY: DBRI_REC) + (substream->stream == \ + SNDRV_PCM_STREAM_PLAYBACK ? DBRI_PLAY: DBRI_REC) /* Return a pointer to dbri_streaminfo */ -#define DBRI_STREAM(dbri, substream) &dbri->stream_info[DBRI_STREAMNO(substream)] - -static struct snd_dbri *dbri_list; /* All DBRI devices */ +#define DBRI_STREAM(dbri, substream) \ + &dbri->stream_info[DBRI_STREAMNO(substream)] /* * Short data pipes transmit LSB first. The CS4215 receives MSB first. Grrr. @@ -593,7 +592,7 @@ static __u32 reverse_bytes(__u32 b, int len) break; default: printk(KERN_ERR "DBRI reverse_bytes: unsupported length\n"); - }; + } return b; } @@ -609,21 +608,21 @@ The list is terminated with a WAIT command, which generates a CPU interrupt to signal completion. Since the DBRI can run in parallel with the CPU, several means of -synchronization present themselves. The method implemented here is only -use of the dbri_cmdwait() to wait for execution of batch of sent commands. +synchronization present themselves. The method implemented here uses +the dbri_cmdwait() to wait for execution of batch of sent commands. -A circular command buffer is used here. A new command is being added +A circular command buffer is used here. A new command is being added while another can be executed. The scheme works by adding two WAIT commands after each sent batch of commands. When the next batch is prepared it is added after the WAIT commands then the WAITs are replaced with single JUMP -command to the new batch. The the DBRI is forced to reread the last WAIT -command (replaced by the JUMP by then). If the DBRI is still executing +command to the new batch. The the DBRI is forced to reread the last WAIT +command (replaced by the JUMP by then). If the DBRI is still executing previous commands the request to reread the WAIT command is ignored. Every time a routine wants to write commands to the DBRI, it must -first call dbri_cmdlock() and get pointer to a free space in -dbri->dma->cmd buffer. After this, the commands can be written to -the buffer, and dbri_cmdsend() is called with the final pointer value +first call dbri_cmdlock() and get pointer to a free space in +dbri->dma->cmd buffer. After this, the commands can be written to +the buffer, and dbri_cmdsend() is called with the final pointer value to send them to the DBRI. */ @@ -646,18 +645,17 @@ static void dbri_cmdwait(struct snd_dbri *dbri) } spin_unlock_irqrestore(&dbri->lock, flags); - if (maxloops == 0) { + if (maxloops == 0) printk(KERN_ERR "DBRI: Chip never completed command buffer\n"); - } else { + else dprintk(D_CMD, "Chip completed command buffer (%d)\n", MAXLOOPS - maxloops - 1); - } } /* - * Lock the command queue and returns pointer to a space for len cmd words + * Lock the command queue and return pointer to space for len cmd words * It locks the cmdlock spinlock. */ -static s32 *dbri_cmdlock(struct snd_dbri * dbri, int len) +static s32 *dbri_cmdlock(struct snd_dbri *dbri, int len) { /* Space for 2 WAIT cmds (replaced later by 1 JUMP cmd) */ len += 2; @@ -673,14 +671,14 @@ static s32 *dbri_cmdlock(struct snd_dbri * dbri, int len) } /* - * Send prepared cmd string. It works by writting a JUMP cmd into + * Send prepared cmd string. It works by writing a JUMP cmd into * the last WAIT cmd and force DBRI to reread the cmd. * The JUMP cmd points to the new cmd string. * It also releases the cmdlock spinlock. * - * Lock must not be held before calling this. + * Lock must be held before calling this. */ -static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len) +static void dbri_cmdsend(struct snd_dbri *dbri, s32 *cmd, int len) { s32 tmp, addr; static int wait_id = 0; @@ -700,16 +698,17 @@ static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len) s32 *ptr; for (ptr = dbri->cmdptr; ptr < cmd+2; ptr++) - dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); + dprintk(D_CMD, "cmd: %lx:%08x\n", + (unsigned long)ptr, *ptr); } else { s32 *ptr = dbri->cmdptr; dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); ptr++; dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); - for (ptr = dbri->dma->cmd; ptr < cmd+2; ptr++) { - dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); - } + for (ptr = dbri->dma->cmd; ptr < cmd+2; ptr++) + dprintk(D_CMD, "cmd: %lx:%08x\n", + (unsigned long)ptr, *ptr); } #endif @@ -723,7 +722,7 @@ static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len) } /* Lock must be held when calling this */ -static void dbri_reset(struct snd_dbri * dbri) +static void dbri_reset(struct snd_dbri *dbri) { int i; u32 tmp; @@ -746,7 +745,7 @@ static void dbri_reset(struct snd_dbri * dbri) } /* Lock must not be held before calling this */ -static void dbri_initialize(struct snd_dbri * dbri) +static void dbri_initialize(struct snd_dbri *dbri) { s32 *cmd; u32 dma_addr; @@ -763,7 +762,7 @@ static void dbri_initialize(struct snd_dbri * dbri) spin_lock_init(&dbri->cmdlock); /* - * Initialize the interrupt ringbuffer. + * Initialize the interrupt ring buffer. */ dma_addr = dbri->dma_dvma + dbri_dma_off(intr, 0); dbri->dma->intr[0] = dma_addr; @@ -801,7 +800,7 @@ list ordering, among other things. The transmit and receive functions here interface closely with the transmit and receive interrupt code. */ -static int pipe_active(struct snd_dbri * dbri, int pipe) +static inline int pipe_active(struct snd_dbri *dbri, int pipe) { return ((pipe >= 0) && (dbri->pipes[pipe].desc != -1)); } @@ -811,20 +810,22 @@ static int pipe_active(struct snd_dbri * dbri, int pipe) * Called on an in-use pipe to clear anything being transmitted or received * Lock must be held before calling this. */ -static void reset_pipe(struct snd_dbri * dbri, int pipe) +static void reset_pipe(struct snd_dbri *dbri, int pipe) { int sdp; int desc; s32 *cmd; if (pipe < 0 || pipe > DBRI_MAX_PIPE) { - printk(KERN_ERR "DBRI: reset_pipe called with illegal pipe number\n"); + printk(KERN_ERR "DBRI: reset_pipe called with " + "illegal pipe number\n"); return; } sdp = dbri->pipes[pipe].sdp; if (sdp == 0) { - printk(KERN_ERR "DBRI: reset_pipe called on uninitialized pipe\n"); + printk(KERN_ERR "DBRI: reset_pipe called " + "on uninitialized pipe\n"); return; } @@ -835,9 +836,10 @@ static void reset_pipe(struct snd_dbri * dbri, int pipe) dbri_cmdsend(dbri, cmd, 3); desc = dbri->pipes[pipe].first_desc; - if ( desc >= 0) + if (desc >= 0) do { - dbri->dma->desc[desc].nda = dbri->dma->desc[desc].ba = 0; + dbri->dma->desc[desc].ba = 0; + dbri->dma->desc[desc].nda = 0; desc = dbri->next_desc[desc]; } while (desc != -1 && desc != dbri->pipes[pipe].first_desc); @@ -848,15 +850,17 @@ static void reset_pipe(struct snd_dbri * dbri, int pipe) /* * Lock must be held before calling this. */ -static void setup_pipe(struct snd_dbri * dbri, int pipe, int sdp) +static void setup_pipe(struct snd_dbri *dbri, int pipe, int sdp) { if (pipe < 0 || pipe > DBRI_MAX_PIPE) { - printk(KERN_ERR "DBRI: setup_pipe called with illegal pipe number\n"); + printk(KERN_ERR "DBRI: setup_pipe called " + "with illegal pipe number\n"); return; } if ((sdp & 0xf800) != sdp) { - printk(KERN_ERR "DBRI: setup_pipe called with strange SDP value\n"); + printk(KERN_ERR "DBRI: setup_pipe called " + "with strange SDP value\n"); /* sdp &= 0xf800; */ } @@ -877,25 +881,26 @@ static void setup_pipe(struct snd_dbri * dbri, int pipe, int sdp) /* * Lock must be held before calling this. */ -static void link_time_slot(struct snd_dbri * dbri, int pipe, +static void link_time_slot(struct snd_dbri *dbri, int pipe, int prevpipe, int nextpipe, int length, int cycle) { s32 *cmd; int val; - if (pipe < 0 || pipe > DBRI_MAX_PIPE + if (pipe < 0 || pipe > DBRI_MAX_PIPE || prevpipe < 0 || prevpipe > DBRI_MAX_PIPE || nextpipe < 0 || nextpipe > DBRI_MAX_PIPE) { - printk(KERN_ERR + printk(KERN_ERR "DBRI: link_time_slot called with illegal pipe number\n"); return; } - if (dbri->pipes[pipe].sdp == 0 + if (dbri->pipes[pipe].sdp == 0 || dbri->pipes[prevpipe].sdp == 0 || dbri->pipes[nextpipe].sdp == 0) { - printk(KERN_ERR "DBRI: link_time_slot called on uninitialized pipe\n"); + printk(KERN_ERR "DBRI: link_time_slot called " + "on uninitialized pipe\n"); return; } @@ -935,17 +940,17 @@ static void link_time_slot(struct snd_dbri * dbri, int pipe, /* * Lock must be held before calling this. */ -static void unlink_time_slot(struct snd_dbri * dbri, int pipe, +static void unlink_time_slot(struct snd_dbri *dbri, int pipe, enum in_or_out direction, int prevpipe, int nextpipe) { s32 *cmd; int val; - if (pipe < 0 || pipe > DBRI_MAX_PIPE + if (pipe < 0 || pipe > DBRI_MAX_PIPE || prevpipe < 0 || prevpipe > DBRI_MAX_PIPE || nextpipe < 0 || nextpipe > DBRI_MAX_PIPE) { - printk(KERN_ERR + printk(KERN_ERR "DBRI: unlink_time_slot called with illegal pipe number\n"); return; } @@ -985,7 +990,7 @@ static void unlink_time_slot(struct snd_dbri * dbri, int pipe, * * Lock must not be held before calling it. */ -static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data) +static void xmit_fixed(struct snd_dbri *dbri, int pipe, unsigned int data) { s32 *cmd; unsigned long flags; @@ -996,7 +1001,8 @@ static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data) } if (D_SDP_MODE(dbri->pipes[pipe].sdp) == 0) { - printk(KERN_ERR "DBRI: xmit_fixed: Uninitialized pipe %d\n", pipe); + printk(KERN_ERR "DBRI: xmit_fixed: " + "Uninitialized pipe %d\n", pipe); return; } @@ -1006,7 +1012,8 @@ static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data) } if (!(dbri->pipes[pipe].sdp & D_SDP_TO_SER)) { - printk(KERN_ERR "DBRI: xmit_fixed: Called on receive pipe %d\n", pipe); + printk(KERN_ERR "DBRI: xmit_fixed: Called on receive pipe %d\n", + pipe); return; } @@ -1028,20 +1035,23 @@ static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data) } -static void recv_fixed(struct snd_dbri * dbri, int pipe, volatile __u32 * ptr) +static void recv_fixed(struct snd_dbri *dbri, int pipe, volatile __u32 *ptr) { if (pipe < 16 || pipe > DBRI_MAX_PIPE) { - printk(KERN_ERR "DBRI: recv_fixed called with illegal pipe number\n"); + printk(KERN_ERR "DBRI: recv_fixed called with " + "illegal pipe number\n"); return; } if (D_SDP_MODE(dbri->pipes[pipe].sdp) != D_SDP_FIXED) { - printk(KERN_ERR "DBRI: recv_fixed called on non-fixed pipe %d\n", pipe); + printk(KERN_ERR "DBRI: recv_fixed called on " + "non-fixed pipe %d\n", pipe); return; } if (dbri->pipes[pipe].sdp & D_SDP_TO_SER) { - printk(KERN_ERR "DBRI: recv_fixed called on transmit pipe %d\n", pipe); + printk(KERN_ERR "DBRI: recv_fixed called on " + "transmit pipe %d\n", pipe); return; } @@ -1064,7 +1074,7 @@ static void recv_fixed(struct snd_dbri * dbri, int pipe, volatile __u32 * ptr) * * Lock must be held before calling this. */ -static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period) +static int setup_descs(struct snd_dbri *dbri, int streamno, unsigned int period) { struct dbri_streaminfo *info = &dbri->stream_info[streamno]; __u32 dvma_buffer; @@ -1089,21 +1099,23 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period if (streamno == DBRI_PLAY) { if (!(dbri->pipes[info->pipe].sdp & D_SDP_TO_SER)) { - printk(KERN_ERR "DBRI: setup_descs: Called on receive pipe %d\n", - info->pipe); + printk(KERN_ERR "DBRI: setup_descs: " + "Called on receive pipe %d\n", info->pipe); return -2; } } else { if (dbri->pipes[info->pipe].sdp & D_SDP_TO_SER) { - printk(KERN_ERR + printk(KERN_ERR "DBRI: setup_descs: Called on transmit pipe %d\n", info->pipe); return -2; } - /* Should be able to queue multiple buffers to receive on a pipe */ + /* Should be able to queue multiple buffers + * to receive on a pipe + */ if (pipe_active(dbri, info->pipe)) { - printk(KERN_ERR "DBRI: recv_on_pipe: Called on active pipe %d\n", - info->pipe); + printk(KERN_ERR "DBRI: recv_on_pipe: " + "Called on active pipe %d\n", info->pipe); return -2; } @@ -1113,11 +1125,13 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period /* Free descriptors if pipe has any */ desc = dbri->pipes[info->pipe].first_desc; - if ( desc >= 0) + if (desc >= 0) do { - dbri->dma->desc[desc].nda = dbri->dma->desc[desc].ba = 0; + dbri->dma->desc[desc].ba = 0; + dbri->dma->desc[desc].nda = 0; desc = dbri->next_desc[desc]; - } while (desc != -1 && desc != dbri->pipes[info->pipe].first_desc); + } while (desc != -1 && + desc != dbri->pipes[info->pipe].first_desc); dbri->pipes[info->pipe].desc = -1; dbri->pipes[info->pipe].first_desc = -1; @@ -1130,6 +1144,7 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period if (!dbri->dma->desc[desc].ba) break; } + if (desc == DBRI_NO_DESCS) { printk(KERN_ERR "DBRI: setup_descs: No descriptors\n"); return -1; @@ -1150,8 +1165,7 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period if (streamno == DBRI_PLAY) { dbri->dma->desc[desc].word1 = DBRI_TD_CNT(mylen); dbri->dma->desc[desc].word4 = 0; - dbri->dma->desc[desc].word1 |= - DBRI_TD_F | DBRI_TD_B; + dbri->dma->desc[desc].word1 |= DBRI_TD_F | DBRI_TD_B; } else { dbri->dma->desc[desc].word1 = 0; dbri->dma->desc[desc].word4 = @@ -1172,7 +1186,8 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period } if (first_desc == -1 || last_desc == -1) { - printk(KERN_ERR "DBRI: setup_descs: Not enough descriptors available\n"); + printk(KERN_ERR "DBRI: setup_descs: " + " Not enough descriptors available\n"); return -1; } @@ -1183,14 +1198,14 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period dbri->pipes[info->pipe].desc = first_desc; #ifdef DBRI_DEBUG - for (desc = first_desc; desc != -1; ) { + for (desc = first_desc; desc != -1;) { dprintk(D_DESC, "DESC %d: %08x %08x %08x %08x\n", desc, dbri->dma->desc[desc].word1, dbri->dma->desc[desc].ba, dbri->dma->desc[desc].nda, dbri->dma->desc[desc].word4); desc = dbri->next_desc[desc]; - if ( desc == first_desc ) + if (desc == first_desc) break; } #endif @@ -1213,7 +1228,8 @@ enum master_or_slave { CHImaster, CHIslave }; /* * Lock must not be held before calling it. */ -static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_slave, +static void reset_chi(struct snd_dbri *dbri, + enum master_or_slave master_or_slave, int bits_per_frame) { s32 *cmd; @@ -1222,7 +1238,7 @@ static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_sla /* Set CHI Anchor: Pipe 16 */ cmd = dbri_cmdlock(dbri, 4); - val = D_DTS_VO | D_DTS_VI | D_DTS_INS + val = D_DTS_VO | D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(16) | D_PIPE(16) | D_DTS_PRVOUT(16); *(cmd++) = DBRI_CMD(D_DTS, 0, val); *(cmd++) = D_TS_ANCHOR | D_TS_NEXT(16); @@ -1246,15 +1262,16 @@ static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_sla } else { /* Setup DBRI for CHI Master - generate clock, FS * - * BPF = bits per 8 kHz frame - * 12.288 MHz / CHICM_divisor = clock rate - * FD = 1 - drive CHIFS on rising edge of CHICK + * BPF = bits per 8 kHz frame + * 12.288 MHz / CHICM_divisor = clock rate + * FD = 1 - drive CHIFS on rising edge of CHICK */ int clockrate = bits_per_frame * 8; int divisor = 12288 / clockrate; if (divisor > 255 || divisor * clockrate != 12288) - printk(KERN_ERR "DBRI: illegal bits_per_frame in setup_chi\n"); + printk(KERN_ERR "DBRI: illegal bits_per_frame " + "in setup_chi\n"); *(cmd++) = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(divisor) | D_CHI_FD | D_CHI_BPF(bits_per_frame)); @@ -1288,7 +1305,7 @@ to the DBRI via the CHI interface and few of the DBRI's PIO pins. * Lock must not be held before calling it. */ -static void cs4215_setup_pipes(struct snd_dbri * dbri) +static void cs4215_setup_pipes(struct snd_dbri *dbri) { unsigned long flags; @@ -1303,9 +1320,9 @@ static void cs4215_setup_pipes(struct snd_dbri * dbri) * not relevant for us (only for doublechecking). * * Control mode: - * Pipe 17: Send timeslots 1-4 (slots 5-8 are readonly) + * Pipe 17: Send timeslots 1-4 (slots 5-8 are read only) * Pipe 18: Receive timeslot 1 (clb). - * Pipe 19: Receive timeslot 7 (version). + * Pipe 19: Receive timeslot 7 (version). */ setup_pipe(dbri, 4, D_SDP_MEM | D_SDP_TO_SER | D_SDP_MSB); @@ -1355,7 +1372,7 @@ static int cs4215_init_data(struct cs4215 *mm) return 0; } -static void cs4215_setdata(struct snd_dbri * dbri, int muted) +static void cs4215_setdata(struct snd_dbri *dbri, int muted) { if (muted) { dbri->mm.data[0] |= 63; @@ -1387,7 +1404,7 @@ static void cs4215_setdata(struct snd_dbri * dbri, int muted) /* * Set the CS4215 to data mode. */ -static void cs4215_open(struct snd_dbri * dbri) +static void cs4215_open(struct snd_dbri *dbri) { int data_width; u32 tmp; @@ -1452,7 +1469,7 @@ static void cs4215_open(struct snd_dbri * dbri) /* * Send the control information (i.e. audio format) */ -static int cs4215_setctrl(struct snd_dbri * dbri) +static int cs4215_setctrl(struct snd_dbri *dbri) { int i, val; u32 tmp; @@ -1502,9 +1519,9 @@ static int cs4215_setctrl(struct snd_dbri * dbri) /* * Control mode: - * Pipe 17: Send timeslots 1-4 (slots 5-8 are readonly) + * Pipe 17: Send timeslots 1-4 (slots 5-8 are read only) * Pipe 18: Receive timeslot 1 (clb). - * Pipe 19: Receive timeslot 7 (version). + * Pipe 19: Receive timeslot 7 (version). */ link_time_slot(dbri, 17, 16, 16, 32, dbri->mm.offset); @@ -1522,9 +1539,9 @@ static int cs4215_setctrl(struct snd_dbri * dbri) sbus_writel(tmp, dbri->regs + REG0); spin_unlock_irqrestore(&dbri->lock, flags); - for (i = 10; ((dbri->mm.status & 0xe4) != 0x20); --i) { + for (i = 10; ((dbri->mm.status & 0xe4) != 0x20); --i) msleep_interruptible(1); - } + if (i == 0) { dprintk(D_MM, "CS4215 didn't respond to CLB (0x%02x)\n", dbri->mm.status); @@ -1556,7 +1573,7 @@ static int cs4215_setctrl(struct snd_dbri * dbri) * As part of the process we resend the settings for the data * timeslots as well. */ -static int cs4215_prepare(struct snd_dbri * dbri, unsigned int rate, +static int cs4215_prepare(struct snd_dbri *dbri, unsigned int rate, snd_pcm_format_t format, unsigned int channels) { int freq_idx; @@ -1613,7 +1630,7 @@ static int cs4215_prepare(struct snd_dbri * dbri, unsigned int rate, /* * */ -static int cs4215_init(struct snd_dbri * dbri) +static int cs4215_init(struct snd_dbri *dbri) { u32 reg2 = sbus_readl(dbri->regs + REG2); dprintk(D_MM, "cs4215_init: reg2=0x%x\n", reg2); @@ -1674,7 +1691,7 @@ interrupts are disabled. /* xmit_descs() * - * Starts transmiting the current TD's for recording/playing. + * Starts transmitting the current TD's for recording/playing. * For playback, ALSA has filled the DMA memory with new data (we hope). */ static void xmit_descs(struct snd_dbri *dbri) @@ -1701,7 +1718,8 @@ static void xmit_descs(struct snd_dbri *dbri) *(cmd++) = DBRI_CMD(D_SDP, 0, dbri->pipes[info->pipe].sdp | D_SDP_P | D_SDP_EVERY | D_SDP_C); - *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_td); + *(cmd++) = dbri->dma_dvma + + dbri_dma_off(desc, first_td); dbri_cmdsend(dbri, cmd, 2); /* Reset our admin of the pipe. */ @@ -1722,7 +1740,8 @@ static void xmit_descs(struct snd_dbri *dbri) *(cmd++) = DBRI_CMD(D_SDP, 0, dbri->pipes[info->pipe].sdp | D_SDP_P | D_SDP_EVERY | D_SDP_C); - *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_td); + *(cmd++) = dbri->dma_dvma + + dbri_dma_off(desc, first_td); dbri_cmdsend(dbri, cmd, 2); /* Reset our admin of the pipe. */ @@ -1747,15 +1766,12 @@ static void xmit_descs(struct snd_dbri *dbri) * */ -static void transmission_complete_intr(struct snd_dbri * dbri, int pipe) +static void transmission_complete_intr(struct snd_dbri *dbri, int pipe) { - struct dbri_streaminfo *info; - int td; + struct dbri_streaminfo *info = &dbri->stream_info[DBRI_PLAY]; + int td = dbri->pipes[pipe].desc; int status; - info = &dbri->stream_info[DBRI_PLAY]; - - td = dbri->pipes[pipe].desc; while (td >= 0) { if (td >= DBRI_NO_DESCS) { printk(KERN_ERR "DBRI: invalid td on pipe %d\n", pipe); @@ -1763,9 +1779,8 @@ static void transmission_complete_intr(struct snd_dbri * dbri, int pipe) } status = DBRI_TD_STATUS(dbri->dma->desc[td].word4); - if (!(status & DBRI_TD_TBC)) { + if (!(status & DBRI_TD_TBC)) break; - } dprintk(D_INT, "TD %d, status 0x%02x\n", td, status); @@ -1777,15 +1792,12 @@ static void transmission_complete_intr(struct snd_dbri * dbri, int pipe) } /* Notify ALSA */ - if (spin_is_locked(&dbri->lock)) { - spin_unlock(&dbri->lock); - snd_pcm_period_elapsed(info->substream); - spin_lock(&dbri->lock); - } else - snd_pcm_period_elapsed(info->substream); + spin_unlock(&dbri->lock); + snd_pcm_period_elapsed(info->substream); + spin_lock(&dbri->lock); } -static void reception_complete_intr(struct snd_dbri * dbri, int pipe) +static void reception_complete_intr(struct snd_dbri *dbri, int pipe) { struct dbri_streaminfo *info; int rd = dbri->pipes[pipe].desc; @@ -1809,15 +1821,12 @@ static void reception_complete_intr(struct snd_dbri * dbri, int pipe) rd, DBRI_RD_STATUS(status), DBRI_RD_CNT(status)); /* Notify ALSA */ - if (spin_is_locked(&dbri->lock)) { - spin_unlock(&dbri->lock); - snd_pcm_period_elapsed(info->substream); - spin_lock(&dbri->lock); - } else - snd_pcm_period_elapsed(info->substream); + spin_unlock(&dbri->lock); + snd_pcm_period_elapsed(info->substream); + spin_lock(&dbri->lock); } -static void dbri_process_one_interrupt(struct snd_dbri * dbri, int x) +static void dbri_process_one_interrupt(struct snd_dbri *dbri, int x) { int val = D_INTR_GETVAL(x); int channel = D_INTR_GETCHAN(x); @@ -1889,7 +1898,7 @@ static void dbri_process_one_interrupt(struct snd_dbri * dbri, int x) * right now). Non-zero words require processing and are handed off * to dbri_process_one_interrupt AFTER advancing the pointer. */ -static void dbri_process_interrupt_buffer(struct snd_dbri * dbri) +static void dbri_process_interrupt_buffer(struct snd_dbri *dbri) { s32 x; @@ -1903,8 +1912,7 @@ static void dbri_process_interrupt_buffer(struct snd_dbri * dbri) } } -static irqreturn_t snd_dbri_interrupt(int irq, void *dev_id, - struct pt_regs *regs) +static irqreturn_t snd_dbri_interrupt(int irq, void *dev_id) { struct snd_dbri *dbri = dev_id; static int errcnt = 0; @@ -1966,20 +1974,21 @@ static irqreturn_t snd_dbri_interrupt(int irq, void *dev_id, PCM Interface ****************************************************************************/ static struct snd_pcm_hardware snd_dbri_pcm_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_MU_LAW | - SNDRV_PCM_FMTBIT_A_LAW | - SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_BE, - .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_5512, + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BATCH, + .formats = SNDRV_PCM_FMTBIT_MU_LAW | + SNDRV_PCM_FMTBIT_A_LAW | + SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_BE, + .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_5512, .rate_min = 5512, .rate_max = 48000, .channels_min = 1, .channels_max = 2, - .buffer_bytes_max = (64 * 1024), + .buffer_bytes_max = 64 * 1024, .period_bytes_min = 1, .period_bytes_max = DBRI_TD_MAXCNT, .periods_min = 1, @@ -2012,7 +2021,8 @@ static int snd_hw_rule_channels(struct snd_pcm_hw_params *params, snd_interval_any(&ch); if (!(f->bits[0] & SNDRV_PCM_FMTBIT_S16_BE)) { - ch.min = ch.max = 1; + ch.min = 1; + ch.max = 1; ch.integer = 1; return snd_interval_refine(c, &ch); } @@ -2036,14 +2046,14 @@ static int snd_dbri_open(struct snd_pcm_substream *substream) info->pipe = -1; spin_unlock_irqrestore(&dbri->lock, flags); - snd_pcm_hw_rule_add(runtime,0,SNDRV_PCM_HW_PARAM_CHANNELS, + snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, snd_hw_rule_format, NULL, SNDRV_PCM_HW_PARAM_FORMAT, -1); - snd_pcm_hw_rule_add(runtime,0,SNDRV_PCM_HW_PARAM_FORMAT, - snd_hw_rule_channels, NULL, + snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, + snd_hw_rule_channels, NULL, SNDRV_PCM_HW_PARAM_CHANNELS, -1); - + cs4215_open(dbri); return 0; @@ -2087,14 +2097,15 @@ static int snd_dbri_hw_params(struct snd_pcm_substream *substream, */ if (info->dvma_buffer == 0) { if (DBRI_STREAMNO(substream) == DBRI_PLAY) - direction = SBUS_DMA_TODEVICE; + direction = DMA_TO_DEVICE; else - direction = SBUS_DMA_FROMDEVICE; + direction = DMA_FROM_DEVICE; - info->dvma_buffer = sbus_map_single(dbri->sdev, - runtime->dma_area, - params_buffer_bytes(hw_params), - direction); + info->dvma_buffer = + dma_map_single(&dbri->op->dev, + runtime->dma_area, + params_buffer_bytes(hw_params), + direction); } direction = params_buffer_bytes(hw_params); @@ -2115,12 +2126,12 @@ static int snd_dbri_hw_free(struct snd_pcm_substream *substream) */ if (info->dvma_buffer) { if (DBRI_STREAMNO(substream) == DBRI_PLAY) - direction = SBUS_DMA_TODEVICE; + direction = DMA_TO_DEVICE; else - direction = SBUS_DMA_FROMDEVICE; + direction = DMA_FROM_DEVICE; - sbus_unmap_single(dbri->sdev, info->dvma_buffer, - substream->runtime->buffer_size, direction); + dma_unmap_single(&dbri->op->dev, info->dvma_buffer, + substream->runtime->buffer_size, direction); info->dvma_buffer = 0; } if (info->pipe != -1) { @@ -2146,7 +2157,7 @@ static int snd_dbri_prepare(struct snd_pcm_substream *substream) spin_lock_irq(&dbri->lock); info->offset = 0; - /* Setup the all the transmit/receive desciptors to cover the + /* Setup the all the transmit/receive descriptors to cover the * whole DMA buffer. */ ret = setup_descs(dbri, DBRI_STREAMNO(substream), @@ -2206,32 +2217,30 @@ static struct snd_pcm_ops snd_dbri_ops = { .pointer = snd_dbri_pointer, }; -static int __devinit snd_dbri_pcm(struct snd_dbri * dbri) +static int snd_dbri_pcm(struct snd_card *card) { struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(dbri->card, + if ((err = snd_pcm_new(card, /* ID */ "sun_dbri", /* device */ 0, /* playback count */ 1, /* capture count */ 1, &pcm)) < 0) return err; - snd_assert(pcm != NULL, return -EINVAL); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_dbri_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_dbri_ops); - pcm->private_data = dbri; + pcm->private_data = card->private_data; pcm->info_flags = 0; - strcpy(pcm->name, dbri->card->shortname); + strcpy(pcm->name, card->shortname); if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), - 64 * 1024, 64 * 1024)) < 0) { + 64 * 1024, 64 * 1024)) < 0) return err; - } return 0; } @@ -2246,11 +2255,10 @@ static int snd_cs4215_info_volume(struct snd_kcontrol *kcontrol, uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 2; uinfo->value.integer.min = 0; - if (kcontrol->private_value == DBRI_PLAY) { + if (kcontrol->private_value == DBRI_PLAY) uinfo->value.integer.max = DBRI_MAX_VOLUME; - } else { + else uinfo->value.integer.max = DBRI_MAX_GAIN; - } return 0; } @@ -2259,9 +2267,10 @@ static int snd_cs4215_get_volume(struct snd_kcontrol *kcontrol, { struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol); struct dbri_streaminfo *info; - snd_assert(dbri != NULL, return -EINVAL); + + if (snd_BUG_ON(!dbri)) + return -EINVAL; info = &dbri->stream_info[kcontrol->private_value]; - snd_assert(info != NULL, return -EINVAL); ucontrol->value.integer.value[0] = info->left_gain; ucontrol->value.integer.value[1] = info->right_gain; @@ -2272,18 +2281,30 @@ static int snd_cs4215_put_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol); - struct dbri_streaminfo *info = &dbri->stream_info[kcontrol->private_value]; + struct dbri_streaminfo *info = + &dbri->stream_info[kcontrol->private_value]; + unsigned int vol[2]; int changed = 0; - if (info->left_gain != ucontrol->value.integer.value[0]) { - info->left_gain = ucontrol->value.integer.value[0]; + vol[0] = ucontrol->value.integer.value[0]; + vol[1] = ucontrol->value.integer.value[1]; + if (kcontrol->private_value == DBRI_PLAY) { + if (vol[0] > DBRI_MAX_VOLUME || vol[1] > DBRI_MAX_VOLUME) + return -EINVAL; + } else { + if (vol[0] > DBRI_MAX_GAIN || vol[1] > DBRI_MAX_GAIN) + return -EINVAL; + } + + if (info->left_gain != vol[0]) { + info->left_gain = vol[0]; changed = 1; } - if (info->right_gain != ucontrol->value.integer.value[1]) { - info->right_gain = ucontrol->value.integer.value[1]; + if (info->right_gain != vol[1]) { + info->right_gain = vol[1]; changed = 1; } - if (changed == 1) { + if (changed) { /* First mute outputs, and wait 1/8000 sec (125 us) * to make sure this takes. This avoids clicking noises. */ @@ -2315,20 +2336,20 @@ static int snd_cs4215_get_single(struct snd_kcontrol *kcontrol, int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 1; - snd_assert(dbri != NULL, return -EINVAL); - if (elem < 4) { + if (snd_BUG_ON(!dbri)) + return -EINVAL; + + if (elem < 4) ucontrol->value.integer.value[0] = (dbri->mm.data[elem] >> shift) & mask; - } else { + else ucontrol->value.integer.value[0] = (dbri->mm.ctrl[elem - 4] >> shift) & mask; - } - if (invert == 1) { + if (invert == 1) ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - } return 0; } @@ -2342,7 +2363,9 @@ static int snd_cs4215_put_single(struct snd_kcontrol *kcontrol, int invert = (kcontrol->private_value >> 24) & 1; int changed = 0; unsigned short val; - snd_assert(dbri != NULL, return -EINVAL); + + if (snd_BUG_ON(!dbri)) + return -EINVAL; val = (ucontrol->value.integer.value[0] & mask); if (invert == 1) @@ -2379,13 +2402,14 @@ static int snd_cs4215_put_single(struct snd_kcontrol *kcontrol, timeslots. Shift is the bit offset in the timeslot, mask defines the number of bits. invert is a boolean for use with attenuation. */ -#define CS4215_SINGLE(xname, entry, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_cs4215_info_single, \ - .get = snd_cs4215_get_single, .put = snd_cs4215_put_single, \ - .private_value = entry | (shift << 8) | (mask << 16) | (invert << 24) }, - -static struct snd_kcontrol_new dbri_controls[] __devinitdata = { +#define CS4215_SINGLE(xname, entry, shift, mask, invert) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .info = snd_cs4215_info_single, \ + .get = snd_cs4215_get_single, .put = snd_cs4215_put_single, \ + .private_value = (entry) | ((shift) << 8) | ((mask) << 16) | \ + ((invert) << 24) }, + +static struct snd_kcontrol_new dbri_controls[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Playback Volume", @@ -2412,21 +2436,21 @@ static struct snd_kcontrol_new dbri_controls[] __devinitdata = { CS4215_SINGLE("Mic boost", 4, 4, 1, 1) }; -#define NUM_CS4215_CONTROLS (sizeof(dbri_controls)/sizeof(struct snd_kcontrol_new)) - -static int __init snd_dbri_mixer(struct snd_dbri * dbri) +static int snd_dbri_mixer(struct snd_card *card) { - struct snd_card *card; int idx, err; + struct snd_dbri *dbri; - snd_assert(dbri != NULL && dbri->card != NULL, return -EINVAL); + if (snd_BUG_ON(!card || !card->private_data)) + return -EINVAL; + dbri = card->private_data; - card = dbri->card; strcpy(card->mixername, card->shortname); - for (idx = 0; idx < NUM_CS4215_CONTROLS; idx++) { - if ((err = snd_ctl_add(card, - snd_ctl_new1(&dbri_controls[idx], dbri))) < 0) + for (idx = 0; idx < ARRAY_SIZE(dbri_controls); idx++) { + err = snd_ctl_add(card, + snd_ctl_new1(&dbri_controls[idx], dbri)); + if (err < 0) return err; } @@ -2441,7 +2465,8 @@ static int __init snd_dbri_mixer(struct snd_dbri * dbri) /**************************************************************************** /proc interface ****************************************************************************/ -static void dbri_regs_read(struct snd_info_entry * entry, struct snd_info_buffer *buffer) +static void dbri_regs_read(struct snd_info_entry *entry, + struct snd_info_buffer *buffer) { struct snd_dbri *dbri = entry->private_data; @@ -2452,7 +2477,7 @@ static void dbri_regs_read(struct snd_info_entry * entry, struct snd_info_buffer } #ifdef DBRI_DEBUG -static void dbri_debug_read(struct snd_info_entry * entry, +static void dbri_debug_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { struct snd_dbri *dbri = entry->private_data; @@ -2466,7 +2491,8 @@ static void dbri_debug_read(struct snd_info_entry * entry, "Pipe %d: %s SDP=0x%x desc=%d, " "len=%d next %d\n", pipe, - ((pptr->sdp & D_SDP_TO_SER) ? "output" : "input"), + (pptr->sdp & D_SDP_TO_SER) ? "output" : + "input", pptr->sdp, pptr->desc, pptr->length, pptr->nextpipe); } @@ -2474,15 +2500,16 @@ static void dbri_debug_read(struct snd_info_entry * entry, } #endif -void snd_dbri_proc(struct snd_dbri * dbri) +static void snd_dbri_proc(struct snd_card *card) { + struct snd_dbri *dbri = card->private_data; struct snd_info_entry *entry; - if (! snd_card_proc_new(dbri->card, "regs", &entry)) + if (!snd_card_proc_new(card, "regs", &entry)) snd_info_set_text_ops(entry, dbri, dbri_regs_read); #ifdef DBRI_DEBUG - if (! snd_card_proc_new(dbri->card, "debug", &entry)) { + if (!snd_card_proc_new(card, "debug", &entry)) { snd_info_set_text_ops(entry, dbri, dbri_debug_read); entry->mode = S_IFREG | S_IRUGO; /* Readable only. */ } @@ -2494,35 +2521,37 @@ void snd_dbri_proc(struct snd_dbri * dbri) **************************** Initialization ******************************** **************************************************************************** */ -static void snd_dbri_free(struct snd_dbri * dbri); +static void snd_dbri_free(struct snd_dbri *dbri); -static int __init snd_dbri_create(struct snd_card *card, - struct sbus_dev *sdev, - struct linux_prom_irqs *irq, int dev) +static int snd_dbri_create(struct snd_card *card, + struct platform_device *op, + int irq, int dev) { struct snd_dbri *dbri = card->private_data; int err; spin_lock_init(&dbri->lock); - dbri->card = card; - dbri->sdev = sdev; - dbri->irq = irq->pri; + dbri->op = op; + dbri->irq = irq; - dbri->dma = sbus_alloc_consistent(sdev, sizeof(struct dbri_dma), - &dbri->dma_dvma); + dbri->dma = dma_alloc_coherent(&op->dev, + sizeof(struct dbri_dma), + &dbri->dma_dvma, GFP_ATOMIC); + if (!dbri->dma) + return -ENOMEM; memset((void *)dbri->dma, 0, sizeof(struct dbri_dma)); dprintk(D_GEN, "DMA Cmd Block 0x%p (0x%08x)\n", dbri->dma, dbri->dma_dvma); /* Map the registers into memory. */ - dbri->regs_size = sdev->reg_addrs[0].reg_size; - dbri->regs = sbus_ioremap(&sdev->resource[0], 0, - dbri->regs_size, "DBRI Registers"); + dbri->regs_size = resource_size(&op->resource[0]); + dbri->regs = of_ioremap(&op->resource[0], 0, + dbri->regs_size, "DBRI Registers"); if (!dbri->regs) { printk(KERN_ERR "DBRI: could not allocate registers\n"); - sbus_free_consistent(sdev, sizeof(struct dbri_dma), - (void *)dbri->dma, dbri->dma_dvma); + dma_free_coherent(&op->dev, sizeof(struct dbri_dma), + (void *)dbri->dma, dbri->dma_dvma); return -EIO; } @@ -2530,9 +2559,9 @@ static int __init snd_dbri_create(struct snd_card *card, "DBRI audio", dbri); if (err) { printk(KERN_ERR "DBRI: Can't get irq %d\n", dbri->irq); - sbus_iounmap(dbri->regs, dbri->regs_size); - sbus_free_consistent(sdev, sizeof(struct dbri_dma), - (void *)dbri->dma, dbri->dma_dvma); + of_iounmap(&op->resource[0], dbri->regs, dbri->regs_size); + dma_free_coherent(&op->dev, sizeof(struct dbri_dma), + (void *)dbri->dma, dbri->dma_dvma); return err; } @@ -2544,13 +2573,10 @@ static int __init snd_dbri_create(struct snd_card *card, return err; } - dbri->next = dbri_list; - dbri_list = dbri; - return 0; } -static void snd_dbri_free(struct snd_dbri * dbri) +static void snd_dbri_free(struct snd_dbri *dbri) { dprintk(D_GEN, "snd_dbri_free\n"); dbri_reset(dbri); @@ -2559,28 +2585,23 @@ static void snd_dbri_free(struct snd_dbri * dbri) free_irq(dbri->irq, dbri); if (dbri->regs) - sbus_iounmap(dbri->regs, dbri->regs_size); + of_iounmap(&dbri->op->resource[0], dbri->regs, dbri->regs_size); if (dbri->dma) - sbus_free_consistent(dbri->sdev, sizeof(struct dbri_dma), - (void *)dbri->dma, dbri->dma_dvma); + dma_free_coherent(&dbri->op->dev, + sizeof(struct dbri_dma), + (void *)dbri->dma, dbri->dma_dvma); } -static int __init dbri_attach(int prom_node, struct sbus_dev *sdev) +static int dbri_probe(struct platform_device *op) { struct snd_dbri *dbri; - struct linux_prom_irqs irq; struct resource *rp; struct snd_card *card; static int dev = 0; + int irq; int err; - if (sdev->prom_name[9] < 'e') { - printk(KERN_ERR "DBRI: unsupported chip version %c found.\n", - sdev->prom_name[9]); - return -EIO; - } - if (dev >= SNDRV_CARDS) return -ENODEV; if (!enable[dev]) { @@ -2588,93 +2609,90 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev) return -ENOENT; } - err = prom_getproperty(prom_node, "intr", (char *)&irq, sizeof(irq)); - if (err < 0) { - printk(KERN_ERR "DBRI-%d: Firmware node lacks IRQ property.\n", dev); + irq = op->archdata.irqs[0]; + if (irq <= 0) { + printk(KERN_ERR "DBRI-%d: No IRQ.\n", dev); return -ENODEV; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_dbri)); - if (card == NULL) - return -ENOMEM; + err = snd_card_new(&op->dev, index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_dbri), &card); + if (err < 0) + return err; strcpy(card->driver, "DBRI"); strcpy(card->shortname, "Sun DBRI"); - rp = &sdev->resource[0]; + rp = &op->resource[0]; sprintf(card->longname, "%s at 0x%02lx:0x%016Lx, irq %d", card->shortname, - rp->flags & 0xffL, (unsigned long long)rp->start, irq.pri); + rp->flags & 0xffL, (unsigned long long)rp->start, irq); - if ((err = snd_dbri_create(card, sdev, &irq, dev)) < 0) { + err = snd_dbri_create(card, op, irq, dev); + if (err < 0) { snd_card_free(card); return err; } dbri = card->private_data; - if ((err = snd_dbri_pcm(dbri)) < 0) + err = snd_dbri_pcm(card); + if (err < 0) goto _err; - if ((err = snd_dbri_mixer(dbri)) < 0) + err = snd_dbri_mixer(card); + if (err < 0) goto _err; /* /proc file handling */ - snd_dbri_proc(dbri); + snd_dbri_proc(card); + dev_set_drvdata(&op->dev, card); - if ((err = snd_card_register(card)) < 0) + err = snd_card_register(card); + if (err < 0) goto _err; printk(KERN_INFO "audio%d at %p (irq %d) is DBRI(%c)+CS4215(%d)\n", dev, dbri->regs, - dbri->irq, sdev->prom_name[9], dbri->mm.version); + dbri->irq, op->dev.of_node->name[9], dbri->mm.version); dev++; return 0; - _err: +_err: snd_dbri_free(dbri); snd_card_free(card); return err; } -/* Probe for the dbri chip and then attach the driver. */ -static int __init dbri_init(void) +static int dbri_remove(struct platform_device *op) { - struct sbus_bus *sbus; - struct sbus_dev *sdev; - int found = 0; - - /* Probe each SBUS for the DBRI chip(s). */ - for_all_sbusdev(sdev, sbus) { - /* - * The version is coded in the last character - */ - if (!strncmp(sdev->prom_name, "SUNW,DBRI", 9)) { - dprintk(D_GEN, "DBRI: Found %s in SBUS slot %d\n", - sdev->prom_name, sdev->slot); + struct snd_card *card = dev_get_drvdata(&op->dev); - if (dbri_attach(sdev->prom_node, sdev) == 0) - found++; - } - } + snd_dbri_free(card->private_data); + snd_card_free(card); - return (found > 0) ? 0 : -EIO; + return 0; } -static void __exit dbri_exit(void) -{ - struct snd_dbri *this = dbri_list; +static const struct of_device_id dbri_match[] = { + { + .name = "SUNW,DBRIe", + }, + { + .name = "SUNW,DBRIf", + }, + {}, +}; - while (this != NULL) { - struct snd_dbri *next = this->next; - struct snd_card *card = this->card; +MODULE_DEVICE_TABLE(of, dbri_match); - snd_dbri_free(this); - snd_card_free(card); - this = next; - } - dbri_list = NULL; -} +static struct platform_driver dbri_sbus_driver = { + .driver = { + .name = "dbri", + .owner = THIS_MODULE, + .of_match_table = dbri_match, + }, + .probe = dbri_probe, + .remove = dbri_remove, +}; -module_init(dbri_init); -module_exit(dbri_exit); +module_platform_driver(dbri_sbus_driver); |
