[alsa-devel] [PATCH] Driver for Emagic Audiowerk 2
Takashi Iwai
tiwai at suse.de
Mon Feb 18 12:07:41 CET 2008
At Sat, 16 Feb 2008 00:30:55 +0100,
Cédric Brégardis wrote:
>
> Hi,
>
> We managed to write ALSA driver for Emagic Audiowerk 2 PCI sound card (based
> on Philips SAA7146 chip). You can find more information on
> https://gna.org/projects/aw2-alsa/.
>
> We think it's time to integrate the sources into the alsa/kernel tree. So,
> here is the patch for this driver. We hope this patch is usable.
>
> Regards,
>
> Jean-Christian Hassler and Cedric Bregardis
>
>
> Signed-off-by: Cedric Bregardis <cedric.bregardis at free.fr>
> Signed-off-by: Jean-Christian Hassler <jhassler at free.fr>
Thanks for the patch.
First of all, could you fix the issues reported by checkpatch.pl?
Below is a quick review.
> --- /dev/null
> +++ b/sound/pci/aw2/aw2-alsa.c
(snip)
> +#include <sound/driver.h>
sound/driver.h is deprecated now. Simply remove this line.
> +struct aw2_pcm_device_t {
Usually *_t is used for typedef'ed types. Use names without _t for
structs, i.e. "struct aw2_pcm_device".
> +/* module parameters (see "Module Parameters") */
The comment (see "Module Parameters") isn't needed for the real
codes. It's a comment that is valid only in my tutorial.
> +/* pci_driver definition */
> +static struct pci_driver driver = {
> + .name = "My Own Chip",
Choose a better name :)
> +/* component-destructor
> + * (see "Management of Cards and Components")
> + */
Ditto about the comment.
> +/* chip-specific constructor
> + * (see "Management of Cards and Components")
> + */
Ditto.
> +static int __devinit snd_aw2_create(struct snd_card *card,
> + struct pci_dev *pci, struct aw2_t **rchip)
> +{
(snip)
> + chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
Use kzalloc.
> + /* (1) PCI resource allocation */
> + err = pci_request_regions(pci, "Audiowerk2");
> + if (err < 0) {
> + kfree(chip);
> + return err;
> + }
> + chip->saa7146.iobase_phys = pci_resource_start(pci, 0);
> + chip->saa7146.iobase_virt =
> + ioremap_nocache(chip->saa7146.iobase_phys,
> + pci_resource_len(pci, 0));
Better to check whether ioremap succeeded or not.
> +/* constructor -- see "Constructor" sub-section */
Fix the comment.
> +/* destructor -- see "Destructor" sub-section */
Dtto.
> +/* open callback */
> +static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream)
> +{
> + struct snd_pcm_runtime *runtime = substream->runtime;
> +
> + printk(KERN_DEBUG "Playback_open \n");
Avoid unconditionally compiled debug messages. If you really want to
keep such debug messages, use snd_printdd() or whatever that won't be
compiled unless explicitly specified.
> +/* create a pcm device */
> +static int __devinit snd_aw2_new_pcm(struct aw2_t *chip)
> +{
> + struct snd_pcm *pcm_playback_ana;
> + struct snd_pcm *pcm_playback_num;
> + struct snd_pcm *pcm_capture;
> + int err = 0;
> +
> + /* Create new Alsa PCM device */
> +
> + err =
> + snd_pcm_new(chip->card, "Audiowerk2 analog playback", 0, 1, 0,
> + &pcm_playback_ana);
> + if (err >= 0) {
It's easier to bail out when the error is returned.
> + err = snd_pcm_new(chip->card, "Audiowerk2 capture", 2, 0, 1,
> + &pcm_capture);
Any reason to make all PCM streams non-duplex?
Oh I see in the below...
> +static int snd_aw2_control_switch_capture_info(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_info *uinfo)
> +{
> + static char *texts[2] = {
> + "Analog", "Digital"
> + };
> + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
> + uinfo->count = 1;
> + uinfo->value.enumerated.items = 2;
> + if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) {
> + uinfo->value.enumerated.item =
> + uinfo->value.enumerated.items - 1;
> + }
> + strcpy(uinfo->value.enumerated.name,
> + texts[uinfo->value.enumerated.item]);
> + return 0;
> +}
So, you'd like to switch the input on the fly rather than selecting at
open time? It's a question of the driver design...
> --- /dev/null
> +++ b/sound/pci/aw2/aw2-saa7146.c
(snip)
> +#define WRITEREG(value, addr) do { writel((value), chip->iobase_virt + (addr));\
> + mb(); } while (0)
Do you really need a barrier here?
> +void snd_aw2_saa7146_dump_registers(struct snd_aw2_saa7146_t *chip)
> +{
> + int i = 0;
> + for (i = 0; i <= 0x148; i += 4) {
> + printk(KERN_DEBUG "###DUMP 0x%03x: 0x%08x\n", i, READREG(i));
> + }
> +}
Better to use proc interface than printk for such a purpose.
> +/* chip-specific destructor
> + * (see "PCI Resource Managements")
> + */
> +int snd_aw2_saa7146_free(struct snd_aw2_saa7146_t *chip)
> +{
> + /* disable all irqs */
> + WRITEREG(0, IER);
> +
> + /* reset saa7146 */
> + WRITEREG((MRST_N << 16), MC1);
> +
> + /* release the irq */
> + if (chip->irq >= 0) {
> + free_irq(chip->irq, (void *)chip);
> + }
> + /* release the i/o ports & memory */
> + if (chip->iobase_virt) {
> + iounmap(chip->iobase_virt);
> + }
> + pci_release_regions(chip->pci);
> + /* disable the PCI entry */
> + pci_disable_device(chip->pci);
> + /* release the data */
> + kfree(chip);
> + return 0;
> +}
Put the destructor in the same place as the constructor. Don't put in
separate files.
> --- /dev/null
> +++ b/sound/pci/aw2/aw2-saa7146.h
(snip)
> +#ifdef AW2_SAA7146_M
> +#define PUBLIC
> +#else
> +#define PUBLIC extern
> +#endif
Don't do this. It's too hackish.
thanks,
Takashi
More information about the Alsa-devel
mailing list