* other DBRI low-level stuff
*/
-#include <sound/driver.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <sound/control.h>
#include <sound/initval.h>
+#include <linux/of.h>
#include <asm/sbus.h>
#include <asm/atomic.h>
/* 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 */
spinlock_t lock;
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 */
#define DBRI_STREAM(dbri, substream) \
&dbri->stream_info[DBRI_STREAMNO(substream)]
-static struct snd_dbri *dbri_list; /* All DBRI devices */
-
/*
* Short data pipes transmit LSB first. The CS4215 receives MSB first. Grrr.
* So we have to reverse the bits. Note: not all bit lengths are supported
}
/* Lock must not be held before calling this */
-static void __init dbri_initialize(struct snd_dbri *dbri)
+static void __devinit dbri_initialize(struct snd_dbri *dbri)
{
s32 *cmd;
u32 dma_addr;
* Lock must not be held before calling it.
*/
-static __init void cs4215_setup_pipes(struct snd_dbri *dbri)
+static __devinit void cs4215_setup_pipes(struct snd_dbri *dbri)
{
unsigned long flags;
dbri_cmdwait(dbri);
}
-static __init int cs4215_init_data(struct cs4215 *mm)
+static __devinit int cs4215_init_data(struct cs4215 *mm)
{
/*
* No action, memory resetting only.
/*
*
*/
-static __init int cs4215_init(struct snd_dbri *dbri)
+static __devinit int cs4215_init(struct snd_dbri *dbri)
{
u32 reg2 = sbus_readl(dbri->regs + REG2);
dprintk(D_MM, "cs4215_init: reg2=0x%x\n", reg2);
.pointer = snd_dbri_pointer,
};
-static int __devinit snd_dbri_pcm(struct snd_dbri *dbri)
+static int __devinit 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,
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,
struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol);
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) {
CS4215_SINGLE("Mic boost", 4, 4, 1, 1)
};
-static int __init snd_dbri_mixer(struct snd_dbri *dbri)
+static int __devinit 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);
+ snd_assert(card != NULL && card->private_data != NULL, return -EINVAL);
+ dbri = card->private_data;
- card = dbri->card;
strcpy(card->mixername, card->shortname);
for (idx = 0; idx < ARRAY_SIZE(dbri_controls); idx++) {
}
#endif
-void snd_dbri_proc(struct snd_dbri *dbri)
+static void __devinit 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. */
}
*/
static void snd_dbri_free(struct snd_dbri *dbri);
-static int __init snd_dbri_create(struct snd_card *card,
+static int __devinit snd_dbri_create(struct snd_card *card,
struct sbus_dev *sdev,
- struct linux_prom_irqs *irq, int dev)
+ 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->irq = irq;
dbri->dma = sbus_alloc_consistent(sdev, sizeof(struct dbri_dma),
&dbri->dma_dvma);
return err;
}
- dbri->next = dbri_list;
- dbri_list = dbri;
-
return 0;
}
(void *)dbri->dma, dbri->dma_dvma);
}
-static int __init dbri_attach(int prom_node, struct sbus_dev *sdev)
+static int __devinit dbri_probe(struct of_device *of_dev,
+ const struct of_device_id *match)
{
+ struct sbus_dev *sdev = to_sbus_device(&of_dev->dev);
struct snd_dbri *dbri;
- struct linux_prom_irqs irq;
+ int irq;
struct resource *rp;
struct snd_card *card;
static int dev = 0;
int err;
- if (sdev->prom_name[9] < 'e') {
- printk(KERN_ERR "DBRI: unsupported chip version %c found.\n",
- sdev->prom_name[9]);
- return -EIO;
- }
+ dprintk(D_GEN, "DBRI: Found %s in SBUS slot %d\n",
+ sdev->prom_name, sdev->slot);
if (dev >= SNDRV_CARDS)
return -ENODEV;
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 = sdev->irqs[0];
+ if (irq <= 0) {
+ printk(KERN_ERR "DBRI-%d: No IRQ.\n", dev);
return -ENODEV;
}
rp = &sdev->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, sdev, irq, dev);
+ if (err < 0) {
snd_card_free(card);
return err;
}
dbri = card->private_data;
- err = snd_dbri_pcm(dbri);
+ err = snd_dbri_pcm(card);
if (err < 0)
goto _err;
- err = snd_dbri_mixer(dbri);
+ err = snd_dbri_mixer(card);
if (err < 0)
goto _err;
/* /proc file handling */
- snd_dbri_proc(dbri);
+ snd_dbri_proc(card);
+ dev_set_drvdata(&of_dev->dev, card);
err = snd_card_register(card);
if (err < 0)
return err;
}
-/* Probe for the dbri chip and then attach the driver. */
-static int __init dbri_init(void)
+static int __devexit dbri_remove(struct of_device *dev)
{
- 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(&dev->dev);
- if (dbri_attach(sdev->prom_node, sdev) == 0)
- found++;
- }
- }
+ snd_dbri_free(card->private_data);
+ snd_card_free(card);
+
+ dev_set_drvdata(&dev->dev, NULL);
- return (found > 0) ? 0 : -EIO;
+ return 0;
}
-static void __exit dbri_exit(void)
-{
- struct snd_dbri *this = dbri_list;
+static 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 of_platform_driver dbri_sbus_driver = {
+ .name = "dbri",
+ .match_table = dbri_match,
+ .probe = dbri_probe,
+ .remove = __devexit_p(dbri_remove),
+};
+
+/* Probe for the dbri chip and then attach the driver. */
+static int __init dbri_init(void)
+{
+ return of_register_driver(&dbri_sbus_driver, &sbus_bus_type);
+}
+
+static void __exit dbri_exit(void)
+{
+ of_unregister_driver(&dbri_sbus_driver);
}
module_init(dbri_init);