[alsa-devel] [PATCH] ALSA driver for SGI O2 audio board

Takashi Iwai tiwai at suse.de
Mon Jul 7 17:57:06 CEST 2008


At Sat,  5 Jul 2008 01:45:59 +0200 (CEST),
Thomas Bogendoerfer wrote:
> 
> This patch adds a new ALSA driver for the audio device found inside
> most of the SGI O2 workstation. The hardware uses a SGI custom chip,
> which feeds a AD codec chip.
> 
> Signed-off-by: Thomas Bogendoerfer <tsbogend at alpha.franken.de>
> ---
> 
> Please apply for 2.6.27.

Thanks for the patch.
Below is a quick review.


> diff --git a/sound/mips/Kconfig b/sound/mips/Kconfig
> index 531f8ba..a3e202e 100644
> --- a/sound/mips/Kconfig
> +++ b/sound/mips/Kconfig
> @@ -11,5 +11,11 @@ config SND_AU1X00
>  	help
>  	  ALSA Sound driver for the Au1x00's AC97 port.
>  
> +config SND_SGI_O2
> +	tristate "SGI O2 Audio"
> +	depends on  SND && SGI_IP32
> +        help
> +                Sound support for the SGI O2 Workstation. 
> +
>  endmenu

The recent version doesn't require "depends on SND" here because of
changes to menuconfig.  Check the latest ALSA tree or linux-next
tree.


> --- /dev/null
> +++ b/sound/mips/ad1843.c
> +const struct ad1843_gain ad1843_gain_RECLEV = {
> +	0, &ad1843_LIG,   &ad1843_RIG
> +};
> +const struct ad1843_gain ad1843_gain_LINE = {
> +	1, &ad1843_LX1M,  &ad1843_RX1M,  &ad1843_LX1MM, &ad1843_RX1MM
> +};
> +const struct ad1843_gain ad1843_gain_LINE_2 = {
> +	1, &ad1843_LDA2G, &ad1843_RDA2G, &ad1843_LDA2GM, &ad1843_RDA2GM
> +};
> +const struct ad1843_gain ad1843_gain_MIC = {
> +	1, &ad1843_LMCM,  &ad1843_RMCM,  &ad1843_LMCMM,  &ad1843_RMCMM
> +};
> +const struct ad1843_gain ad1843_gain_PCM_0 = {
> +	1, &ad1843_LDA1G, &ad1843_RDA1G, &ad1843_LDA1GM, &ad1843_RDA1GM
> +};
> +const struct ad1843_gain ad1843_gain_PCM_1 = {
> +	1, &ad1843_LD2M,  &ad1843_RD2M,  &ad1843_LD2MM,  &ad1843_RD2MM
> +};

Missing static?

> +
> +const struct ad1843_gain *ad1843_gain[AD1843_GAIN_SIZE] =
> +{
> +	&ad1843_gain_RECLEV,
> +	&ad1843_gain_LINE,
> +	&ad1843_gain_LINE_2,
> +	&ad1843_gain_MIC,
> +	&ad1843_gain_PCM_0,
> +	&ad1843_gain_PCM_1,
> +};

Ditto.
Also, better to use C99 style initialization.

> +int ad1843_init(struct snd_ad1843 *ad1843)
> +{
> +	unsigned long later;
> +
> +	if (ad1843_read_bits(ad1843, &ad1843_INIT) != 0) {
> +		printk(KERN_ERR "ad1843: AD1843 won't initialize\n");
> +		return -EIO;
> +	}
> +
> +	ad1843_write_bits(ad1843, &ad1843_SCF, 1);
> +
> +	/* 4. Put the conversion resources into standby. */
> +	ad1843_write_bits(ad1843, &ad1843_PDNI, 0);
> +	later = jiffies + HZ / 2;	/* roughly half a second */

Use msecs_to_jiffies().

> +
> +	while (ad1843_read_bits(ad1843, &ad1843_PDNO)) {
> +		if (time_after(jiffies, later)) {
> +			printk(KERN_ERR
> +			       "ad1843: AD1843 won't power up\n");
> +			return -EIO;
> +		}
> +		schedule();

No set_current_state() ?


> --- /dev/null
> +++ b/sound/mips/sgio2audio.c
> +static int read_ad1843_reg(void *priv, int reg)
> +{
> +	struct snd_sgio2audio *chip = priv;
> +	int val;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&chip->ad1843_lock, flags);
> +
> +	writeq((reg << CODEC_CONTROL_ADDRESS_SHIFT) |
> +	       CODEC_CONTROL_READ, &mace->perif.audio.codec_control);
> +	wmb();
> +	val = readq(&mace->perif.audio.codec_control); /* flush bus */
> +	udelay(200);

It'd be nicer if this long delay can be avoided.  Or, could it be
mutex?

This isn't a fatal problem, so it's OK as is, though.

> +static int __devinit snd_sgio2audio_create(struct snd_card *card,
> +					   struct snd_sgio2audio **rchip)
> +{
> +	struct snd_sgio2audio *chip;
> +	int i, err;
> +
> +	*rchip = NULL;
> +
> +	/* check if a codec is attached to the interface */
> +	/* (Audio or Audio/Video board present) */
> +	if (!(readq(&mace->perif.audio.control) & AUDIO_CONTROL_CODEC_PRESENT))
> +		return -ENOENT;
> +
> +	chip = kzalloc(sizeof(struct snd_sgio2audio), GFP_KERNEL);
> +	if (chip == NULL)
> +		return -ENOMEM;
> +
> +	chip->card = card;
> +
> +	chip->ring_base = dma_alloc_coherent(NULL, MACEISA_RINGBUFFERS_SIZE,
> +					     &chip->ring_base_dma, GFP_USER);
> +	if (chip->ring_base == NULL) {
> +		printk(KERN_ERR
> +		       "sgio2audio: could not allocate ring buffers\n");
> +		kfree(chip);
> +		return -ENOMEM;
> +	}
> +
> +	spin_lock_init(&chip->ad1843_lock);
> +
> +	chip->volume = SGIO2AUDIO_MAX_VOLUME;
> +
> +	/* initialize channels */
> +	for (i = 0; i < 3; i++) {
> +		spin_lock_init(&chip->channel[i].lock);
> +		chip->channel[i].idx = i;
> +	}
> +
> +	/* allocate IRQs */
> +	for (i = 0; i < ARRAY_SIZE(snd_sgio2_isr_table); i++) {
> +		if (request_irq(snd_sgio2_isr_table[i].irq,
> +				snd_sgio2_isr_table[i].isr,
> +				IRQF_SHARED,
> +				snd_sgio2_isr_table[i].desc,
> +				&chip->channel[snd_sgio2_isr_table[i].idx])) {
> +			snd_sgio2audio_free(chip);
> +			printk(KERN_ERR "sgio2audio: cannot allocate irq %d\n",
> +			       snd_sgio2_isr_table[i].irq);
> +			return -EBUSY;
> +		}
> +	}

If there are shared interrupts, they could be called before the
initialization below.  So, safer to move after the init.


thanks,

Takashi


More information about the Alsa-devel mailing list