[ALSA] dbri: conversion to OpenFirmware framework
This patch converts the dbri driver to use OF framework. Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
This commit is contained in:
parent
f545714ece
commit
afeacfd5f7
|
@ -66,6 +66,7 @@
|
||||||
#include <sound/control.h>
|
#include <sound/control.h>
|
||||||
#include <sound/initval.h>
|
#include <sound/initval.h>
|
||||||
|
|
||||||
|
#include <asm/prom.h>
|
||||||
#include <asm/sbus.h>
|
#include <asm/sbus.h>
|
||||||
#include <asm/atomic.h>
|
#include <asm/atomic.h>
|
||||||
|
|
||||||
|
@ -296,8 +297,6 @@ struct dbri_streaminfo {
|
||||||
|
|
||||||
/* This structure holds the information for both chips (DBRI & CS4215) */
|
/* This structure holds the information for both chips (DBRI & CS4215) */
|
||||||
struct snd_dbri {
|
struct snd_dbri {
|
||||||
struct snd_card *card; /* ALSA card */
|
|
||||||
|
|
||||||
int regs_size, irq; /* Needed for unload */
|
int regs_size, irq; /* Needed for unload */
|
||||||
struct sbus_dev *sdev; /* SBUS device info */
|
struct sbus_dev *sdev; /* SBUS device info */
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
|
@ -318,8 +317,6 @@ struct snd_dbri {
|
||||||
struct cs4215 mm; /* mmcodec special info */
|
struct cs4215 mm; /* mmcodec special info */
|
||||||
/* per stream (playback/record) info */
|
/* per stream (playback/record) info */
|
||||||
struct dbri_streaminfo stream_info[DBRI_NO_STREAMS];
|
struct dbri_streaminfo stream_info[DBRI_NO_STREAMS];
|
||||||
|
|
||||||
struct snd_dbri *next;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DBRI_MAX_VOLUME 63 /* Output volume */
|
#define DBRI_MAX_VOLUME 63 /* Output volume */
|
||||||
|
@ -571,8 +568,6 @@ struct snd_dbri {
|
||||||
#define DBRI_STREAM(dbri, substream) \
|
#define DBRI_STREAM(dbri, substream) \
|
||||||
&dbri->stream_info[DBRI_STREAMNO(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.
|
* 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
|
* So we have to reverse the bits. Note: not all bit lengths are supported
|
||||||
|
@ -748,7 +743,7 @@ static void dbri_reset(struct snd_dbri *dbri)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lock must not be held before calling this */
|
/* 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;
|
s32 *cmd;
|
||||||
u32 dma_addr;
|
u32 dma_addr;
|
||||||
|
@ -1308,7 +1303,7 @@ to the DBRI via the CHI interface and few of the DBRI's PIO pins.
|
||||||
* Lock must not be held before calling it.
|
* 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;
|
unsigned long flags;
|
||||||
|
|
||||||
|
@ -1341,7 +1336,7 @@ static __init void cs4215_setup_pipes(struct snd_dbri *dbri)
|
||||||
dbri_cmdwait(dbri);
|
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.
|
* No action, memory resetting only.
|
||||||
|
@ -1633,7 +1628,7 @@ static int cs4215_prepare(struct snd_dbri *dbri, unsigned int rate,
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
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);
|
u32 reg2 = sbus_readl(dbri->regs + REG2);
|
||||||
dprintk(D_MM, "cs4215_init: reg2=0x%x\n", reg2);
|
dprintk(D_MM, "cs4215_init: reg2=0x%x\n", reg2);
|
||||||
|
@ -2218,12 +2213,12 @@ static struct snd_pcm_ops snd_dbri_ops = {
|
||||||
.pointer = snd_dbri_pointer,
|
.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;
|
struct snd_pcm *pcm;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if ((err = snd_pcm_new(dbri->card,
|
if ((err = snd_pcm_new(card,
|
||||||
/* ID */ "sun_dbri",
|
/* ID */ "sun_dbri",
|
||||||
/* device */ 0,
|
/* device */ 0,
|
||||||
/* playback count */ 1,
|
/* playback count */ 1,
|
||||||
|
@ -2234,9 +2229,9 @@ static int __devinit snd_dbri_pcm(struct snd_dbri *dbri)
|
||||||
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_dbri_ops);
|
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_dbri_ops);
|
||||||
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &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;
|
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,
|
if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm,
|
||||||
SNDRV_DMA_TYPE_CONTINUOUS,
|
SNDRV_DMA_TYPE_CONTINUOUS,
|
||||||
|
@ -2422,14 +2417,14 @@ static struct snd_kcontrol_new dbri_controls[] __devinitdata = {
|
||||||
CS4215_SINGLE("Mic boost", 4, 4, 1, 1)
|
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;
|
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);
|
strcpy(card->mixername, card->shortname);
|
||||||
|
|
||||||
for (idx = 0; idx < ARRAY_SIZE(dbri_controls); idx++) {
|
for (idx = 0; idx < ARRAY_SIZE(dbri_controls); idx++) {
|
||||||
|
@ -2485,15 +2480,16 @@ static void dbri_debug_read(struct snd_info_entry *entry,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void snd_dbri_proc(struct snd_dbri *dbri)
|
void __devinit snd_dbri_proc(struct snd_card *card)
|
||||||
{
|
{
|
||||||
|
struct snd_dbri *dbri = card->private_data;
|
||||||
struct snd_info_entry *entry;
|
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);
|
snd_info_set_text_ops(entry, dbri, dbri_regs_read);
|
||||||
|
|
||||||
#ifdef DBRI_DEBUG
|
#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);
|
snd_info_set_text_ops(entry, dbri, dbri_debug_read);
|
||||||
entry->mode = S_IFREG | S_IRUGO; /* Readable only. */
|
entry->mode = S_IFREG | S_IRUGO; /* Readable only. */
|
||||||
}
|
}
|
||||||
|
@ -2507,17 +2503,16 @@ void snd_dbri_proc(struct snd_dbri *dbri)
|
||||||
*/
|
*/
|
||||||
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,
|
static int __devinit snd_dbri_create(struct snd_card *card,
|
||||||
struct sbus_dev *sdev,
|
struct sbus_dev *sdev,
|
||||||
struct linux_prom_irqs *irq, int dev)
|
int irq, int dev)
|
||||||
{
|
{
|
||||||
struct snd_dbri *dbri = card->private_data;
|
struct snd_dbri *dbri = card->private_data;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
spin_lock_init(&dbri->lock);
|
spin_lock_init(&dbri->lock);
|
||||||
dbri->card = card;
|
|
||||||
dbri->sdev = sdev;
|
dbri->sdev = sdev;
|
||||||
dbri->irq = irq->pri;
|
dbri->irq = irq;
|
||||||
|
|
||||||
dbri->dma = sbus_alloc_consistent(sdev, sizeof(struct dbri_dma),
|
dbri->dma = sbus_alloc_consistent(sdev, sizeof(struct dbri_dma),
|
||||||
&dbri->dma_dvma);
|
&dbri->dma_dvma);
|
||||||
|
@ -2555,9 +2550,6 @@ static int __init snd_dbri_create(struct snd_card *card,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbri->next = dbri_list;
|
|
||||||
dbri_list = dbri;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2577,20 +2569,19 @@ static void snd_dbri_free(struct snd_dbri *dbri)
|
||||||
(void *)dbri->dma, dbri->dma_dvma);
|
(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 snd_dbri *dbri;
|
||||||
struct linux_prom_irqs irq;
|
int irq;
|
||||||
struct resource *rp;
|
struct resource *rp;
|
||||||
struct snd_card *card;
|
struct snd_card *card;
|
||||||
static int dev = 0;
|
static int dev = 0;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (sdev->prom_name[9] < 'e') {
|
dprintk(D_GEN, "DBRI: Found %s in SBUS slot %d\n",
|
||||||
printk(KERN_ERR "DBRI: unsupported chip version %c found.\n",
|
sdev->prom_name, sdev->slot);
|
||||||
sdev->prom_name[9]);
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dev >= SNDRV_CARDS)
|
if (dev >= SNDRV_CARDS)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -2599,10 +2590,9 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = prom_getproperty(prom_node, "intr", (char *)&irq, sizeof(irq));
|
irq = sdev->irqs[0];
|
||||||
if (err < 0) {
|
if (irq <= 0) {
|
||||||
printk(KERN_ERR "DBRI-%d: Firmware node lacks IRQ property.\n",
|
printk(KERN_ERR "DBRI-%d: No IRQ.\n", dev);
|
||||||
dev);
|
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2616,24 +2606,26 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev)
|
||||||
rp = &sdev->resource[0];
|
rp = &sdev->resource[0];
|
||||||
sprintf(card->longname, "%s at 0x%02lx:0x%016Lx, irq %d",
|
sprintf(card->longname, "%s at 0x%02lx:0x%016Lx, irq %d",
|
||||||
card->shortname,
|
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);
|
snd_card_free(card);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbri = card->private_data;
|
dbri = card->private_data;
|
||||||
err = snd_dbri_pcm(dbri);
|
err = snd_dbri_pcm(card);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto _err;
|
goto _err;
|
||||||
|
|
||||||
err = snd_dbri_mixer(dbri);
|
err = snd_dbri_mixer(card);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto _err;
|
goto _err;
|
||||||
|
|
||||||
/* /proc file handling */
|
/* /proc file handling */
|
||||||
snd_dbri_proc(dbri);
|
snd_dbri_proc(card);
|
||||||
|
dev_set_drvdata(&of_dev->dev, card);
|
||||||
|
|
||||||
err = snd_card_register(card);
|
err = snd_card_register(card);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
@ -2652,43 +2644,46 @@ _err:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int __devexit dbri_remove(struct of_device *dev)
|
||||||
|
{
|
||||||
|
struct snd_card *card = dev_get_drvdata(&dev->dev);
|
||||||
|
|
||||||
|
snd_dbri_free(card->private_data);
|
||||||
|
snd_card_free(card);
|
||||||
|
|
||||||
|
dev_set_drvdata(&dev->dev, NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct of_device_id dbri_match[] = {
|
||||||
|
{
|
||||||
|
.name = "SUNW,DBRIe",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "SUNW,DBRIf",
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
|
||||||
|
MODULE_DEVICE_TABLE(of, dbri_match);
|
||||||
|
|
||||||
|
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. */
|
/* Probe for the dbri chip and then attach the driver. */
|
||||||
static int __init dbri_init(void)
|
static int __init dbri_init(void)
|
||||||
{
|
{
|
||||||
struct sbus_bus *sbus;
|
return of_register_driver(&dbri_sbus_driver, &sbus_bus_type);
|
||||||
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);
|
|
||||||
|
|
||||||
if (dbri_attach(sdev->prom_node, sdev) == 0)
|
|
||||||
found++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (found > 0) ? 0 : -EIO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit dbri_exit(void)
|
static void __exit dbri_exit(void)
|
||||||
{
|
{
|
||||||
struct snd_dbri *this = dbri_list;
|
of_unregister_driver(&dbri_sbus_driver);
|
||||||
|
|
||||||
while (this != NULL) {
|
|
||||||
struct snd_dbri *next = this->next;
|
|
||||||
struct snd_card *card = this->card;
|
|
||||||
|
|
||||||
snd_dbri_free(this);
|
|
||||||
snd_card_free(card);
|
|
||||||
this = next;
|
|
||||||
}
|
|
||||||
dbri_list = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(dbri_init);
|
module_init(dbri_init);
|
||||||
|
|
Loading…
Reference in a new issue