vserver 1.9.3
[linux-2.6.git] / sound / parisc / harmony.c
index 423ab05..0c02a5f 100644 (file)
@@ -6,7 +6,7 @@
  *
  *     Harmony is found in HP 712s, 715/new and many other GSC based machines.
  *     On older 715 machines you'll find the technically identical chip 
- *     called 'Vivace'. Both Harmony and Vicace are supported by this driver.
+ *     called 'Vivace'. Both Harmony and Vivace are supported by this driver.
  *
  *  this ALSA driver is based on OSS driver by:
  *     Copyright 2000 (c) Linuxcare Canada, Alex deVries <alex@linuxcare.com>
@@ -43,7 +43,7 @@
  * to be recorded is put in RNXTADD. There is 2 read-only registers, PCURADD and 
  * RCURADD that provides adress of current page.
  * 
- * Harmony has no way to controll full duplex or half duplex mode. It means
+ * Harmony has no way to control full duplex or half duplex mode. It means
  * that we always need to provide adresses of playback and capture data, even
  * when this is not needed. That's why we statically alloc one graveyard
  * buffer (to put recorded data in play-only mode) and a silence buffer.
@@ -80,8 +80,7 @@
 MODULE_AUTHOR("Laurent Canet <canetl@esiee.fr>");
 MODULE_DESCRIPTION("ALSA Harmony sound driver");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ALSA,Harmony soundcard}}");
+MODULE_SUPPORTED_DEVICE("{{ALSA,Harmony soundcard}}");
 
 #undef DEBUG
 #ifdef DEBUG
@@ -138,13 +137,10 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Sun CS4231 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Sun CS4231 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Sun CS4231 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 
 /* Register offset (from base hpa) */
 #define REG_ID         0x00
@@ -216,7 +212,6 @@ typedef struct snd_card_harmony {
        snd_pcm_substream_t *capture_substream;
        snd_info_entry_t *proc_entry;
 } snd_card_harmony_t;
-#define chip_t snd_card_harmony_t
 
 static snd_card_t *snd_harmony_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
@@ -243,10 +238,8 @@ static unsigned int snd_card_harmony_rates[] = {
        44100, 48000
 };
 
-#define RATES sizeof(snd_card_harmony_rates) / sizeof(snd_card_harmony_rates[0])
-
 static snd_pcm_hw_constraint_list_t hw_constraint_rates = {
-       .count = RATES,
+       .count = ARRAY_SIZE(snd_card_harmony_rates),
        .list = snd_card_harmony_rates,
        .mask = 0,
 };
@@ -283,7 +276,7 @@ static unsigned int snd_card_harmony_rate_bits(int rate)
 {
        unsigned int idx;
        
-       for (idx = 0; idx <= RATES; idx++)
+       for (idx = 0; idx <= ARRAY_SIZE(snd_card_harmony_rates); idx++)
                if (snd_card_harmony_rates[idx] == rate)
                        return rate_bits[idx];
        return HARMONY_SR_44KHZ; /* fallback */
@@ -556,7 +549,7 @@ static int snd_card_harmony_playback_prepare(snd_pcm_substream_t * substream)
        harmony->sample_rate = snd_card_harmony_rate_bits(runtime->rate);
 
        /* data format */
-       harmony->data_format = snd_harmony_set_data_format(haromny, runtime->format);
+       harmony->data_format = snd_harmony_set_data_format(harmony, runtime->format);
 
        /* number of channels */
        if (runtime->channels == 2)
@@ -587,7 +580,7 @@ static int snd_card_harmony_capture_prepare(snd_pcm_substream_t * substream)
        harmony->sample_rate = snd_card_harmony_rate_bits(runtime->rate);
        
        /* data format */
-       harmony->data_format = snd_harmony_set_data_format(haromny, runtime->format);
+       harmony->data_format = snd_harmony_set_data_format(harmony, runtime->format);
        
        /* number of channels */
        if (runtime->channels == 1)
@@ -751,6 +744,8 @@ static int snd_card_harmony_hw_params(snd_pcm_substream_t *substream,
        int err;
        
        err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+       if (err > 0 && substream->dma_device.type == SNDRV_DMA_TYPE_CONTINUOUS)
+               substream->runtime->dma_addr = __pa(substream->runtime->dma_area);
        DPRINTK(KERN_INFO PFX "HW Params returned %d, dma_addr %lx\n", err,
                        (unsigned long)substream->runtime->dma_addr);
        return err;
@@ -784,7 +779,7 @@ static snd_pcm_ops_t snd_card_harmony_capture_ops = {
        .pointer =              snd_card_harmony_capture_pointer,
 };
 
-static int snd_card_harmony_pcm_init(snd_card_harmony_t *harmony, int device)
+static int snd_card_harmony_pcm_init(snd_card_harmony_t *harmony)
 {
        snd_pcm_t *pcm;
        int err;
@@ -797,7 +792,7 @@ static int snd_card_harmony_pcm_init(snd_card_harmony_t *harmony, int device)
        
        snd_harmony_disable_interrupts(harmony);
        
-       if ((err = snd_pcm_new(harmony->card, "Harmony", device, 1, 1, &pcm)) < 0)
+       if ((err = snd_pcm_new(harmony->card, "Harmony", 0, 1, 1, &pcm)) < 0)
                return err;
        
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_harmony_playback_ops);
@@ -811,28 +806,54 @@ static int snd_card_harmony_pcm_init(snd_card_harmony_t *harmony, int device)
        /* initialize graveyard buffer */
        harmony->dma_dev.type = SNDRV_DMA_TYPE_DEV;
        harmony->dma_dev.dev = &harmony->pa_dev->dev;
-       err = snd_dma_alloc_pages(&harmony->dma_dev, HARMONY_BUF_SIZE*GRAVEYARD_BUFS,
+       err = snd_dma_alloc_pages(harmony->dma_dev.type,
+                                 harmony->dma_dev.dev,
+                                 HARMONY_BUF_SIZE*GRAVEYARD_BUFS,
                                  &harmony->graveyard_dma);
-       if (err < 0)
+       if (err == -ENOMEM) {
+               /* use continuous buffers */
+               harmony->dma_dev.type = SNDRV_DMA_TYPE_CONTINUOUS;
+               harmony->dma_dev.dev = snd_dma_continuous_data(GFP_KERNEL);
+               err = snd_dma_alloc_pages(harmony->dma_dev.type,
+                                         harmony->dma_dev.dev,
+                                         HARMONY_BUF_SIZE*GRAVEYARD_BUFS,
+                                         &harmony->graveyard_dma);
+       }
+       if (err < 0) {
+               printk(KERN_ERR PFX "can't allocate graveyard buffer\n");
                return err;
+       }
        harmony->graveyard_count = 0;
        
        /* initialize silence buffers */
-       err = snd_dma_alloc_pages(&harmony->dma_dev, HARMONY_BUF_SIZE*SILENCE_BUFS,
+       err = snd_dma_alloc_pages(harmony->dma_dev.type,
+                                 harmony->dma_dev.dev,
+                                 HARMONY_BUF_SIZE*SILENCE_BUFS,
                                  &harmony->silence_dma);
-       if (err < 0)
+       if (err < 0) {
+               printk(KERN_ERR PFX "can't allocate silence buffer\n");
                return err;
+       }
        harmony->silence_count = 0;
 
+       if (harmony->dma_dev.type == SNDRV_DMA_TYPE_CONTINUOUS) {
+               harmony->graveyard_dma.addr = __pa(harmony->graveyard_dma.area);
+               harmony->silence_dma.addr = __pa(harmony->silence_dma.area);
+       }
+
        harmony->ply_stopped = harmony->cap_stopped = 1;
        
        harmony->playback_substream = NULL;
        harmony->capture_substream = NULL;
        harmony->graveyard_count = 0;
-       
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &harmony->pa_dev->dev,
-                                             MAX_BUFFER_SIZE, MAX_BUFFER_SIZE);
+
+       err = snd_pcm_lib_preallocate_pages_for_all(pcm, harmony->dma_dev.type,
+                                                   harmony->dma_dev.dev,
+                                                   MAX_BUFFER_SIZE, MAX_BUFFER_SIZE);
+       if (err < 0) {
+               printk(KERN_ERR PFX "buffer allocation error %d\n", err);
+               // return err;
+       }
 
        return 0;
 }
@@ -871,7 +892,7 @@ static int snd_harmony_mixercontrol_info(snd_kcontrol_t * kcontrol, snd_ctl_elem
  
 static int snd_harmony_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-       snd_card_harmony_t *harmony = _snd_kcontrol_chip(kcontrol);
+       snd_card_harmony_t *harmony = snd_kcontrol_chip(kcontrol);
        int shift_left = (kcontrol->private_value) & 0xff;
        int shift_right = (kcontrol->private_value >> 8) & 0xff;
        int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -896,7 +917,7 @@ static int snd_harmony_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
 
 static int snd_harmony_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-       snd_card_harmony_t *harmony = _snd_kcontrol_chip(kcontrol);
+       snd_card_harmony_t *harmony = snd_kcontrol_chip(kcontrol);
        int shift_left = (kcontrol->private_value) & 0xff;
        int shift_right = (kcontrol->private_value >> 8) & 0xff;
        int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -1037,7 +1058,7 @@ static int __init snd_card_harmony_probe(struct parisc_device *pa_dev)
                snd_card_free(card);
                return err;
        }
-       if ((err = snd_card_harmony_pcm_init(chip, dev)) < 0) {
+       if ((err = snd_card_harmony_pcm_init(chip)) < 0) {
                printk(KERN_ERR PFX "PCM Init failed\n");
                snd_card_free(card);
                return err;