fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / sound / pci / trident / trident_main.c
index 83b7d8a..474f2d4 100644 (file)
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/gameport.h>
+#include <linux/dma-mapping.h>
 
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
+#include <sound/tlv.h>
 #include <sound/trident.h>
 #include <sound/asoundef.h>
 
@@ -50,8 +52,7 @@ static int snd_trident_pcm_mixer_build(struct snd_trident *trident,
 static int snd_trident_pcm_mixer_free(struct snd_trident *trident,
                                      struct snd_trident_voice * voice,
                                      struct snd_pcm_substream *substream);
-static irqreturn_t snd_trident_interrupt(int irq, void *dev_id,
-                                        struct pt_regs *regs);
+static irqreturn_t snd_trident_interrupt(int irq, void *dev_id);
 static int snd_trident_sis_reset(struct snd_trident *trident);
 
 static void snd_trident_clear_voices(struct snd_trident * trident,
@@ -305,6 +306,8 @@ void snd_trident_start_voice(struct snd_trident * trident, unsigned int voice)
        outl(mask, TRID_REG(trident, reg));
 }
 
+EXPORT_SYMBOL(snd_trident_start_voice);
+
 /*---------------------------------------------------------------------------
    void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice)
 
@@ -327,6 +330,8 @@ void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice)
        outl(mask, TRID_REG(trident, reg));
 }
 
+EXPORT_SYMBOL(snd_trident_stop_voice);
+
 /*---------------------------------------------------------------------------
     int snd_trident_allocate_pcm_channel(struct snd_trident *trident)
   
@@ -501,6 +506,8 @@ void snd_trident_write_voice_regs(struct snd_trident * trident,
 #endif
 }
 
+EXPORT_SYMBOL(snd_trident_write_voice_regs);
+
 /*---------------------------------------------------------------------------
    snd_trident_write_cso_reg
   
@@ -2620,6 +2627,8 @@ static int snd_trident_vol_control_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
+static DECLARE_TLV_DB_SCALE(db_scale_gvol, -6375, 25, 0);
+
 static int snd_trident_vol_control_put(struct snd_kcontrol *kcontrol,
                                       struct snd_ctl_elem_value *ucontrol)
 {
@@ -2646,6 +2655,7 @@ static struct snd_kcontrol_new snd_trident_vol_music_control __devinitdata =
        .get =          snd_trident_vol_control_get,
        .put =          snd_trident_vol_control_put,
        .private_value = 16,
+       .tlv = { .p = db_scale_gvol },
 };
 
 static struct snd_kcontrol_new snd_trident_vol_wave_control __devinitdata =
@@ -2656,6 +2666,7 @@ static struct snd_kcontrol_new snd_trident_vol_wave_control __devinitdata =
        .get =          snd_trident_vol_control_get,
        .put =          snd_trident_vol_control_put,
        .private_value = 0,
+       .tlv = { .p = db_scale_gvol },
 };
 
 /*---------------------------------------------------------------------------
@@ -2723,6 +2734,7 @@ static struct snd_kcontrol_new snd_trident_pcm_vol_control __devinitdata =
        .info =         snd_trident_pcm_vol_control_info,
        .get =          snd_trident_pcm_vol_control_get,
        .put =          snd_trident_pcm_vol_control_put,
+       /* FIXME: no tlv yet */
 };
 
 /*---------------------------------------------------------------------------
@@ -2832,6 +2844,8 @@ static int snd_trident_pcm_rvol_control_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
+static DECLARE_TLV_DB_SCALE(db_scale_crvol, -3175, 25, 1);
+
 static struct snd_kcontrol_new snd_trident_pcm_rvol_control __devinitdata =
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -2841,6 +2855,7 @@ static struct snd_kcontrol_new snd_trident_pcm_rvol_control __devinitdata =
        .info =         snd_trident_pcm_rvol_control_info,
        .get =          snd_trident_pcm_rvol_control_get,
        .put =          snd_trident_pcm_rvol_control_put,
+       .tlv = { .p = db_scale_crvol },
 };
 
 /*---------------------------------------------------------------------------
@@ -2896,6 +2911,7 @@ static struct snd_kcontrol_new snd_trident_pcm_cvol_control __devinitdata =
        .info =         snd_trident_pcm_cvol_control_info,
        .get =          snd_trident_pcm_cvol_control_get,
        .put =          snd_trident_pcm_cvol_control_put,
+       .tlv = { .p = db_scale_crvol },
 };
 
 static void snd_trident_notify_pcm_change1(struct snd_card *card,
@@ -3331,7 +3347,7 @@ static void __devinit snd_trident_proc_init(struct snd_trident * trident)
        if (trident->device == TRIDENT_DEVICE_ID_SI7018)
                s = "sis7018";
        if (! snd_card_proc_new(trident->card, s, &entry))
-               snd_info_set_text_ops(entry, trident, 1024, snd_trident_proc_read);
+               snd_info_set_text_ops(entry, trident, snd_trident_proc_read);
 }
 
 static int snd_trident_dev_free(struct snd_device *device)
@@ -3364,8 +3380,8 @@ static int __devinit snd_trident_tlb_alloc(struct snd_trident *trident)
                snd_printk(KERN_ERR "trident: unable to allocate TLB buffer\n");
                return -ENOMEM;
        }
-       trident->tlb.entries = (unsigned int*)(((unsigned long)trident->tlb.buffer.area + SNDRV_TRIDENT_MAX_PAGES * 4 - 1) & ~(SNDRV_TRIDENT_MAX_PAGES * 4 - 1));
-       trident->tlb.entries_dmaaddr = (trident->tlb.buffer.addr + SNDRV_TRIDENT_MAX_PAGES * 4 - 1) & ~(SNDRV_TRIDENT_MAX_PAGES * 4 - 1);
+       trident->tlb.entries = (unsigned int*)ALIGN((unsigned long)trident->tlb.buffer.area, SNDRV_TRIDENT_MAX_PAGES * 4);
+       trident->tlb.entries_dmaaddr = ALIGN(trident->tlb.buffer.addr, SNDRV_TRIDENT_MAX_PAGES * 4);
        /* allocate shadow TLB page table (virtual addresses) */
        trident->tlb.shadow_entries = vmalloc(SNDRV_TRIDENT_MAX_PAGES*sizeof(unsigned long));
        if (trident->tlb.shadow_entries == NULL) {
@@ -3554,8 +3570,8 @@ int __devinit snd_trident_create(struct snd_card *card,
        if ((err = pci_enable_device(pci)) < 0)
                return err;
        /* check, if we can restrict PCI DMA transfers to 30 bits */
-       if (pci_set_dma_mask(pci, 0x3fffffff) < 0 ||
-           pci_set_consistent_dma_mask(pci, 0x3fffffff) < 0) {
+       if (pci_set_dma_mask(pci, DMA_30BIT_MASK) < 0 ||
+           pci_set_consistent_dma_mask(pci, DMA_30BIT_MASK) < 0) {
                snd_printk(KERN_ERR "architecture does not support 30bit PCI busmaster DMA\n");
                pci_disable_device(pci);
                return -ENXIO;
@@ -3592,7 +3608,7 @@ int __devinit snd_trident_create(struct snd_card *card,
        }
        trident->port = pci_resource_start(pci, 0);
 
-       if (request_irq(pci->irq, snd_trident_interrupt, SA_INTERRUPT|SA_SHIRQ,
+       if (request_irq(pci->irq, snd_trident_interrupt, IRQF_SHARED,
                        "Trident Audio", trident)) {
                snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
                snd_trident_free(trident);
@@ -3720,7 +3736,7 @@ static int snd_trident_free(struct snd_trident *trident)
   
   ---------------------------------------------------------------------------*/
 
-static irqreturn_t snd_trident_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_trident_interrupt(int irq, void *dev_id)
 {
        struct snd_trident *trident = dev_id;
        unsigned int audio_int, chn_int, stimer, channel, mask, tmp;
@@ -3808,7 +3824,7 @@ static irqreturn_t snd_trident_interrupt(int irq, void *dev_id, struct pt_regs *
        }
        if (audio_int & MPU401_IRQ) {
                if (trident->rmidi) {
-                       snd_mpu401_uart_interrupt(irq, trident->rmidi->private_data, regs);
+                       snd_mpu401_uart_interrupt(irq, trident->rmidi->private_data);
                } else {
                        inb(TRID_REG(trident, T4D_MPUR0));
                }
@@ -3883,6 +3899,8 @@ struct snd_trident_voice *snd_trident_alloc_voice(struct snd_trident * trident,
        return NULL;
 }
 
+EXPORT_SYMBOL(snd_trident_alloc_voice);
+
 void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voice *voice)
 {
        unsigned long flags;
@@ -3911,6 +3929,8 @@ void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voi
                private_free(voice);
 }
 
+EXPORT_SYMBOL(snd_trident_free_voice);
+
 static void snd_trident_clear_voices(struct snd_trident * trident, unsigned short v_min, unsigned short v_max)
 {
        unsigned int i, val, mask[2] = { 0, 0 };
@@ -3946,15 +3966,9 @@ int snd_trident_suspend(struct pci_dev *pci, pm_message_t state)
        snd_ac97_suspend(trident->ac97);
        snd_ac97_suspend(trident->ac97_sec);
 
-       switch (trident->device) {
-       case TRIDENT_DEVICE_ID_DX:
-       case TRIDENT_DEVICE_ID_NX:
-               break;                  /* TODO */
-       case TRIDENT_DEVICE_ID_SI7018:
-               break;
-       }
        pci_disable_device(pci);
        pci_save_state(pci);
+       pci_set_power_state(pci, pci_choose_state(pci, state));
        return 0;
 }
 
@@ -3963,9 +3977,15 @@ int snd_trident_resume(struct pci_dev *pci)
        struct snd_card *card = pci_get_drvdata(pci);
        struct snd_trident *trident = card->private_data;
 
+       pci_set_power_state(pci, PCI_D0);
        pci_restore_state(pci);
-       pci_enable_device(pci);
-       pci_set_master(pci); /* to be sure */
+       if (pci_enable_device(pci) < 0) {
+               printk(KERN_ERR "trident: pci_enable_device failed, "
+                      "disabling device\n");
+               snd_card_disconnect(card);
+               return -EIO;
+       }
+       pci_set_master(pci);
 
        switch (trident->device) {
        case TRIDENT_DEVICE_ID_DX:
@@ -3992,13 +4012,3 @@ int snd_trident_resume(struct pci_dev *pci)
        return 0;
 }
 #endif /* CONFIG_PM */
-
-EXPORT_SYMBOL(snd_trident_alloc_voice);
-EXPORT_SYMBOL(snd_trident_free_voice);
-EXPORT_SYMBOL(snd_trident_start_voice);
-EXPORT_SYMBOL(snd_trident_stop_voice);
-EXPORT_SYMBOL(snd_trident_write_voice_regs);
-/* trident_memory.c symbols */
-EXPORT_SYMBOL(snd_trident_synth_alloc);
-EXPORT_SYMBOL(snd_trident_synth_free);
-EXPORT_SYMBOL(snd_trident_synth_copy_from_user);