Ignore:
Timestamp:
Dec 11, 2005, 5:57:39 PM (20 years ago)
Author:
vladest
Message:

Latest update from ALSA. some intial > 15 interrupts support

Location:
GPL/trunk/alsa-kernel/pci/cs46xx
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • GPL/trunk/alsa-kernel/pci/cs46xx/cs46xx.c

    r33 r34  
    3030#include <linux/time.h>
    3131#include <linux/init.h>
     32#include <linux/moduleparam.h>
    3233#include <sound/core.h>
    3334#include <sound/cs46xx.h>
    34 #define SNDRV_GET_ID
    3535#include <sound/initval.h>
    3636
     
    3838MODULE_DESCRIPTION("Cirrus Logic Sound Fusion CS46XX");
    3939MODULE_LICENSE("GPL");
    40 MODULE_CLASSES("{sound}");
    41 MODULE_DEVICES("{{Cirrus Logic,Sound Fusion (CS4280)},"
     40MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,Sound Fusion (CS4280)},"
    4241                "{Cirrus Logic,Sound Fusion (CS4610)},"
    4342                "{Cirrus Logic,Sound Fusion (CS4612)},"
     
    5049static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;       /* ID for this card */
    5150static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;      /* Enable this card */
    52 #ifdef TARGET_OS2
    5351static int external_amp[SNDRV_CARDS] = {0};
    5452static int thinkpad[SNDRV_CARDS] = {1,0,0,0,0,0,0,0};
    5553static int mmap_valid[SNDRV_CARDS] = {0};
    56 #else
    57 static int external_amp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
    58 static int thinkpad[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
    59 static int mmap_valid[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
    60 #endif
    6154
    62 MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
     55//module_param_array(index, int, NULL, 0444);
    6356MODULE_PARM_DESC(index, "Index value for the CS46xx soundcard.");
    64 MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
    65 MODULE_PARM(id, "1-" __MODULE_STRING(SNDRV_CARDS) "s");
     57//module_param_array(id, charp, NULL, 0444);
    6658MODULE_PARM_DESC(id, "ID string for the CS46xx soundcard.");
    67 MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
    68 MODULE_PARM(enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
     59//module_param_array(enable, bool, NULL, 0444);
    6960MODULE_PARM_DESC(enable, "Enable CS46xx soundcard.");
    70 MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
    71 MODULE_PARM(external_amp, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
     61//module_param_array(external_amp, bool, NULL, 0444);
    7262MODULE_PARM_DESC(external_amp, "Force to enable external amplifer.");
    73 MODULE_PARM_SYNTAX(external_amp, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
    74 MODULE_PARM(thinkpad, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
     63//module_param_array(thinkpad, bool, NULL, 0444);
    7564MODULE_PARM_DESC(thinkpad, "Force to enable Thinkpad's CLKRUN control.");
    76 MODULE_PARM_SYNTAX(thinkpad, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
    77 MODULE_PARM(mmap_valid, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
     65//module_param_array(mmap_valid, bool, NULL, 0444);
    7866MODULE_PARM_DESC(mmap_valid, "Support OSS mmap.");
    79 MODULE_PARM_SYNTAX(mmap_valid, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
    8067
    8168static struct pci_device_id snd_cs46xx_ids[] = {
     
    9279{
    9380        static int dev;
    94         snd_card_t *card;
    95         cs46xx_t *chip;
     81        struct snd_card *card;
     82        struct snd_cs46xx *chip;
    9683        int err;
    9784
     
    11299                return err;
    113100        }
     101        card->private_data = chip;
    114102        chip->accept_valid = mmap_valid[dev];
    115103        if ((err = snd_cs46xx_pcm(chip, 0, NULL)) < 0) {
     
    127115        }
    128116#endif
    129         if ((err = snd_cs46xx_mixer(chip)) < 0) {
     117        if ((err = snd_cs46xx_mixer(chip, 2)) < 0) {
    130118                snd_card_free(card);
    131119                return err;
     
    164152        }
    165153
    166         pci_set_drvdata(pci, card);
     154        pci_set_drvdata(pci, card);
    167155        dev++;
    168156        return 0;
    169157}
    170158
    171 
    172159static void __devexit snd_card_cs46xx_remove(struct pci_dev *pci)
    173160{
    174     snd_card_free(pci_get_drvdata(pci));
    175     pci_set_drvdata(pci, NULL);
     161        snd_card_free(pci_get_drvdata(pci));
     162        pci_set_drvdata(pci, NULL);
    176163}
    177164
    178165static struct pci_driver driver = {
    179         0, 0, 0,
    180         "Sound Fusion CS46xx",
    181         snd_cs46xx_ids,
    182         snd_card_cs46xx_probe,
    183         snd_card_cs46xx_remove,
    184         SND_PCI_PM_CALLBACKS
     166        .name = "Sound Fusion CS46xx",
     167        .id_table = snd_cs46xx_ids,
     168        .probe = snd_card_cs46xx_probe,
     169        .remove = snd_card_cs46xx_remove,
     170#ifdef CONFIG_PM
     171        .suspend = snd_cs46xx_suspend,
     172        .resume = snd_cs46xx_resume,
     173#endif
    185174};
    186  
     175
    187176static int __init alsa_card_cs46xx_init(void)
    188177{
    189         int err;
    190 
    191         if ((err = pci_module_init(&driver)) < 0) {
    192 #ifdef MODULE
    193 //              printk(KERN_ERR "Sound Fusion CS46xx soundcard not found or device busy\n");
    194 #endif
    195                 return err;
    196         }
    197         return 0;
     178        return pci_register_driver(&driver);
    198179}
    199180
     
    205186module_init(alsa_card_cs46xx_init)
    206187module_exit(alsa_card_cs46xx_exit)
    207 
    208 #ifndef MODULE
    209 
    210 /* format is: snd-cs46xx=snd_enable,snd_index,snd_id */
    211 
    212 static int __init alsa_card_cs46xx_setup(char *str)
    213 {
    214         static unsigned __initdata nr_dev = 0;
    215 
    216         if (nr_dev >= SNDRV_CARDS)
    217                 return 0;
    218         (void)(get_option(&str,&enable[nr_dev]) == 2 &&
    219                get_option(&str,&index[nr_dev]) == 2 &&
    220                get_id(&str,&id[nr_dev]) == 2);
    221         nr_dev++;
    222         return 1;
    223 }
    224 
    225 __setup("snd-cs46xx=", alsa_card_cs46xx_setup);
    226 
    227 #endif /* ifndef MODULE */
  • GPL/trunk/alsa-kernel/pci/cs46xx/cs46xx_lib.c

    r33 r34  
    88 *    - Sometimes the SPDIF input DSP tasks get's unsynchronized
    99 *      and the SPDIF get somewhat "distorcionated", or/and left right channel
    10  *      are swapped. To get around this problem when it happens, mute and unmute
     10 *      are swapped. To get around this problem when it happens, mute and unmute 
    1111 *      the SPDIF input mixer controll.
    1212 *    - On the Hercules Game Theater XP the amplifier are sometimes turned
     
    2323 *        multi channel PCM.  But known to work.
    2424 *
    25  *  FINALLY: A credit to the developers Tom and Jordan
     25 *  FINALLY: A credit to the developers Tom and Jordan 
    2626 *           at Cirrus for have helping me out with the DSP, however we
    2727 *           still don't have sufficient documentation and technical
    2828 *           references to be able to implement all fancy feutures
    29  *           supported by the cs46xx DSP's.
     29 *           supported by the cs46xx DSP's. 
    3030 *           Benny <benny@hostmobility.com>
    31  *
     31 *               
    3232 *   This program is free software; you can redistribute it and/or modify
    3333 *   it under the terms of the GNU General Public License as published by
     
    4545 *
    4646 */
     47
    4748#include <sound/driver.h>
    48 #include <asm/io.h>
    4949#include <linux/delay.h>
    5050#include <linux/pci.h>
    5151#include <linux/pm.h>
    5252#include <linux/init.h>
     53#include <linux/interrupt.h>
    5354#include <linux/slab.h>
     55//#include <linux/gameport.h>
     56
    5457#include <sound/core.h>
    5558#include <sound/control.h>
    5659#include <sound/info.h>
     60#include <sound/pcm.h>
     61#include <sound/pcm_params.h>
    5762#include <sound/cs46xx.h>
    58 #ifndef LINUX_2_2
    59 #include <linux/gameport.h>
    60 #endif
     63
     64#include <asm/io.h>
     65
    6166#include "cs46xx_lib.h"
    6267#include "dsp_spos.h"
    63 #include <sound/pcm_params.h>
    64 
    65 static void amp_voyetra(cs46xx_t *chip, int change);
    66 
    67 static unsigned short snd_cs46xx_codec_read(cs46xx_t *chip,
    68                                             unsigned short reg,
    69                                             int codec_index)
    70 {
    71     int count;
    72     unsigned short result,tmp;
    73     u32 offset = 0;
    74     snd_assert ( (codec_index == CS46XX_PRIMARY_CODEC_INDEX) ||
    75                 (codec_index == CS46XX_SECONDARY_CODEC_INDEX),
    76                 return -EINVAL);
    77 
    78     chip->active_ctrl(chip, 1);
    79 
    80     if (codec_index == CS46XX_SECONDARY_CODEC_INDEX)
    81         offset = CS46XX_SECONDARY_CODEC_OFFSET;
    82 
    83     /*
    84      *  1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
    85      *  2. Write ACCDA = Command Data Register = 470h    for data to write to AC97
    86      *  3. Write ACCTL = Control Register = 460h for initiating the write7---55
    87      *  4. Read ACCTL = 460h, DCV should be reset by now and 460h = 17h
    88      *  5. if DCV not cleared, break and return error
    89      *  6. Read ACSTS = Status Register = 464h, check VSTS bit
    90      */
    91 
    92     snd_cs46xx_peekBA0(chip, BA0_ACSDA + offset);
    93 
    94     tmp = snd_cs46xx_peekBA0(chip, BA0_ACCTL);
    95     if ((tmp & ACCTL_VFRM) == 0) {
    96         snd_printk(KERN_WARNING  "cs46xx: ACCTL_VFRM not set 0x%x\n",tmp);
    97         snd_cs46xx_pokeBA0(chip, BA0_ACCTL, (tmp & (~ACCTL_ESYN)) | ACCTL_VFRM );
    98         msleep(50);
    99         tmp = snd_cs46xx_peekBA0(chip, BA0_ACCTL + offset);
    100         snd_cs46xx_pokeBA0(chip, BA0_ACCTL, tmp | ACCTL_ESYN | ACCTL_VFRM );
    101 
    102     }
    103 
    104     /*
    105      *  Setup the AC97 control registers on the CS461x to send the
    106      *  appropriate command to the AC97 to perform the read.
    107      *  ACCAD = Command Address Register = 46Ch
    108      *  ACCDA = Command Data Register = 470h
    109      *  ACCTL = Control Register = 460h
    110      *  set DCV - will clear when process completed
    111      *  set CRW - Read command
    112      *  set VFRM - valid frame enabled
    113      *  set ESYN - ASYNC generation enabled
    114      *  set RSTN - ARST# inactive, AC97 codec not reset
    115      */
    116 
    117     snd_cs46xx_pokeBA0(chip, BA0_ACCAD, reg);
    118     snd_cs46xx_pokeBA0(chip, BA0_ACCDA, 0);
    119     if (codec_index == CS46XX_PRIMARY_CODEC_INDEX) {
    120         snd_cs46xx_pokeBA0(chip, BA0_ACCTL,/* clear ACCTL_DCV */ ACCTL_CRW |
    121                            ACCTL_VFRM | ACCTL_ESYN |
    122                            ACCTL_RSTN);
    123         snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_CRW |
    124                            ACCTL_VFRM | ACCTL_ESYN |
    125                            ACCTL_RSTN);
    126     } else {
    127         snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_TC |
    128                            ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN |
    129                            ACCTL_RSTN);
    130     }
    131 
    132     /*
    133      *  Wait for the read to occur.
    134      */
    135     for (count = 0; count < 1000; count++) {
    136         /*
    137          *  First, we want to wait for a short time.
     68
     69static void amp_voyetra(struct snd_cs46xx *chip, int change);
     70
     71#ifdef CONFIG_SND_CS46XX_NEW_DSP
     72static struct snd_pcm_ops snd_cs46xx_playback_rear_ops;
     73static struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops;
     74static struct snd_pcm_ops snd_cs46xx_playback_clfe_ops;
     75static struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops;
     76static struct snd_pcm_ops snd_cs46xx_playback_iec958_ops;
     77static struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops;
     78#endif
     79
     80static struct snd_pcm_ops snd_cs46xx_playback_ops;
     81static struct snd_pcm_ops snd_cs46xx_playback_indirect_ops;
     82static struct snd_pcm_ops snd_cs46xx_capture_ops;
     83static struct snd_pcm_ops snd_cs46xx_capture_indirect_ops;
     84
     85static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip,
     86                                            unsigned short reg,
     87                                            int codec_index)
     88{
     89        int count;
     90        unsigned short result,tmp;
     91        u32 offset = 0;
     92        snd_assert ( (codec_index == CS46XX_PRIMARY_CODEC_INDEX) ||
     93                     (codec_index == CS46XX_SECONDARY_CODEC_INDEX),
     94                     return -EINVAL);
     95
     96        chip->active_ctrl(chip, 1);
     97
     98        if (codec_index == CS46XX_SECONDARY_CODEC_INDEX)
     99                offset = CS46XX_SECONDARY_CODEC_OFFSET;
     100
     101        /*
     102         *  1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
     103         *  2. Write ACCDA = Command Data Register = 470h    for data to write to AC97
     104         *  3. Write ACCTL = Control Register = 460h for initiating the write7---55
     105         *  4. Read ACCTL = 460h, DCV should be reset by now and 460h = 17h
     106         *  5. if DCV not cleared, break and return error
     107         *  6. Read ACSTS = Status Register = 464h, check VSTS bit
     108         */
     109
     110        snd_cs46xx_peekBA0(chip, BA0_ACSDA + offset);
     111
     112        tmp = snd_cs46xx_peekBA0(chip, BA0_ACCTL);
     113        if ((tmp & ACCTL_VFRM) == 0) {
     114                snd_printk(KERN_WARNING  "cs46xx: ACCTL_VFRM not set 0x%x\n",tmp);
     115                snd_cs46xx_pokeBA0(chip, BA0_ACCTL, (tmp & (~ACCTL_ESYN)) | ACCTL_VFRM );
     116                msleep(50);
     117                tmp = snd_cs46xx_peekBA0(chip, BA0_ACCTL + offset);
     118                snd_cs46xx_pokeBA0(chip, BA0_ACCTL, tmp | ACCTL_ESYN | ACCTL_VFRM );
     119
     120        }
     121
     122        /*
     123         *  Setup the AC97 control registers on the CS461x to send the
     124         *  appropriate command to the AC97 to perform the read.
     125         *  ACCAD = Command Address Register = 46Ch
     126         *  ACCDA = Command Data Register = 470h
     127         *  ACCTL = Control Register = 460h
     128         *  set DCV - will clear when process completed
     129         *  set CRW - Read command
     130         *  set VFRM - valid frame enabled
     131         *  set ESYN - ASYNC generation enabled
     132         *  set RSTN - ARST# inactive, AC97 codec not reset
     133         */
     134
     135        snd_cs46xx_pokeBA0(chip, BA0_ACCAD, reg);
     136        snd_cs46xx_pokeBA0(chip, BA0_ACCDA, 0);
     137        if (codec_index == CS46XX_PRIMARY_CODEC_INDEX) {
     138                snd_cs46xx_pokeBA0(chip, BA0_ACCTL,/* clear ACCTL_DCV */ ACCTL_CRW |
     139                                   ACCTL_VFRM | ACCTL_ESYN |
     140                                   ACCTL_RSTN);
     141                snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_CRW |
     142                                   ACCTL_VFRM | ACCTL_ESYN |
     143                                   ACCTL_RSTN);
     144        } else {
     145                snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_TC |
     146                                   ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN |
     147                                   ACCTL_RSTN);
     148        }
     149
     150        /*
     151         *  Wait for the read to occur.
     152         */
     153        for (count = 0; count < 1000; count++) {
     154                /*
     155                 *  First, we want to wait for a short time.
     156                 */
     157                udelay(10);
     158                /*
     159                 *  Now, check to see if the read has completed.
     160                 *  ACCTL = 460h, DCV should be reset by now and 460h = 17h
     161                 */
     162                if (!(snd_cs46xx_peekBA0(chip, BA0_ACCTL) & ACCTL_DCV))
     163                        goto ok1;
     164        }
     165
     166        snd_printk(KERN_ERR "AC'97 read problem (ACCTL_DCV), reg = 0x%x\n", reg);
     167        result = 0xffff;
     168        goto end;
     169       
     170 ok1:
     171        /*
     172         *  Wait for the valid status bit to go active.
     173         */
     174        for (count = 0; count < 100; count++) {
     175                /*
     176                 *  Read the AC97 status register.
     177                 *  ACSTS = Status Register = 464h
     178                 *  VSTS - Valid Status
     179                 */
     180                if (snd_cs46xx_peekBA0(chip, BA0_ACSTS + offset) & ACSTS_VSTS)
     181                        goto ok2;
     182                udelay(10);
     183        }
     184       
     185        snd_printk(KERN_ERR "AC'97 read problem (ACSTS_VSTS), codec_index %d, reg = 0x%x\n", codec_index, reg);
     186        result = 0xffff;
     187        goto end;
     188
     189 ok2:
     190        /*
     191         *  Read the data returned from the AC97 register.
     192         *  ACSDA = Status Data Register = 474h
     193         */
     194#if 0
     195        printk("e) reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n", reg,
     196                        snd_cs46xx_peekBA0(chip, BA0_ACSDA),
     197                        snd_cs46xx_peekBA0(chip, BA0_ACCAD));
     198#endif
     199
     200        //snd_cs46xx_peekBA0(chip, BA0_ACCAD);
     201        result = snd_cs46xx_peekBA0(chip, BA0_ACSDA + offset);
     202 end:
     203        chip->active_ctrl(chip, -1);
     204        return result;
     205}
     206
     207static unsigned short snd_cs46xx_ac97_read(struct snd_ac97 * ac97,
     208                                            unsigned short reg)
     209{
     210        struct snd_cs46xx *chip = ac97->private_data;
     211        unsigned short val;
     212        int codec_index = ac97->num;
     213
     214        snd_assert(codec_index == CS46XX_PRIMARY_CODEC_INDEX ||
     215                   codec_index == CS46XX_SECONDARY_CODEC_INDEX,
     216                   return 0xffff);
     217
     218        val = snd_cs46xx_codec_read(chip, reg, codec_index);
     219
     220        return val;
     221}
     222
     223
     224static void snd_cs46xx_codec_write(struct snd_cs46xx *chip,
     225                                   unsigned short reg,
     226                                   unsigned short val,
     227                                   int codec_index)
     228{
     229        int count;
     230
     231        snd_assert ((codec_index == CS46XX_PRIMARY_CODEC_INDEX) ||
     232                    (codec_index == CS46XX_SECONDARY_CODEC_INDEX),
     233                    return);
     234
     235        chip->active_ctrl(chip, 1);
     236
     237        /*
     238         *  1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
     239         *  2. Write ACCDA = Command Data Register = 470h    for data to write to AC97
     240         *  3. Write ACCTL = Control Register = 460h for initiating the write
     241         *  4. Read ACCTL = 460h, DCV should be reset by now and 460h = 07h
     242         *  5. if DCV not cleared, break and return error
     243         */
     244
     245        /*
     246         *  Setup the AC97 control registers on the CS461x to send the
     247         *  appropriate command to the AC97 to perform the read.
     248         *  ACCAD = Command Address Register = 46Ch
     249         *  ACCDA = Command Data Register = 470h
     250         *  ACCTL = Control Register = 460h
     251         *  set DCV - will clear when process completed
     252         *  reset CRW - Write command
     253         *  set VFRM - valid frame enabled
     254         *  set ESYN - ASYNC generation enabled
     255         *  set RSTN - ARST# inactive, AC97 codec not reset
    138256         */
    139         udelay(10);
    140         /*
    141          *  Now, check to see if the read has completed.
    142          *  ACCTL = 460h, DCV should be reset by now and 460h = 17h
    143          */
    144         if (!(snd_cs46xx_peekBA0(chip, BA0_ACCTL) & ACCTL_DCV))
    145             goto ok1;
    146     }
    147 
    148     snd_printk("AC'97 read problem (ACCTL_DCV), reg = 0x%x\n", reg);
    149     result = 0xffff;
    150     goto end;
    151 
    152     ok1:
    153         /*
    154          *  Wait for the valid status bit to go active.
    155          */
    156         for (count = 0; count < 100; count++) {
    157             /*
    158              *  Read the AC97 status register.
    159              *  ACSTS = Status Register = 464h
    160              *  VSTS - Valid Status
    161              */
    162             if (snd_cs46xx_peekBA0(chip, BA0_ACSTS + offset) & ACSTS_VSTS)
    163                 goto ok2;
    164             udelay(10);
    165         }
    166 
    167         snd_printk("AC'97 read problem (ACSTS_VSTS), codec_index %d, reg = 0x%x\n", codec_index, reg);
    168         result = 0xffff;
    169         goto end;
    170 
    171         ok2:
    172             /*
    173              *  Read the data returned from the AC97 register.
    174              *  ACSDA = Status Data Register = 474h
    175              */
    176 #if 0
    177             printk("e) reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n", reg,
    178                    snd_cs46xx_peekBA0(chip, BA0_ACSDA),
    179                    snd_cs46xx_peekBA0(chip, BA0_ACCAD));
    180 #endif
    181 
    182             //snd_cs46xx_peekBA0(chip, BA0_ACCAD);
    183             result = snd_cs46xx_peekBA0(chip, BA0_ACSDA + offset);
    184         end:
    185             chip->active_ctrl(chip, -1);
    186             return result;
    187 }
    188 
    189 static unsigned short snd_cs46xx_ac97_read(ac97_t * ac97,
    190                                            unsigned short reg)
    191 {
    192     cs46xx_t *chip = ac97->private_data;
    193     unsigned short val;
    194     int codec_index = ac97->num;
    195 
    196     snd_assert(codec_index == CS46XX_PRIMARY_CODEC_INDEX ||
    197                codec_index == CS46XX_SECONDARY_CODEC_INDEX,
    198                return 0xffff);
    199 
    200     val = snd_cs46xx_codec_read(chip, reg, codec_index);
    201 
    202     /* HACK: voyetra uses EAPD bit in the reverse way.
    203      * we flip the bit to show the mixer status correctly
    204      */
    205     if (reg == AC97_POWERDOWN && chip->amplifier_ctrl == amp_voyetra)
    206         val ^= 0x8000;
    207 
    208     return val;
    209 }
    210 
    211 
    212 static void snd_cs46xx_codec_write(cs46xx_t *chip,
    213                                    unsigned short reg,
    214                                    unsigned short val,
    215                                    int codec_index)
    216 {
    217     int count;
    218 
    219     snd_assert ((codec_index == CS46XX_PRIMARY_CODEC_INDEX) ||
    220                 (codec_index == CS46XX_SECONDARY_CODEC_INDEX),
    221                 return);
    222 
    223     chip->active_ctrl(chip, 1);
    224 
    225     /*
    226      *  1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
    227      *  2. Write ACCDA = Command Data Register = 470h    for data to write to AC97
    228      *  3. Write ACCTL = Control Register = 460h for initiating the write
    229      *  4. Read ACCTL = 460h, DCV should be reset by now and 460h = 07h
    230      *  5. if DCV not cleared, break and return error
    231      */
    232 
    233     /*
    234      *  Setup the AC97 control registers on the CS461x to send the
    235      *  appropriate command to the AC97 to perform the read.
    236      *  ACCAD = Command Address Register = 46Ch
    237      *  ACCDA = Command Data Register = 470h
    238      *  ACCTL = Control Register = 460h
    239      *  set DCV - will clear when process completed
    240      *  reset CRW - Write command
    241      *  set VFRM - valid frame enabled
    242      *  set ESYN - ASYNC generation enabled
    243      *  set RSTN - ARST# inactive, AC97 codec not reset
    244      */
    245     snd_cs46xx_pokeBA0(chip, BA0_ACCAD , reg);
    246     snd_cs46xx_pokeBA0(chip, BA0_ACCDA , val);
    247     snd_cs46xx_peekBA0(chip, BA0_ACCTL);
    248 
    249     if (codec_index == CS46XX_PRIMARY_CODEC_INDEX) {
    250         snd_cs46xx_pokeBA0(chip, BA0_ACCTL, /* clear ACCTL_DCV */ ACCTL_VFRM |
    251                            ACCTL_ESYN | ACCTL_RSTN);
    252         snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM |
    253                            ACCTL_ESYN | ACCTL_RSTN);
    254     } else {
    255         snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_TC |
    256                            ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
    257     }
    258 
    259     for (count = 0; count < 4000; count++) {
    260         /*
    261          *  First, we want to wait for a short time.
    262          */
    263         udelay(10);
    264         /*
    265          *  Now, check to see if the write has completed.
    266          *  ACCTL = 460h, DCV should be reset by now and 460h = 07h
    267          */
    268         if (!(snd_cs46xx_peekBA0(chip, BA0_ACCTL) & ACCTL_DCV)) {
    269             goto end;
    270         }
    271     }
    272     snd_printk("AC'97 write problem, codec_index = %d, reg = 0x%x, val = 0x%x\n", codec_index, reg, val);
    273 end:
    274     chip->active_ctrl(chip, -1);
    275 }
    276 
    277 static void snd_cs46xx_ac97_write(ac97_t *ac97,
    278                                   unsigned short reg,
    279                                   unsigned short val)
    280 {
    281     cs46xx_t *chip = ac97->private_data;
    282     int codec_index = ac97->num;
    283 
    284     snd_assert(codec_index == CS46XX_PRIMARY_CODEC_INDEX ||
    285                codec_index == CS46XX_SECONDARY_CODEC_INDEX,
    286                return);
    287     /* HACK: voyetra uses EAPD bit in the reverse way.
    288      * we flip the bit to show the mixer status correctly
    289      */
    290     if (reg == AC97_POWERDOWN && chip->amplifier_ctrl == amp_voyetra)
    291         val ^= 0x8000;
    292 
    293     snd_cs46xx_codec_write(chip, reg, val, codec_index);
     257        snd_cs46xx_pokeBA0(chip, BA0_ACCAD , reg);
     258        snd_cs46xx_pokeBA0(chip, BA0_ACCDA , val);
     259        snd_cs46xx_peekBA0(chip, BA0_ACCTL);
     260
     261        if (codec_index == CS46XX_PRIMARY_CODEC_INDEX) {
     262                snd_cs46xx_pokeBA0(chip, BA0_ACCTL, /* clear ACCTL_DCV */ ACCTL_VFRM |
     263                                   ACCTL_ESYN | ACCTL_RSTN);
     264                snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM |
     265                                   ACCTL_ESYN | ACCTL_RSTN);
     266        } else {
     267                snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_TC |
     268                                   ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
     269        }
     270
     271        for (count = 0; count < 4000; count++) {
     272                /*
     273                 *  First, we want to wait for a short time.
     274                 */
     275                udelay(10);
     276                /*
     277                 *  Now, check to see if the write has completed.
     278                 *  ACCTL = 460h, DCV should be reset by now and 460h = 07h
     279                 */
     280                if (!(snd_cs46xx_peekBA0(chip, BA0_ACCTL) & ACCTL_DCV)) {
     281                        goto end;
     282                }
     283        }
     284        snd_printk(KERN_ERR "AC'97 write problem, codec_index = %d, reg = 0x%x, val = 0x%x\n", codec_index, reg, val);
     285 end:
     286        chip->active_ctrl(chip, -1);
     287}
     288
     289static void snd_cs46xx_ac97_write(struct snd_ac97 *ac97,
     290                                   unsigned short reg,
     291                                   unsigned short val)
     292{
     293        struct snd_cs46xx *chip = ac97->private_data;
     294        int codec_index = ac97->num;
     295
     296        snd_assert(codec_index == CS46XX_PRIMARY_CODEC_INDEX ||
     297                   codec_index == CS46XX_SECONDARY_CODEC_INDEX,
     298                   return);
     299
     300        snd_cs46xx_codec_write(chip, reg, val, codec_index);
    294301}
    295302
     
    299306 */
    300307
    301 int snd_cs46xx_download(cs46xx_t *chip,
    302                         u32 *src,
     308int snd_cs46xx_download(struct snd_cs46xx *chip,
     309                        u32 *src,
    303310                        unsigned long offset,
    304311                        unsigned long len)
    305312{
    306     unsigned long dst;
    307     unsigned int bank = offset >> 16;
    308     offset = offset & 0xffff;
    309 
    310     snd_assert(!(offset & 3) && !(len & 3), return -EINVAL);
    311     dst = (unsigned long)chip->region.idx[bank+1].remap_addr + offset;
    312     len /= sizeof(u32);
    313 
    314     /* writel already converts 32-bit value to right endianess */
    315     while (len-- > 0) {
    316         writel(*src++, dst);
    317         dst += sizeof(u32);
    318     }
    319     return 0;
     313        void __iomem *dst;
     314        unsigned int bank = offset >> 16;
     315        offset = offset & 0xffff;
     316
     317        snd_assert(!(offset & 3) && !(len & 3), return -EINVAL);
     318        dst = (char*)chip->region.idx[bank+1].remap_addr + offset;
     319        len /= sizeof(u32);
     320
     321        /* writel already converts 32-bit value to right endianess */
     322        while (len-- > 0) {
     323                writel(*src++, dst);
     324                (char*)dst += sizeof(u32);
     325        }
     326        return 0;
    320327}
    321328
     
    328335#include "imgs/cwcdma.h"
    329336
    330 int snd_cs46xx_clear_BA1(cs46xx_t *chip,
     337int snd_cs46xx_clear_BA1(struct snd_cs46xx *chip,
    331338                         unsigned long offset,
    332                          unsigned long len)
    333 {
    334     unsigned long dst;
    335     unsigned int bank = offset >> 16;
    336     offset = offset & 0xffff;
    337 
    338     snd_assert(!(offset & 3) && !(len & 3), return -EINVAL);
    339     dst = chip->region.idx[bank+1].remap_addr + offset;
    340     len /= sizeof(u32);
    341 
    342     /* writel already converts 32-bit value to right endianess */
    343     while (len-- > 0) {
    344         writel(0, dst);
    345         dst += sizeof(u32);
    346     }
    347     return 0;
     339                         unsigned long len) 
     340{
     341        void __iomem *dst;
     342        unsigned int bank = offset >> 16;
     343        offset = offset & 0xffff;
     344
     345        snd_assert(!(offset & 3) && !(len & 3), return -EINVAL);
     346        dst = chip->region.idx[bank+1].remap_addr + offset;
     347        len /= sizeof(u32);
     348
     349        /* writel already converts 32-bit value to right endianess */
     350        while (len-- > 0) {
     351                writel(0, dst);
     352                dst += sizeof(u32);
     353        }
     354        return 0;
    348355}
    349356
     
    352359#include "cs46xx_image.h"
    353360
    354 int snd_cs46xx_download_image(cs46xx_t *chip)
    355 {
    356     int idx, err;
    357     unsigned long offset = 0;
    358 
    359     for (idx = 0; idx < BA1_MEMORY_COUNT; idx++) {
    360         if ((err = snd_cs46xx_download(chip,
    361                                        &BA1Struct.map[offset],
    362                                        BA1Struct.memory[idx].offset,
    363                                        BA1Struct.memory[idx].size)) < 0)
    364             return err;
    365         offset += BA1Struct.memory[idx].size >> 2;
    366     }
    367     return 0;
     361int snd_cs46xx_download_image(struct snd_cs46xx *chip)
     362{
     363        int idx, err;
     364        unsigned long offset = 0;
     365
     366        for (idx = 0; idx < BA1_MEMORY_COUNT; idx++) {
     367                if ((err = snd_cs46xx_download(chip,
     368                                               &BA1Struct.map[offset],
     369                                               BA1Struct.memory[idx].offset,
     370                                               BA1Struct.memory[idx].size)) < 0)
     371                        return err;
     372                offset += BA1Struct.memory[idx].size >> 2;
     373        }       
     374        return 0;
    368375}
    369376#endif /* CONFIG_SND_CS46XX_NEW_DSP */
     
    373380 */
    374381
    375 static void snd_cs46xx_reset(cs46xx_t *chip)
    376 {
    377     int idx;
    378 
    379     /*
    380      *  Write the reset bit of the SP control register.
    381      */
    382     snd_cs46xx_poke(chip, BA1_SPCR, SPCR_RSTSP);
    383 
    384     /*
    385      *  Write the control register.
    386      */
    387     snd_cs46xx_poke(chip, BA1_SPCR, SPCR_DRQEN);
    388 
    389     /*
    390      *  Clear the trap registers.
    391      */
    392     for (idx = 0; idx < 8; idx++) {
    393         snd_cs46xx_poke(chip, BA1_DREG, DREG_REGID_TRAP_SELECT + idx);
    394         snd_cs46xx_poke(chip, BA1_TWPR, 0xFFFF);
    395     }
    396     snd_cs46xx_poke(chip, BA1_DREG, 0);
    397 
    398     /*
    399      *  Set the frame timer to reflect the number of cycles per frame.
    400      */
    401     snd_cs46xx_poke(chip, BA1_FRMT, 0xadf);
    402 }
    403 
    404 static int cs46xx_wait_for_fifo(cs46xx_t * chip,int retry_timeout)
    405 {
    406     u32 i, status = 0;
    407     /*
    408      * Make sure the previous FIFO write operation has completed.
    409      */
    410     for(i = 0; i < 50; i++){
    411         status = snd_cs46xx_peekBA0(chip, BA0_SERBST);
    412 
    413         if( !(status & SERBST_WBSY) )
    414             break;
    415 
    416         mdelay(retry_timeout);
    417     }
    418 
    419     if(status & SERBST_WBSY) {
    420         snd_printk( KERN_ERR "cs46xx: failure waiting for FIFO command to complete\n");
    421 
    422         return -EINVAL;
    423     }
    424 
    425     return 0;
    426 }
    427 
    428 static void snd_cs46xx_clear_serial_FIFOs(cs46xx_t *chip)
    429 {
    430     int idx, powerdown = 0;
    431     unsigned int tmp;
    432 
    433     /*
    434      *  See if the devices are powered down.  If so, we must power them up first
    435      *  or they will not respond.
    436      */
    437     tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1);
    438     if (!(tmp & CLKCR1_SWCE)) {
    439         snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp | CLKCR1_SWCE);
    440         powerdown = 1;
    441     }
    442 
    443     /*
    444      *  We want to clear out the serial port FIFOs so we don't end up playing
    445      *  whatever random garbage happens to be in them.  We fill the sample FIFOS
    446      *  with zero (silence).
    447      */
    448     snd_cs46xx_pokeBA0(chip, BA0_SERBWP, 0);
    449 
    450     /*
    451      *  Fill all 256 sample FIFO locations.
    452      */
    453     for (idx = 0; idx < 0xFF; idx++) {
    454         /*
    455          *  Make sure the previous FIFO write operation has completed.
    456          */
    457         if (cs46xx_wait_for_fifo(chip,1)) {
    458             snd_printdd ("failed waiting for FIFO at addr (%02X)\n",idx);
    459             if (powerdown)
    460                 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);
    461 
    462             break;
    463         }
    464         /*
    465          *  Write the serial port FIFO index.
    466          */
    467         snd_cs46xx_pokeBA0(chip, BA0_SERBAD, idx);
    468         /*
    469          *  Tell the serial port to load the new value into the FIFO location.
    470          */
    471         snd_cs46xx_pokeBA0(chip, BA0_SERBCM, SERBCM_WRC);
    472     }
    473     /*
    474      *  Now, if we powered up the devices, then power them back down again.
    475      *  This is kinda ugly, but should never happen.
    476      */
    477     if (powerdown)
    478         snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);
    479 }
    480 
    481 static void snd_cs46xx_proc_start(cs46xx_t *chip)
    482 {
    483     int cnt;
    484 
    485     /*
    486      *  Set the frame timer to reflect the number of cycles per frame.
    487      */
    488     snd_cs46xx_poke(chip, BA1_FRMT, 0xadf);
    489     /*
    490      *  Turn on the run, run at frame, and DMA enable bits in the local copy of
    491      *  the SP control register.
    492      */
    493     snd_cs46xx_poke(chip, BA1_SPCR, SPCR_RUN | SPCR_RUNFR | SPCR_DRQEN);
    494     /*
    495      *  Wait until the run at frame bit resets itself in the SP control
    496      *  register.
    497      */
    498     for (cnt = 0; cnt < 25; cnt++) {
    499         udelay(50);
    500         if (!(snd_cs46xx_peek(chip, BA1_SPCR) & SPCR_RUNFR))
    501             break;
    502     }
    503 
    504     if (snd_cs46xx_peek(chip, BA1_SPCR) & SPCR_RUNFR)
    505         snd_printk("SPCR_RUNFR never reset\n");
    506 }
    507 
    508 static void snd_cs46xx_proc_stop(cs46xx_t *chip)
    509 {
    510     /*
    511      *  Turn off the run, run at frame, and DMA enable bits in the local copy of
    512      *  the SP control register.
    513      */
    514     snd_cs46xx_poke(chip, BA1_SPCR, 0);
     382static void snd_cs46xx_reset(struct snd_cs46xx *chip)
     383{
     384        int idx;
     385
     386        /*
     387         *  Write the reset bit of the SP control register.
     388         */
     389        snd_cs46xx_poke(chip, BA1_SPCR, SPCR_RSTSP);
     390
     391        /*
     392         *  Write the control register.
     393         */
     394        snd_cs46xx_poke(chip, BA1_SPCR, SPCR_DRQEN);
     395
     396        /*
     397         *  Clear the trap registers.
     398         */
     399        for (idx = 0; idx < 8; idx++) {
     400                snd_cs46xx_poke(chip, BA1_DREG, DREG_REGID_TRAP_SELECT + idx);
     401                snd_cs46xx_poke(chip, BA1_TWPR, 0xFFFF);
     402        }
     403        snd_cs46xx_poke(chip, BA1_DREG, 0);
     404
     405        /*
     406         *  Set the frame timer to reflect the number of cycles per frame.
     407         */
     408        snd_cs46xx_poke(chip, BA1_FRMT, 0xadf);
     409}
     410
     411static int cs46xx_wait_for_fifo(struct snd_cs46xx * chip,int retry_timeout)
     412{
     413        u32 i, status = 0;
     414        /*
     415         * Make sure the previous FIFO write operation has completed.
     416         */
     417        for(i = 0; i < 50; i++){
     418                status = snd_cs46xx_peekBA0(chip, BA0_SERBST);
     419   
     420                if( !(status & SERBST_WBSY) )
     421                        break;
     422
     423                mdelay(retry_timeout);
     424        }
     425 
     426        if(status & SERBST_WBSY) {
     427                snd_printk( KERN_ERR "cs46xx: failure waiting for FIFO command to complete\n");
     428
     429                return -EINVAL;
     430        }
     431
     432        return 0;
     433}
     434
     435static void snd_cs46xx_clear_serial_FIFOs(struct snd_cs46xx *chip)
     436{
     437        int idx, powerdown = 0;
     438        unsigned int tmp;
     439
     440        /*
     441         *  See if the devices are powered down.  If so, we must power them up first
     442         *  or they will not respond.
     443         */
     444        tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1);
     445        if (!(tmp & CLKCR1_SWCE)) {
     446                snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp | CLKCR1_SWCE);
     447                powerdown = 1;
     448        }
     449
     450        /*
     451         *  We want to clear out the serial port FIFOs so we don't end up playing
     452         *  whatever random garbage happens to be in them.  We fill the sample FIFOS
     453         *  with zero (silence).
     454         */
     455        snd_cs46xx_pokeBA0(chip, BA0_SERBWP, 0);
     456
     457        /*
     458         *  Fill all 256 sample FIFO locations.
     459         */
     460        for (idx = 0; idx < 0xFF; idx++) {
     461                /*
     462                 *  Make sure the previous FIFO write operation has completed.
     463                 */
     464                if (cs46xx_wait_for_fifo(chip,1)) {
     465                        snd_printdd ("failed waiting for FIFO at addr (%02X)\n",idx);
     466
     467                        if (powerdown)
     468                                snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);
     469         
     470                        break;
     471                }
     472                /*
     473                 *  Write the serial port FIFO index.
     474                 */
     475                snd_cs46xx_pokeBA0(chip, BA0_SERBAD, idx);
     476                /*
     477                 *  Tell the serial port to load the new value into the FIFO location.
     478                 */
     479                snd_cs46xx_pokeBA0(chip, BA0_SERBCM, SERBCM_WRC);
     480        }
     481        /*
     482         *  Now, if we powered up the devices, then power them back down again.
     483         *  This is kinda ugly, but should never happen.
     484         */
     485        if (powerdown)
     486                snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);
     487}
     488
     489static void snd_cs46xx_proc_start(struct snd_cs46xx *chip)
     490{
     491        int cnt;
     492
     493        /*
     494         *  Set the frame timer to reflect the number of cycles per frame.
     495         */
     496        snd_cs46xx_poke(chip, BA1_FRMT, 0xadf);
     497        /*
     498         *  Turn on the run, run at frame, and DMA enable bits in the local copy of
     499         *  the SP control register.
     500         */
     501        snd_cs46xx_poke(chip, BA1_SPCR, SPCR_RUN | SPCR_RUNFR | SPCR_DRQEN);
     502        /*
     503         *  Wait until the run at frame bit resets itself in the SP control
     504         *  register.
     505         */
     506        for (cnt = 0; cnt < 25; cnt++) {
     507                udelay(50);
     508                if (!(snd_cs46xx_peek(chip, BA1_SPCR) & SPCR_RUNFR))
     509                        break;
     510        }
     511
     512        if (snd_cs46xx_peek(chip, BA1_SPCR) & SPCR_RUNFR)
     513                snd_printk(KERN_ERR "SPCR_RUNFR never reset\n");
     514}
     515
     516static void snd_cs46xx_proc_stop(struct snd_cs46xx *chip)
     517{
     518        /*
     519         *  Turn off the run, run at frame, and DMA enable bits in the local copy of
     520         *  the SP control register.
     521         */
     522        snd_cs46xx_poke(chip, BA1_SPCR, 0);
    515523}
    516524
     
    521529#define GOF_PER_SEC 200
    522530
    523 static void snd_cs46xx_set_play_sample_rate(cs46xx_t *chip, unsigned int rate)
    524 {
    525     unsigned long flags;
    526     unsigned int tmp1, tmp2;
    527     unsigned int phiIncr;
    528     unsigned int correctionPerGOF, correctionPerSec;
    529 
    530     /*
    531     *  Compute the values used to drive the actual sample rate conversion.
    532     *  The following formulas are being computed, using inline assembly
    533     *  since we need to use 64 bit arithmetic to compute the values:
    534     *
    535     *  phiIncr = floor((Fs,in * 2^26) / Fs,out)
    536     *  correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) /
    537      *                                   GOF_PER_SEC)
    538      *  ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -M
    539      *                       GOF_PER_SEC * correctionPerGOF
    540     *
    541     *  i.e.
    542     *
    543     *  phiIncr:other = dividend:remainder((Fs,in * 2^26) / Fs,out)
    544     *  correctionPerGOF:correctionPerSec =
    545     *      dividend:remainder(ulOther / GOF_PER_SEC)
    546     */
    547     tmp1 = rate << 16;
    548     phiIncr = tmp1 / 48000;
    549     tmp1 -= phiIncr * 48000;
    550     tmp1 <<= 10;
    551     phiIncr <<= 10;
    552     tmp2 = tmp1 / 48000;
    553     phiIncr += tmp2;
    554     tmp1 -= tmp2 * 48000;
    555     correctionPerGOF = tmp1 / GOF_PER_SEC;
    556     tmp1 -= correctionPerGOF * GOF_PER_SEC;
    557     correctionPerSec = tmp1;
    558 
    559     /*
    560     *  Fill in the SampleRateConverter control block.
    561     */
    562     spin_lock_irqsave(&chip->reg_lock, flags);
    563     snd_cs46xx_poke(chip, BA1_PSRC,
    564                     ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF));
    565     snd_cs46xx_poke(chip, BA1_PPI, phiIncr);
    566     spin_unlock_irqrestore(&chip->reg_lock, flags);
    567 }
    568 
    569 static void snd_cs46xx_set_capture_sample_rate(cs46xx_t *chip, unsigned int rate)
    570 {
    571     unsigned long flags;
    572     unsigned int phiIncr, coeffIncr, tmp1, tmp2;
    573     unsigned int correctionPerGOF, correctionPerSec, initialDelay;
    574     unsigned int frameGroupLength, cnt;
    575 
    576     /*
    577     *  We can only decimate by up to a factor of 1/9th the hardware rate.
    578     *  Correct the value if an attempt is made to stray outside that limit.
    579     */
    580     if ((rate * 9) < 48000)
    581         rate = 48000 / 9;
    582 
    583     /*
    584     *  We can not capture at at rate greater than the Input Rate (48000).
    585     *  Return an error if an attempt is made to stray outside that limit.
    586     */
    587     if (rate > 48000)
    588         rate = 48000;
    589 
    590     /*
    591     *  Compute the values used to drive the actual sample rate conversion.
    592     *  The following formulas are being computed, using inline assembly
    593     *  since we need to use 64 bit arithmetic to compute the values:
    594     *
    595     *     coeffIncr = -floor((Fs,out * 2^23) / Fs,in)
    596     *     phiIncr = floor((Fs,in * 2^26) / Fs,out)
    597     *     correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) /
    598     *                                GOF_PER_SEC)
    599     *     correctionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -
    600     *                          GOF_PER_SEC * correctionPerGOF
    601     *     initialDelay = ceil((24 * Fs,in) / Fs,out)
    602     *
    603     * i.e.
    604     *
    605     *     coeffIncr = neg(dividend((Fs,out * 2^23) / Fs,in))
    606     *     phiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out)
    607     *     correctionPerGOF:correctionPerSec =
    608     *      dividend:remainder(ulOther / GOF_PER_SEC)
    609     *     initialDelay = dividend(((24 * Fs,in) + Fs,out - 1) / Fs,out)
    610     */
    611 
    612     tmp1 = rate << 16;
    613     coeffIncr = tmp1 / 48000;
    614     tmp1 -= coeffIncr * 48000;
    615     tmp1 <<= 7;
    616     coeffIncr <<= 7;
    617     coeffIncr += tmp1 / 48000;
    618     coeffIncr ^= 0xFFFFFFFF;
    619     coeffIncr++;
    620     tmp1 = 48000 << 16;
    621     phiIncr = tmp1 / rate;
    622     tmp1 -= phiIncr * rate;
    623     tmp1 <<= 10;
    624     phiIncr <<= 10;
    625     tmp2 = tmp1 / rate;
    626     phiIncr += tmp2;
    627     tmp1 -= tmp2 * rate;
    628     correctionPerGOF = tmp1 / GOF_PER_SEC;
    629     tmp1 -= correctionPerGOF * GOF_PER_SEC;
    630     correctionPerSec = tmp1;
    631     initialDelay = ((48000 * 24) + rate - 1) / rate;
    632 
    633     /*
    634     *  Fill in the VariDecimate control block.
    635     */
    636     spin_lock_irqsave(&chip->reg_lock, flags);
    637     snd_cs46xx_poke(chip, BA1_CSRC,
    638                     ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF));
    639     snd_cs46xx_poke(chip, BA1_CCI, coeffIncr);
    640     snd_cs46xx_poke(chip, BA1_CD,
    641                     (((BA1_VARIDEC_BUF_1 + (initialDelay << 2)) << 16) & 0xFFFF0000) | 0x80);
    642     snd_cs46xx_poke(chip, BA1_CPI, phiIncr);
    643     spin_unlock_irqrestore(&chip->reg_lock, flags);
    644 
    645     /*
    646     *  Figure out the frame group length for the write back task.  Basically,
    647     *  this is just the factors of 24000 (2^6*3*5^3) that are not present in
    648     *  the output sample rate.
    649     */
    650     frameGroupLength = 1;
    651     for (cnt = 2; cnt <= 64; cnt *= 2) {
    652         if (((rate / cnt) * cnt) != rate)
    653             frameGroupLength *= 2;
    654     }
    655     if (((rate / 3) * 3) != rate) {
    656         frameGroupLength *= 3;
    657     }
    658     for (cnt = 5; cnt <= 125; cnt *= 5) {
    659         if (((rate / cnt) * cnt) != rate)
    660             frameGroupLength *= 5;
    661     }
    662 
    663     /*
    664     * Fill in the WriteBack control block.
    665     */
    666     spin_lock_irqsave(&chip->reg_lock, flags);
    667     snd_cs46xx_poke(chip, BA1_CFG1, frameGroupLength);
    668     snd_cs46xx_poke(chip, BA1_CFG2, (0x00800000 | frameGroupLength));
    669     snd_cs46xx_poke(chip, BA1_CCST, 0x0000FFFF);
    670     snd_cs46xx_poke(chip, BA1_CSPB, ((65536 * rate) / 24000));
    671     snd_cs46xx_poke(chip, (BA1_CSPB + 4), 0x0000FFFF);
    672     spin_unlock_irqrestore(&chip->reg_lock, flags);
     531static void snd_cs46xx_set_play_sample_rate(struct snd_cs46xx *chip, unsigned int rate)
     532{
     533        unsigned long flags;
     534        unsigned int tmp1, tmp2;
     535        unsigned int phiIncr;
     536        unsigned int correctionPerGOF, correctionPerSec;
     537
     538        /*
     539        *  Compute the values used to drive the actual sample rate conversion.
     540        *  The following formulas are being computed, using inline assembly
     541        *  since we need to use 64 bit arithmetic to compute the values:
     542        *
     543        *  phiIncr = floor((Fs,in * 2^26) / Fs,out)
     544        *  correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) /
     545         *                                   GOF_PER_SEC)
     546         *  ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -M
     547         *                       GOF_PER_SEC * correctionPerGOF
     548        *
     549        *  i.e.
     550        *
     551        *  phiIncr:other = dividend:remainder((Fs,in * 2^26) / Fs,out)
     552        *  correctionPerGOF:correctionPerSec =
     553        *      dividend:remainder(ulOther / GOF_PER_SEC)
     554        */
     555        tmp1 = rate << 16;
     556        phiIncr = tmp1 / 48000;
     557        tmp1 -= phiIncr * 48000;
     558        tmp1 <<= 10;
     559        phiIncr <<= 10;
     560        tmp2 = tmp1 / 48000;
     561        phiIncr += tmp2;
     562        tmp1 -= tmp2 * 48000;
     563        correctionPerGOF = tmp1 / GOF_PER_SEC;
     564        tmp1 -= correctionPerGOF * GOF_PER_SEC;
     565        correctionPerSec = tmp1;
     566
     567        /*
     568        *  Fill in the SampleRateConverter control block.
     569        */
     570        spin_lock_irqsave(&chip->reg_lock, flags);
     571        snd_cs46xx_poke(chip, BA1_PSRC,
     572          ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF));
     573        snd_cs46xx_poke(chip, BA1_PPI, phiIncr);
     574        spin_unlock_irqrestore(&chip->reg_lock, flags);
     575}
     576
     577static void snd_cs46xx_set_capture_sample_rate(struct snd_cs46xx *chip, unsigned int rate)
     578{
     579        unsigned long flags;
     580        unsigned int phiIncr, coeffIncr, tmp1, tmp2;
     581        unsigned int correctionPerGOF, correctionPerSec, initialDelay;
     582        unsigned int frameGroupLength, cnt;
     583
     584        /*
     585        *  We can only decimate by up to a factor of 1/9th the hardware rate.
     586        *  Correct the value if an attempt is made to stray outside that limit.
     587        */
     588        if ((rate * 9) < 48000)
     589                rate = 48000 / 9;
     590
     591        /*
     592        *  We can not capture at at rate greater than the Input Rate (48000).
     593        *  Return an error if an attempt is made to stray outside that limit.
     594        */
     595        if (rate > 48000)
     596                rate = 48000;
     597
     598        /*
     599        *  Compute the values used to drive the actual sample rate conversion.
     600        *  The following formulas are being computed, using inline assembly
     601        *  since we need to use 64 bit arithmetic to compute the values:
     602        *
     603        *     coeffIncr = -floor((Fs,out * 2^23) / Fs,in)
     604        *     phiIncr = floor((Fs,in * 2^26) / Fs,out)
     605        *     correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) /
     606        *                                GOF_PER_SEC)
     607        *     correctionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -
     608        *                          GOF_PER_SEC * correctionPerGOF
     609        *     initialDelay = ceil((24 * Fs,in) / Fs,out)
     610        *
     611        * i.e.
     612        *
     613        *     coeffIncr = neg(dividend((Fs,out * 2^23) / Fs,in))
     614        *     phiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out)
     615        *     correctionPerGOF:correctionPerSec =
     616        *          dividend:remainder(ulOther / GOF_PER_SEC)
     617        *     initialDelay = dividend(((24 * Fs,in) + Fs,out - 1) / Fs,out)
     618        */
     619
     620        tmp1 = rate << 16;
     621        coeffIncr = tmp1 / 48000;
     622        tmp1 -= coeffIncr * 48000;
     623        tmp1 <<= 7;
     624        coeffIncr <<= 7;
     625        coeffIncr += tmp1 / 48000;
     626        coeffIncr ^= 0xFFFFFFFF;
     627        coeffIncr++;
     628        tmp1 = 48000 << 16;
     629        phiIncr = tmp1 / rate;
     630        tmp1 -= phiIncr * rate;
     631        tmp1 <<= 10;
     632        phiIncr <<= 10;
     633        tmp2 = tmp1 / rate;
     634        phiIncr += tmp2;
     635        tmp1 -= tmp2 * rate;
     636        correctionPerGOF = tmp1 / GOF_PER_SEC;
     637        tmp1 -= correctionPerGOF * GOF_PER_SEC;
     638        correctionPerSec = tmp1;
     639        initialDelay = ((48000 * 24) + rate - 1) / rate;
     640
     641        /*
     642        *  Fill in the VariDecimate control block.
     643        */
     644        spin_lock_irqsave(&chip->reg_lock, flags);
     645        snd_cs46xx_poke(chip, BA1_CSRC,
     646                ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF));
     647        snd_cs46xx_poke(chip, BA1_CCI, coeffIncr);
     648        snd_cs46xx_poke(chip, BA1_CD,
     649                (((BA1_VARIDEC_BUF_1 + (initialDelay << 2)) << 16) & 0xFFFF0000) | 0x80);
     650        snd_cs46xx_poke(chip, BA1_CPI, phiIncr);
     651        spin_unlock_irqrestore(&chip->reg_lock, flags);
     652
     653        /*
     654        *  Figure out the frame group length for the write back task.  Basically,
     655        *  this is just the factors of 24000 (2^6*3*5^3) that are not present in
     656        *  the output sample rate.
     657        */
     658        frameGroupLength = 1;
     659        for (cnt = 2; cnt <= 64; cnt *= 2) {
     660                if (((rate / cnt) * cnt) != rate)
     661                        frameGroupLength *= 2;
     662        }
     663        if (((rate / 3) * 3) != rate) {
     664                frameGroupLength *= 3;
     665        }
     666        for (cnt = 5; cnt <= 125; cnt *= 5) {
     667                if (((rate / cnt) * cnt) != rate)
     668                        frameGroupLength *= 5;
     669        }
     670
     671        /*
     672        * Fill in the WriteBack control block.
     673        */
     674        spin_lock_irqsave(&chip->reg_lock, flags);
     675        snd_cs46xx_poke(chip, BA1_CFG1, frameGroupLength);
     676        snd_cs46xx_poke(chip, BA1_CFG2, (0x00800000 | frameGroupLength));
     677        snd_cs46xx_poke(chip, BA1_CCST, 0x0000FFFF);
     678        snd_cs46xx_poke(chip, BA1_CSPB, ((65536 * rate) / 24000));
     679        snd_cs46xx_poke(chip, (BA1_CSPB + 4), 0x0000FFFF);
     680        spin_unlock_irqrestore(&chip->reg_lock, flags);
    673681}
    674682
     
    677685 */
    678686
    679 static void snd_cs46xx_pb_trans_copy(snd_pcm_substream_t *substream,
    680                                      snd_pcm_indirect_t *rec, size_t bytes)
    681 {
    682     snd_pcm_runtime_t *runtime = substream->runtime;
    683     cs46xx_pcm_t * cpcm = runtime->private_data;
    684     memcpy(cpcm->hw_buf.area + rec->hw_data, runtime->dma_area + rec->sw_data, bytes);
    685 }
    686 
    687 static int snd_cs46xx_playback_transfer(snd_pcm_substream_t *substream)
    688 {
    689     snd_pcm_runtime_t *runtime = substream->runtime;
    690     cs46xx_pcm_t * cpcm = runtime->private_data;
    691     snd_pcm_indirect_playback_transfer(substream, &cpcm->pcm_rec, snd_cs46xx_pb_trans_copy);
    692     return 0;
    693 }
    694 
    695 static void snd_cs46xx_cp_trans_copy(snd_pcm_substream_t *substream,
    696                                      snd_pcm_indirect_t *rec, size_t bytes)
    697 {
    698     cs46xx_t *chip = snd_pcm_substream_chip(substream);
    699     snd_pcm_runtime_t *runtime = substream->runtime;
    700     memcpy(runtime->dma_area + rec->sw_data,
    701            chip->capt.hw_buf.area + rec->hw_data, bytes);
    702 }
    703 
    704 static int snd_cs46xx_capture_transfer(snd_pcm_substream_t *substream)
    705 {
    706     cs46xx_t *chip = snd_pcm_substream_chip(substream);
    707     snd_pcm_indirect_capture_transfer(substream, &chip->capt.pcm_rec, snd_cs46xx_cp_trans_copy);
    708     return 0;
    709 }
    710 
    711 static snd_pcm_uframes_t snd_cs46xx_playback_direct_pointer(snd_pcm_substream_t * substream)
    712 {
    713     cs46xx_t *chip = snd_pcm_substream_chip(substream);
    714     size_t ptr;
    715     cs46xx_pcm_t *cpcm = substream->runtime->private_data;
    716     snd_assert (cpcm->pcm_channel,return -ENXIO);
    717 
    718 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    719     ptr = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 2) << 2);
     687static void snd_cs46xx_pb_trans_copy(struct snd_pcm_substream *substream,
     688                                     struct snd_pcm_indirect *rec, size_t bytes)
     689{
     690        struct snd_pcm_runtime *runtime = substream->runtime;
     691        struct snd_cs46xx_pcm * cpcm = runtime->private_data;
     692        memcpy(cpcm->hw_buf.area + rec->hw_data, runtime->dma_area + rec->sw_data, bytes);
     693}
     694
     695static int snd_cs46xx_playback_transfer(struct snd_pcm_substream *substream)
     696{
     697        struct snd_pcm_runtime *runtime = substream->runtime;
     698        struct snd_cs46xx_pcm * cpcm = runtime->private_data;
     699        snd_pcm_indirect_playback_transfer(substream, &cpcm->pcm_rec, snd_cs46xx_pb_trans_copy);
     700        return 0;
     701}
     702
     703static void snd_cs46xx_cp_trans_copy(struct snd_pcm_substream *substream,
     704                                     struct snd_pcm_indirect *rec, size_t bytes)
     705{
     706        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
     707        struct snd_pcm_runtime *runtime = substream->runtime;
     708        memcpy(runtime->dma_area + rec->sw_data,
     709               chip->capt.hw_buf.area + rec->hw_data, bytes);
     710}
     711
     712static int snd_cs46xx_capture_transfer(struct snd_pcm_substream *substream)
     713{
     714        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
     715        snd_pcm_indirect_capture_transfer(substream, &chip->capt.pcm_rec, snd_cs46xx_cp_trans_copy);
     716        return 0;
     717}
     718
     719static snd_pcm_uframes_t snd_cs46xx_playback_direct_pointer(struct snd_pcm_substream *substream)
     720{
     721        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
     722        size_t ptr;
     723        struct snd_cs46xx_pcm *cpcm = substream->runtime->private_data;
     724        snd_assert (cpcm->pcm_channel,return -ENXIO);
     725
     726#ifdef CONFIG_SND_CS46XX_NEW_DSP
     727        ptr = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 2) << 2);
    720728#else
    721     ptr = snd_cs46xx_peek(chip, BA1_PBA);
    722 #endif
    723     ptr -= cpcm->hw_buf.addr;
    724     return ptr >> cpcm->shift;
    725 }
    726 
    727 static snd_pcm_uframes_t snd_cs46xx_playback_indirect_pointer(snd_pcm_substream_t * substream)
    728 {
    729     cs46xx_t *chip = snd_pcm_substream_chip(substream);
    730     size_t ptr;
    731     cs46xx_pcm_t *cpcm = substream->runtime->private_data;
    732 
    733 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    734     snd_assert (cpcm->pcm_channel,return -ENXIO);
    735     ptr = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 2) << 2);
     729        ptr = snd_cs46xx_peek(chip, BA1_PBA);
     730#endif
     731        ptr -= cpcm->hw_buf.addr;
     732        return ptr >> cpcm->shift;
     733}
     734
     735static snd_pcm_uframes_t snd_cs46xx_playback_indirect_pointer(struct snd_pcm_substream *substream)
     736{
     737        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
     738        size_t ptr;
     739        struct snd_cs46xx_pcm *cpcm = substream->runtime->private_data;
     740
     741#ifdef CONFIG_SND_CS46XX_NEW_DSP
     742        snd_assert (cpcm->pcm_channel,return -ENXIO);
     743        ptr = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 2) << 2);
    736744#else
    737     ptr = snd_cs46xx_peek(chip, BA1_PBA);
    738 #endif
    739     ptr -= cpcm->hw_buf.addr;
    740     return snd_pcm_indirect_playback_pointer(substream, &cpcm->pcm_rec, ptr);
    741 }
    742 
    743 static snd_pcm_uframes_t snd_cs46xx_capture_direct_pointer(snd_pcm_substream_t * substream)
    744 {
    745     cs46xx_t *chip = snd_pcm_substream_chip(substream);
    746     size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_buf.addr;
    747     return ptr >> chip->capt.shift;
    748 }
    749 
    750 static snd_pcm_uframes_t snd_cs46xx_capture_indirect_pointer(snd_pcm_substream_t * substream)
    751 {
    752     cs46xx_t *chip = snd_pcm_substream_chip(substream);
    753     size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_buf.addr;
    754     return snd_pcm_indirect_capture_pointer(substream, &chip->capt.pcm_rec, ptr);
    755 }
    756 
    757 static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
    758                                        int cmd)
    759 {
    760     cs46xx_t *chip = snd_pcm_substream_chip(substream);
    761     /*snd_pcm_runtime_t *runtime = substream->runtime;*/
    762     int result = 0;
    763 
    764 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    765     cs46xx_pcm_t *cpcm = substream->runtime->private_data;
    766     if (! cpcm->pcm_channel) {
    767         return -ENXIO;
    768     }
    769 #endif
    770     switch (cmd) {
    771     case SNDRV_PCM_TRIGGER_START:
    772     case SNDRV_PCM_TRIGGER_RESUME:
    773 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    774         /* magic value to unmute PCM stream  playback volume */
    775         snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address +
    776                                SCBVolumeCtrl) << 2, 0x80008000);
    777 
    778         if (cpcm->pcm_channel->unlinked)
    779             cs46xx_dsp_pcm_link(chip,cpcm->pcm_channel);
    780 
    781         if (substream->runtime->periods != CS46XX_FRAGS)
    782             snd_cs46xx_playback_transfer(substream);
     745        ptr = snd_cs46xx_peek(chip, BA1_PBA);
     746#endif
     747        ptr -= cpcm->hw_buf.addr;
     748        return snd_pcm_indirect_playback_pointer(substream, &cpcm->pcm_rec, ptr);
     749}
     750
     751static snd_pcm_uframes_t snd_cs46xx_capture_direct_pointer(struct snd_pcm_substream *substream)
     752{
     753        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
     754        size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_buf.addr;
     755        return ptr >> chip->capt.shift;
     756}
     757
     758static snd_pcm_uframes_t snd_cs46xx_capture_indirect_pointer(struct snd_pcm_substream *substream)
     759{
     760        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
     761        size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_buf.addr;
     762        return snd_pcm_indirect_capture_pointer(substream, &chip->capt.pcm_rec, ptr);
     763}
     764
     765static int snd_cs46xx_playback_trigger(struct snd_pcm_substream *substream,
     766                                       int cmd)
     767{
     768        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
     769        /*struct snd_pcm_runtime *runtime = substream->runtime;*/
     770        int result = 0;
     771
     772#ifdef CONFIG_SND_CS46XX_NEW_DSP
     773        struct snd_cs46xx_pcm *cpcm = substream->runtime->private_data;
     774        if (! cpcm->pcm_channel) {
     775                return -ENXIO;
     776        }
     777#endif
     778        switch (cmd) {
     779        case SNDRV_PCM_TRIGGER_START:
     780        case SNDRV_PCM_TRIGGER_RESUME:
     781#ifdef CONFIG_SND_CS46XX_NEW_DSP
     782                /* magic value to unmute PCM stream  playback volume */
     783                snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address +
     784                                       SCBVolumeCtrl) << 2, 0x80008000);
     785
     786                if (cpcm->pcm_channel->unlinked)
     787                        cs46xx_dsp_pcm_link(chip,cpcm->pcm_channel);
     788
     789                if (substream->runtime->periods != CS46XX_FRAGS)
     790                        snd_cs46xx_playback_transfer(substream);
    783791#else
    784         spin_lock(&chip->reg_lock);
    785         if (substream->runtime->periods != CS46XX_FRAGS)
    786             snd_cs46xx_playback_transfer(substream);
    787         { unsigned int tmp;
    788             tmp = snd_cs46xx_peek(chip, BA1_PCTL);
    789         tmp &= 0x0000ffff;
    790         snd_cs46xx_poke(chip, BA1_PCTL, chip->play_ctl | tmp);
    791         }
    792         spin_unlock(&chip->reg_lock);
    793 #endif
    794         break;
    795     case SNDRV_PCM_TRIGGER_STOP:
    796     case SNDRV_PCM_TRIGGER_SUSPEND:
    797 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    798         /* magic mute channel */
    799         snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address +
    800                                SCBVolumeCtrl) << 2, 0xffffffff);
    801 
    802         if (!cpcm->pcm_channel->unlinked)
    803             cs46xx_dsp_pcm_unlink(chip,cpcm->pcm_channel);
     792                spin_lock(&chip->reg_lock);
     793                if (substream->runtime->periods != CS46XX_FRAGS)
     794                        snd_cs46xx_playback_transfer(substream);
     795                { unsigned int tmp;
     796                tmp = snd_cs46xx_peek(chip, BA1_PCTL);
     797                tmp &= 0x0000ffff;
     798                snd_cs46xx_poke(chip, BA1_PCTL, chip->play_ctl | tmp);
     799                }
     800                spin_unlock(&chip->reg_lock);
     801#endif
     802                break;
     803        case SNDRV_PCM_TRIGGER_STOP:
     804        case SNDRV_PCM_TRIGGER_SUSPEND:
     805#ifdef CONFIG_SND_CS46XX_NEW_DSP
     806                /* magic mute channel */
     807                snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address +
     808                                       SCBVolumeCtrl) << 2, 0xffffffff);
     809
     810                if (!cpcm->pcm_channel->unlinked)
     811                        cs46xx_dsp_pcm_unlink(chip,cpcm->pcm_channel);
    804812#else
    805         spin_lock(&chip->reg_lock);
    806         { unsigned int tmp;
    807             tmp = snd_cs46xx_peek(chip, BA1_PCTL);
    808         tmp &= 0x0000ffff;
    809         snd_cs46xx_poke(chip, BA1_PCTL, tmp);
    810         }
    811         spin_unlock(&chip->reg_lock);
    812 #endif
    813         break;
    814     default:
    815         result = -EINVAL;
    816         break;
    817     }
    818 
    819     return result;
    820 }
    821 
    822 static int snd_cs46xx_capture_trigger(snd_pcm_substream_t * substream,
    823                                       int cmd)
    824 {
    825     cs46xx_t *chip = snd_pcm_substream_chip(substream);
    826     unsigned int tmp;
    827     int result = 0;
    828 
    829     spin_lock(&chip->reg_lock);
    830     switch (cmd) {
    831     case SNDRV_PCM_TRIGGER_START:
    832     case SNDRV_PCM_TRIGGER_RESUME:
    833         tmp = snd_cs46xx_peek(chip, BA1_CCTL);
    834         tmp &= 0xffff0000;
    835         snd_cs46xx_poke(chip, BA1_CCTL, chip->capt.ctl | tmp);
    836         break;
    837     case SNDRV_PCM_TRIGGER_STOP:
    838     case SNDRV_PCM_TRIGGER_SUSPEND:
    839         tmp = snd_cs46xx_peek(chip, BA1_CCTL);
    840         tmp &= 0xffff0000;
    841         snd_cs46xx_poke(chip, BA1_CCTL, tmp);
    842         break;
    843     default:
    844         result = -EINVAL;
    845         break;
    846     }
    847     spin_unlock(&chip->reg_lock);
    848 
    849     return result;
    850 }
    851 
    852 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    853 static int _cs46xx_adjust_sample_rate (cs46xx_t *chip, cs46xx_pcm_t *cpcm,
    854                                        int sample_rate)
    855 {
    856 
    857     /* If PCMReaderSCB and SrcTaskSCB not created yet ... */
    858     if ( cpcm->pcm_channel == NULL) {
    859         cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate,
    860                                                            cpcm, cpcm->hw_addr,cpcm->pcm_channel_id);
    861         if (cpcm->pcm_channel == NULL) {
    862             snd_printk(KERN_ERR "cs46xx: failed to create virtual PCM channel\n");
    863             return -ENOMEM;
    864         }
    865         cpcm->pcm_channel->sample_rate = sample_rate;
    866     } else
    867         /* if sample rate is changed */
    868         if ((int)cpcm->pcm_channel->sample_rate != sample_rate) {
    869             int unlinked = cpcm->pcm_channel->unlinked;
    870             cs46xx_dsp_destroy_pcm_channel (chip,cpcm->pcm_channel);
    871 
    872             if ( (cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate, cpcm,
    873                                                                      cpcm->hw_addr,
    874                                                                     cpcm->pcm_channel_id)) == NULL) {
    875                 snd_printk(KERN_ERR "cs46xx: failed to re-create virtual PCM channel\n");
    876                 return -ENOMEM;
    877             }
    878 
    879             if (!unlinked) cs46xx_dsp_pcm_link (chip,cpcm->pcm_channel);
    880             cpcm->pcm_channel->sample_rate = sample_rate;
    881         }
    882 
    883     return 0;
    884 }
    885 #endif
    886 
    887 
    888 static int snd_cs46xx_playback_hw_params(snd_pcm_substream_t * substream,
    889                                          snd_pcm_hw_params_t * hw_params)
    890 {
    891     snd_pcm_runtime_t *runtime = substream->runtime;
    892     cs46xx_pcm_t *cpcm;
    893     int err;
    894 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    895     cs46xx_t *chip = snd_pcm_substream_chip(substream);
    896     int sample_rate = params_rate(hw_params);
    897     int period_size = params_period_bytes(hw_params);
    898 #endif
    899     cpcm = runtime->private_data;
    900 
    901 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    902     snd_assert (sample_rate != 0, return -ENXIO);
    903 
    904     down (&chip->spos_mutex);
    905 
    906     if (_cs46xx_adjust_sample_rate (chip,cpcm,sample_rate)) {
    907         up (&chip->spos_mutex);
    908         return -ENXIO;
    909     }
    910 
    911     //  snd_assert (cpcm->pcm_channel != NULL);
    912     if (!cpcm->pcm_channel) {
    913         up (&chip->spos_mutex);
    914         return -ENXIO;
    915     }
    916 
    917 
    918     if (cs46xx_dsp_pcm_channel_set_period (chip,cpcm->pcm_channel,period_size)) {
    919         up (&chip->spos_mutex);
    920         return -EINVAL;
    921     }
    922 
    923     snd_printdd ("period_size (%d), periods (%d) buffer_size(%d)\n",
    924                  period_size, params_periods(hw_params),
    925                  params_buffer_bytes(hw_params));
    926 #endif
    927 
    928     if (params_periods(hw_params) == CS46XX_FRAGS) {
    929         if (runtime->dma_area != cpcm->hw_buf.area)
    930             snd_pcm_lib_free_pages(substream);
    931         runtime->dma_area = cpcm->hw_buf.area;
    932         runtime->dma_addr = cpcm->hw_buf.addr;
    933         runtime->dma_bytes = cpcm->hw_buf.bytes;
    934 
    935 
    936 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    937         if (cpcm->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) {
    938             substream->ops = &snd_cs46xx_playback_ops;
    939         } else if (cpcm->pcm_channel_id == DSP_PCM_REAR_CHANNEL) {
    940             substream->ops = &snd_cs46xx_playback_rear_ops;
    941         } else if (cpcm->pcm_channel_id == DSP_PCM_CENTER_LFE_CHANNEL) {
    942             substream->ops = &snd_cs46xx_playback_clfe_ops;
    943         } else if (cpcm->pcm_channel_id == DSP_IEC958_CHANNEL) {
    944             substream->ops = &snd_cs46xx_playback_iec958_ops;
    945         } else {
    946             //                  snd_assert(0);
    947         }
     813                spin_lock(&chip->reg_lock);
     814                { unsigned int tmp;
     815                tmp = snd_cs46xx_peek(chip, BA1_PCTL);
     816                tmp &= 0x0000ffff;
     817                snd_cs46xx_poke(chip, BA1_PCTL, tmp);
     818                }
     819                spin_unlock(&chip->reg_lock);
     820#endif
     821                break;
     822        default:
     823                result = -EINVAL;
     824                break;
     825        }
     826
     827        return result;
     828}
     829
     830static int snd_cs46xx_capture_trigger(struct snd_pcm_substream *substream,
     831                                      int cmd)
     832{
     833        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
     834        unsigned int tmp;
     835        int result = 0;
     836
     837        spin_lock(&chip->reg_lock);
     838        switch (cmd) {
     839        case SNDRV_PCM_TRIGGER_START:
     840        case SNDRV_PCM_TRIGGER_RESUME:
     841                tmp = snd_cs46xx_peek(chip, BA1_CCTL);
     842                tmp &= 0xffff0000;
     843                snd_cs46xx_poke(chip, BA1_CCTL, chip->capt.ctl | tmp);
     844                break;
     845        case SNDRV_PCM_TRIGGER_STOP:
     846        case SNDRV_PCM_TRIGGER_SUSPEND:
     847                tmp = snd_cs46xx_peek(chip, BA1_CCTL);
     848                tmp &= 0xffff0000;
     849                snd_cs46xx_poke(chip, BA1_CCTL, tmp);
     850                break;
     851        default:
     852                result = -EINVAL;
     853                break;
     854        }
     855        spin_unlock(&chip->reg_lock);
     856
     857        return result;
     858}
     859
     860#ifdef CONFIG_SND_CS46XX_NEW_DSP
     861static int _cs46xx_adjust_sample_rate (struct snd_cs46xx *chip, struct snd_cs46xx_pcm *cpcm,
     862                                       int sample_rate)
     863{
     864
     865        /* If PCMReaderSCB and SrcTaskSCB not created yet ... */
     866        if ( cpcm->pcm_channel == NULL) {
     867                cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate,
     868                                                                   cpcm, cpcm->hw_buf.addr,cpcm->pcm_channel_id);
     869                if (cpcm->pcm_channel == NULL) {
     870                        snd_printk(KERN_ERR "cs46xx: failed to create virtual PCM channel\n");
     871                        return -ENOMEM;
     872                }
     873                cpcm->pcm_channel->sample_rate = sample_rate;
     874        } else
     875        /* if sample rate is changed */
     876        if ((int)cpcm->pcm_channel->sample_rate != sample_rate) {
     877                int unlinked = cpcm->pcm_channel->unlinked;
     878                cs46xx_dsp_destroy_pcm_channel (chip,cpcm->pcm_channel);
     879
     880                if ( (cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate, cpcm,
     881                                                                         cpcm->hw_buf.addr,
     882                                                                        cpcm->pcm_channel_id)) == NULL) {
     883                        snd_printk(KERN_ERR "cs46xx: failed to re-create virtual PCM channel\n");
     884                        return -ENOMEM;
     885                }
     886
     887                if (!unlinked) cs46xx_dsp_pcm_link (chip,cpcm->pcm_channel);
     888                cpcm->pcm_channel->sample_rate = sample_rate;
     889        }
     890
     891        return 0;
     892}
     893#endif
     894
     895
     896static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream,
     897                                         struct snd_pcm_hw_params *hw_params)
     898{
     899        struct snd_pcm_runtime *runtime = substream->runtime;
     900        struct snd_cs46xx_pcm *cpcm;
     901        int err;
     902#ifdef CONFIG_SND_CS46XX_NEW_DSP
     903        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
     904        int sample_rate = params_rate(hw_params);
     905        int period_size = params_period_bytes(hw_params);
     906#endif
     907        cpcm = runtime->private_data;
     908
     909#ifdef CONFIG_SND_CS46XX_NEW_DSP
     910        snd_assert (sample_rate != 0, return -ENXIO);
     911
     912        down (&chip->spos_mutex);
     913
     914        if (_cs46xx_adjust_sample_rate (chip,cpcm,sample_rate)) {
     915                up (&chip->spos_mutex);
     916                return -ENXIO;
     917        }
     918
     919        snd_assert (cpcm->pcm_channel != NULL);
     920        if (!cpcm->pcm_channel) {
     921                up (&chip->spos_mutex);
     922                return -ENXIO;
     923        }
     924
     925
     926        if (cs46xx_dsp_pcm_channel_set_period (chip,cpcm->pcm_channel,period_size)) {
     927                up (&chip->spos_mutex);
     928                return -EINVAL;
     929        }
     930
     931        snd_printdd ("period_size (%d), periods (%d) buffer_size(%d)\n",
     932                     period_size, params_periods(hw_params),
     933                     params_buffer_bytes(hw_params));
     934#endif
     935
     936        if (params_periods(hw_params) == CS46XX_FRAGS) {
     937                if (runtime->dma_area != cpcm->hw_buf.area)
     938                        snd_pcm_lib_free_pages(substream);
     939                runtime->dma_area = cpcm->hw_buf.area;
     940                runtime->dma_addr = cpcm->hw_buf.addr;
     941                runtime->dma_bytes = cpcm->hw_buf.bytes;
     942
     943
     944#ifdef CONFIG_SND_CS46XX_NEW_DSP
     945                if (cpcm->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) {
     946                        substream->ops = &snd_cs46xx_playback_ops;
     947                } else if (cpcm->pcm_channel_id == DSP_PCM_REAR_CHANNEL) {
     948                        substream->ops = &snd_cs46xx_playback_rear_ops;
     949                } else if (cpcm->pcm_channel_id == DSP_PCM_CENTER_LFE_CHANNEL) {
     950                        substream->ops = &snd_cs46xx_playback_clfe_ops;
     951                } else if (cpcm->pcm_channel_id == DSP_IEC958_CHANNEL) {
     952                        substream->ops = &snd_cs46xx_playback_iec958_ops;
     953                } else {
     954                        snd_assert(0);
     955                }
    948956#else
    949         substream->ops = &snd_cs46xx_playback_ops;
    950 #endif
    951 
    952     } else {
    953         if (runtime->dma_area == cpcm->hw_buf.area) {
    954             runtime->dma_area = NULL;
    955             runtime->dma_addr = 0;
    956             runtime->dma_bytes = 0;
    957         }
    958         if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) {
    959 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    960             up (&chip->spos_mutex);
    961 #endif
    962             return err;
    963         }
    964 
    965 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    966         if (cpcm->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) {
    967             substream->ops = &snd_cs46xx_playback_indirect_ops;
    968         } else if (cpcm->pcm_channel_id == DSP_PCM_REAR_CHANNEL) {
    969             substream->ops = &snd_cs46xx_playback_indirect_rear_ops;
    970         } else if (cpcm->pcm_channel_id == DSP_PCM_CENTER_LFE_CHANNEL) {
    971             substream->ops = &snd_cs46xx_playback_indirect_clfe_ops;
    972         } else if (cpcm->pcm_channel_id == DSP_IEC958_CHANNEL) {
    973             substream->ops = &snd_cs46xx_playback_indirect_iec958_ops;
    974         } else {
    975             //                  snd_assert(0);
    976         }
     957                substream->ops = &snd_cs46xx_playback_ops;
     958#endif
     959
     960        } else {
     961                if (runtime->dma_area == cpcm->hw_buf.area) {
     962                        runtime->dma_area = NULL;
     963                        runtime->dma_addr = 0;
     964                        runtime->dma_bytes = 0;
     965                }
     966                if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) {
     967#ifdef CONFIG_SND_CS46XX_NEW_DSP
     968                        up (&chip->spos_mutex);
     969#endif
     970                        return err;
     971                }
     972
     973#ifdef CONFIG_SND_CS46XX_NEW_DSP
     974                if (cpcm->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) {
     975                        substream->ops = &snd_cs46xx_playback_indirect_ops;
     976                } else if (cpcm->pcm_channel_id == DSP_PCM_REAR_CHANNEL) {
     977                        substream->ops = &snd_cs46xx_playback_indirect_rear_ops;
     978                } else if (cpcm->pcm_channel_id == DSP_PCM_CENTER_LFE_CHANNEL) {
     979                        substream->ops = &snd_cs46xx_playback_indirect_clfe_ops;
     980                } else if (cpcm->pcm_channel_id == DSP_IEC958_CHANNEL) {
     981                        substream->ops = &snd_cs46xx_playback_indirect_iec958_ops;
     982                } else {
     983                        snd_assert(0);
     984                }
    977985#else
    978         substream->ops = &snd_cs46xx_playback_indirect_ops;
    979 #endif
    980 
    981     }
    982 
    983 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    984     up (&chip->spos_mutex);
    985 #endif
    986 
    987     return 0;
    988 }
    989 
    990 static int snd_cs46xx_playback_hw_free(snd_pcm_substream_t * substream)
    991 {
    992     /*cs46xx_t *chip = snd_pcm_substream_chip(substream);*/
    993     snd_pcm_runtime_t *runtime = substream->runtime;
    994     cs46xx_pcm_t *cpcm;
    995 
    996     cpcm = runtime->private_data;
    997 
    998     /* if play_back open fails, then this function
    999      is called and cpcm can actually be NULL here */
    1000     if (!cpcm) return -ENXIO;
    1001 
    1002     if (runtime->dma_area != cpcm->hw_buf.area)
    1003         snd_pcm_lib_free_pages(substream);
    1004 
    1005     runtime->dma_area = NULL;
    1006     runtime->dma_addr = 0;
    1007     runtime->dma_bytes = 0;
    1008 
    1009     return 0;
    1010 }
    1011 
    1012 static int snd_cs46xx_playback_prepare(snd_pcm_substream_t * substream)
    1013 {
    1014     unsigned int tmp;
    1015     unsigned int pfie;
    1016     cs46xx_t *chip = snd_pcm_substream_chip(substream);
    1017     snd_pcm_runtime_t *runtime = substream->runtime;
    1018     cs46xx_pcm_t *cpcm;
    1019 
    1020     cpcm = runtime->private_data;
     986                substream->ops = &snd_cs46xx_playback_indirect_ops;
     987#endif
     988
     989        }
     990
     991#ifdef CONFIG_SND_CS46XX_NEW_DSP
     992        up (&chip->spos_mutex);
     993#endif
     994
     995        return 0;
     996}
     997
     998static int snd_cs46xx_playback_hw_free(struct snd_pcm_substream *substream)
     999{
     1000        /*struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);*/
     1001        struct snd_pcm_runtime *runtime = substream->runtime;
     1002        struct snd_cs46xx_pcm *cpcm;
     1003
     1004        cpcm = runtime->private_data;
     1005
     1006        /* if play_back open fails, then this function
     1007           is called and cpcm can actually be NULL here */
     1008        if (!cpcm) return -ENXIO;
     1009
     1010        if (runtime->dma_area != cpcm->hw_buf.area)
     1011                snd_pcm_lib_free_pages(substream);
     1012   
     1013        runtime->dma_area = NULL;
     1014        runtime->dma_addr = 0;
     1015        runtime->dma_bytes = 0;
     1016
     1017        return 0;
     1018}
     1019
     1020static int snd_cs46xx_playback_prepare(struct snd_pcm_substream *substream)
     1021{
     1022        unsigned int tmp;
     1023        unsigned int pfie;
     1024        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
     1025        struct snd_pcm_runtime *runtime = substream->runtime;
     1026        struct snd_cs46xx_pcm *cpcm;
     1027
     1028        cpcm = runtime->private_data;
    10211029
    10221030#ifdef CONFIG_SND_CS46XX_NEW_DSP
    10231031    snd_assert (cpcm->pcm_channel != NULL, return -ENXIO);
    10241032
    1025     pfie = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 1) << 2 );
    1026     pfie &= ~0x0000f03f;
     1033        pfie = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 1) << 2 );
     1034        pfie &= ~0x0000f03f;
    10271035#else
    1028     /* old dsp */
    1029     pfie = snd_cs46xx_peek(chip, BA1_PFIE);
    1030     pfie &= ~0x0000f03f;
    1031 #endif
    1032 
    1033     cpcm->shift = 2;
    1034     /* if to convert from stereo to mono */
    1035     if (runtime->channels == 1) {
    1036         cpcm->shift--;
    1037         pfie |= 0x00002000;
    1038     }
    1039     /* if to convert from 8 bit to 16 bit */
    1040     if (snd_pcm_format_width(runtime->format) == 8) {
    1041         cpcm->shift--;
    1042         pfie |= 0x00001000;
    1043     }
    1044     /* if to convert to unsigned */
    1045     if (snd_pcm_format_unsigned(runtime->format))
    1046         pfie |= 0x00008000;
    1047 
    1048     /* Never convert byte order when sample stream is 8 bit */
    1049     if (snd_pcm_format_width(runtime->format) != 8) {
    1050         /* convert from big endian to little endian */
    1051         if (snd_pcm_format_big_endian(runtime->format))
    1052             pfie |= 0x00004000;
    1053     }
    1054 
    1055     memset(&cpcm->pcm_rec, 0, sizeof(cpcm->pcm_rec));
    1056     cpcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
    1057     cpcm->pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << cpcm->shift;
    1058 
    1059 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    1060 
    1061     tmp = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address) << 2);
    1062     tmp &= ~0x000003ff;
    1063     tmp |= (4 << cpcm->shift) - 1;
    1064     /* playback transaction count register */
    1065     snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address) << 2, tmp);
    1066 
    1067     /* playback format && interrupt enable */
    1068     snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 1) << 2, pfie | cpcm->pcm_channel->pcm_slot);
     1036        /* old dsp */
     1037        pfie = snd_cs46xx_peek(chip, BA1_PFIE);
     1038        pfie &= ~0x0000f03f;
     1039#endif
     1040
     1041        cpcm->shift = 2;
     1042        /* if to convert from stereo to mono */
     1043        if (runtime->channels == 1) {
     1044                cpcm->shift--;
     1045                pfie |= 0x00002000;
     1046        }
     1047        /* if to convert from 8 bit to 16 bit */
     1048        if (snd_pcm_format_width(runtime->format) == 8) {
     1049                cpcm->shift--;
     1050                pfie |= 0x00001000;
     1051        }
     1052        /* if to convert to unsigned */
     1053        if (snd_pcm_format_unsigned(runtime->format))
     1054                pfie |= 0x00008000;
     1055
     1056        /* Never convert byte order when sample stream is 8 bit */
     1057        if (snd_pcm_format_width(runtime->format) != 8) {
     1058                /* convert from big endian to little endian */
     1059                if (snd_pcm_format_big_endian(runtime->format))
     1060                        pfie |= 0x00004000;
     1061        }
     1062       
     1063        memset(&cpcm->pcm_rec, 0, sizeof(cpcm->pcm_rec));
     1064        cpcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
     1065        cpcm->pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << cpcm->shift;
     1066
     1067#ifdef CONFIG_SND_CS46XX_NEW_DSP
     1068
     1069        tmp = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address) << 2);
     1070        tmp &= ~0x000003ff;
     1071        tmp |= (4 << cpcm->shift) - 1;
     1072        /* playback transaction count register */
     1073        snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address) << 2, tmp);
     1074
     1075        /* playback format && interrupt enable */
     1076        snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 1) << 2, pfie | cpcm->pcm_channel->pcm_slot);
    10691077#else
    1070     snd_cs46xx_poke(chip, BA1_PBA, cpcm->hw_buf.addr);
    1071     tmp = snd_cs46xx_peek(chip, BA1_PDTC);
    1072     tmp &= ~0x000003ff;
    1073     tmp |= (4 << cpcm->shift) - 1;
    1074     snd_cs46xx_poke(chip, BA1_PDTC, tmp);
    1075     snd_cs46xx_poke(chip, BA1_PFIE, pfie);
    1076     snd_cs46xx_set_play_sample_rate(chip, runtime->rate);
    1077 #endif
    1078 
    1079     return 0;
    1080 }
    1081 
    1082 static int snd_cs46xx_capture_hw_params(snd_pcm_substream_t * substream,
    1083                                         snd_pcm_hw_params_t * hw_params)
    1084 {
    1085     cs46xx_t *chip = snd_pcm_substream_chip(substream);
    1086     snd_pcm_runtime_t *runtime = substream->runtime;
    1087     int err;
    1088 
    1089 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    1090     cs46xx_dsp_pcm_ostream_set_period (chip, params_period_bytes(hw_params));
    1091 #endif
    1092     if (runtime->periods == CS46XX_FRAGS) {
    1093         if (runtime->dma_area != chip->capt.hw_buf.area)
    1094             snd_pcm_lib_free_pages(substream);
    1095         runtime->dma_area = chip->capt.hw_buf.area;
    1096         runtime->dma_addr = chip->capt.hw_buf.addr;
    1097         runtime->dma_bytes = chip->capt.hw_buf.bytes;
    1098         substream->ops = &snd_cs46xx_capture_ops;
    1099     } else {
    1100         if (runtime->dma_area == chip->capt.hw_buf.area) {
    1101             runtime->dma_area = NULL;
    1102             runtime->dma_addr = 0;
    1103             runtime->dma_bytes = 0;
    1104         }
    1105         if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
    1106             return err;
    1107         substream->ops = &snd_cs46xx_capture_indirect_ops;
    1108     }
    1109 
    1110     return 0;
    1111 }
    1112 
    1113 static int snd_cs46xx_capture_hw_free(snd_pcm_substream_t * substream)
    1114 {
    1115     cs46xx_t *chip = snd_pcm_substream_chip(substream);
    1116     snd_pcm_runtime_t *runtime = substream->runtime;
    1117 
    1118     if (runtime->dma_area != chip->capt.hw_buf.area)
    1119         snd_pcm_lib_free_pages(substream);
    1120     runtime->dma_area = NULL;
    1121     runtime->dma_addr = 0;
    1122     runtime->dma_bytes = 0;
    1123 
    1124     return 0;
    1125 }
    1126 
    1127 static int snd_cs46xx_capture_prepare(snd_pcm_substream_t * substream)
    1128 {
    1129     cs46xx_t *chip = snd_pcm_substream_chip(substream);
    1130     snd_pcm_runtime_t *runtime = substream->runtime;
    1131 
    1132     snd_cs46xx_poke(chip, BA1_CBA, chip->capt.hw_buf.addr);
    1133     chip->capt.shift = 2;
    1134     memset(&chip->capt.pcm_rec, 0, sizeof(chip->capt.pcm_rec));
    1135     chip->capt.pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
    1136     chip->capt.pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << 2;
    1137     snd_cs46xx_set_capture_sample_rate(chip, runtime->rate);
    1138 
    1139     return 0;
     1078        snd_cs46xx_poke(chip, BA1_PBA, cpcm->hw_buf.addr);
     1079        tmp = snd_cs46xx_peek(chip, BA1_PDTC);
     1080        tmp &= ~0x000003ff;
     1081        tmp |= (4 << cpcm->shift) - 1;
     1082        snd_cs46xx_poke(chip, BA1_PDTC, tmp);
     1083        snd_cs46xx_poke(chip, BA1_PFIE, pfie);
     1084        snd_cs46xx_set_play_sample_rate(chip, runtime->rate);
     1085#endif
     1086
     1087        return 0;
     1088}
     1089
     1090static int snd_cs46xx_capture_hw_params(struct snd_pcm_substream *substream,
     1091                                        struct snd_pcm_hw_params *hw_params)
     1092{
     1093        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
     1094        struct snd_pcm_runtime *runtime = substream->runtime;
     1095        int err;
     1096
     1097#ifdef CONFIG_SND_CS46XX_NEW_DSP
     1098        cs46xx_dsp_pcm_ostream_set_period (chip, params_period_bytes(hw_params));
     1099#endif
     1100        if (runtime->periods == CS46XX_FRAGS) {
     1101                if (runtime->dma_area != chip->capt.hw_buf.area)
     1102                        snd_pcm_lib_free_pages(substream);
     1103                runtime->dma_area = chip->capt.hw_buf.area;
     1104                runtime->dma_addr = chip->capt.hw_buf.addr;
     1105                runtime->dma_bytes = chip->capt.hw_buf.bytes;
     1106                substream->ops = &snd_cs46xx_capture_ops;
     1107        } else {
     1108                if (runtime->dma_area == chip->capt.hw_buf.area) {
     1109                        runtime->dma_area = NULL;
     1110                        runtime->dma_addr = 0;
     1111                        runtime->dma_bytes = 0;
     1112                }
     1113                if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
     1114                        return err;
     1115                substream->ops = &snd_cs46xx_capture_indirect_ops;
     1116        }
     1117
     1118        return 0;
     1119}
     1120
     1121static int snd_cs46xx_capture_hw_free(struct snd_pcm_substream *substream)
     1122{
     1123        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
     1124        struct snd_pcm_runtime *runtime = substream->runtime;
     1125
     1126        if (runtime->dma_area != chip->capt.hw_buf.area)
     1127                snd_pcm_lib_free_pages(substream);
     1128        runtime->dma_area = NULL;
     1129        runtime->dma_addr = 0;
     1130        runtime->dma_bytes = 0;
     1131
     1132        return 0;
     1133}
     1134
     1135static int snd_cs46xx_capture_prepare(struct snd_pcm_substream *substream)
     1136{
     1137        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
     1138        struct snd_pcm_runtime *runtime = substream->runtime;
     1139
     1140        snd_cs46xx_poke(chip, BA1_CBA, chip->capt.hw_buf.addr);
     1141        chip->capt.shift = 2;
     1142        memset(&chip->capt.pcm_rec, 0, sizeof(chip->capt.pcm_rec));
     1143        chip->capt.pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
     1144        chip->capt.pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << 2;
     1145        snd_cs46xx_set_capture_sample_rate(chip, runtime->rate);
     1146
     1147        return 0;
    11401148}
    11411149
    11421150static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
    11431151{
    1144     cs46xx_t *chip = dev_id;
    1145     u32 status1;
    1146 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    1147     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    1148     u32 status2;
    1149     int i;
    1150     cs46xx_pcm_t *cpcm = NULL;
    1151 #endif
    1152 #ifdef TARGET_OS2
    1153     int fOurIrq = FALSE;
    1154 #endif
    1155 
    1156     /*
    1157      *  Read the Interrupt Status Register to clear the interrupt
    1158      */
    1159     status1 = snd_cs46xx_peekBA0(chip, BA0_HISR);
    1160     if ((status1 & 0x7fffffff) == 0) {
    1161         snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_CHGM | HICR_IEV);
    1162         return IRQ_NONE;
    1163     }
    1164 
    1165 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    1166     status2 = snd_cs46xx_peekBA0(chip, BA0_HSR0);
    1167 
    1168     for (i = 0; i < DSP_MAX_PCM_CHANNELS; ++i) {
    1169         if (i <= 15) {
    1170             if ( status1 & (1 << i) ) {
    1171                 if (i == CS46XX_DSP_CAPTURE_CHANNEL) {
    1172                     if (chip->capt.substream)
    1173                         snd_pcm_period_elapsed(chip->capt.substream);
    1174                 } else {
    1175                     if (ins->pcm_channels[i].active &&
    1176                         ins->pcm_channels[i].private_data &&
    1177                         !ins->pcm_channels[i].unlinked) {
    1178                         cpcm = ins->pcm_channels[i].private_data;
    1179                         snd_pcm_period_elapsed(cpcm->substream);
    1180                     }
    1181                 }
    1182             }
    1183         } else {
    1184             if ( status2 & (1 << (i - 16))) {
    1185                 if (ins->pcm_channels[i].active &&
    1186                     ins->pcm_channels[i].private_data &&
    1187                     !ins->pcm_channels[i].unlinked) {
    1188                     cpcm = ins->pcm_channels[i].private_data;
    1189                     snd_pcm_period_elapsed(cpcm->substream);
    1190                 }
    1191             }
    1192         }
    1193     }
     1152        struct snd_cs46xx *chip = dev_id;
     1153        u32 status1;
     1154#ifdef CONFIG_SND_CS46XX_NEW_DSP
     1155        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     1156        u32 status2;
     1157        int i;
     1158        struct snd_cs46xx_pcm *cpcm = NULL;
     1159#endif
     1160
     1161        /*
     1162         *  Read the Interrupt Status Register to clear the interrupt
     1163         */
     1164        status1 = snd_cs46xx_peekBA0(chip, BA0_HISR);
     1165        if ((status1 & 0x7fffffff) == 0) {
     1166                snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_CHGM | HICR_IEV);
     1167                return IRQ_NONE;
     1168        }
     1169
     1170#ifdef CONFIG_SND_CS46XX_NEW_DSP
     1171        status2 = snd_cs46xx_peekBA0(chip, BA0_HSR0);
     1172
     1173        for (i = 0; i < DSP_MAX_PCM_CHANNELS; ++i) {
     1174                if (i <= 15) {
     1175                        if ( status1 & (1 << i) ) {
     1176                                if (i == CS46XX_DSP_CAPTURE_CHANNEL) {
     1177                                        if (chip->capt.substream)
     1178                                                snd_pcm_period_elapsed(chip->capt.substream);
     1179                                } else {
     1180                                        if (ins->pcm_channels[i].active &&
     1181                                            ins->pcm_channels[i].private_data &&
     1182                                            !ins->pcm_channels[i].unlinked) {
     1183                                                cpcm = ins->pcm_channels[i].private_data;
     1184                                                snd_pcm_period_elapsed(cpcm->substream);
     1185                                        }
     1186                                }
     1187                        }
     1188                } else {
     1189                        if ( status2 & (1 << (i - 16))) {
     1190                                if (ins->pcm_channels[i].active &&
     1191                                    ins->pcm_channels[i].private_data &&
     1192                                    !ins->pcm_channels[i].unlinked) {
     1193                                        cpcm = ins->pcm_channels[i].private_data;
     1194                                        snd_pcm_period_elapsed(cpcm->substream);
     1195                                }
     1196                        }
     1197                }
     1198        }
    11941199
    11951200#else
    1196 #ifdef TARGET_OS2
    1197     if (status1 & (HISR_VC0|HISR_VC1))
    1198     {
    1199         fOurIrq = TRUE;
    1200     }
    1201 #endif
    1202 
    1203     /* old dsp */
    1204     if ((status1 & HISR_VC0) && chip->playback_pcm) {
    1205         if (chip->playback_pcm->substream)
    1206             snd_pcm_period_elapsed(chip->playback_pcm->substream);
    1207     }
    1208     if ((status1 & HISR_VC1) && chip->pcm) {
    1209         if (chip->capt.substream)
    1210             snd_pcm_period_elapsed(chip->capt.substream);
    1211     }
    1212 #endif
    1213 
    1214     if ((status1 & HISR_MIDI) && chip->rmidi) {
    1215         unsigned char c;
    1216 
    1217 #ifdef TARGET_OS2
    1218         fOurIrq = TRUE;
    1219 #endif
    1220         spin_lock(&chip->reg_lock);
    1221         while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_RBE) == 0) {
    1222             c = snd_cs46xx_peekBA0(chip, BA0_MIDRP);
    1223             if ((chip->midcr & MIDCR_RIE) == 0)
    1224                 continue;
    1225             spin_unlock(&chip->reg_lock);
    1226             snd_rawmidi_receive(chip->midi_input, &c, 1);
    1227             spin_lock(&chip->reg_lock);
    1228         }
    1229         while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) {
    1230             if ((chip->midcr & MIDCR_TIE) == 0)
    1231                 break;
    1232             if (snd_rawmidi_transmit(chip->midi_output, &c, 1) != 1) {
    1233                 chip->midcr &= ~MIDCR_TIE;
    1234                 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
    1235                 break;
    1236             }
    1237             snd_cs46xx_pokeBA0(chip, BA0_MIDWP, c);
    1238         }
    1239         spin_unlock(&chip->reg_lock);
    1240     }
    1241     /*
    1242      *  EOI to the PCI part....reenables interrupts
    1243      */
    1244     snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_CHGM | HICR_IEV);
    1245 #ifdef TARGET_OS2
    1246     if (fOurIrq) {
    1247         eoi_irq(irq);
    1248     }
    1249 #endif //TARGET_OS2
    1250     return IRQ_HANDLED;
    1251 
    1252 }
    1253 
    1254 static snd_pcm_hardware_t snd_cs46xx_playback =
    1255 {
    1256     /*  info:             */    (SNDRV_PCM_INFO_MMAP |
    1257                                  SNDRV_PCM_INFO_INTERLEAVED |
    1258                                  SNDRV_PCM_INFO_BLOCK_TRANSFER /*|*/
    1259                                  /*SNDRV_PCM_INFO_RESUME*/),
    1260                                  /*     formats:          */    (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 |
    1261                                                                  SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
    1262                                                                  SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE),
    1263                                                                  /*     rates:            */    SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
    1264                                                                  /*     rate_min:         */    5500,
    1265                                                                  /*     rate_max:         */    48000,
    1266                                                                  /*     channels_min:     */    1,
    1267                                                                  /*     channels_max:     */    2,
    1268                                                                  /*     buffer_bytes_max:  */   (256 * 1024),
    1269                                                                  /*     period_bytes_min:  */   CS46XX_MIN_PERIOD_SIZE,
    1270                                                                  /*     period_bytes_max:  */   CS46XX_MAX_PERIOD_SIZE,
    1271                                                                  /*     periods_min:      */    CS46XX_FRAGS,
    1272                                                                  /*     periods_max:      */    1024,
    1273                                                                  /*     fifo_size:        */    0,
     1201        /* old dsp */
     1202        if ((status1 & HISR_VC0) && chip->playback_pcm) {
     1203                if (chip->playback_pcm->substream)
     1204                        snd_pcm_period_elapsed(chip->playback_pcm->substream);
     1205        }
     1206        if ((status1 & HISR_VC1) && chip->pcm) {
     1207                if (chip->capt.substream)
     1208                        snd_pcm_period_elapsed(chip->capt.substream);
     1209        }
     1210#endif
     1211
     1212        if ((status1 & HISR_MIDI) && chip->rmidi) {
     1213                unsigned char c;
     1214               
     1215                spin_lock(&chip->reg_lock);
     1216                while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_RBE) == 0) {
     1217                        c = snd_cs46xx_peekBA0(chip, BA0_MIDRP);
     1218                        if ((chip->midcr & MIDCR_RIE) == 0)
     1219                                continue;
     1220                        snd_rawmidi_receive(chip->midi_input, &c, 1);
     1221                }
     1222                while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) {
     1223                        if ((chip->midcr & MIDCR_TIE) == 0)
     1224                                break;
     1225                        if (snd_rawmidi_transmit(chip->midi_output, &c, 1) != 1) {
     1226                                chip->midcr &= ~MIDCR_TIE;
     1227                                snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
     1228                                break;
     1229                        }
     1230                        snd_cs46xx_pokeBA0(chip, BA0_MIDWP, c);
     1231                }
     1232                spin_unlock(&chip->reg_lock);
     1233        }
     1234        /*
     1235         *  EOI to the PCI part....reenables interrupts
     1236         */
     1237        snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_CHGM | HICR_IEV);
     1238
     1239        return IRQ_HANDLED;
     1240}
     1241
     1242static struct snd_pcm_hardware snd_cs46xx_playback =
     1243{
     1244        .info =                 (SNDRV_PCM_INFO_MMAP |
     1245                                 SNDRV_PCM_INFO_INTERLEAVED |
     1246                                 SNDRV_PCM_INFO_BLOCK_TRANSFER /*|*/
     1247                                 /*SNDRV_PCM_INFO_RESUME*/),
     1248        .formats =              (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 |
     1249                                 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
     1250                                 SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE),
     1251        .rates =                SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
     1252        .rate_min =             5500,
     1253        .rate_max =             48000,
     1254        .channels_min =         1,
     1255        .channels_max =         2,
     1256        .buffer_bytes_max =     (256 * 1024),
     1257        .period_bytes_min =     CS46XX_MIN_PERIOD_SIZE,
     1258        .period_bytes_max =     CS46XX_MAX_PERIOD_SIZE,
     1259        .periods_min =          CS46XX_FRAGS,
     1260        .periods_max =          1024,
     1261        .fifo_size =            0,
    12741262};
    12751263
    1276 static snd_pcm_hardware_t snd_cs46xx_capture =
    1277 {
    1278     /*  info:             */    (SNDRV_PCM_INFO_MMAP |
    1279                                 SNDRV_PCM_INFO_INTERLEAVED |
    1280                                 SNDRV_PCM_INFO_BLOCK_TRANSFER /*|*/
    1281                                 /*SNDRV_PCM_INFO_RESUME*/),
    1282                                  /*     formats:          */    SNDRV_PCM_FMTBIT_S16_LE,
    1283                                  /*     rates:            */    SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
    1284                                  /*     rate_min:         */    5500,
    1285                                  /*     rate_max:         */    48000,
    1286                                  /*     channels_min:     */    2,
    1287                                  /*     channels_max:     */    2,
    1288                                  /*     buffer_bytes_max:  */   (256 * 1024),
    1289                                  /*     period_bytes_min:  */   CS46XX_MIN_PERIOD_SIZE,
    1290                                  /*     period_bytes_max:  */   CS46XX_MAX_PERIOD_SIZE,
    1291                                  /*     periods_min:      */    CS46XX_FRAGS,
    1292                                  /*     periods_max:      */    1024,
    1293                                  /*     fifo_size:        */    0,
     1264static struct snd_pcm_hardware snd_cs46xx_capture =
     1265{
     1266        .info =                 (SNDRV_PCM_INFO_MMAP |
     1267                                SNDRV_PCM_INFO_INTERLEAVED |
     1268                                SNDRV_PCM_INFO_BLOCK_TRANSFER /*|*/
     1269                                /*SNDRV_PCM_INFO_RESUME*/),
     1270        .formats =              SNDRV_PCM_FMTBIT_S16_LE,
     1271        .rates =                SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
     1272        .rate_min =             5500,
     1273        .rate_max =             48000,
     1274        .channels_min =         2,
     1275        .channels_max =         2,
     1276        .buffer_bytes_max =     (256 * 1024),
     1277        .period_bytes_min =     CS46XX_MIN_PERIOD_SIZE,
     1278        .period_bytes_max =     CS46XX_MAX_PERIOD_SIZE,
     1279        .periods_min =          CS46XX_FRAGS,
     1280        .periods_max =          1024,
     1281        .fifo_size =            0,
    12941282};
    12951283
     
    12981286static unsigned int period_sizes[] = { 32, 64, 128, 256, 512, 1024, 2048 };
    12991287
    1300 #define PERIOD_SIZES sizeof(period_sizes) / sizeof(period_sizes[0])
    1301 
    1302 static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = {
    1303     /*.count = */PERIOD_SIZES,
    1304     /*.list =  */period_sizes,
    1305     /*.mask =  */0
     1288static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = {
     1289        .count = ARRAY_SIZE(period_sizes),
     1290        .list = period_sizes,
     1291        .mask = 0
    13061292};
    13071293
    13081294#endif
    13091295
    1310 static void snd_cs46xx_pcm_free_substream(snd_pcm_runtime_t *runtime)
    1311 {
    1312     cs46xx_pcm_t * cpcm = runtime->private_data;
    1313     kfree(cpcm);
    1314 }
    1315 
    1316 static int _cs46xx_playback_open_channel (snd_pcm_substream_t * substream,int pcm_channel_id)
    1317 {
    1318     cs46xx_t *chip = snd_pcm_substream_chip(substream);
    1319     cs46xx_pcm_t * cpcm;
    1320     snd_pcm_runtime_t *runtime = substream->runtime;
    1321 
    1322     cpcm = kcalloc(1, sizeof(*cpcm), GFP_KERNEL);
    1323     if (cpcm == NULL)
    1324         return -ENOMEM;
    1325     if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
    1326                             PAGE_SIZE, &cpcm->hw_buf) < 0) {
    1327         kfree(cpcm);
    1328         return -ENOMEM;
    1329     }
    1330 
    1331     runtime->hw = snd_cs46xx_playback;
    1332     runtime->private_data = cpcm;
    1333     runtime->private_free = snd_cs46xx_pcm_free_substream;
    1334 
    1335     cpcm->substream = substream;
    1336 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    1337     down (&chip->spos_mutex);
    1338     cpcm->pcm_channel = NULL;
    1339     cpcm->pcm_channel_id = pcm_channel_id;
    1340 
    1341 
    1342     snd_pcm_hw_constraint_list(runtime, 0,
    1343                                SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
    1344                                &hw_constraints_period_sizes);
    1345 
    1346     up (&chip->spos_mutex);
     1296static void snd_cs46xx_pcm_free_substream(struct snd_pcm_runtime *runtime)
     1297{
     1298        kfree(runtime->private_data);
     1299}
     1300
     1301static int _cs46xx_playback_open_channel (struct snd_pcm_substream *substream,int pcm_channel_id)
     1302{
     1303        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
     1304        struct snd_cs46xx_pcm * cpcm;
     1305        struct snd_pcm_runtime *runtime = substream->runtime;
     1306
     1307        cpcm = (struct snd_cs46xx_pcm * )kzalloc(sizeof(*cpcm), GFP_KERNEL);
     1308        if (cpcm == NULL)
     1309                return -ENOMEM;
     1310        if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
     1311                                PAGE_SIZE, &cpcm->hw_buf) < 0) {
     1312                kfree(cpcm);
     1313                return -ENOMEM;
     1314        }
     1315
     1316        runtime->hw = snd_cs46xx_playback;
     1317        runtime->private_data = cpcm;
     1318        runtime->private_free = snd_cs46xx_pcm_free_substream;
     1319
     1320        cpcm->substream = substream;
     1321#ifdef CONFIG_SND_CS46XX_NEW_DSP
     1322        down (&chip->spos_mutex);
     1323        cpcm->pcm_channel = NULL;
     1324        cpcm->pcm_channel_id = pcm_channel_id;
     1325
     1326
     1327        snd_pcm_hw_constraint_list(runtime, 0,
     1328                                   SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
     1329                                   &hw_constraints_period_sizes);
     1330
     1331        up (&chip->spos_mutex);
    13471332#else
    1348     chip->playback_pcm = cpcm; /* HACK */
    1349 #endif
    1350 
    1351     if (chip->accept_valid)
    1352         substream->runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID;
    1353     chip->active_ctrl(chip, 1);
    1354 
    1355     return 0;
    1356 }
    1357 
    1358 static int snd_cs46xx_playback_open(snd_pcm_substream_t * substream)
    1359 {
    1360     snd_printdd("open front channel\n");
    1361     return _cs46xx_playback_open_channel(substream,DSP_PCM_MAIN_CHANNEL);
    1362 }
    1363 
    1364 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    1365 static int snd_cs46xx_playback_open_rear(snd_pcm_substream_t * substream)
    1366 {
    1367     snd_printdd("open rear channel\n");
    1368 
    1369     return _cs46xx_playback_open_channel(substream,DSP_PCM_REAR_CHANNEL);
    1370 }
    1371 
    1372 static int snd_cs46xx_playback_open_clfe(snd_pcm_substream_t * substream)
    1373 {
    1374     snd_printdd("open center - LFE channel\n");
    1375 
    1376     return _cs46xx_playback_open_channel(substream,DSP_PCM_CENTER_LFE_CHANNEL);
    1377 }
    1378 
    1379 static int snd_cs46xx_playback_open_iec958(snd_pcm_substream_t * substream)
    1380 {
    1381     cs46xx_t *chip = snd_pcm_substream_chip(substream);
    1382 
    1383     snd_printdd("open raw iec958 channel\n");
    1384 
    1385     down (&chip->spos_mutex);
    1386     cs46xx_iec958_pre_open (chip);
    1387     up (&chip->spos_mutex);
    1388 
    1389     return _cs46xx_playback_open_channel(substream,DSP_IEC958_CHANNEL);
    1390 }
    1391 
    1392 static int snd_cs46xx_playback_close(snd_pcm_substream_t * substream);
    1393 
    1394 static int snd_cs46xx_playback_close_iec958(snd_pcm_substream_t * substream)
    1395 {
    1396     int err;
    1397     cs46xx_t *chip = snd_pcm_substream_chip(substream);
    1398 
    1399     snd_printdd("close raw iec958 channel\n");
    1400 
    1401     err = snd_cs46xx_playback_close(substream);
    1402 
    1403     down (&chip->spos_mutex);
    1404     cs46xx_iec958_post_close (chip);
    1405     up (&chip->spos_mutex);
    1406 
    1407     return err;
    1408 }
    1409 #endif
    1410 
    1411 static int snd_cs46xx_capture_open(snd_pcm_substream_t * substream)
    1412 {
    1413     cs46xx_t *chip = snd_pcm_substream_chip(substream);
    1414 
    1415     if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
    1416                             PAGE_SIZE, &chip->capt.hw_buf) < 0)
    1417         return -ENOMEM;
    1418     chip->capt.substream = substream;
    1419     substream->runtime->hw = snd_cs46xx_capture;
    1420 
    1421     if (chip->accept_valid)
    1422         substream->runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID;
    1423 
    1424     chip->active_ctrl(chip, 1);
    1425 
    1426 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    1427     snd_pcm_hw_constraint_list(substream->runtime, 0,
    1428                                SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
    1429                                &hw_constraints_period_sizes);
    1430 #endif
    1431     return 0;
    1432 }
    1433 
    1434 static int snd_cs46xx_playback_close(snd_pcm_substream_t * substream)
    1435 {
    1436     cs46xx_t *chip = snd_pcm_substream_chip(substream);
    1437     snd_pcm_runtime_t *runtime = substream->runtime;
    1438     cs46xx_pcm_t * cpcm;
    1439 
    1440     cpcm = runtime->private_data;
    1441 
    1442     /* when playback_open fails, then cpcm can be NULL */
    1443     if (!cpcm) return -ENXIO;
    1444 
    1445 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    1446     down (&chip->spos_mutex);
    1447     if (cpcm->pcm_channel) {
    1448         cs46xx_dsp_destroy_pcm_channel(chip,cpcm->pcm_channel);
    1449         cpcm->pcm_channel = NULL;
    1450     }
    1451     up (&chip->spos_mutex);
     1333        chip->playback_pcm = cpcm; /* HACK */
     1334#endif
     1335
     1336        if (chip->accept_valid)
     1337                substream->runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID;
     1338        chip->active_ctrl(chip, 1);
     1339
     1340        return 0;
     1341}
     1342
     1343static int snd_cs46xx_playback_open(struct snd_pcm_substream *substream)
     1344{
     1345        snd_printdd("open front channel\n");
     1346        return _cs46xx_playback_open_channel(substream,DSP_PCM_MAIN_CHANNEL);
     1347}
     1348
     1349#ifdef CONFIG_SND_CS46XX_NEW_DSP
     1350static int snd_cs46xx_playback_open_rear(struct snd_pcm_substream *substream)
     1351{
     1352        snd_printdd("open rear channel\n");
     1353
     1354        return _cs46xx_playback_open_channel(substream,DSP_PCM_REAR_CHANNEL);
     1355}
     1356
     1357static int snd_cs46xx_playback_open_clfe(struct snd_pcm_substream *substream)
     1358{
     1359        snd_printdd("open center - LFE channel\n");
     1360
     1361        return _cs46xx_playback_open_channel(substream,DSP_PCM_CENTER_LFE_CHANNEL);
     1362}
     1363
     1364static int snd_cs46xx_playback_open_iec958(struct snd_pcm_substream *substream)
     1365{
     1366        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
     1367
     1368        snd_printdd("open raw iec958 channel\n");
     1369
     1370        down (&chip->spos_mutex);
     1371        cs46xx_iec958_pre_open (chip);
     1372        up (&chip->spos_mutex);
     1373
     1374        return _cs46xx_playback_open_channel(substream,DSP_IEC958_CHANNEL);
     1375}
     1376
     1377static int snd_cs46xx_playback_close(struct snd_pcm_substream *substream);
     1378
     1379static int snd_cs46xx_playback_close_iec958(struct snd_pcm_substream *substream)
     1380{
     1381        int err;
     1382        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
     1383 
     1384        snd_printdd("close raw iec958 channel\n");
     1385
     1386        err = snd_cs46xx_playback_close(substream);
     1387
     1388        down (&chip->spos_mutex);
     1389        cs46xx_iec958_post_close (chip);
     1390        up (&chip->spos_mutex);
     1391
     1392        return err;
     1393}
     1394#endif
     1395
     1396static int snd_cs46xx_capture_open(struct snd_pcm_substream *substream)
     1397{
     1398        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
     1399
     1400        if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
     1401                                PAGE_SIZE, &chip->capt.hw_buf) < 0)
     1402                return -ENOMEM;
     1403        chip->capt.substream = substream;
     1404        substream->runtime->hw = snd_cs46xx_capture;
     1405
     1406        if (chip->accept_valid)
     1407                substream->runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID;
     1408
     1409        chip->active_ctrl(chip, 1);
     1410
     1411#ifdef CONFIG_SND_CS46XX_NEW_DSP
     1412        snd_pcm_hw_constraint_list(substream->runtime, 0,
     1413                                   SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
     1414                                   &hw_constraints_period_sizes);
     1415#endif
     1416        return 0;
     1417}
     1418
     1419static int snd_cs46xx_playback_close(struct snd_pcm_substream *substream)
     1420{
     1421        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
     1422        struct snd_pcm_runtime *runtime = substream->runtime;
     1423        struct snd_cs46xx_pcm * cpcm;
     1424
     1425        cpcm = runtime->private_data;
     1426
     1427        /* when playback_open fails, then cpcm can be NULL */
     1428        if (!cpcm) return -ENXIO;
     1429
     1430#ifdef CONFIG_SND_CS46XX_NEW_DSP
     1431        down (&chip->spos_mutex);
     1432        if (cpcm->pcm_channel) {
     1433                cs46xx_dsp_destroy_pcm_channel(chip,cpcm->pcm_channel);
     1434                cpcm->pcm_channel = NULL;
     1435        }
     1436        up (&chip->spos_mutex);
    14521437#else
    1453     chip->playback_pcm = NULL;
    1454 #endif
    1455 
    1456     cpcm->substream = NULL;
    1457     snd_dma_free_pages(&cpcm->hw_buf);
    1458     chip->active_ctrl(chip, -1);
    1459 
    1460     return 0;
    1461 }
    1462 
    1463 static int snd_cs46xx_capture_close(snd_pcm_substream_t * substream)
    1464 {
    1465     cs46xx_t *chip = snd_pcm_substream_chip(substream);
    1466 
    1467     chip->capt.substream = NULL;
    1468     snd_dma_free_pages(&chip->capt.hw_buf);
    1469     chip->active_ctrl(chip, -1);
    1470 
    1471     return 0;
    1472 }
    1473 
    1474 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    1475 snd_pcm_ops_t snd_cs46xx_playback_rear_ops = {
    1476     /*  .open =           */      snd_cs46xx_playback_open_rear,
    1477     /*  .close =          */      snd_cs46xx_playback_close,
    1478     /*  .ioctl =          */      snd_pcm_lib_ioctl,
    1479     /*  .hw_params =      */      snd_cs46xx_playback_hw_params,
    1480     /*  .hw_free =        */      snd_cs46xx_playback_hw_free,
    1481     /*  .prepare =        */      snd_cs46xx_playback_prepare,
    1482     /*  .trigger =        */      snd_cs46xx_playback_trigger,
    1483     /*  .pointer =        */      snd_cs46xx_playback_direct_pointer,
    1484     0,0,0,0
     1438        chip->playback_pcm = NULL;
     1439#endif
     1440
     1441        cpcm->substream = NULL;
     1442        snd_dma_free_pages(&cpcm->hw_buf);
     1443        chip->active_ctrl(chip, -1);
     1444
     1445        return 0;
     1446}
     1447
     1448static int snd_cs46xx_capture_close(struct snd_pcm_substream *substream)
     1449{
     1450        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
     1451
     1452        chip->capt.substream = NULL;
     1453        snd_dma_free_pages(&chip->capt.hw_buf);
     1454        chip->active_ctrl(chip, -1);
     1455
     1456        return 0;
     1457}
     1458
     1459#ifdef CONFIG_SND_CS46XX_NEW_DSP
     1460static struct snd_pcm_ops snd_cs46xx_playback_rear_ops = {
     1461        .open =                 snd_cs46xx_playback_open_rear,
     1462        .close =                snd_cs46xx_playback_close,
     1463        .ioctl =                snd_pcm_lib_ioctl,
     1464        .hw_params =            snd_cs46xx_playback_hw_params,
     1465        .hw_free =              snd_cs46xx_playback_hw_free,
     1466        .prepare =              snd_cs46xx_playback_prepare,
     1467        .trigger =              snd_cs46xx_playback_trigger,
     1468        .pointer =              snd_cs46xx_playback_direct_pointer,
    14851469};
    1486 snd_pcm_ops_t snd_cs46xx_playback_indirect_rear_ops = {
    1487     /*  .open =           */      snd_cs46xx_playback_open_rear,
    1488     /*  .close =          */      snd_cs46xx_playback_close,
    1489     /*  .ioctl =          */      snd_pcm_lib_ioctl,
    1490     /*  .hw_params =      */      snd_cs46xx_playback_hw_params,
    1491     /*  .hw_free =        */      snd_cs46xx_playback_hw_free,
    1492     /*  .prepare =        */      snd_cs46xx_playback_prepare,
    1493     /*  .trigger =        */      snd_cs46xx_playback_trigger,
    1494     /*  .pointer =        */      snd_cs46xx_playback_indirect_pointer,
    1495     0,0,0,
    1496     /*  .ack =            */      snd_cs46xx_playback_transfer,
     1470
     1471static struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops = {
     1472        .open =                 snd_cs46xx_playback_open_rear,
     1473        .close =                snd_cs46xx_playback_close,
     1474        .ioctl =                snd_pcm_lib_ioctl,
     1475        .hw_params =            snd_cs46xx_playback_hw_params,
     1476        .hw_free =              snd_cs46xx_playback_hw_free,
     1477        .prepare =              snd_cs46xx_playback_prepare,
     1478        .trigger =              snd_cs46xx_playback_trigger,
     1479        .pointer =              snd_cs46xx_playback_indirect_pointer,
     1480        .ack =                  snd_cs46xx_playback_transfer,
    14971481};
    14981482
    1499 snd_pcm_ops_t snd_cs46xx_playback_clfe_ops = {
    1500     /*  .open =           */      snd_cs46xx_playback_open_clfe,
    1501     /*  .close =          */      snd_cs46xx_playback_close,
    1502     /*  .ioctl =          */      snd_pcm_lib_ioctl,
    1503     /*  .hw_params =      */      snd_cs46xx_playback_hw_params,
    1504     /*  .hw_free =        */      snd_cs46xx_playback_hw_free,
    1505     /*  .prepare =        */      snd_cs46xx_playback_prepare,
    1506     /*  .trigger =        */      snd_cs46xx_playback_trigger,
    1507     /*  .pointer =        */      snd_cs46xx_playback_direct_pointer,
    1508     0,0,0,0
     1483static struct snd_pcm_ops snd_cs46xx_playback_clfe_ops = {
     1484        .open =                 snd_cs46xx_playback_open_clfe,
     1485        .close =                snd_cs46xx_playback_close,
     1486        .ioctl =                snd_pcm_lib_ioctl,
     1487        .hw_params =            snd_cs46xx_playback_hw_params,
     1488        .hw_free =              snd_cs46xx_playback_hw_free,
     1489        .prepare =              snd_cs46xx_playback_prepare,
     1490        .trigger =              snd_cs46xx_playback_trigger,
     1491        .pointer =              snd_cs46xx_playback_direct_pointer,
    15091492};
    15101493
    1511 snd_pcm_ops_t snd_cs46xx_playback_indirect_clfe_ops = {
    1512     /*  .open =           */      snd_cs46xx_playback_open_clfe,
    1513     /*  .close =          */      snd_cs46xx_playback_close,
    1514     /*  .ioctl =          */      snd_pcm_lib_ioctl,
    1515     /*  .hw_params =      */      snd_cs46xx_playback_hw_params,
    1516     /*  .hw_free =        */      snd_cs46xx_playback_hw_free,
    1517     /*  .prepare =        */      snd_cs46xx_playback_prepare,
    1518     /*  .trigger =        */      snd_cs46xx_playback_trigger,
    1519     /*  .pointer =        */      snd_cs46xx_playback_indirect_pointer,
    1520     0,0,0,
    1521     /*  .ack =            */      snd_cs46xx_playback_transfer,
     1494static struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops = {
     1495        .open =                 snd_cs46xx_playback_open_clfe,
     1496        .close =                snd_cs46xx_playback_close,
     1497        .ioctl =                snd_pcm_lib_ioctl,
     1498        .hw_params =            snd_cs46xx_playback_hw_params,
     1499        .hw_free =              snd_cs46xx_playback_hw_free,
     1500        .prepare =              snd_cs46xx_playback_prepare,
     1501        .trigger =              snd_cs46xx_playback_trigger,
     1502        .pointer =              snd_cs46xx_playback_indirect_pointer,
     1503        .ack =                  snd_cs46xx_playback_transfer,
    15221504};
    15231505
    1524 snd_pcm_ops_t snd_cs46xx_playback_iec958_ops = {
    1525     /*  .open =           */      snd_cs46xx_playback_open_iec958,
    1526     /*  .close =          */      snd_cs46xx_playback_close_iec958,
    1527     /*  .ioctl =          */      snd_pcm_lib_ioctl,
    1528     /*  .hw_params =      */      snd_cs46xx_playback_hw_params,
    1529     /*  .hw_free =        */      snd_cs46xx_playback_hw_free,
    1530     /*  .prepare =        */      snd_cs46xx_playback_prepare,
    1531     /*  .trigger =        */      snd_cs46xx_playback_trigger,
    1532     /*  .pointer =        */      snd_cs46xx_playback_direct_pointer,
    1533     0,0,0,0
     1506static struct snd_pcm_ops snd_cs46xx_playback_iec958_ops = {
     1507        .open =                 snd_cs46xx_playback_open_iec958,
     1508        .close =                snd_cs46xx_playback_close_iec958,
     1509        .ioctl =                snd_pcm_lib_ioctl,
     1510        .hw_params =            snd_cs46xx_playback_hw_params,
     1511        .hw_free =              snd_cs46xx_playback_hw_free,
     1512        .prepare =              snd_cs46xx_playback_prepare,
     1513        .trigger =              snd_cs46xx_playback_trigger,
     1514        .pointer =              snd_cs46xx_playback_direct_pointer,
    15341515};
    15351516
    1536 snd_pcm_ops_t snd_cs46xx_playback_indirect_iec958_ops = {
    1537     /*  .open =           */      snd_cs46xx_playback_open_iec958,
    1538     /*  .close =          */      snd_cs46xx_playback_close_iec958,
    1539     /*  .ioctl =          */      snd_pcm_lib_ioctl,
    1540     /*  .hw_params =      */      snd_cs46xx_playback_hw_params,
    1541     /*  .hw_free =        */      snd_cs46xx_playback_hw_free,
    1542     /*  .prepare =        */      snd_cs46xx_playback_prepare,
    1543     /*  .trigger =        */      snd_cs46xx_playback_trigger,
    1544     /*  .pointer =        */      snd_cs46xx_playback_indirect_pointer,
    1545     0,0,0,
    1546     /*  .ack =            */      snd_cs46xx_playback_transfer,
     1517static struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops = {
     1518        .open =                 snd_cs46xx_playback_open_iec958,
     1519        .close =                snd_cs46xx_playback_close_iec958,
     1520        .ioctl =                snd_pcm_lib_ioctl,
     1521        .hw_params =            snd_cs46xx_playback_hw_params,
     1522        .hw_free =              snd_cs46xx_playback_hw_free,
     1523        .prepare =              snd_cs46xx_playback_prepare,
     1524        .trigger =              snd_cs46xx_playback_trigger,
     1525        .pointer =              snd_cs46xx_playback_indirect_pointer,
     1526        .ack =                  snd_cs46xx_playback_transfer,
    15471527};
    15481528
    15491529#endif
    15501530
    1551 snd_pcm_ops_t snd_cs46xx_playback_ops = {
    1552     snd_cs46xx_playback_open,
    1553     snd_cs46xx_playback_close,
    1554     snd_pcm_lib_ioctl,
    1555     snd_cs46xx_playback_hw_params,
    1556     snd_cs46xx_playback_hw_free,
    1557     snd_cs46xx_playback_prepare,
    1558     snd_cs46xx_playback_trigger,
    1559     snd_cs46xx_playback_direct_pointer,
    1560     0,0,0,0
     1531static struct snd_pcm_ops snd_cs46xx_playback_ops = {
     1532        .open =                 snd_cs46xx_playback_open,
     1533        .close =                snd_cs46xx_playback_close,
     1534        .ioctl =                snd_pcm_lib_ioctl,
     1535        .hw_params =            snd_cs46xx_playback_hw_params,
     1536        .hw_free =              snd_cs46xx_playback_hw_free,
     1537        .prepare =              snd_cs46xx_playback_prepare,
     1538        .trigger =              snd_cs46xx_playback_trigger,
     1539        .pointer =              snd_cs46xx_playback_direct_pointer,
    15611540};
    15621541
    1563 snd_pcm_ops_t snd_cs46xx_playback_indirect_ops = {
    1564     snd_cs46xx_playback_open,
    1565     snd_cs46xx_playback_close,
    1566     snd_pcm_lib_ioctl,
    1567     snd_cs46xx_playback_hw_params,
    1568     snd_cs46xx_playback_hw_free,
    1569     snd_cs46xx_playback_prepare,
    1570     snd_cs46xx_playback_trigger,
    1571     snd_cs46xx_playback_indirect_pointer,0,0,0,
    1572     snd_cs46xx_playback_transfer
     1542static struct snd_pcm_ops snd_cs46xx_playback_indirect_ops = {
     1543        .open =                 snd_cs46xx_playback_open,
     1544        .close =                snd_cs46xx_playback_close,
     1545        .ioctl =                snd_pcm_lib_ioctl,
     1546        .hw_params =            snd_cs46xx_playback_hw_params,
     1547        .hw_free =              snd_cs46xx_playback_hw_free,
     1548        .prepare =              snd_cs46xx_playback_prepare,
     1549        .trigger =              snd_cs46xx_playback_trigger,
     1550        .pointer =              snd_cs46xx_playback_indirect_pointer,
     1551        .ack =                  snd_cs46xx_playback_transfer,
    15731552};
    15741553
    1575 snd_pcm_ops_t snd_cs46xx_capture_ops = {
    1576     snd_cs46xx_capture_open,
    1577     snd_cs46xx_capture_close,
    1578     snd_pcm_lib_ioctl,
    1579     snd_cs46xx_capture_hw_params,
    1580     snd_cs46xx_capture_hw_free,
    1581     snd_cs46xx_capture_prepare,
    1582     snd_cs46xx_capture_trigger,
    1583     snd_cs46xx_capture_direct_pointer,
    1584     0,0,0,0
     1554static struct snd_pcm_ops snd_cs46xx_capture_ops = {
     1555        .open =                 snd_cs46xx_capture_open,
     1556        .close =                snd_cs46xx_capture_close,
     1557        .ioctl =                snd_pcm_lib_ioctl,
     1558        .hw_params =            snd_cs46xx_capture_hw_params,
     1559        .hw_free =              snd_cs46xx_capture_hw_free,
     1560        .prepare =              snd_cs46xx_capture_prepare,
     1561        .trigger =              snd_cs46xx_capture_trigger,
     1562        .pointer =              snd_cs46xx_capture_direct_pointer,
    15851563};
    15861564
    1587 snd_pcm_ops_t snd_cs46xx_capture_indirect_ops = {
    1588     snd_cs46xx_capture_open,
    1589     snd_cs46xx_capture_close,
    1590     snd_pcm_lib_ioctl,
    1591     snd_cs46xx_capture_hw_params,
    1592     snd_cs46xx_capture_hw_free,
    1593     snd_cs46xx_capture_prepare,
    1594     snd_cs46xx_capture_trigger,
    1595     snd_cs46xx_capture_indirect_pointer,0,0,0,
    1596     snd_cs46xx_capture_transfer
     1565static struct snd_pcm_ops snd_cs46xx_capture_indirect_ops = {
     1566        .open =                 snd_cs46xx_capture_open,
     1567        .close =                snd_cs46xx_capture_close,
     1568        .ioctl =                snd_pcm_lib_ioctl,
     1569        .hw_params =            snd_cs46xx_capture_hw_params,
     1570        .hw_free =              snd_cs46xx_capture_hw_free,
     1571        .prepare =              snd_cs46xx_capture_prepare,
     1572        .trigger =              snd_cs46xx_capture_trigger,
     1573        .pointer =              snd_cs46xx_capture_indirect_pointer,
     1574        .ack =                  snd_cs46xx_capture_transfer,
    15971575};
    15981576
    1599 
    1600 static void snd_cs46xx_pcm_free(snd_pcm_t *pcm)
    1601 {
    1602     cs46xx_t *chip = pcm->private_data;
    1603     chip->pcm = NULL;
    1604     snd_pcm_lib_preallocate_free_for_all(pcm);
    1605 }
    1606 
    1607 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    1608 static void snd_cs46xx_pcm_rear_free(snd_pcm_t *pcm)
    1609 {
    1610     cs46xx_t *chip = pcm->private_data;
    1611     chip->pcm_rear = NULL;
    1612     snd_pcm_lib_preallocate_free_for_all(pcm);
    1613 }
    1614 
    1615 static void snd_cs46xx_pcm_center_lfe_free(snd_pcm_t *pcm)
    1616 {
    1617     cs46xx_t *chip = pcm->private_data;
    1618     chip->pcm_center_lfe = NULL;
    1619     snd_pcm_lib_preallocate_free_for_all(pcm);
    1620 }
    1621 
    1622 static void snd_cs46xx_pcm_iec958_free(snd_pcm_t *pcm)
    1623 {
    1624     cs46xx_t *chip = pcm->private_data;
    1625     chip->pcm_iec958 = NULL;
    1626     snd_pcm_lib_preallocate_free_for_all(pcm);
    1627 }
    1628 
     1577#ifdef CONFIG_SND_CS46XX_NEW_DSP
    16291578#define MAX_PLAYBACK_CHANNELS   (DSP_MAX_PCM_CHANNELS - 1)
    16301579#else
     
    16321581#endif
    16331582
    1634 int __devinit snd_cs46xx_pcm(cs46xx_t *chip, int device, snd_pcm_t ** rpcm)
    1635 {
    1636         snd_pcm_t *pcm;
     1583int __devinit snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
     1584{
     1585        struct snd_pcm *pcm;
    16371586        int err;
    16381587
     
    16431592
    16441593        pcm->private_data = chip;
    1645         pcm->private_free = snd_cs46xx_pcm_free;
    16461594
    16471595        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_ops);
     
    16641612
    16651613#ifdef CONFIG_SND_CS46XX_NEW_DSP
    1666 int __devinit snd_cs46xx_pcm_rear(cs46xx_t *chip, int device, snd_pcm_t ** rpcm)
    1667 {
    1668         snd_pcm_t *pcm;
     1614int __devinit snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
     1615{
     1616        struct snd_pcm *pcm;
    16691617        int err;
    16701618
     
    16761624
    16771625        pcm->private_data = chip;
    1678         pcm->private_free = snd_cs46xx_pcm_rear_free;
    16791626
    16801627        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_rear_ops);
     
    16941641}
    16951642
    1696 int __devinit snd_cs46xx_pcm_center_lfe(cs46xx_t *chip, int device, snd_pcm_t ** rpcm)
    1697 {
    1698         snd_pcm_t *pcm;
     1643int __devinit snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
     1644{
     1645        struct snd_pcm *pcm;
    16991646        int err;
    17001647
     
    17061653
    17071654        pcm->private_data = chip;
    1708         pcm->private_free = snd_cs46xx_pcm_center_lfe_free;
    17091655
    17101656        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_clfe_ops);
     
    17241670}
    17251671
    1726 int __devinit snd_cs46xx_pcm_iec958(cs46xx_t *chip, int device, snd_pcm_t ** rpcm)
    1727 {
    1728         snd_pcm_t *pcm;
     1672int __devinit snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
     1673{
     1674        struct snd_pcm *pcm;
    17291675        int err;
    17301676
     
    17361682
    17371683        pcm->private_data = chip;
    1738         pcm->private_free = snd_cs46xx_pcm_iec958_free;
    17391684
    17401685        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_iec958_ops);
     
    17531698        return 0;
    17541699}
    1755 
    17561700#endif
    17571701
     
    17591703 *  Mixer routines
    17601704 */
    1761 static void snd_cs46xx_mixer_free_ac97_bus(ac97_bus_t *bus)
    1762 {
    1763     cs46xx_t *chip = bus->private_data;
    1764 
    1765     chip->ac97_bus = NULL;
    1766 }
    1767 
    1768 static void snd_cs46xx_mixer_free_ac97(ac97_t *ac97)
    1769 {
    1770     cs46xx_t *chip = ac97->private_data;
    1771 
    1772     snd_assert ((ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]) ||
    1773                 (ac97 == chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]),
    1774                 return);
    1775 
    1776     if (ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]) {
    1777         chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] = NULL;
    1778         chip->eapd_switch = NULL;
    1779     }
    1780     else
    1781         chip->ac97[CS46XX_SECONDARY_CODEC_INDEX] = NULL;
    1782 }
    1783 
    1784 static int snd_cs46xx_vol_info(snd_kcontrol_t *kcontrol,
    1785                                snd_ctl_elem_info_t *uinfo)
    1786 {
    1787     uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
    1788     uinfo->count = 2;
    1789     uinfo->value.integer.min = 0;
    1790     uinfo->value.integer.max = 0x7fff;
    1791     return 0;
    1792 }
    1793 
    1794 static int snd_cs46xx_vol_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
    1795 {
    1796     cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
    1797     int reg = kcontrol->private_value;
    1798     unsigned int val = snd_cs46xx_peek(chip, reg);
    1799     ucontrol->value.integer.value[0] = 0xffff - (val >> 16);
    1800     ucontrol->value.integer.value[1] = 0xffff - (val & 0xffff);
    1801     return 0;
    1802 }
    1803 
    1804 static int snd_cs46xx_vol_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
    1805 {
    1806     cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
    1807     int reg = kcontrol->private_value;
    1808     unsigned int val = ((0xffff - ucontrol->value.integer.value[0]) << 16 |
    1809                         (0xffff - ucontrol->value.integer.value[1]));
    1810     unsigned int old = snd_cs46xx_peek(chip, reg);
    1811     int change = (old != val);
    1812 
    1813     if (change) {
    1814         snd_cs46xx_poke(chip, reg, val);
    1815     }
    1816 
    1817     return change;
    1818 }
    1819 
    1820 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    1821 
    1822 static int snd_cs46xx_vol_dac_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
    1823 {
    1824     cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
    1825 
    1826     ucontrol->value.integer.value[0] = chip->dsp_spos_instance->dac_volume_left;
    1827     ucontrol->value.integer.value[1] = chip->dsp_spos_instance->dac_volume_right;
    1828 
    1829     return 0;
    1830 }
    1831 
    1832 static int snd_cs46xx_vol_dac_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
    1833 {
    1834     cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
    1835     int change = 0;
    1836 
    1837     if (chip->dsp_spos_instance->dac_volume_right != ucontrol->value.integer.value[0] ||
    1838         chip->dsp_spos_instance->dac_volume_left != ucontrol->value.integer.value[1]) {
    1839         cs46xx_dsp_set_dac_volume(chip,
    1840                                   ucontrol->value.integer.value[0],
    1841                                   ucontrol->value.integer.value[1]);
    1842         change = 1;
    1843     }
    1844 
    1845     return change;
     1705static void snd_cs46xx_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
     1706{
     1707        struct snd_cs46xx *chip = bus->private_data;
     1708
     1709        chip->ac97_bus = NULL;
     1710}
     1711
     1712static void snd_cs46xx_mixer_free_ac97(struct snd_ac97 *ac97)
     1713{
     1714        struct snd_cs46xx *chip = ac97->private_data;
     1715
     1716        snd_assert ((ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]) ||
     1717                    (ac97 == chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]),
     1718                    return);
     1719
     1720        if (ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]) {
     1721                chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] = NULL;
     1722                chip->eapd_switch = NULL;
     1723        }
     1724        else
     1725                chip->ac97[CS46XX_SECONDARY_CODEC_INDEX] = NULL;
     1726}
     1727
     1728static int snd_cs46xx_vol_info(struct snd_kcontrol *kcontrol,
     1729                               struct snd_ctl_elem_info *uinfo)
     1730{
     1731        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
     1732        uinfo->count = 2;
     1733        uinfo->value.integer.min = 0;
     1734        uinfo->value.integer.max = 0x7fff;
     1735        return 0;
     1736}
     1737
     1738static int snd_cs46xx_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
     1739{
     1740        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
     1741        int reg = kcontrol->private_value;
     1742        unsigned int val = snd_cs46xx_peek(chip, reg);
     1743        ucontrol->value.integer.value[0] = 0xffff - (val >> 16);
     1744        ucontrol->value.integer.value[1] = 0xffff - (val & 0xffff);
     1745        return 0;
     1746}
     1747
     1748static int snd_cs46xx_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
     1749{
     1750        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
     1751        int reg = kcontrol->private_value;
     1752        unsigned int val = ((0xffff - ucontrol->value.integer.value[0]) << 16 |
     1753                            (0xffff - ucontrol->value.integer.value[1]));
     1754        unsigned int old = snd_cs46xx_peek(chip, reg);
     1755        int change = (old != val);
     1756
     1757        if (change) {
     1758                snd_cs46xx_poke(chip, reg, val);
     1759        }
     1760
     1761        return change;
     1762}
     1763
     1764#ifdef CONFIG_SND_CS46XX_NEW_DSP
     1765
     1766static int snd_cs46xx_vol_dac_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
     1767{
     1768        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
     1769
     1770        ucontrol->value.integer.value[0] = chip->dsp_spos_instance->dac_volume_left;
     1771        ucontrol->value.integer.value[1] = chip->dsp_spos_instance->dac_volume_right;
     1772
     1773        return 0;
     1774}
     1775
     1776static int snd_cs46xx_vol_dac_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
     1777{
     1778        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
     1779        int change = 0;
     1780
     1781        if (chip->dsp_spos_instance->dac_volume_right != ucontrol->value.integer.value[0] ||
     1782            chip->dsp_spos_instance->dac_volume_left != ucontrol->value.integer.value[1]) {
     1783                cs46xx_dsp_set_dac_volume(chip,
     1784                                          ucontrol->value.integer.value[0],
     1785                                          ucontrol->value.integer.value[1]);
     1786                change = 1;
     1787        }
     1788
     1789        return change;
    18461790}
    18471791
    18481792#if 0
    1849 static int snd_cs46xx_vol_iec958_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
    1850 {
    1851     cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
    1852 
    1853     ucontrol->value.integer.value[0] = chip->dsp_spos_instance->spdif_input_volume_left;
    1854     ucontrol->value.integer.value[1] = chip->dsp_spos_instance->spdif_input_volume_right;
    1855     return 0;
    1856 }
    1857 
    1858 static int snd_cs46xx_vol_iec958_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
    1859 {
    1860     cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
    1861     int change = 0;
    1862 
    1863     if (chip->dsp_spos_instance->spdif_input_volume_left  != ucontrol->value.integer.value[0] ||
    1864         chip->dsp_spos_instance->spdif_input_volume_right!= ucontrol->value.integer.value[1]) {
    1865         cs46xx_dsp_set_iec958_volume (chip,
    1866                                       ucontrol->value.integer.value[0],
    1867                                       ucontrol->value.integer.value[1]);
    1868         change = 1;
    1869     }
    1870 
    1871     return change;
    1872 }
    1873 #endif
    1874 
    1875 static int snd_mixer_boolean_info(snd_kcontrol_t *kcontrol,
    1876                                   snd_ctl_elem_info_t *uinfo)
    1877 {
    1878     uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
    1879     uinfo->count = 1;
    1880     uinfo->value.integer.min = 0;
    1881     uinfo->value.integer.max = 1;
    1882     return 0;
    1883 }
    1884 
    1885 static int snd_cs46xx_iec958_get(snd_kcontrol_t *kcontrol,
    1886                                  snd_ctl_elem_value_t *ucontrol)
    1887 {
    1888     cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
    1889     int reg = kcontrol->private_value;
    1890 
    1891     if (reg == CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT)
    1892         ucontrol->value.integer.value[0] = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED);
    1893     else
    1894         ucontrol->value.integer.value[0] = chip->dsp_spos_instance->spdif_status_in;
    1895 
    1896     return 0;
    1897 }
    1898 
    1899 static int snd_cs46xx_iec958_put(snd_kcontrol_t *kcontrol,
    1900                                  snd_ctl_elem_value_t *ucontrol)
    1901 {
    1902     cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
    1903     int change, res;
    1904 
    1905     switch (kcontrol->private_value) {
    1906     case CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT:
    1907         down (&chip->spos_mutex);
    1908         change = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED);
    1909         if (ucontrol->value.integer.value[0] && !change)
    1910             cs46xx_dsp_enable_spdif_out(chip);
    1911         else if (change && !ucontrol->value.integer.value[0])
    1912             cs46xx_dsp_disable_spdif_out(chip);
    1913 
    1914         res = (change != (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED));
    1915         up (&chip->spos_mutex);
    1916         break;
    1917     case CS46XX_MIXER_SPDIF_INPUT_ELEMENT:
    1918         change = chip->dsp_spos_instance->spdif_status_in;
    1919         if (ucontrol->value.integer.value[0] && !change) {
    1920             cs46xx_dsp_enable_spdif_in(chip);
    1921             /* restore volume */
    1922         }
    1923         else if (change && !ucontrol->value.integer.value[0])
    1924             cs46xx_dsp_disable_spdif_in(chip);
    1925 
    1926         res = (change != chip->dsp_spos_instance->spdif_status_in);
    1927         break;
    1928     default:
    1929         res = -EINVAL;
    1930         snd_assert(0, (void)0);
    1931     }
    1932 
    1933     return res;
    1934 }
    1935 
    1936 static int snd_cs46xx_adc_capture_get(snd_kcontrol_t *kcontrol,
    1937                                       snd_ctl_elem_value_t *ucontrol)
    1938 {
    1939     cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
    1940     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    1941 
    1942     if (ins->adc_input != NULL)
    1943         ucontrol->value.integer.value[0] = 1;
    1944     else
    1945         ucontrol->value.integer.value[0] = 0;
    1946 
    1947     return 0;
    1948 }
    1949 
    1950 
    1951 static int snd_cs46xx_adc_capture_put(snd_kcontrol_t *kcontrol,
    1952                                       snd_ctl_elem_value_t *ucontrol)
    1953 {
    1954     cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
    1955     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    1956     int change = 0;
    1957 
    1958     if (ucontrol->value.integer.value[0] && !ins->adc_input) {
    1959         cs46xx_dsp_enable_adc_capture(chip);
    1960         change = 1;
    1961     } else  if (!ucontrol->value.integer.value[0] && ins->adc_input) {
    1962         cs46xx_dsp_disable_adc_capture(chip);
    1963         change = 1;
    1964     }
    1965     return change;
    1966 }
    1967 
    1968 static int snd_cs46xx_pcm_capture_get(snd_kcontrol_t *kcontrol,
    1969                                       snd_ctl_elem_value_t *ucontrol)
    1970 {
    1971     cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
    1972     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    1973 
    1974     if (ins->pcm_input != NULL)
    1975         ucontrol->value.integer.value[0] = 1;
    1976     else
    1977         ucontrol->value.integer.value[0] = 0;
    1978 
    1979     return 0;
    1980 }
    1981 
    1982 static int snd_cs46xx_pcm_capture_put(snd_kcontrol_t *kcontrol,
    1983                                       snd_ctl_elem_value_t *ucontrol)
    1984 {
    1985     cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
    1986     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    1987     int change = 0;
    1988 
    1989     if (ucontrol->value.integer.value[0] && !ins->pcm_input) {
    1990         cs46xx_dsp_enable_pcm_capture(chip);
    1991         change = 1;
    1992     } else  if (!ucontrol->value.integer.value[0] && ins->pcm_input) {
    1993         cs46xx_dsp_disable_pcm_capture(chip);
    1994         change = 1;
    1995     }
    1996 
    1997     return change;
    1998 }
    1999 
    2000 static int snd_herc_spdif_select_get(snd_kcontrol_t *kcontrol,
    2001                                      snd_ctl_elem_value_t *ucontrol)
    2002 {
    2003     cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
    2004 
    2005     int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR);
    2006 
    2007     if (val1 & EGPIODR_GPOE0)
    2008         ucontrol->value.integer.value[0] = 1;
    2009     else
    2010         ucontrol->value.integer.value[0] = 0;
    2011 
    2012     return 0;
     1793static int snd_cs46xx_vol_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
     1794{
     1795        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
     1796
     1797        ucontrol->value.integer.value[0] = chip->dsp_spos_instance->spdif_input_volume_left;
     1798        ucontrol->value.integer.value[1] = chip->dsp_spos_instance->spdif_input_volume_right;
     1799        return 0;
     1800}
     1801
     1802static int snd_cs46xx_vol_iec958_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
     1803{
     1804        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
     1805        int change = 0;
     1806
     1807        if (chip->dsp_spos_instance->spdif_input_volume_left  != ucontrol->value.integer.value[0] ||
     1808            chip->dsp_spos_instance->spdif_input_volume_right!= ucontrol->value.integer.value[1]) {
     1809                cs46xx_dsp_set_iec958_volume (chip,
     1810                                              ucontrol->value.integer.value[0],
     1811                                              ucontrol->value.integer.value[1]);
     1812                change = 1;
     1813        }
     1814
     1815        return change;
     1816}
     1817#endif
     1818
     1819static int snd_mixer_boolean_info(struct snd_kcontrol *kcontrol,
     1820                                  struct snd_ctl_elem_info *uinfo)
     1821{
     1822        uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
     1823        uinfo->count = 1;
     1824        uinfo->value.integer.min = 0;
     1825        uinfo->value.integer.max = 1;
     1826        return 0;
     1827}
     1828
     1829static int snd_cs46xx_iec958_get(struct snd_kcontrol *kcontrol,
     1830                                 struct snd_ctl_elem_value *ucontrol)
     1831{
     1832        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
     1833        int reg = kcontrol->private_value;
     1834
     1835        if (reg == CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT)
     1836                ucontrol->value.integer.value[0] = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED);
     1837        else
     1838                ucontrol->value.integer.value[0] = chip->dsp_spos_instance->spdif_status_in;
     1839
     1840        return 0;
     1841}
     1842
     1843static int snd_cs46xx_iec958_put(struct snd_kcontrol *kcontrol,
     1844                                  struct snd_ctl_elem_value *ucontrol)
     1845{
     1846        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
     1847        int change, res;
     1848
     1849        switch (kcontrol->private_value) {
     1850        case CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT:
     1851                down (&chip->spos_mutex);
     1852                change = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED);
     1853                if (ucontrol->value.integer.value[0] && !change)
     1854                        cs46xx_dsp_enable_spdif_out(chip);
     1855                else if (change && !ucontrol->value.integer.value[0])
     1856                        cs46xx_dsp_disable_spdif_out(chip);
     1857
     1858                res = (change != (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED));
     1859                up (&chip->spos_mutex);
     1860                break;
     1861        case CS46XX_MIXER_SPDIF_INPUT_ELEMENT:
     1862                change = chip->dsp_spos_instance->spdif_status_in;
     1863                if (ucontrol->value.integer.value[0] && !change) {
     1864                        cs46xx_dsp_enable_spdif_in(chip);
     1865                        /* restore volume */
     1866                }
     1867                else if (change && !ucontrol->value.integer.value[0])
     1868                        cs46xx_dsp_disable_spdif_in(chip);
     1869               
     1870                res = (change != chip->dsp_spos_instance->spdif_status_in);
     1871                break;
     1872        default:
     1873                res = -EINVAL;
     1874                snd_assert(0, (void)0);
     1875        }
     1876
     1877        return res;
     1878}
     1879
     1880static int snd_cs46xx_adc_capture_get(struct snd_kcontrol *kcontrol,
     1881                                      struct snd_ctl_elem_value *ucontrol)
     1882{
     1883        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
     1884        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     1885
     1886        if (ins->adc_input != NULL)
     1887                ucontrol->value.integer.value[0] = 1;
     1888        else
     1889                ucontrol->value.integer.value[0] = 0;
     1890       
     1891        return 0;
     1892}
     1893
     1894static int snd_cs46xx_adc_capture_put(struct snd_kcontrol *kcontrol,
     1895                                      struct snd_ctl_elem_value *ucontrol)
     1896{
     1897        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
     1898        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     1899        int change = 0;
     1900
     1901        if (ucontrol->value.integer.value[0] && !ins->adc_input) {
     1902                cs46xx_dsp_enable_adc_capture(chip);
     1903                change = 1;
     1904        } else  if (!ucontrol->value.integer.value[0] && ins->adc_input) {
     1905                cs46xx_dsp_disable_adc_capture(chip);
     1906                change = 1;
     1907        }
     1908        return change;
     1909}
     1910
     1911static int snd_cs46xx_pcm_capture_get(struct snd_kcontrol *kcontrol,
     1912                                      struct snd_ctl_elem_value *ucontrol)
     1913{
     1914        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
     1915        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     1916
     1917        if (ins->pcm_input != NULL)
     1918                ucontrol->value.integer.value[0] = 1;
     1919        else
     1920                ucontrol->value.integer.value[0] = 0;
     1921
     1922        return 0;
     1923}
     1924
     1925
     1926static int snd_cs46xx_pcm_capture_put(struct snd_kcontrol *kcontrol,
     1927                                      struct snd_ctl_elem_value *ucontrol)
     1928{
     1929        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
     1930        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     1931        int change = 0;
     1932
     1933        if (ucontrol->value.integer.value[0] && !ins->pcm_input) {
     1934                cs46xx_dsp_enable_pcm_capture(chip);
     1935                change = 1;
     1936        } else  if (!ucontrol->value.integer.value[0] && ins->pcm_input) {
     1937                cs46xx_dsp_disable_pcm_capture(chip);
     1938                change = 1;
     1939        }
     1940
     1941        return change;
     1942}
     1943
     1944static int snd_herc_spdif_select_get(struct snd_kcontrol *kcontrol,
     1945                                     struct snd_ctl_elem_value *ucontrol)
     1946{
     1947        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
     1948
     1949        int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR);
     1950
     1951        if (val1 & EGPIODR_GPOE0)
     1952                ucontrol->value.integer.value[0] = 1;
     1953        else
     1954                ucontrol->value.integer.value[0] = 0;
     1955
     1956        return 0;
    20131957}
    20141958
    20151959/*
    20161960 *      Game Theatre XP card - EGPIO[0] is used to select SPDIF input optical or coaxial.
    2017  */
    2018 static int snd_herc_spdif_select_put(snd_kcontrol_t *kcontrol,
    2019                                      snd_ctl_elem_value_t *ucontrol)
    2020 {
    2021     cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
    2022     int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR);
    2023     int val2 = snd_cs46xx_peekBA0(chip, BA0_EGPIOPTR);
    2024 
    2025     if (ucontrol->value.integer.value[0]) {
    2026         /* optical is default */
    2027         snd_cs46xx_pokeBA0(chip, BA0_EGPIODR,
    2028                            EGPIODR_GPOE0 | val1);  /* enable EGPIO0 output */
    2029         snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR,
    2030                            EGPIOPTR_GPPT0 | val2); /* open-drain on output */
    2031     } else {
    2032         /* coaxial */
    2033         snd_cs46xx_pokeBA0(chip, BA0_EGPIODR,  val1 & ~EGPIODR_GPOE0); /* disable */
    2034         snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, val2 & ~EGPIOPTR_GPPT0); /* disable */
    2035     }
    2036 
    2037     /* checking diff from the EGPIO direction register
    2038      should be enough */
    2039     return (val1 != (int)snd_cs46xx_peekBA0(chip, BA0_EGPIODR));
    2040 }
    2041 
    2042 
    2043 static int snd_cs46xx_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
    2044 {
    2045     uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
    2046     uinfo->count = 1;
    2047     return 0;
    2048 }
    2049 
    2050 static int snd_cs46xx_spdif_default_get(snd_kcontrol_t * kcontrol,
    2051                                         snd_ctl_elem_value_t * ucontrol)
    2052 {
    2053     cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
    2054     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    2055 
    2056     down (&chip->spos_mutex);
    2057     ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_default >> 24) & 0xff);
    2058     ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_default >> 16) & 0xff);
    2059     ucontrol->value.iec958.status[2] = 0;
    2060     ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_default) & 0xff);
    2061     up (&chip->spos_mutex);
    2062 
    2063     return 0;
    2064 }
    2065 
    2066 static int snd_cs46xx_spdif_default_put(snd_kcontrol_t * kcontrol,
    2067                                         snd_ctl_elem_value_t * ucontrol)
    2068 {
    2069     cs46xx_t * chip = snd_kcontrol_chip(kcontrol);
    2070     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    2071     unsigned int val;
    2072     int change;
    2073 
    2074     down (&chip->spos_mutex);
    2075     val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) |
    2076         ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[2]) << 16) |
    2077         ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3]))  |
    2078         /* left and right validity bit */
    2079         (1 << 13) | (1 << 12);
    2080 
    2081 
    2082     change = (unsigned int)ins->spdif_csuv_default != val;
    2083     ins->spdif_csuv_default = val;
    2084 
    2085     if ( !(ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) )
    2086         cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val);
    2087 
    2088     up (&chip->spos_mutex);
    2089 
    2090     return change;
    2091 }
    2092 
    2093 static int snd_cs46xx_spdif_mask_get(snd_kcontrol_t * kcontrol,
    2094                                      snd_ctl_elem_value_t * ucontrol)
    2095 {
    2096     ucontrol->value.iec958.status[0] = 0xff;
    2097     ucontrol->value.iec958.status[1] = 0xff;
    2098     ucontrol->value.iec958.status[2] = 0x00;
    2099     ucontrol->value.iec958.status[3] = 0xff;
    2100     return 0;
    2101 }
    2102 
    2103 static int snd_cs46xx_spdif_stream_get(snd_kcontrol_t * kcontrol,
    2104                                        snd_ctl_elem_value_t * ucontrol)
    2105 {
    2106     cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
    2107     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    2108 
    2109     down (&chip->spos_mutex);
    2110     ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_stream >> 24) & 0xff);
    2111     ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_stream >> 16) & 0xff);
    2112     ucontrol->value.iec958.status[2] = 0;
    2113     ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_stream) & 0xff);
    2114     up (&chip->spos_mutex);
    2115 
    2116     return 0;
    2117 }
    2118 
    2119 static int snd_cs46xx_spdif_stream_put(snd_kcontrol_t * kcontrol,
    2120                                        snd_ctl_elem_value_t * ucontrol)
    2121 {
    2122     cs46xx_t * chip = snd_kcontrol_chip(kcontrol);
    2123     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    2124     unsigned int val;
    2125     int change;
    2126 
    2127     down (&chip->spos_mutex);
    2128     val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) |
    2129         ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[1]) << 16) |
    2130         ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) |
    2131         /* left and right validity bit */
    2132         (1 << 13) | (1 << 12);
    2133 
    2134 
    2135     change = ins->spdif_csuv_stream != val;
    2136     ins->spdif_csuv_stream = val;
    2137 
    2138     if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN )
    2139         cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val);
    2140 
    2141     up (&chip->spos_mutex);
    2142 
    2143     return change;
     1961 */ 
     1962static int snd_herc_spdif_select_put(struct snd_kcontrol *kcontrol,
     1963                                       struct snd_ctl_elem_value *ucontrol)
     1964{
     1965        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
     1966        int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR);
     1967        int val2 = snd_cs46xx_peekBA0(chip, BA0_EGPIOPTR);
     1968
     1969        if (ucontrol->value.integer.value[0]) {
     1970                /* optical is default */
     1971                snd_cs46xx_pokeBA0(chip, BA0_EGPIODR,
     1972                                   EGPIODR_GPOE0 | val1);  /* enable EGPIO0 output */
     1973                snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR,
     1974                                   EGPIOPTR_GPPT0 | val2); /* open-drain on output */
     1975        } else {
     1976                /* coaxial */
     1977                snd_cs46xx_pokeBA0(chip, BA0_EGPIODR,  val1 & ~EGPIODR_GPOE0); /* disable */
     1978                snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, val2 & ~EGPIOPTR_GPPT0); /* disable */
     1979        }
     1980
     1981        /* checking diff from the EGPIO direction register
     1982           should be enough */
     1983        return (val1 != (int)snd_cs46xx_peekBA0(chip, BA0_EGPIODR));
     1984}
     1985
     1986
     1987static int snd_cs46xx_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
     1988{
     1989        uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
     1990        uinfo->count = 1;
     1991        return 0;
     1992}
     1993
     1994static int snd_cs46xx_spdif_default_get(struct snd_kcontrol *kcontrol,
     1995                                        struct snd_ctl_elem_value *ucontrol)
     1996{
     1997        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
     1998        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     1999
     2000        down (&chip->spos_mutex);
     2001        ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_default >> 24) & 0xff);
     2002        ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_default >> 16) & 0xff);
     2003        ucontrol->value.iec958.status[2] = 0;
     2004        ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_default) & 0xff);
     2005        up (&chip->spos_mutex);
     2006
     2007        return 0;
     2008}
     2009
     2010static int snd_cs46xx_spdif_default_put(struct snd_kcontrol *kcontrol,
     2011                                        struct snd_ctl_elem_value *ucontrol)
     2012{
     2013        struct snd_cs46xx * chip = snd_kcontrol_chip(kcontrol);
     2014        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     2015        unsigned int val;
     2016        int change;
     2017
     2018        down (&chip->spos_mutex);
     2019        val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) |
     2020                ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[2]) << 16) |
     2021                ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3]))  |
     2022                /* left and right validity bit */
     2023                (1 << 13) | (1 << 12);
     2024
     2025
     2026        change = (unsigned int)ins->spdif_csuv_default != val;
     2027        ins->spdif_csuv_default = val;
     2028
     2029        if ( !(ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) )
     2030                cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val);
     2031
     2032        up (&chip->spos_mutex);
     2033
     2034        return change;
     2035}
     2036
     2037static int snd_cs46xx_spdif_mask_get(struct snd_kcontrol *kcontrol,
     2038                                     struct snd_ctl_elem_value *ucontrol)
     2039{
     2040        ucontrol->value.iec958.status[0] = 0xff;
     2041        ucontrol->value.iec958.status[1] = 0xff;
     2042        ucontrol->value.iec958.status[2] = 0x00;
     2043        ucontrol->value.iec958.status[3] = 0xff;
     2044        return 0;
     2045}
     2046
     2047static int snd_cs46xx_spdif_stream_get(struct snd_kcontrol *kcontrol,
     2048                                         struct snd_ctl_elem_value *ucontrol)
     2049{
     2050        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
     2051        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     2052
     2053        down (&chip->spos_mutex);
     2054        ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_stream >> 24) & 0xff);
     2055        ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_stream >> 16) & 0xff);
     2056        ucontrol->value.iec958.status[2] = 0;
     2057        ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_stream) & 0xff);
     2058        up (&chip->spos_mutex);
     2059
     2060        return 0;
     2061}
     2062
     2063static int snd_cs46xx_spdif_stream_put(struct snd_kcontrol *kcontrol,
     2064                                        struct snd_ctl_elem_value *ucontrol)
     2065{
     2066        struct snd_cs46xx * chip = snd_kcontrol_chip(kcontrol);
     2067        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     2068        unsigned int val;
     2069        int change;
     2070
     2071        down (&chip->spos_mutex);
     2072        val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) |
     2073                ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[1]) << 16) |
     2074                ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) |
     2075                /* left and right validity bit */
     2076                (1 << 13) | (1 << 12);
     2077
     2078
     2079        change = ins->spdif_csuv_stream != val;
     2080        ins->spdif_csuv_stream = val;
     2081
     2082        if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN )
     2083                cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val);
     2084
     2085        up (&chip->spos_mutex);
     2086
     2087        return change;
    21442088}
    21452089
     
    21482092
    21492093#ifdef CONFIG_SND_CS46XX_DEBUG_GPIO
    2150 static int snd_cs46xx_egpio_select_info(snd_kcontrol_t *kcontrol,
    2151                                         snd_ctl_elem_info_t *uinfo)
    2152 {
    2153     uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
    2154     uinfo->count = 1;
    2155     uinfo->value.integer.min = 0;
    2156     uinfo->value.integer.max = 8;
    2157     return 0;
    2158 }
    2159 
    2160 static int snd_cs46xx_egpio_select_get(snd_kcontrol_t *kcontrol,
    2161                                        snd_ctl_elem_value_t *ucontrol)
    2162 {
    2163     cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
    2164     ucontrol->value.integer.value[0] = chip->current_gpio;
    2165 
    2166     return 0;
    2167 }
    2168 
    2169 static int snd_cs46xx_egpio_select_put(snd_kcontrol_t *kcontrol,
    2170                                        snd_ctl_elem_value_t *ucontrol)
    2171 {
    2172     cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
    2173     int change = (chip->current_gpio != ucontrol->value.integer.value[0]);
    2174     chip->current_gpio = ucontrol->value.integer.value[0];
    2175 
    2176     return change;
    2177 }
    2178 
    2179 
    2180 static int snd_cs46xx_egpio_get(snd_kcontrol_t *kcontrol,
    2181                                 snd_ctl_elem_value_t *ucontrol)
    2182 {
    2183     cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
    2184     int reg = kcontrol->private_value;
    2185 
    2186     snd_printdd ("put: reg = %04x, gpio %02x\n",reg,chip->current_gpio);
    2187     ucontrol->value.integer.value[0] =
    2188         (snd_cs46xx_peekBA0(chip, reg) & (1 << chip->current_gpio)) ? 1 : 0;
    2189 
    2190     return 0;
    2191 }
    2192 
    2193 static int snd_cs46xx_egpio_put(snd_kcontrol_t *kcontrol,
    2194                                 snd_ctl_elem_value_t *ucontrol)
    2195 {
    2196     cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
    2197     int reg = kcontrol->private_value;
    2198     int val = snd_cs46xx_peekBA0(chip, reg);
    2199     int oldval = val;
    2200     snd_printdd ("put: reg = %04x, gpio %02x\n",reg,chip->current_gpio);
    2201 
    2202     if (ucontrol->value.integer.value[0])
    2203         val |= (1 << chip->current_gpio);
    2204     else
    2205         val &= ~(1 << chip->current_gpio);
    2206 
    2207     snd_cs46xx_pokeBA0(chip, reg,val);
    2208     snd_printdd ("put: val %08x oldval %08x\n",val,oldval);
    2209 
    2210     return (oldval != val);
     2094static int snd_cs46xx_egpio_select_info(struct snd_kcontrol *kcontrol,
     2095                                        struct snd_ctl_elem_info *uinfo)
     2096{
     2097        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
     2098        uinfo->count = 1;
     2099        uinfo->value.integer.min = 0;
     2100        uinfo->value.integer.max = 8;
     2101        return 0;
     2102}
     2103
     2104static int snd_cs46xx_egpio_select_get(struct snd_kcontrol *kcontrol,
     2105                                       struct snd_ctl_elem_value *ucontrol)
     2106{
     2107        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
     2108        ucontrol->value.integer.value[0] = chip->current_gpio;
     2109
     2110        return 0;
     2111}
     2112
     2113static int snd_cs46xx_egpio_select_put(struct snd_kcontrol *kcontrol,
     2114                                       struct snd_ctl_elem_value *ucontrol)
     2115{
     2116        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
     2117        int change = (chip->current_gpio != ucontrol->value.integer.value[0]);
     2118        chip->current_gpio = ucontrol->value.integer.value[0];
     2119
     2120        return change;
     2121}
     2122
     2123
     2124static int snd_cs46xx_egpio_get(struct snd_kcontrol *kcontrol,
     2125                                       struct snd_ctl_elem_value *ucontrol)
     2126{
     2127        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
     2128        int reg = kcontrol->private_value;
     2129
     2130        snd_printdd ("put: reg = %04x, gpio %02x\n",reg,chip->current_gpio);
     2131        ucontrol->value.integer.value[0] =
     2132                (snd_cs46xx_peekBA0(chip, reg) & (1 << chip->current_gpio)) ? 1 : 0;
     2133 
     2134        return 0;
     2135}
     2136
     2137static int snd_cs46xx_egpio_put(struct snd_kcontrol *kcontrol,
     2138                                       struct snd_ctl_elem_value *ucontrol)
     2139{
     2140        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
     2141        int reg = kcontrol->private_value;
     2142        int val = snd_cs46xx_peekBA0(chip, reg);
     2143        int oldval = val;
     2144        snd_printdd ("put: reg = %04x, gpio %02x\n",reg,chip->current_gpio);
     2145
     2146        if (ucontrol->value.integer.value[0])
     2147                val |= (1 << chip->current_gpio);
     2148        else
     2149                val &= ~(1 << chip->current_gpio);
     2150
     2151        snd_cs46xx_pokeBA0(chip, reg,val);
     2152        snd_printdd ("put: val %08x oldval %08x\n",val,oldval);
     2153
     2154        return (oldval != val);
    22112155}
    22122156#endif /* CONFIG_SND_CS46XX_DEBUG_GPIO */
    22132157
    2214 static snd_kcontrol_new_t snd_cs46xx_controls[] __devinitdata = {
    2215     {
    2216         SNDRV_CTL_ELEM_IFACE_MIXER,0,0,
    2217         "DAC Volume",0,0,0,
    2218         snd_cs46xx_vol_info,
     2158static struct snd_kcontrol_new snd_cs46xx_controls[] __devinitdata = {
     2159{
     2160        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
     2161        .name = "DAC Volume",
     2162        .info = snd_cs46xx_vol_info,
    22192163#ifndef CONFIG_SND_CS46XX_NEW_DSP
    2220         snd_cs46xx_vol_get,
    2221         snd_cs46xx_vol_put,
    2222         BA1_PVOL,
     2164        .get = snd_cs46xx_vol_get,
     2165        .put = snd_cs46xx_vol_put,
     2166        .private_value = BA1_PVOL,
    22232167#else
    2224         snd_cs46xx_vol_dac_get,
    2225         snd_cs46xx_vol_dac_put,
    2226         0
    2227 #endif
    2228     },
    2229     {
    2230         SNDRV_CTL_ELEM_IFACE_MIXER,0,0,
    2231         "ADC Volume",0,0,0,
    2232         snd_cs46xx_vol_info,
    2233         snd_cs46xx_vol_get,
    2234         snd_cs46xx_vol_put,
     2168        .get = snd_cs46xx_vol_dac_get,
     2169        .put = snd_cs46xx_vol_dac_put,
     2170#endif
     2171},
     2172
     2173{
     2174        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
     2175        .name = "ADC Volume",
     2176        .info = snd_cs46xx_vol_info,
     2177        .get = snd_cs46xx_vol_get,
     2178        .put = snd_cs46xx_vol_put,
    22352179#ifndef CONFIG_SND_CS46XX_NEW_DSP
    2236         BA1_CVOL,
     2180        .private_value = BA1_CVOL,
    22372181#else
    2238         (VARIDECIMATE_SCB_ADDR + 0xE) << 2,
    2239 #endif
    2240     },
    2241 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    2242     {
    2243         /* .iface = */SNDRV_CTL_ELEM_IFACE_MIXER,0,0,
    2244         /* .name = */"ADC Capture Switch",0,0,0,
    2245         /* .info = */snd_mixer_boolean_info,
    2246         /* .get = */snd_cs46xx_adc_capture_get,
    2247         /* .put = */snd_cs46xx_adc_capture_put,0
    2248     },
    2249     {
    2250         /* .iface = */SNDRV_CTL_ELEM_IFACE_MIXER,0,0,
    2251         /* .name = */"DAC Capture Switch",0,0,0,
    2252         /* .info = */snd_mixer_boolean_info,
    2253         /* .get = */snd_cs46xx_pcm_capture_get,
    2254         /* .put = */snd_cs46xx_pcm_capture_put,0
    2255     },
    2256     {
    2257         /* .iface = */SNDRV_CTL_ELEM_IFACE_MIXER,0,0,
    2258         /* .name = */"IEC958 Output Switch",0,0,0,
    2259         /* .info = */snd_mixer_boolean_info,
    2260         /* .get = */snd_cs46xx_iec958_get,
    2261         /* .put = */snd_cs46xx_iec958_put,
    2262         /* .private_value = */CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT,
    2263     },
    2264     {
    2265         /* .iface = */SNDRV_CTL_ELEM_IFACE_MIXER,0,0,
    2266         /* .name = */"IEC958 Input Switch",0,0,0,
    2267         /* .info = */snd_mixer_boolean_info,
    2268         /* .get = */snd_cs46xx_iec958_get,
    2269         /* .put = */snd_cs46xx_iec958_put,
    2270         /* .private_value = */CS46XX_MIXER_SPDIF_INPUT_ELEMENT,
    2271     },
     2182        .private_value = (VARIDECIMATE_SCB_ADDR + 0xE) << 2,
     2183#endif
     2184},
     2185#ifdef CONFIG_SND_CS46XX_NEW_DSP
     2186{
     2187        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
     2188        .name = "ADC Capture Switch",
     2189        .info = snd_mixer_boolean_info,
     2190        .get = snd_cs46xx_adc_capture_get,
     2191        .put = snd_cs46xx_adc_capture_put
     2192},
     2193{
     2194        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
     2195        .name = "DAC Capture Switch",
     2196        .info = snd_mixer_boolean_info,
     2197        .get = snd_cs46xx_pcm_capture_get,
     2198        .put = snd_cs46xx_pcm_capture_put
     2199},
     2200{
     2201        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
     2202        .name = SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH),
     2203        .info = snd_mixer_boolean_info,
     2204        .get = snd_cs46xx_iec958_get,
     2205        .put = snd_cs46xx_iec958_put,
     2206        .private_value = CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT,
     2207},
     2208{
     2209        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
     2210        .name = SNDRV_CTL_NAME_IEC958("Input ",NONE,SWITCH),
     2211        .info = snd_mixer_boolean_info,
     2212        .get = snd_cs46xx_iec958_get,
     2213        .put = snd_cs46xx_iec958_put,
     2214        .private_value = CS46XX_MIXER_SPDIF_INPUT_ELEMENT,
     2215},
    22722216#if 0
    2273     /* Input IEC958 volume does not work for the moment. (Benny) */
    2274     {
    2275         /* .iface = */SNDRV_CTL_ELEM_IFACE_MIXER,0,0,
    2276         /* .name = */"IEC958 Input Volume",0,0,0,
    2277         /* .info = */snd_cs46xx_vol_info,
    2278         /* .get = */snd_cs46xx_vol_iec958_get,
    2279         /* .put = */snd_cs46xx_vol_iec958_put,
    2280         /* .private_value = */(ASYNCRX_SCB_ADDR + 0xE) << 2,
    2281     },
    2282 #endif
    2283     {
    2284         /* .iface = */SNDRV_CTL_ELEM_IFACE_PCM,0,0,
    2285         /* .name =  */SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),0,0,0,
    2286         /* .info =  */      snd_cs46xx_spdif_info,
    2287         /* .get =   */      snd_cs46xx_spdif_default_get,
    2288         /* .put =   */snd_cs46xx_spdif_default_put,0
    2289     },
    2290     {
    2291         /* .iface = */SNDRV_CTL_ELEM_IFACE_PCM,0,0,
    2292         /* .name =  */      SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),0,
    2293         SNDRV_CTL_ELEM_ACCESS_READ,0,
    2294         /* .info =  */      snd_cs46xx_spdif_info,
    2295         /* .get =   */      snd_cs46xx_spdif_mask_get,NULL,0
    2296     },
    2297     {
    2298         /* .iface = */SNDRV_CTL_ELEM_IFACE_PCM,0,0,
    2299         /* .name =  */      SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),0,0,0,
    2300         /* .info =  */      snd_cs46xx_spdif_info,
    2301         /* .get =   */      snd_cs46xx_spdif_stream_get,
    2302         /* .put =   */      snd_cs46xx_spdif_stream_put,0
    2303     },
     2217/* Input IEC958 volume does not work for the moment. (Benny) */
     2218{
     2219        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
     2220        .name = SNDRV_CTL_NAME_IEC958("Input ",NONE,VOLUME),
     2221        .info = snd_cs46xx_vol_info,
     2222        .get = snd_cs46xx_vol_iec958_get,
     2223        .put = snd_cs46xx_vol_iec958_put,
     2224        .private_value = (ASYNCRX_SCB_ADDR + 0xE) << 2,
     2225},
     2226#endif
     2227{
     2228        .iface = SNDRV_CTL_ELEM_IFACE_PCM,
     2229        .name =  SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
     2230        .info =  snd_cs46xx_spdif_info,
     2231        .get =   snd_cs46xx_spdif_default_get,
     2232        .put =   snd_cs46xx_spdif_default_put,
     2233},
     2234{
     2235        .iface = SNDRV_CTL_ELEM_IFACE_PCM,
     2236        .name =  SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
     2237        .info =  snd_cs46xx_spdif_info,
     2238        .get =   snd_cs46xx_spdif_mask_get,
     2239        .access = SNDRV_CTL_ELEM_ACCESS_READ
     2240},
     2241{
     2242        .iface = SNDRV_CTL_ELEM_IFACE_PCM,
     2243        .name =  SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
     2244        .info =  snd_cs46xx_spdif_info,
     2245        .get =   snd_cs46xx_spdif_stream_get,
     2246        .put =   snd_cs46xx_spdif_stream_put
     2247},
     2248
    23042249#endif
    23052250#ifdef CONFIG_SND_CS46XX_DEBUG_GPIO
    2306     {
    2307         /* .iface = */SNDRV_CTL_ELEM_IFACE_MIXER,0,0,
    2308         /* .name = */"EGPIO select",0,0,0,
    2309         /* .info = */snd_cs46xx_egpio_select_info,
    2310         /* .get = */snd_cs46xx_egpio_select_get,
    2311         /* .put = */snd_cs46xx_egpio_select_put,
    2312         /* .private_value = */0,
    2313     },
    2314     {
    2315         /* .iface = */SNDRV_CTL_ELEM_IFACE_MIXER,0,0,
    2316         /* .name = */"EGPIO Input/Output",0,0,0,
    2317         /* .info = */snd_mixer_boolean_info,
    2318         /* .get = */snd_cs46xx_egpio_get,
    2319         /* .put = */snd_cs46xx_egpio_put,
    2320         /* .private_value = */BA0_EGPIODR,
    2321     },
    2322     {
    2323         /* .iface = */SNDRV_CTL_ELEM_IFACE_MIXER,0,0,
    2324         /* .name = */"EGPIO CMOS/Open drain",0,0,0,
    2325         /* .info = */snd_mixer_boolean_info,
    2326         /* .get = */snd_cs46xx_egpio_get,
    2327         /* .put = */snd_cs46xx_egpio_put,
    2328         /* .private_value = */BA0_EGPIOPTR,
    2329     },
    2330     {
    2331         /* .iface = */SNDRV_CTL_ELEM_IFACE_MIXER,0,0,
    2332         /* .name = */"EGPIO On/Off",0,0,0,
    2333         /* .info = */snd_mixer_boolean_info,
    2334         /* .get = */snd_cs46xx_egpio_get,
    2335         /* .put = */snd_cs46xx_egpio_put,
    2336         /* .private_value = */BA0_EGPIOSR
    2337     },
     2251{
     2252        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
     2253        .name = "EGPIO select",
     2254        .info = snd_cs46xx_egpio_select_info,
     2255        .get = snd_cs46xx_egpio_select_get,
     2256        .put = snd_cs46xx_egpio_select_put,
     2257        .private_value = 0,
     2258},
     2259{
     2260        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
     2261        .name = "EGPIO Input/Output",
     2262        .info = snd_mixer_boolean_info,
     2263        .get = snd_cs46xx_egpio_get,
     2264        .put = snd_cs46xx_egpio_put,
     2265        .private_value = BA0_EGPIODR,
     2266},
     2267{
     2268        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
     2269        .name = "EGPIO CMOS/Open drain",
     2270        .info = snd_mixer_boolean_info,
     2271        .get = snd_cs46xx_egpio_get,
     2272        .put = snd_cs46xx_egpio_put,
     2273        .private_value = BA0_EGPIOPTR,
     2274},
     2275{
     2276        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
     2277        .name = "EGPIO On/Off",
     2278        .info = snd_mixer_boolean_info,
     2279        .get = snd_cs46xx_egpio_get,
     2280        .put = snd_cs46xx_egpio_put,
     2281        .private_value = BA0_EGPIOSR,
     2282},
    23382283#endif
    23392284};
     
    23412286#ifdef CONFIG_SND_CS46XX_NEW_DSP
    23422287/* set primary cs4294 codec into Extended Audio Mode */
    2343 static int snd_cs46xx_front_dup_get(snd_kcontrol_t *kcontrol,
    2344                                     snd_ctl_elem_value_t *ucontrol)
    2345 {
    2346     cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
    2347     unsigned short val;
    2348     val = snd_ac97_read(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX], AC97_CSR_ACMODE);
    2349     ucontrol->value.integer.value[0] = (val & 0x200) ? 0 : 1;
    2350     return 0;
    2351 }
    2352 
    2353 static int snd_cs46xx_front_dup_put(snd_kcontrol_t *kcontrol,
    2354                                     snd_ctl_elem_value_t *ucontrol)
    2355 {
    2356     cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
    2357     return snd_ac97_update_bits(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX],
    2358                                 AC97_CSR_ACMODE, 0x200,
    2359                                 ucontrol->value.integer.value[0] ? 0 : 0x200);
    2360 }
    2361 
    2362 static snd_kcontrol_new_t snd_cs46xx_front_dup_ctl = {
    2363     /*.iface = */SNDRV_CTL_ELEM_IFACE_MIXER, 0,0,
    2364     /*.name = */"Duplicate Front",0,0,0,
    2365     /*.info = */snd_mixer_boolean_info,
    2366     /*.get = */snd_cs46xx_front_dup_get,
    2367     /*.put = */snd_cs46xx_front_dup_put,0
     2288static int snd_cs46xx_front_dup_get(struct snd_kcontrol *kcontrol,
     2289                                    struct snd_ctl_elem_value *ucontrol)
     2290{
     2291        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
     2292        unsigned short val;
     2293        val = snd_ac97_read(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX], AC97_CSR_ACMODE);
     2294        ucontrol->value.integer.value[0] = (val & 0x200) ? 0 : 1;
     2295        return 0;
     2296}
     2297
     2298static int snd_cs46xx_front_dup_put(struct snd_kcontrol *kcontrol,
     2299                                    struct snd_ctl_elem_value *ucontrol)
     2300{
     2301        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
     2302        return snd_ac97_update_bits(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX],
     2303                                    AC97_CSR_ACMODE, 0x200,
     2304                                    ucontrol->value.integer.value[0] ? 0 : 0x200);
     2305}
     2306
     2307static struct snd_kcontrol_new snd_cs46xx_front_dup_ctl = {
     2308        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
     2309        .name = "Duplicate Front",
     2310        .info = snd_mixer_boolean_info,
     2311        .get = snd_cs46xx_front_dup_get,
     2312        .put = snd_cs46xx_front_dup_put,
    23682313};
    23692314#endif
    23702315
    23712316#ifdef CONFIG_SND_CS46XX_NEW_DSP
    2372 /* Only available on the Hercules Game Theater XP soundcard */
    2373 static snd_kcontrol_new_t snd_hercules_controls[] __devinitdata = {
    2374     {
    2375         /* .iface = */SNDRV_CTL_ELEM_IFACE_MIXER,0,0,
    2376         /* .name =  */"Optical/Coaxial SPDIF Input Switch",0,0,0,
    2377         /* .info =  */snd_mixer_boolean_info,
    2378         /* .get =   */snd_herc_spdif_select_get,
    2379         /* .put =   */snd_herc_spdif_select_put,0,
    2380     }
     2317/* Only available on the Hercules Game Theater XP soundcard */
     2318static struct snd_kcontrol_new snd_hercules_controls[] __devinitdata = {
     2319{
     2320        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
     2321        .name = "Optical/Coaxial SPDIF Input Switch",
     2322        .info = snd_mixer_boolean_info,
     2323        .get = snd_herc_spdif_select_get,
     2324        .put = snd_herc_spdif_select_put,
     2325},
    23812326};
    23822327
    23832328
    2384 static void snd_cs46xx_codec_reset (ac97_t * ac97)
    2385 {
    2386     unsigned long end_time;
    2387     int err;
    2388 
    2389     /* reset to defaults */
    2390     snd_ac97_write(ac97, AC97_RESET, 0);
    2391 
    2392     /* set the desired CODEC mode */
    2393     if (ac97->num == CS46XX_PRIMARY_CODEC_INDEX) {
    2394         snd_printdd("cs46xx: CODOEC1 mode %04x\n",0x0);
    2395         snd_cs46xx_ac97_write(ac97,AC97_CSR_ACMODE,0x0);
    2396     } else if (ac97->num == CS46XX_SECONDARY_CODEC_INDEX) {
    2397         snd_printdd("cs46xx: CODOEC2 mode %04x\n",0x3);
    2398         snd_cs46xx_ac97_write(ac97,AC97_CSR_ACMODE,0x3);
    2399     } else {
    2400         //              snd_assert(0); /* should never happen ... */
    2401     }
    2402 
    2403     udelay(50);
    2404 
    2405     /* it's necessary to wait awhile until registers are accessible after RESET */
    2406     /* because the PCM or MASTER volume registers can be modified, */
    2407     /* the REC_GAIN register is used for tests */
    2408     end_time = jiffies + HZ;
    2409     do {
    2410         unsigned short ext_mid;
    2411 
    2412         /* use preliminary reads to settle the communication */
    2413         snd_ac97_read(ac97, AC97_RESET);
    2414         snd_ac97_read(ac97, AC97_VENDOR_ID1);
    2415         snd_ac97_read(ac97, AC97_VENDOR_ID2);
    2416         /* modem? */
    2417         ext_mid = snd_ac97_read(ac97, AC97_EXTENDED_MID);
    2418         if (ext_mid != 0xffff && (ext_mid & 1) != 0)
    2419             return;
    2420 
    2421         /* test if we can write to the record gain volume register */
    2422         snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a05);
    2423         if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a05)
    2424             return;
    2425 
    2426         msleep(10);
    2427     } while (time_after_eq(end_time, jiffies));
    2428 
    2429     snd_printk("CS46xx secondary codec dont respond!\n");
    2430 }
    2431 #endif
    2432 
    2433 static int __devinit cs46xx_detect_codec(cs46xx_t *chip, int codec)
    2434 {
    2435     int idx, err;
    2436     ac97_template_t ac97;
    2437 
    2438     memset(&ac97, 0, sizeof(ac97));
    2439     ac97.private_data = chip;
    2440     ac97.private_free = snd_cs46xx_mixer_free_ac97;
    2441     ac97.num = codec;
    2442     if (chip->amplifier_ctrl == amp_voyetra)
    2443         ac97.scaps = AC97_SCAP_INV_EAPD;
    2444 
    2445     if (codec == CS46XX_SECONDARY_CODEC_INDEX) {
    2446         snd_cs46xx_codec_write(chip, AC97_RESET, 0, codec);
    2447         udelay(10);
    2448         if (snd_cs46xx_codec_read(chip, AC97_RESET, codec) & 0x8000) {
    2449             snd_printdd("snd_cs46xx: seconadry codec not present\n");
    2450             return -ENXIO;
    2451         }
    2452     }
    2453 
    2454     snd_cs46xx_codec_write(chip, AC97_MASTER, 0x8000, codec);
    2455     for (idx = 0; idx < 100; ++idx) {
    2456         if (snd_cs46xx_codec_read(chip, AC97_MASTER, codec) == 0x8000) {
    2457             err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97[codec]);
    2458             return err;
    2459         }
    2460         msleep(10);
    2461     }
    2462     snd_printdd("snd_cs46xx: codec %d detection timeout\n", codec);
    2463     return -ENXIO;
    2464 }
    2465 
    2466 int __devinit snd_cs46xx_mixer(cs46xx_t *chip)
    2467 {
    2468     snd_card_t *card = chip->card;
    2469     snd_ctl_elem_id_t id;
    2470     int err;
    2471     unsigned int idx;
    2472     static ac97_bus_ops_t ops = {
    2473 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    2474         snd_cs46xx_codec_reset,
    2475 #else
    2476         0,
    2477 #endif
    2478         snd_cs46xx_ac97_write,
    2479         snd_cs46xx_ac97_read,0,0
    2480     };
    2481     /* detect primary codec */
    2482     chip->nr_ac97_codecs = 0;
    2483     snd_printdd("snd_cs46xx: detecting primary codec\n");
    2484     if ((err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus)) < 0)
    2485         return err;
    2486     chip->ac97_bus->private_free = snd_cs46xx_mixer_free_ac97_bus;
    2487 
    2488     if (cs46xx_detect_codec(chip, CS46XX_PRIMARY_CODEC_INDEX) < 0)
    2489         return -ENXIO;
    2490     chip->nr_ac97_codecs = 1;
    2491 
    2492 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    2493         snd_printdd("snd_cs46xx: detecting seconadry codec\n");
    2494         /* try detect a secondary codec */
    2495         if (! cs46xx_detect_codec(chip, CS46XX_SECONDARY_CODEC_INDEX))
    2496             chip->nr_ac97_codecs = 2;
     2329static void snd_cs46xx_codec_reset (struct snd_ac97 * ac97)
     2330{
     2331        unsigned long end_time;
     2332        int err;
     2333
     2334        /* reset to defaults */
     2335        snd_ac97_write(ac97, AC97_RESET, 0);   
     2336
     2337        /* set the desired CODEC mode */
     2338        if (ac97->num == CS46XX_PRIMARY_CODEC_INDEX) {
     2339                snd_printdd("cs46xx: CODOEC1 mode %04x\n",0x0);
     2340                snd_cs46xx_ac97_write(ac97,AC97_CSR_ACMODE,0x0);
     2341        } else if (ac97->num == CS46XX_SECONDARY_CODEC_INDEX) {
     2342                snd_printdd("cs46xx: CODOEC2 mode %04x\n",0x3);
     2343                snd_cs46xx_ac97_write(ac97,AC97_CSR_ACMODE,0x3);
     2344        } else {
     2345                snd_assert(0); /* should never happen ... */
     2346        }
     2347
     2348        udelay(50);
     2349
     2350        /* it's necessary to wait awhile until registers are accessible after RESET */
     2351        /* because the PCM or MASTER volume registers can be modified, */
     2352        /* the REC_GAIN register is used for tests */
     2353        end_time = jiffies + HZ;
     2354        do {
     2355                unsigned short ext_mid;
     2356   
     2357                /* use preliminary reads to settle the communication */
     2358                snd_ac97_read(ac97, AC97_RESET);
     2359                snd_ac97_read(ac97, AC97_VENDOR_ID1);
     2360                snd_ac97_read(ac97, AC97_VENDOR_ID2);
     2361                /* modem? */
     2362                ext_mid = snd_ac97_read(ac97, AC97_EXTENDED_MID);
     2363                if (ext_mid != 0xffff && (ext_mid & 1) != 0)
     2364                        return;
     2365
     2366                /* test if we can write to the record gain volume register */
     2367                snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a05);
     2368                if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a05)
     2369                        return;
     2370
     2371                msleep(10);
     2372        } while (time_after_eq(end_time, jiffies));
     2373
     2374        snd_printk(KERN_ERR "CS46xx secondary codec doesn't respond!\n"); 
     2375}
     2376#endif
     2377
     2378static int __devinit cs46xx_detect_codec(struct snd_cs46xx *chip, int codec)
     2379{
     2380        int idx, err;
     2381        struct snd_ac97_template ac97;
     2382
     2383        memset(&ac97, 0, sizeof(ac97));
     2384        ac97.private_data = chip;
     2385        ac97.private_free = snd_cs46xx_mixer_free_ac97;
     2386        ac97.num = codec;
     2387        if (chip->amplifier_ctrl == amp_voyetra)
     2388                ac97.scaps = AC97_SCAP_INV_EAPD;
     2389
     2390        if (codec == CS46XX_SECONDARY_CODEC_INDEX) {
     2391                snd_cs46xx_codec_write(chip, AC97_RESET, 0, codec);
     2392                udelay(10);
     2393                if (snd_cs46xx_codec_read(chip, AC97_RESET, codec) & 0x8000) {
     2394                        snd_printdd("snd_cs46xx: seconadry codec not present\n");
     2395                        return -ENXIO;
     2396                }
     2397        }
     2398
     2399        snd_cs46xx_codec_write(chip, AC97_MASTER, 0x8000, codec);
     2400        for (idx = 0; idx < 100; ++idx) {
     2401                if (snd_cs46xx_codec_read(chip, AC97_MASTER, codec) == 0x8000) {
     2402                        err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97[codec]);
     2403                        return err;
     2404                }
     2405                msleep(10);
     2406        }
     2407        snd_printdd("snd_cs46xx: codec %d detection timeout\n", codec);
     2408        return -ENXIO;
     2409}
     2410
     2411int __devinit snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device)
     2412{
     2413        struct snd_card *card = chip->card;
     2414        struct snd_ctl_elem_id id;
     2415        int err;
     2416        unsigned int idx;
     2417        static struct snd_ac97_bus_ops ops = {
     2418#ifdef CONFIG_SND_CS46XX_NEW_DSP
     2419                .reset = snd_cs46xx_codec_reset,
     2420#endif
     2421                .write = snd_cs46xx_ac97_write,
     2422                .read = snd_cs46xx_ac97_read,
     2423        };
     2424
     2425        /* detect primary codec */
     2426        chip->nr_ac97_codecs = 0;
     2427        snd_printdd("snd_cs46xx: detecting primary codec\n");
     2428        if ((err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus)) < 0)
     2429                return err;
     2430        chip->ac97_bus->private_free = snd_cs46xx_mixer_free_ac97_bus;
     2431
     2432        if (cs46xx_detect_codec(chip, CS46XX_PRIMARY_CODEC_INDEX) < 0)
     2433                return -ENXIO;
     2434        chip->nr_ac97_codecs = 1;
     2435
     2436#ifdef CONFIG_SND_CS46XX_NEW_DSP
     2437        snd_printdd("snd_cs46xx: detecting seconadry codec\n");
     2438        /* try detect a secondary codec */
     2439        if (! cs46xx_detect_codec(chip, CS46XX_SECONDARY_CODEC_INDEX))
     2440                chip->nr_ac97_codecs = 2;
    24972441#endif /* CONFIG_SND_CS46XX_NEW_DSP */
    24982442
    2499                 /* add cs4630 mixer controls */
    2500                 for (idx = 0; idx < ARRAY_SIZE(snd_cs46xx_controls); idx++) {
    2501                     snd_kcontrol_t *kctl;
    2502                     kctl = snd_ctl_new1(&snd_cs46xx_controls[idx], chip);
    2503                     if ((err = snd_ctl_add(card, kctl)) < 0)
    2504                         return err;
    2505                 }
    2506 
    2507                 /* get EAPD mixer switch (for voyetra hack) */
    2508                 memset(&id, 0, sizeof(id));
    2509                 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
    2510                 strcpy(id.name, "External Amplifier");
    2511                 chip->eapd_switch = snd_ctl_find_id(chip->card, &id);
    2512 
    2513 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    2514                 if (chip->nr_ac97_codecs == 1) {
    2515                     unsigned int id2 = chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]->id & 0xffff;
    2516                     if (id2 == 0x592b || id2 == 0x592d) {
    2517                         err = snd_ctl_add(card, snd_ctl_new1(&snd_cs46xx_front_dup_ctl, chip));
    2518                         if (err < 0)
    2519                             return err;
    2520                         snd_ac97_write_cache(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX],
    2521                                              AC97_CSR_ACMODE, 0x200);
    2522                     }
    2523                 }
    2524                 /* do soundcard specific mixer setup */
    2525                 if (chip->mixer_init) {
    2526                     snd_printdd ("calling chip->mixer_init(chip);\n");
    2527                     chip->mixer_init(chip);
    2528                 }
    2529 #endif
    2530 
    2531                 /* turn on amplifier */
    2532                 chip->amplifier_ctrl(chip, 1);
    2533 
    2534                 return 0;
     2443        /* add cs4630 mixer controls */
     2444        for (idx = 0; idx < ARRAY_SIZE(snd_cs46xx_controls); idx++) {
     2445                struct snd_kcontrol *kctl;
     2446                kctl = snd_ctl_new1(&snd_cs46xx_controls[idx], chip);
     2447                if (kctl && kctl->id.iface == SNDRV_CTL_ELEM_IFACE_PCM)
     2448                        kctl->id.device = spdif_device;
     2449                if ((err = snd_ctl_add(card, kctl)) < 0)
     2450                        return err;
     2451        }
     2452
     2453        /* get EAPD mixer switch (for voyetra hack) */
     2454        memset(&id, 0, sizeof(id));
     2455        id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
     2456        strcpy(id.name, "External Amplifier");
     2457        chip->eapd_switch = snd_ctl_find_id(chip->card, &id);
     2458   
     2459#ifdef CONFIG_SND_CS46XX_NEW_DSP
     2460        if (chip->nr_ac97_codecs == 1) {
     2461                unsigned int id2 = chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]->id & 0xffff;
     2462                if (id2 == 0x592b || id2 == 0x592d) {
     2463                        err = snd_ctl_add(card, snd_ctl_new1(&snd_cs46xx_front_dup_ctl, chip));
     2464                        if (err < 0)
     2465                                return err;
     2466                        snd_ac97_write_cache(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX],
     2467                                             AC97_CSR_ACMODE, 0x200);
     2468                }
     2469        }
     2470        /* do soundcard specific mixer setup */
     2471        if (chip->mixer_init) {
     2472                snd_printdd ("calling chip->mixer_init(chip);\n");
     2473                chip->mixer_init(chip);
     2474        }
     2475#endif
     2476
     2477        /* turn on amplifier */
     2478        chip->amplifier_ctrl(chip, 1);
     2479   
     2480        return 0;
    25352481}
    25362482
     
    25392485 */
    25402486
    2541 static void snd_cs46xx_midi_reset(cs46xx_t *chip)
    2542 {
    2543     snd_cs46xx_pokeBA0(chip, BA0_MIDCR, MIDCR_MRST);
    2544     udelay(100);
    2545     snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
    2546 }
    2547 
    2548 static int snd_cs46xx_midi_input_open(snd_rawmidi_substream_t * substream)
    2549 {
    2550     cs46xx_t *chip = substream->rmidi->private_data;
    2551 
    2552     chip->active_ctrl(chip, 1);
    2553     spin_lock_irq(&chip->reg_lock);
    2554     chip->uartm |= CS46XX_MODE_INPUT;
    2555     chip->midcr |= MIDCR_RXE;
    2556     chip->midi_input = substream;
    2557     if (!(chip->uartm & CS46XX_MODE_OUTPUT)) {
    2558         snd_cs46xx_midi_reset(chip);
    2559     } else {
    2560         snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
    2561     }
    2562     spin_unlock_irq(&chip->reg_lock);
    2563     return 0;
    2564 }
    2565 
    2566 static int snd_cs46xx_midi_input_close(snd_rawmidi_substream_t * substream)
    2567 {
    2568     cs46xx_t *chip = substream->rmidi->private_data;
    2569 
    2570     spin_lock_irq(&chip->reg_lock);
    2571     chip->midcr &= ~(MIDCR_RXE | MIDCR_RIE);
    2572     chip->midi_input = NULL;
    2573     if (!(chip->uartm & CS46XX_MODE_OUTPUT)) {
    2574         snd_cs46xx_midi_reset(chip);
    2575     } else {
    2576         snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
    2577     }
    2578     chip->uartm &= ~CS46XX_MODE_INPUT;
    2579     spin_unlock_irq(&chip->reg_lock);
    2580     chip->active_ctrl(chip, -1);
    2581     return 0;
    2582 }
    2583 
    2584 static int snd_cs46xx_midi_output_open(snd_rawmidi_substream_t * substream)
    2585 {
    2586     cs46xx_t *chip = substream->rmidi->private_data;
    2587 
    2588     chip->active_ctrl(chip, 1);
    2589 
    2590     spin_lock_irq(&chip->reg_lock);
    2591     chip->uartm |= CS46XX_MODE_OUTPUT;
    2592     chip->midcr |= MIDCR_TXE;
    2593     chip->midi_output = substream;
    2594     if (!(chip->uartm & CS46XX_MODE_INPUT)) {
    2595         snd_cs46xx_midi_reset(chip);
    2596     } else {
    2597         snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
    2598     }
    2599     spin_unlock_irq(&chip->reg_lock);
    2600     return 0;
    2601 }
    2602 
    2603 static int snd_cs46xx_midi_output_close(snd_rawmidi_substream_t * substream)
    2604 {
    2605     cs46xx_t *chip = substream->rmidi->private_data;
    2606 
    2607     spin_lock_irq(&chip->reg_lock);
    2608     chip->midcr &= ~(MIDCR_TXE | MIDCR_TIE);
    2609     chip->midi_output = NULL;
    2610     if (!(chip->uartm & CS46XX_MODE_INPUT)) {
    2611         snd_cs46xx_midi_reset(chip);
    2612     } else {
    2613         snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
    2614     }
    2615     chip->uartm &= ~CS46XX_MODE_OUTPUT;
    2616     spin_unlock_irq(&chip->reg_lock);
    2617     chip->active_ctrl(chip, -1);
    2618     return 0;
    2619 }
    2620 
    2621 static void snd_cs46xx_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
    2622 {
    2623     unsigned long flags;
    2624     cs46xx_t *chip = substream->rmidi->private_data;
    2625 
    2626     spin_lock_irqsave(&chip->reg_lock, flags);
    2627     if (up) {
    2628         if ((chip->midcr & MIDCR_RIE) == 0) {
    2629             chip->midcr |= MIDCR_RIE;
    2630             snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
    2631         }
    2632     } else {
    2633         if (chip->midcr & MIDCR_RIE) {
    2634             chip->midcr &= ~MIDCR_RIE;
    2635             snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
    2636         }
    2637     }
    2638     spin_unlock_irqrestore(&chip->reg_lock, flags);
    2639 }
    2640 
    2641 static void snd_cs46xx_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
    2642 {
    2643     unsigned long flags;
    2644     cs46xx_t *chip = substream->rmidi->private_data;
    2645     unsigned char byte;
    2646 
    2647     spin_lock_irqsave(&chip->reg_lock, flags);
    2648     if (up) {
    2649         if ((chip->midcr & MIDCR_TIE) == 0) {
    2650             chip->midcr |= MIDCR_TIE;
    2651             /* fill UART FIFO buffer at first, and turn Tx interrupts only if necessary */
    2652             while ((chip->midcr & MIDCR_TIE) &&
    2653                    (snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) {
    2654                 if (snd_rawmidi_transmit(substream, &byte, 1) != 1) {
    2655                     chip->midcr &= ~MIDCR_TIE;
    2656                 } else {
    2657                     snd_cs46xx_pokeBA0(chip, BA0_MIDWP, byte);
    2658                 }
    2659             }
    2660             snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
    2661         }
    2662     } else {
    2663         if (chip->midcr & MIDCR_TIE) {
    2664             chip->midcr &= ~MIDCR_TIE;
    2665             snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
    2666         }
    2667     }
    2668     spin_unlock_irqrestore(&chip->reg_lock, flags);
    2669 }
    2670 
    2671 static snd_rawmidi_ops_t snd_cs46xx_midi_output =
    2672 {
    2673     snd_cs46xx_midi_output_open,
    2674     snd_cs46xx_midi_output_close,
    2675     snd_cs46xx_midi_output_trigger,0
     2487static void snd_cs46xx_midi_reset(struct snd_cs46xx *chip)
     2488{
     2489        snd_cs46xx_pokeBA0(chip, BA0_MIDCR, MIDCR_MRST);
     2490        udelay(100);
     2491        snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
     2492}
     2493
     2494static int snd_cs46xx_midi_input_open(struct snd_rawmidi_substream *substream)
     2495{
     2496        struct snd_cs46xx *chip = substream->rmidi->private_data;
     2497
     2498        chip->active_ctrl(chip, 1);
     2499        spin_lock_irq(&chip->reg_lock);
     2500        chip->uartm |= CS46XX_MODE_INPUT;
     2501        chip->midcr |= MIDCR_RXE;
     2502        chip->midi_input = substream;
     2503        if (!(chip->uartm & CS46XX_MODE_OUTPUT)) {
     2504                snd_cs46xx_midi_reset(chip);
     2505        } else {
     2506                snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
     2507        }
     2508        spin_unlock_irq(&chip->reg_lock);
     2509        return 0;
     2510}
     2511
     2512static int snd_cs46xx_midi_input_close(struct snd_rawmidi_substream *substream)
     2513{
     2514        struct snd_cs46xx *chip = substream->rmidi->private_data;
     2515
     2516        spin_lock_irq(&chip->reg_lock);
     2517        chip->midcr &= ~(MIDCR_RXE | MIDCR_RIE);
     2518        chip->midi_input = NULL;
     2519        if (!(chip->uartm & CS46XX_MODE_OUTPUT)) {
     2520                snd_cs46xx_midi_reset(chip);
     2521        } else {
     2522                snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
     2523        }
     2524        chip->uartm &= ~CS46XX_MODE_INPUT;
     2525        spin_unlock_irq(&chip->reg_lock);
     2526        chip->active_ctrl(chip, -1);
     2527        return 0;
     2528}
     2529
     2530static int snd_cs46xx_midi_output_open(struct snd_rawmidi_substream *substream)
     2531{
     2532        struct snd_cs46xx *chip = substream->rmidi->private_data;
     2533
     2534        chip->active_ctrl(chip, 1);
     2535
     2536        spin_lock_irq(&chip->reg_lock);
     2537        chip->uartm |= CS46XX_MODE_OUTPUT;
     2538        chip->midcr |= MIDCR_TXE;
     2539        chip->midi_output = substream;
     2540        if (!(chip->uartm & CS46XX_MODE_INPUT)) {
     2541                snd_cs46xx_midi_reset(chip);
     2542        } else {
     2543                snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
     2544        }
     2545        spin_unlock_irq(&chip->reg_lock);
     2546        return 0;
     2547}
     2548
     2549static int snd_cs46xx_midi_output_close(struct snd_rawmidi_substream *substream)
     2550{
     2551        struct snd_cs46xx *chip = substream->rmidi->private_data;
     2552
     2553        spin_lock_irq(&chip->reg_lock);
     2554        chip->midcr &= ~(MIDCR_TXE | MIDCR_TIE);
     2555        chip->midi_output = NULL;
     2556        if (!(chip->uartm & CS46XX_MODE_INPUT)) {
     2557                snd_cs46xx_midi_reset(chip);
     2558        } else {
     2559                snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
     2560        }
     2561        chip->uartm &= ~CS46XX_MODE_OUTPUT;
     2562        spin_unlock_irq(&chip->reg_lock);
     2563        chip->active_ctrl(chip, -1);
     2564        return 0;
     2565}
     2566
     2567static void snd_cs46xx_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
     2568{
     2569        unsigned long flags;
     2570        struct snd_cs46xx *chip = substream->rmidi->private_data;
     2571
     2572        spin_lock_irqsave(&chip->reg_lock, flags);
     2573        if (up) {
     2574                if ((chip->midcr & MIDCR_RIE) == 0) {
     2575                        chip->midcr |= MIDCR_RIE;
     2576                        snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
     2577                }
     2578        } else {
     2579                if (chip->midcr & MIDCR_RIE) {
     2580                        chip->midcr &= ~MIDCR_RIE;
     2581                        snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
     2582                }
     2583        }
     2584        spin_unlock_irqrestore(&chip->reg_lock, flags);
     2585}
     2586
     2587static void snd_cs46xx_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
     2588{
     2589        unsigned long flags;
     2590        struct snd_cs46xx *chip = substream->rmidi->private_data;
     2591        unsigned char byte;
     2592
     2593        spin_lock_irqsave(&chip->reg_lock, flags);
     2594        if (up) {
     2595                if ((chip->midcr & MIDCR_TIE) == 0) {
     2596                        chip->midcr |= MIDCR_TIE;
     2597                        /* fill UART FIFO buffer at first, and turn Tx interrupts only if necessary */
     2598                        while ((chip->midcr & MIDCR_TIE) &&
     2599                               (snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) {
     2600                                if (snd_rawmidi_transmit(substream, &byte, 1) != 1) {
     2601                                        chip->midcr &= ~MIDCR_TIE;
     2602                                } else {
     2603                                        snd_cs46xx_pokeBA0(chip, BA0_MIDWP, byte);
     2604                                }
     2605                        }
     2606                        snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
     2607                }
     2608        } else {
     2609                if (chip->midcr & MIDCR_TIE) {
     2610                        chip->midcr &= ~MIDCR_TIE;
     2611                        snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
     2612                }
     2613        }
     2614        spin_unlock_irqrestore(&chip->reg_lock, flags);
     2615}
     2616
     2617static struct snd_rawmidi_ops snd_cs46xx_midi_output =
     2618{
     2619        .open =         snd_cs46xx_midi_output_open,
     2620        .close =        snd_cs46xx_midi_output_close,
     2621        .trigger =      snd_cs46xx_midi_output_trigger,
    26762622};
    26772623
    2678 static snd_rawmidi_ops_t snd_cs46xx_midi_input =
    2679 {
    2680     snd_cs46xx_midi_input_open,
    2681     snd_cs46xx_midi_input_close,
    2682     snd_cs46xx_midi_input_trigger,0
     2624static struct snd_rawmidi_ops snd_cs46xx_midi_input =
     2625{
     2626        .open =         snd_cs46xx_midi_input_open,
     2627        .close =        snd_cs46xx_midi_input_close,
     2628        .trigger =      snd_cs46xx_midi_input_trigger,
    26832629};
    26842630
    2685 int __devinit snd_cs46xx_midi(cs46xx_t *chip, int device, snd_rawmidi_t **rrawmidi)
    2686 {
    2687     snd_rawmidi_t *rmidi;
    2688     int err;
    2689 
    2690     if (rrawmidi)
    2691         *rrawmidi = NULL;
    2692     if ((err = snd_rawmidi_new(chip->card, "CS46XX", device, 1, 1, &rmidi)) < 0)
    2693         return err;
    2694     strcpy(rmidi->name, "CS46XX");
    2695     snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_cs46xx_midi_output);
    2696     snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_cs46xx_midi_input);
    2697     rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
    2698     rmidi->private_data = chip;
    2699     chip->rmidi = rmidi;
    2700     if (rrawmidi)
    2701         *rrawmidi = NULL;
    2702     return 0;
     2631int __devinit snd_cs46xx_midi(struct snd_cs46xx *chip, int device, struct snd_rawmidi **rrawmidi)
     2632{
     2633        struct snd_rawmidi *rmidi;
     2634        int err;
     2635
     2636        if (rrawmidi)
     2637                *rrawmidi = NULL;
     2638        if ((err = snd_rawmidi_new(chip->card, "CS46XX", device, 1, 1, &rmidi)) < 0)
     2639                return err;
     2640        strcpy(rmidi->name, "CS46XX");
     2641        snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_cs46xx_midi_output);
     2642        snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_cs46xx_midi_input);
     2643        rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
     2644        rmidi->private_data = chip;
     2645        chip->rmidi = rmidi;
     2646        if (rrawmidi)
     2647                *rrawmidi = NULL;
     2648        return 0;
    27032649}
    27042650
     
    27082654 */
    27092655
    2710 #ifndef LINUX_2_2
    2711 
    2712 typedef struct snd_cs46xx_gameport {
    2713     struct gameport info;
    2714     cs46xx_t *chip;
    2715 } cs46xx_gameport_t;
     2656#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
    27162657
    27172658static void snd_cs46xx_gameport_trigger(struct gameport *gameport)
    27182659{
    2719     cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport;
    2720     cs46xx_t *chip;
    2721     snd_assert(gp, return);
    2722     chip = gp->chip;
    2723     snd_cs46xx_pokeBA0(chip, BA0_JSPT, 0xFF);  //outb(gameport->io, 0xFF);
     2660        struct snd_cs46xx *chip = gameport_get_port_data(gameport);
     2661
     2662        snd_assert(chip, return);
     2663        snd_cs46xx_pokeBA0(chip, BA0_JSPT, 0xFF);  //outb(gameport->io, 0xFF);
    27242664}
    27252665
    27262666static unsigned char snd_cs46xx_gameport_read(struct gameport *gameport)
    27272667{
    2728     cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport;
    2729     cs46xx_t *chip;
    2730     snd_assert(gp, return 0);
    2731     chip = gp->chip;
    2732     return snd_cs46xx_peekBA0(chip, BA0_JSPT); //inb(gameport->io);
     2668        struct snd_cs46xx *chip = gameport_get_port_data(gameport);
     2669
     2670        snd_assert(chip, return 0);
     2671        return snd_cs46xx_peekBA0(chip, BA0_JSPT); //inb(gameport->io);
    27332672}
    27342673
    27352674static int snd_cs46xx_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
    27362675{
    2737     cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport;
    2738     cs46xx_t *chip;
    2739     unsigned js1, js2, jst;
    2740 
    2741     snd_assert(gp, return 0);
    2742     chip = gp->chip;
    2743 
    2744     js1 = snd_cs46xx_peekBA0(chip, BA0_JSC1);
    2745     js2 = snd_cs46xx_peekBA0(chip, BA0_JSC2);
    2746     jst = snd_cs46xx_peekBA0(chip, BA0_JSPT);
    2747 
    2748     *buttons = (~jst >> 4) & 0x0F;
    2749 
    2750     axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF;
    2751     axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF;
    2752     axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF;
    2753     axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF;
    2754 
    2755     for(jst=0;jst<4;++jst)
    2756         if(axes[jst]==0xFFFF) axes[jst] = -1;
    2757     return 0;
     2676        struct snd_cs46xx *chip = gameport_get_port_data(gameport);
     2677        unsigned js1, js2, jst;
     2678
     2679        snd_assert(chip, return 0);
     2680
     2681        js1 = snd_cs46xx_peekBA0(chip, BA0_JSC1);
     2682        js2 = snd_cs46xx_peekBA0(chip, BA0_JSC2);
     2683        jst = snd_cs46xx_peekBA0(chip, BA0_JSPT);
     2684       
     2685        *buttons = (~jst >> 4) & 0x0F;
     2686       
     2687        axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF;
     2688        axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF;
     2689        axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF;
     2690        axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF;
     2691
     2692        for(jst=0;jst<4;++jst)
     2693                if(axes[jst]==0xFFFF) axes[jst] = -1;
     2694        return 0;
    27582695}
    27592696
    27602697static int snd_cs46xx_gameport_open(struct gameport *gameport, int mode)
    27612698{
    2762     switch (mode) {
    2763     case GAMEPORT_MODE_COOKED:
    2764         return 0;
    2765     case GAMEPORT_MODE_RAW:
    2766         return 0;
    2767     default:
    2768         return -1;
    2769     }
    2770     return 0;
    2771 }
    2772 
    2773 void __devinit snd_cs46xx_gameport(cs46xx_t *chip)
    2774 {
    2775     cs46xx_gameport_t *gp;
    2776     gp = kmalloc(sizeof(*gp), GFP_KERNEL);
    2777     if (! gp) {
    2778         snd_printk("cannot allocate gameport area\n");
    2779         return;
    2780     }
    2781     memset(gp, 0, sizeof(*gp));
    2782     gp->info.open = snd_cs46xx_gameport_open;
    2783     gp->info.read = snd_cs46xx_gameport_read;
    2784     gp->info.trigger = snd_cs46xx_gameport_trigger;
    2785     gp->info.cooked_read = snd_cs46xx_gameport_cooked_read;
    2786     gp->chip = chip;
    2787     chip->gameport = gp;
    2788 
    2789     snd_cs46xx_pokeBA0(chip, BA0_JSIO, 0xFF); // ?
    2790     snd_cs46xx_pokeBA0(chip, BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW);
    2791     gameport_register_port(&gp->info);
    2792 }
    2793 
    2794 #else /* LINUX_2_2 */
    2795 
    2796 void __devinit snd_cs46xx_gameport(cs46xx_t *chip)
    2797 {
    2798 }
    2799 
    2800 #endif /* !LINUX_2_2 */
     2699        switch (mode) {
     2700        case GAMEPORT_MODE_COOKED:
     2701                return 0;
     2702        case GAMEPORT_MODE_RAW:
     2703                return 0;
     2704        default:
     2705                return -1;
     2706        }
     2707        return 0;
     2708}
     2709
     2710int __devinit snd_cs46xx_gameport(struct snd_cs46xx *chip)
     2711{
     2712        struct gameport *gp;
     2713
     2714        chip->gameport = gp = gameport_allocate_port();
     2715        if (!gp) {
     2716                printk(KERN_ERR "cs46xx: cannot allocate memory for gameport\n");
     2717                return -ENOMEM;
     2718        }
     2719
     2720        gameport_set_name(gp, "CS46xx Gameport");
     2721        gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
     2722        gameport_set_dev_parent(gp, &chip->pci->dev);
     2723        gameport_set_port_data(gp, chip);
     2724
     2725        gp->open = snd_cs46xx_gameport_open;
     2726        gp->read = snd_cs46xx_gameport_read;
     2727        gp->trigger = snd_cs46xx_gameport_trigger;
     2728        gp->cooked_read = snd_cs46xx_gameport_cooked_read;
     2729
     2730        snd_cs46xx_pokeBA0(chip, BA0_JSIO, 0xFF); // ?
     2731        snd_cs46xx_pokeBA0(chip, BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW);
     2732
     2733        gameport_register_port(gp);
     2734
     2735        return 0;
     2736}
     2737
     2738static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip)
     2739{
     2740        if (chip->gameport) {
     2741                gameport_unregister_port(chip->gameport);
     2742                chip->gameport = NULL;
     2743        }
     2744}
     2745#else
     2746int __devinit snd_cs46xx_gameport(struct snd_cs46xx *chip) { return -ENOSYS; }
     2747static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip) { }
     2748#endif /* CONFIG_GAMEPORT */
    28012749
    28022750/*
    28032751 *  proc interface
    28042752 */
    2805 static long snd_cs46xx_io_read(snd_info_entry_t *entry, void *file_private_data,
     2753
     2754static long snd_cs46xx_io_read(struct snd_info_entry *entry, void *file_private_data,
    28062755                               struct file *file, char __user *buf,
    28072756                               unsigned long count, unsigned long pos)
    28082757{
    28092758        long size;
    2810         snd_cs46xx_region_t *region = (snd_cs46xx_region_t *)entry->private_data;
    2811 
     2759        struct snd_cs46xx_region *region = entry->private_data;
     2760       
    28122761        size = count;
    28132762        if (pos + (size_t)size > region->size)
     
    28212770
    28222771static struct snd_info_entry_ops snd_cs46xx_proc_io_ops = {
    2823     0,0,snd_cs46xx_io_read,0,0,0,0,0
     2772        .read = snd_cs46xx_io_read,
    28242773};
    28252774
    2826 static int __devinit snd_cs46xx_proc_init(snd_card_t * card, cs46xx_t *chip)
    2827 {
    2828     snd_info_entry_t *entry;
    2829     int idx;
    2830 
    2831     for (idx = 0; idx < 5; idx++) {
    2832         snd_cs46xx_region_t *region = &chip->region.idx[idx];
    2833         if (! snd_card_proc_new(card, region->name, &entry)) {
    2834             entry->content = SNDRV_INFO_CONTENT_DATA;
    2835             entry->private_data = chip;
    2836             entry->c.ops = &snd_cs46xx_proc_io_ops;
    2837             entry->size = region->size;
    2838             entry->mode = S_IFREG | S_IRUSR;
    2839         }
    2840     }
    2841 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    2842     cs46xx_dsp_proc_init(card, chip);
    2843 #endif
    2844     return 0;
    2845 }
    2846 
    2847 static int snd_cs46xx_proc_done(cs46xx_t *chip)
    2848 {
    2849 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    2850     cs46xx_dsp_proc_done(chip);
    2851 #endif
    2852     return 0;
     2775static int __devinit snd_cs46xx_proc_init(struct snd_card *card, struct snd_cs46xx *chip)
     2776{
     2777        struct snd_info_entry *entry;
     2778        int idx;
     2779       
     2780        for (idx = 0; idx < 5; idx++) {
     2781                struct snd_cs46xx_region *region = &chip->region.idx[idx];
     2782                if (! snd_card_proc_new(card, region->name, &entry)) {
     2783                        entry->content = SNDRV_INFO_CONTENT_DATA;
     2784                        entry->private_data = chip;
     2785                        entry->c.ops = &snd_cs46xx_proc_io_ops;
     2786                        entry->size = region->size;
     2787                        entry->mode = S_IFREG | S_IRUSR;
     2788                }
     2789        }
     2790#ifdef CONFIG_SND_CS46XX_NEW_DSP
     2791        cs46xx_dsp_proc_init(card, chip);
     2792#endif
     2793        return 0;
     2794}
     2795
     2796static int snd_cs46xx_proc_done(struct snd_cs46xx *chip)
     2797{
     2798#ifdef CONFIG_SND_CS46XX_NEW_DSP
     2799        cs46xx_dsp_proc_done(chip);
     2800#endif
     2801        return 0;
    28532802}
    28542803
     
    28562805 * stop the h/w
    28572806 */
    2858 static void snd_cs46xx_hw_stop(cs46xx_t *chip)
    2859 {
    2860     unsigned int tmp;
    2861 
    2862     tmp = snd_cs46xx_peek(chip, BA1_PFIE);
    2863     tmp &= ~0x0000f03f;
    2864     tmp |=  0x00000010;
    2865     snd_cs46xx_poke(chip, BA1_PFIE, tmp);       /* playback interrupt disable */
    2866 
    2867     tmp = snd_cs46xx_peek(chip, BA1_CIE);
    2868     tmp &= ~0x0000003f;
    2869     tmp |=  0x00000011;
    2870     snd_cs46xx_poke(chip, BA1_CIE, tmp);        /* capture interrupt disable */
    2871 
    2872     /*
    2873      *  Stop playback DMA.
    2874      */
    2875     tmp = snd_cs46xx_peek(chip, BA1_PCTL);
    2876     snd_cs46xx_poke(chip, BA1_PCTL, tmp & 0x0000ffff);
    2877 
    2878     /*
    2879      *  Stop capture DMA.
    2880      */
    2881     tmp = snd_cs46xx_peek(chip, BA1_CCTL);
    2882     snd_cs46xx_poke(chip, BA1_CCTL, tmp & 0xffff0000);
    2883 
    2884     /*
    2885      *  Reset the processor.
    2886      */
    2887     snd_cs46xx_reset(chip);
    2888 
    2889     snd_cs46xx_proc_stop(chip);
    2890 
    2891     /*
    2892      *  Power down the PLL.
    2893      */
    2894     snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, 0);
    2895 
    2896     /*
    2897      *  Turn off the Processor by turning off the software clock enable flag in
    2898      *  the clock control register.
    2899      */
    2900     tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1) & ~CLKCR1_SWCE;
    2901     snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);
    2902 }
    2903 
    2904 
    2905 static int snd_cs46xx_free(cs46xx_t *chip)
    2906 {
    2907     int idx;
    2908 
    2909     snd_assert(chip != NULL, return -EINVAL);
    2910 
    2911     if (chip->active_ctrl)
    2912         chip->active_ctrl(chip, 1);
    2913 
    2914 #ifndef LINUX_2_2
    2915     if (chip->gameport) {
    2916         gameport_unregister_port(&chip->gameport->info);
    2917         kfree(chip->gameport);
    2918     }
    2919 #endif
    2920     if (chip->amplifier_ctrl)
    2921         chip->amplifier_ctrl(chip, -chip->amplifier); /* force to off */
    2922 
    2923     snd_cs46xx_proc_done(chip);
    2924 
    2925     if (chip->region.idx[0].resource)
    2926         snd_cs46xx_hw_stop(chip);
    2927 
    2928     for (idx = 0; idx < 5; idx++) {
    2929         snd_cs46xx_region_t *region = &chip->region.idx[idx];
    2930         if (region->remap_addr)
    2931             iounmap((void *) region->remap_addr);
    2932         if (region->resource) {
    2933             release_resource(region->resource);
    2934             kfree_nocheck(region->resource);
    2935         }
    2936     }
    2937     if (chip->irq >= 0)
    2938         free_irq(chip->irq, (void *)chip);
    2939 
    2940     if (chip->active_ctrl)
    2941         chip->active_ctrl(chip, -chip->amplifier);
    2942 
    2943 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    2944     if (chip->dsp_spos_instance) {
    2945         cs46xx_dsp_spos_destroy(chip);
    2946         chip->dsp_spos_instance = NULL;
    2947     }
    2948 #endif
    2949 
    2950     pci_disable_device(chip->pci);
    2951     kfree(chip);
    2952     return 0;
    2953 }
    2954 
    2955 static int snd_cs46xx_dev_free(snd_device_t *device)
    2956 {
    2957     cs46xx_t *chip = device->device_data;
    2958     return snd_cs46xx_free(chip);
     2807static void snd_cs46xx_hw_stop(struct snd_cs46xx *chip)
     2808{
     2809        unsigned int tmp;
     2810
     2811        tmp = snd_cs46xx_peek(chip, BA1_PFIE);
     2812        tmp &= ~0x0000f03f;
     2813        tmp |=  0x00000010;
     2814        snd_cs46xx_poke(chip, BA1_PFIE, tmp);   /* playback interrupt disable */
     2815
     2816        tmp = snd_cs46xx_peek(chip, BA1_CIE);
     2817        tmp &= ~0x0000003f;
     2818        tmp |=  0x00000011;
     2819        snd_cs46xx_poke(chip, BA1_CIE, tmp);    /* capture interrupt disable */
     2820
     2821        /*
     2822         *  Stop playback DMA.
     2823         */
     2824        tmp = snd_cs46xx_peek(chip, BA1_PCTL);
     2825        snd_cs46xx_poke(chip, BA1_PCTL, tmp & 0x0000ffff);
     2826
     2827        /*
     2828         *  Stop capture DMA.
     2829         */
     2830        tmp = snd_cs46xx_peek(chip, BA1_CCTL);
     2831        snd_cs46xx_poke(chip, BA1_CCTL, tmp & 0xffff0000);
     2832
     2833        /*
     2834         *  Reset the processor.
     2835         */
     2836        snd_cs46xx_reset(chip);
     2837
     2838        snd_cs46xx_proc_stop(chip);
     2839
     2840        /*
     2841         *  Power down the PLL.
     2842         */
     2843        snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, 0);
     2844
     2845        /*
     2846         *  Turn off the Processor by turning off the software clock enable flag in
     2847         *  the clock control register.
     2848         */
     2849        tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1) & ~CLKCR1_SWCE;
     2850        snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);
     2851}
     2852
     2853
     2854static int snd_cs46xx_free(struct snd_cs46xx *chip)
     2855{
     2856        int idx;
     2857
     2858        snd_assert(chip != NULL, return -EINVAL);
     2859
     2860        if (chip->active_ctrl)
     2861                chip->active_ctrl(chip, 1);
     2862
     2863        snd_cs46xx_remove_gameport(chip);
     2864
     2865        if (chip->amplifier_ctrl)
     2866                chip->amplifier_ctrl(chip, -chip->amplifier); /* force to off */
     2867       
     2868        snd_cs46xx_proc_done(chip);
     2869
     2870        if (chip->region.idx[0].resource)
     2871                snd_cs46xx_hw_stop(chip);
     2872
     2873        for (idx = 0; idx < 5; idx++) {
     2874                struct snd_cs46xx_region *region = &chip->region.idx[idx];
     2875                if (region->remap_addr)
     2876                        iounmap(region->remap_addr);
     2877                release_and_free_resource(region->resource);
     2878        }
     2879        if (chip->irq >= 0)
     2880                free_irq(chip->irq, chip);
     2881
     2882        if (chip->active_ctrl)
     2883                chip->active_ctrl(chip, -chip->amplifier);
     2884       
     2885#ifdef CONFIG_SND_CS46XX_NEW_DSP
     2886        if (chip->dsp_spos_instance) {
     2887                cs46xx_dsp_spos_destroy(chip);
     2888                chip->dsp_spos_instance = NULL;
     2889        }
     2890#endif
     2891       
     2892        pci_disable_device(chip->pci);
     2893        kfree(chip);
     2894        return 0;
     2895}
     2896
     2897static int snd_cs46xx_dev_free(struct snd_device *device)
     2898{
     2899        struct snd_cs46xx *chip = device->device_data;
     2900        return snd_cs46xx_free(chip);
    29592901}
    29602902
     
    29622904 *  initialize chip
    29632905 */
    2964 static int snd_cs46xx_chip_init(cs46xx_t *chip)
    2965 {
    2966     int timeout;
    2967 
    2968     /*
    2969     *  First, blast the clock control register to zero so that the PLL starts
    2970      *  out in a known state, and blast the master serial port control register
    2971      *  to zero so that the serial ports also start out in a known state.
    2972      */
    2973     snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, 0);
    2974     snd_cs46xx_pokeBA0(chip, BA0_SERMC1, 0);
    2975 
    2976     /*
    2977     *  If we are in AC97 mode, then we must set the part to a host controlled
    2978      *  AC-link.  Otherwise, we won't be able to bring up the link.
    2979      */
    2980 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    2981     snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_2_0 |
    2982                        SERACC_TWO_CODECS);      /* 2.00 dual codecs */
    2983     /* snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_2_0); */ /* 2.00 codec */
     2906static int snd_cs46xx_chip_init(struct snd_cs46xx *chip)
     2907{
     2908        int timeout;
     2909
     2910        /*
     2911        *  First, blast the clock control register to zero so that the PLL starts
     2912         *  out in a known state, and blast the master serial port control register
     2913         *  to zero so that the serial ports also start out in a known state.
     2914         */
     2915        snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, 0);
     2916        snd_cs46xx_pokeBA0(chip, BA0_SERMC1, 0);
     2917
     2918        /*
     2919        *  If we are in AC97 mode, then we must set the part to a host controlled
     2920         *  AC-link.  Otherwise, we won't be able to bring up the link.
     2921         */       
     2922#ifdef CONFIG_SND_CS46XX_NEW_DSP
     2923        snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_2_0 |
     2924                           SERACC_TWO_CODECS);  /* 2.00 dual codecs */
     2925        /* snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_2_0); */ /* 2.00 codec */
    29842926#else
    2985     snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_1_03); /* 1.03 codec */
    2986 #endif
    2987 
    2988     /*
    2989      *  Drive the ARST# pin low for a minimum of 1uS (as defined in the AC97
    2990      *  spec) and then drive it high.  This is done for non AC97 modes since
    2991      *  there might be logic external to the CS461x that uses the ARST# line
    2992      *  for a reset.
    2993      */
    2994     snd_cs46xx_pokeBA0(chip, BA0_ACCTL, 0);
    2995 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    2996     snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, 0);
    2997 #endif
    2998     udelay(50);
    2999     snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_RSTN);
    3000 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    3001     snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_RSTN);
    3002 #endif
    3003 
    3004     /*
    3005      *  The first thing we do here is to enable sync generation.  As soon
    3006      *  as we start receiving bit clock, we'll start producing the SYNC
    3007      *  signal.
    3008      */
    3009     snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_ESYN | ACCTL_RSTN);
    3010 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    3011     snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_ESYN | ACCTL_RSTN);
    3012 #endif
    3013 
    3014     /*
    3015      *  Now wait for a short while to allow the AC97 part to start
    3016      *  generating bit clock (so we don't try to start the PLL without an
    3017      *  input clock).
    3018      */
    3019     mdelay(10);
    3020 
    3021     /*
    3022      *  Set the serial port timing configuration, so that
    3023      *  the clock control circuit gets its clock from the correct place.
    3024      */
    3025     snd_cs46xx_pokeBA0(chip, BA0_SERMC1, SERMC1_PTC_AC97);
    3026 
    3027     /*
    3028      *  Write the selected clock control setup to the hardware.  Do not turn on
    3029      *  SWCE yet (if requested), so that the devices clocked by the output of
    3030      *  PLL are not clocked until the PLL is stable.
    3031      */
    3032     snd_cs46xx_pokeBA0(chip, BA0_PLLCC, PLLCC_LPF_1050_2780_KHZ | PLLCC_CDR_73_104_MHZ);
    3033     snd_cs46xx_pokeBA0(chip, BA0_PLLM, 0x3a);
    3034     snd_cs46xx_pokeBA0(chip, BA0_CLKCR2, CLKCR2_PDIVS_8);
    3035 
    3036     /*
    3037      *  Power up the PLL.
    3038      */
    3039     snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, CLKCR1_PLLP);
    3040 
    3041     /*
    3042      *  Wait until the PLL has stabilized.
    3043      */
    3044     msleep(100);
    3045 
    3046     /*
    3047      *  Turn on clocking of the core so that we can setup the serial ports.
    3048      */
    3049     snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, CLKCR1_PLLP | CLKCR1_SWCE);
    3050 
    3051     /*
    3052      * Enable FIFO  Host Bypass
    3053      */
    3054     snd_cs46xx_pokeBA0(chip, BA0_SERBCF, SERBCF_HBP);
    3055 
    3056     /*
    3057      *  Fill the serial port FIFOs with silence.
    3058      */
    3059     snd_cs46xx_clear_serial_FIFOs(chip);
    3060 
    3061     /*
    3062      *  Set the serial port FIFO pointer to the first sample in the FIFO.
    3063      */
    3064     /* snd_cs46xx_pokeBA0(chip, BA0_SERBSP, 0); */
    3065 
    3066     /*
    3067      *  Write the serial port configuration to the part.  The master
    3068      *  enable bit is not set until all other values have been written.
    3069      */
    3070     snd_cs46xx_pokeBA0(chip, BA0_SERC1, SERC1_SO1F_AC97 | SERC1_SO1EN);
    3071     snd_cs46xx_pokeBA0(chip, BA0_SERC2, SERC2_SI1F_AC97 | SERC1_SO1EN);
    3072     snd_cs46xx_pokeBA0(chip, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE);
    3073 
    3074 
    3075 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    3076     snd_cs46xx_pokeBA0(chip, BA0_SERC7, SERC7_ASDI2EN);
    3077     snd_cs46xx_pokeBA0(chip, BA0_SERC3, 0);
    3078     snd_cs46xx_pokeBA0(chip, BA0_SERC4, 0);
    3079     snd_cs46xx_pokeBA0(chip, BA0_SERC5, 0);
    3080     snd_cs46xx_pokeBA0(chip, BA0_SERC6, 1);
    3081 #endif
    3082 
    3083     mdelay(5);
    3084 
    3085 
    3086     /*
    3087      * Wait for the codec ready signal from the AC97 codec.
    3088      */
    3089     timeout = 150;
    3090     while (timeout-- > 0) {
     2927        snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_1_03); /* 1.03 codec */
     2928#endif
     2929
    30912930        /*
    3092          *  Read the AC97 status register to see if we've seen a CODEC READY
    3093          *  signal from the AC97 codec.
     2931         *  Drive the ARST# pin low for a minimum of 1uS (as defined in the AC97
     2932         *  spec) and then drive it high.  This is done for non AC97 modes since
     2933         *  there might be logic external to the CS461x that uses the ARST# line
     2934         *  for a reset.
    30942935         */
    3095         if (snd_cs46xx_peekBA0(chip, BA0_ACSTS) & ACSTS_CRDY)
    3096             goto ok1;
    3097         msleep(10);
    3098     }
    3099 
    3100 
    3101     snd_printk("create - never read codec ready from AC'97\n");
    3102     snd_printk("it is not probably bug, try to use CS4236 driver\n");
    3103     return -EIO;
    3104     ok1:
    3105 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    3106         {
    3107             int count;
    3108             for (count = 0; count < 150; count++) {
    3109                 /* First, we want to wait for a short time. */
    3110                 udelay(25);
    3111 
    3112                 if (snd_cs46xx_peekBA0(chip, BA0_ACSTS2) & ACSTS_CRDY)
    3113                     break;
    3114             }
    3115 
    3116             /*
    3117              *  Make sure CODEC is READY.
    3118              */
    3119             if (!(snd_cs46xx_peekBA0(chip, BA0_ACSTS2) & ACSTS_CRDY))
    3120                 snd_printdd("cs46xx: never read card ready from secondary AC'97\n");
    3121         }
    3122 #endif
    3123 
    3124         /*
    3125          *  Assert the vaid frame signal so that we can start sending commands
    3126          *  to the AC97 codec.
    3127          */
    3128         snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
    3129 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    3130         snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
    3131 #endif
    3132 
    3133 
    3134         /*
    3135          *  Wait until we've sampled input slots 3 and 4 as valid, meaning that
    3136          *  the codec is pumping ADC data across the AC-link.
    3137          */
    3138         timeout = 150;
    3139         while (timeout-- > 0) {
    3140             /*
    3141              *  Read the input slot valid register and see if input slots 3 and
    3142              *  4 are valid yet.
    3143              */
    3144             if ((snd_cs46xx_peekBA0(chip, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4))
    3145                 goto ok2;
    3146             msleep(10);
    3147         }
     2936        snd_cs46xx_pokeBA0(chip, BA0_ACCTL, 0);
     2937#ifdef CONFIG_SND_CS46XX_NEW_DSP
     2938        snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, 0);
     2939#endif
     2940        udelay(50);
     2941        snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_RSTN);
     2942#ifdef CONFIG_SND_CS46XX_NEW_DSP
     2943        snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_RSTN);
     2944#endif
     2945   
     2946        /*
     2947         *  The first thing we do here is to enable sync generation.  As soon
     2948         *  as we start receiving bit clock, we'll start producing the SYNC
     2949         *  signal.
     2950         */
     2951        snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_ESYN | ACCTL_RSTN);
     2952#ifdef CONFIG_SND_CS46XX_NEW_DSP
     2953        snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_ESYN | ACCTL_RSTN);
     2954#endif
     2955
     2956        /*
     2957         *  Now wait for a short while to allow the AC97 part to start
     2958         *  generating bit clock (so we don't try to start the PLL without an
     2959         *  input clock).
     2960         */
     2961        mdelay(10);
     2962
     2963        /*
     2964         *  Set the serial port timing configuration, so that
     2965         *  the clock control circuit gets its clock from the correct place.
     2966         */
     2967        snd_cs46xx_pokeBA0(chip, BA0_SERMC1, SERMC1_PTC_AC97);
     2968
     2969        /*
     2970         *  Write the selected clock control setup to the hardware.  Do not turn on
     2971         *  SWCE yet (if requested), so that the devices clocked by the output of
     2972         *  PLL are not clocked until the PLL is stable.
     2973         */
     2974        snd_cs46xx_pokeBA0(chip, BA0_PLLCC, PLLCC_LPF_1050_2780_KHZ | PLLCC_CDR_73_104_MHZ);
     2975        snd_cs46xx_pokeBA0(chip, BA0_PLLM, 0x3a);
     2976        snd_cs46xx_pokeBA0(chip, BA0_CLKCR2, CLKCR2_PDIVS_8);
     2977
     2978        /*
     2979         *  Power up the PLL.
     2980         */
     2981        snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, CLKCR1_PLLP);
     2982
     2983        /*
     2984         *  Wait until the PLL has stabilized.
     2985         */
     2986        msleep(100);
     2987
     2988        /*
     2989         *  Turn on clocking of the core so that we can setup the serial ports.
     2990         */
     2991        snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, CLKCR1_PLLP | CLKCR1_SWCE);
     2992
     2993        /*
     2994         * Enable FIFO  Host Bypass
     2995         */
     2996        snd_cs46xx_pokeBA0(chip, BA0_SERBCF, SERBCF_HBP);
     2997
     2998        /*
     2999         *  Fill the serial port FIFOs with silence.
     3000         */
     3001        snd_cs46xx_clear_serial_FIFOs(chip);
     3002
     3003        /*
     3004         *  Set the serial port FIFO pointer to the first sample in the FIFO.
     3005         */
     3006        /* snd_cs46xx_pokeBA0(chip, BA0_SERBSP, 0); */
     3007
     3008        /*
     3009         *  Write the serial port configuration to the part.  The master
     3010         *  enable bit is not set until all other values have been written.
     3011         */
     3012        snd_cs46xx_pokeBA0(chip, BA0_SERC1, SERC1_SO1F_AC97 | SERC1_SO1EN);
     3013        snd_cs46xx_pokeBA0(chip, BA0_SERC2, SERC2_SI1F_AC97 | SERC1_SO1EN);
     3014        snd_cs46xx_pokeBA0(chip, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE);
     3015
     3016
     3017#ifdef CONFIG_SND_CS46XX_NEW_DSP
     3018        snd_cs46xx_pokeBA0(chip, BA0_SERC7, SERC7_ASDI2EN);
     3019        snd_cs46xx_pokeBA0(chip, BA0_SERC3, 0);
     3020        snd_cs46xx_pokeBA0(chip, BA0_SERC4, 0);
     3021        snd_cs46xx_pokeBA0(chip, BA0_SERC5, 0);
     3022        snd_cs46xx_pokeBA0(chip, BA0_SERC6, 1);
     3023#endif
     3024
     3025        mdelay(5);
     3026
     3027
     3028        /*
     3029         * Wait for the codec ready signal from the AC97 codec.
     3030         */
     3031        timeout = 150;
     3032        while (timeout-- > 0) {
     3033                /*
     3034                 *  Read the AC97 status register to see if we've seen a CODEC READY
     3035                 *  signal from the AC97 codec.
     3036                 */
     3037                if (snd_cs46xx_peekBA0(chip, BA0_ACSTS) & ACSTS_CRDY)
     3038                        goto ok1;
     3039                msleep(10);
     3040        }
     3041
     3042
     3043        snd_printk(KERN_ERR "create - never read codec ready from AC'97\n");
     3044        snd_printk(KERN_ERR "it is not probably bug, try to use CS4236 driver\n");
     3045        return -EIO;
     3046 ok1:
     3047#ifdef CONFIG_SND_CS46XX_NEW_DSP
     3048        {
     3049                int count;
     3050                for (count = 0; count < 150; count++) {
     3051                        /* First, we want to wait for a short time. */
     3052                        udelay(25);
     3053       
     3054                        if (snd_cs46xx_peekBA0(chip, BA0_ACSTS2) & ACSTS_CRDY)
     3055                                break;
     3056                }
     3057
     3058                /*
     3059                 *  Make sure CODEC is READY.
     3060                 */
     3061                if (!(snd_cs46xx_peekBA0(chip, BA0_ACSTS2) & ACSTS_CRDY))
     3062                        snd_printdd("cs46xx: never read card ready from secondary AC'97\n");
     3063        }
     3064#endif
     3065
     3066        /*
     3067         *  Assert the vaid frame signal so that we can start sending commands
     3068         *  to the AC97 codec.
     3069         */
     3070        snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
     3071#ifdef CONFIG_SND_CS46XX_NEW_DSP
     3072        snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
     3073#endif
     3074
     3075
     3076        /*
     3077         *  Wait until we've sampled input slots 3 and 4 as valid, meaning that
     3078         *  the codec is pumping ADC data across the AC-link.
     3079         */
     3080        timeout = 150;
     3081        while (timeout-- > 0) {
     3082                /*
     3083                 *  Read the input slot valid register and see if input slots 3 and
     3084                 *  4 are valid yet.
     3085                 */
     3086                if ((snd_cs46xx_peekBA0(chip, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4))
     3087                        goto ok2;
     3088                msleep(10);
     3089        }
    31483090
    31493091#ifndef CONFIG_SND_CS46XX_NEW_DSP
    3150         snd_printk("create - never read ISV3 & ISV4 from AC'97\n");
    3151         return -EIO;
     3092        snd_printk(KERN_ERR "create - never read ISV3 & ISV4 from AC'97\n");
     3093        return -EIO;
    31523094#else
    3153         /* This may happen on a cold boot with a Terratec SiXPack 5.1.
    3154          Reloading the driver may help, if there's other soundcards
    3155          with the same problem I would like to know. (Benny) */
    3156 
    3157         snd_printk("ERROR: snd-cs46xx: never read ISV3 & ISV4 from AC'97\n");
    3158         snd_printk("       Try reloading the ALSA driver, if you find something\n");
    3159         snd_printk("       broken or not working on your soundcard upon\n");
    3160         snd_printk("       this message please report to alsa-devel@lists.sourceforge.net\n");
    3161 
    3162         return -EIO;
    3163 #endif
    3164         ok2:
    3165 
    3166             /*
    3167             *  Now, assert valid frame and the slot 3 and 4 valid bits.  This will
    3168             *  commense the transfer of digital audio data to the AC97 codec.
    3169             */
    3170 
    3171             snd_cs46xx_pokeBA0(chip, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4);
    3172 
    3173 
    3174             /*
    3175             *  Power down the DAC and ADC.  We will power them up (if) when we need
    3176             *  them.
    3177             */
    3178             /* snd_cs46xx_pokeBA0(chip, BA0_AC97_POWERDOWN, 0x300); */
    3179 
    3180             /*
    3181              *  Turn off the Processor by turning off the software clock enable flag in
    3182             *  the clock control register.
    3183             */
    3184             /* tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1) & ~CLKCR1_SWCE; */
    3185             /* snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp); */
    3186 
    3187             return 0;
     3095        /* This may happen on a cold boot with a Terratec SiXPack 5.1.
     3096           Reloading the driver may help, if there's other soundcards
     3097           with the same problem I would like to know. (Benny) */
     3098
     3099        snd_printk(KERN_ERR "ERROR: snd-cs46xx: never read ISV3 & ISV4 from AC'97\n");
     3100        snd_printk(KERN_ERR "       Try reloading the ALSA driver, if you find something\n");
     3101        snd_printk(KERN_ERR "       broken or not working on your soundcard upon\n");
     3102        snd_printk(KERN_ERR "       this message please report to alsa-devel@lists.sourceforge.net\n");
     3103
     3104        return -EIO;
     3105#endif
     3106 ok2:
     3107
     3108        /*
     3109        *  Now, assert valid frame and the slot 3 and 4 valid bits.  This will
     3110        *  commense the transfer of digital audio data to the AC97 codec.
     3111        */
     3112
     3113        snd_cs46xx_pokeBA0(chip, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4);
     3114
     3115
     3116        /*
     3117        *  Power down the DAC and ADC.  We will power them up (if) when we need
     3118        *  them.
     3119        */
     3120        /* snd_cs46xx_pokeBA0(chip, BA0_AC97_POWERDOWN, 0x300); */
     3121
     3122        /*
     3123         *  Turn off the Processor by turning off the software clock enable flag in
     3124        *  the clock control register.
     3125        */
     3126        /* tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1) & ~CLKCR1_SWCE; */
     3127        /* snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp); */
     3128
     3129        return 0;
    31883130}
    31893131
    31903132/*
    3191  *  start and load DSP
     3133 *  start and load DSP 
    31923134 */
    3193 int __devinit snd_cs46xx_start_dsp(cs46xx_t *chip)
    3194 {
    3195     unsigned int tmp;
    3196     /*
    3197     *  Reset the processor.
    3198     */
    3199     snd_cs46xx_reset(chip);
    3200     /*
    3201     *  Download the image to the processor.
    3202     */
     3135int __devinit snd_cs46xx_start_dsp(struct snd_cs46xx *chip)
     3136{       
     3137        unsigned int tmp;
     3138        /*
     3139        *  Reset the processor.
     3140        */
     3141        snd_cs46xx_reset(chip);
     3142        /*
     3143        *  Download the image to the processor.
     3144        */
    32033145#ifdef CONFIG_SND_CS46XX_NEW_DSP
    32043146#if 0
    3205     if (cs46xx_dsp_load_module(chip, &cwcemb80_module) < 0) {
    3206         snd_printk(KERN_ERR "image download error\n");
    3207         return -EIO;
    3208     }
    3209 #endif
    3210 
    3211     if (cs46xx_dsp_load_module(chip, &cwc4630_module) < 0) {
    3212         snd_printk(KERN_ERR "image download error [cwc4630]\n");
    3213         return -EIO;
    3214     }
    3215 
    3216     if (cs46xx_dsp_load_module(chip, &cwcasync_module) < 0) {
    3217         snd_printk(KERN_ERR "image download error [cwcasync]\n");
    3218         return -EIO;
    3219     }
    3220 
    3221     if (cs46xx_dsp_load_module(chip, &cwcsnoop_module) < 0) {
    3222         snd_printk(KERN_ERR "image download error [cwcsnoop]\n");
    3223         return -EIO;
    3224     }
    3225 
    3226     if (cs46xx_dsp_load_module(chip, &cwcbinhack_module) < 0) {
    3227         snd_printk(KERN_ERR "image download error [cwcbinhack]\n");
    3228         return -EIO;
    3229     }
    3230 
    3231     if (cs46xx_dsp_load_module(chip, &cwcdma_module) < 0) {
    3232         snd_printk(KERN_ERR "image download error [cwcdma]\n");
    3233         return -EIO;
    3234     }
    3235 
    3236     if (cs46xx_dsp_scb_and_task_init(chip) < 0)
    3237         return -EIO;
     3147        if (cs46xx_dsp_load_module(chip, &cwcemb80_module) < 0) {
     3148                snd_printk(KERN_ERR "image download error\n");
     3149                return -EIO;
     3150        }
     3151#endif
     3152
     3153        if (cs46xx_dsp_load_module(chip, &cwc4630_module) < 0) {
     3154                snd_printk(KERN_ERR "image download error [cwc4630]\n");
     3155                return -EIO;
     3156        }
     3157
     3158        if (cs46xx_dsp_load_module(chip, &cwcasync_module) < 0) {
     3159                snd_printk(KERN_ERR "image download error [cwcasync]\n");
     3160                return -EIO;
     3161        }
     3162
     3163        if (cs46xx_dsp_load_module(chip, &cwcsnoop_module) < 0) {
     3164                snd_printk(KERN_ERR "image download error [cwcsnoop]\n");
     3165                return -EIO;
     3166        }
     3167
     3168        if (cs46xx_dsp_load_module(chip, &cwcbinhack_module) < 0) {
     3169                snd_printk(KERN_ERR "image download error [cwcbinhack]\n");
     3170                return -EIO;
     3171        }
     3172
     3173        if (cs46xx_dsp_load_module(chip, &cwcdma_module) < 0) {
     3174                snd_printk(KERN_ERR "image download error [cwcdma]\n");
     3175                return -EIO;
     3176        }
     3177
     3178        if (cs46xx_dsp_scb_and_task_init(chip) < 0)
     3179                return -EIO;
    32383180#else
    3239     /* old image */
    3240     if (snd_cs46xx_download_image(chip) < 0) {
    3241         snd_printk("image download error\n");
    3242         return -EIO;
    3243     }
    3244 
    3245     /*
    3246      *  Stop playback DMA.
    3247     */
    3248     tmp = snd_cs46xx_peek(chip, BA1_PCTL);
    3249     chip->play_ctl = tmp & 0xffff0000;
    3250     snd_cs46xx_poke(chip, BA1_PCTL, tmp & 0x0000ffff);
    3251 #endif
    3252 
    3253     /*
    3254      *  Stop capture DMA.
    3255     */
    3256     tmp = snd_cs46xx_peek(chip, BA1_CCTL);
    3257     chip->capt.ctl = tmp & 0x0000ffff;
    3258     snd_cs46xx_poke(chip, BA1_CCTL, tmp & 0xffff0000);
    3259 
    3260     mdelay(5);
    3261 
    3262     snd_cs46xx_set_play_sample_rate(chip, 8000);
    3263     snd_cs46xx_set_capture_sample_rate(chip, 8000);
    3264 
    3265     snd_cs46xx_proc_start(chip);
    3266 
    3267     /*
    3268     *  Enable interrupts on the part.
    3269     */
    3270     snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_IEV | HICR_CHGM);
    3271 
    3272     tmp = snd_cs46xx_peek(chip, BA1_PFIE);
    3273     tmp &= ~0x0000f03f;
    3274     snd_cs46xx_poke(chip, BA1_PFIE, tmp);       /* playback interrupt enable */
    3275 
    3276     tmp = snd_cs46xx_peek(chip, BA1_CIE);
    3277     tmp &= ~0x0000003f;
    3278     tmp |=  0x00000001;
    3279     snd_cs46xx_poke(chip, BA1_CIE, tmp);        /* capture interrupt enable */
    3280 
     3181        /* old image */
     3182        if (snd_cs46xx_download_image(chip) < 0) {
     3183                snd_printk(KERN_ERR "image download error\n");
     3184                return -EIO;
     3185        }
     3186
     3187        /*
     3188         *  Stop playback DMA.
     3189        */
     3190        tmp = snd_cs46xx_peek(chip, BA1_PCTL);
     3191        chip->play_ctl = tmp & 0xffff0000;
     3192        snd_cs46xx_poke(chip, BA1_PCTL, tmp & 0x0000ffff);
     3193#endif
     3194
     3195        /*
     3196         *  Stop capture DMA.
     3197        */
     3198        tmp = snd_cs46xx_peek(chip, BA1_CCTL);
     3199        chip->capt.ctl = tmp & 0x0000ffff;
     3200        snd_cs46xx_poke(chip, BA1_CCTL, tmp & 0xffff0000);
     3201
     3202        mdelay(5);
     3203
     3204        snd_cs46xx_set_play_sample_rate(chip, 8000);
     3205        snd_cs46xx_set_capture_sample_rate(chip, 8000);
     3206
     3207        snd_cs46xx_proc_start(chip);
     3208
     3209        /*
     3210        *  Enable interrupts on the part.
     3211        */
     3212        snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_IEV | HICR_CHGM);
     3213       
     3214        tmp = snd_cs46xx_peek(chip, BA1_PFIE);
     3215        tmp &= ~0x0000f03f;
     3216        snd_cs46xx_poke(chip, BA1_PFIE, tmp);   /* playback interrupt enable */
     3217
     3218        tmp = snd_cs46xx_peek(chip, BA1_CIE);
     3219        tmp &= ~0x0000003f;
     3220        tmp |=  0x00000001;
     3221        snd_cs46xx_poke(chip, BA1_CIE, tmp);    /* capture interrupt enable */
     3222       
    32813223#ifndef CONFIG_SND_CS46XX_NEW_DSP
    3282     /* set the attenuation to 0dB */
    3283     snd_cs46xx_poke(chip, BA1_PVOL, 0x80008000);
    3284     snd_cs46xx_poke(chip, BA1_CVOL, 0x80008000);
    3285 #endif
    3286 
    3287     return 0;
     3224        /* set the attenuation to 0dB */
     3225        snd_cs46xx_poke(chip, BA1_PVOL, 0x80008000);
     3226        snd_cs46xx_poke(chip, BA1_CVOL, 0x80008000);
     3227#endif
     3228
     3229        return 0;
    32883230}
    32893231
     
    32923234 *      AMP control - null AMP
    32933235 */
    3294 
    3295 static void amp_none(cs46xx_t *chip, int change)
    3296 {
    3297 }
    3298 
    3299 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    3300 static int voyetra_setup_eapd_slot(cs46xx_t *chip)
    3301 {
    3302 
    3303     u32 idx, valid_slots,tmp,powerdown = 0;
    3304     u16 modem_power,pin_config,logic_type;
    3305 
    3306     snd_printdd ("cs46xx: cs46xx_setup_eapd_slot()+\n");
    3307 
    3308     /*
    3309     *  See if the devices are powered down.  If so, we must power them up first
    3310     *  or they will not respond.
    3311     */
    3312     tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1);
    3313 
    3314     if (!(tmp & CLKCR1_SWCE)) {
    3315         snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp | CLKCR1_SWCE);
    3316         powerdown = 1;
    3317     }
    3318 
    3319     /*
    3320     * Clear PRA.  The Bonzo chip will be used for GPIO not for modem
    3321     * stuff.
    3322     */
    3323     if(chip->nr_ac97_codecs != 2) {
    3324         snd_printk (KERN_ERR "cs46xx: cs46xx_setup_eapd_slot() - no secondary codec configured\n");
    3325         return -EINVAL;
    3326     }
    3327 
    3328     modem_power = snd_cs46xx_codec_read (chip,
    3329                                          AC97_EXTENDED_MSTATUS,
    3330                                          CS46XX_SECONDARY_CODEC_INDEX);
    3331     modem_power &=0xFEFF;
    3332 
    3333     snd_cs46xx_codec_write(chip,
    3334                            AC97_EXTENDED_MSTATUS, modem_power,
    3335                            CS46XX_SECONDARY_CODEC_INDEX);
    3336 
    3337     /*
    3338     * Set GPIO pin's 7 and 8 so that they are configured for output.
    3339     */
    3340     pin_config = snd_cs46xx_codec_read (chip,
    3341                                         AC97_GPIO_CFG,
    3342                                         CS46XX_SECONDARY_CODEC_INDEX);
    3343     pin_config &=0x27F;
    3344 
    3345     snd_cs46xx_codec_write(chip,
    3346                            AC97_GPIO_CFG, pin_config,
    3347                            CS46XX_SECONDARY_CODEC_INDEX);
    3348 
    3349     /*
    3350     * Set GPIO pin's 7 and 8 so that they are compatible with CMOS logic.
    3351     */
    3352 
    3353     logic_type = snd_cs46xx_codec_read(chip, AC97_GPIO_POLARITY,
    3354                                        CS46XX_SECONDARY_CODEC_INDEX);
    3355     logic_type &=0x27F;
    3356 
    3357     snd_cs46xx_codec_write (chip, AC97_GPIO_POLARITY, logic_type,
    3358                             CS46XX_SECONDARY_CODEC_INDEX);
    3359 
    3360     valid_slots = snd_cs46xx_peekBA0(chip, BA0_ACOSV);
    3361     valid_slots |= 0x200;
    3362     snd_cs46xx_pokeBA0(chip, BA0_ACOSV, valid_slots);
    3363 
    3364     if ( cs46xx_wait_for_fifo(chip,1) ) {
    3365         snd_printdd("FIFO is busy\n");
    3366 
    3367         return -EINVAL;
    3368     }
    3369 
    3370     /*
    3371      * Fill slots 12 with the correct value for the GPIO pins.
    3372     */
    3373     for(idx = 0x90; idx <= 0x9F; idx++) {
    3374         /*
    3375         * Initialize the fifo so that bits 7 and 8 are on.
    3376         *
    3377         * Remember that the GPIO pins in bonzo are shifted by 4 bits to
    3378         * the left.  0x1800 corresponds to bits 7 and 8.
    3379         */
    3380         snd_cs46xx_pokeBA0(chip, BA0_SERBWP, 0x1800);
    3381 
    3382         /*
    3383         * Wait for command to complete
    3384         */
    3385         if ( cs46xx_wait_for_fifo(chip,200) ) {
    3386             snd_printdd("failed waiting for FIFO at addr (%02X)\n",idx);
    3387 
    3388             return -EINVAL;
    3389         }
    3390 
    3391         /*
    3392         * Write the serial port FIFO index.
    3393         */
    3394         snd_cs46xx_pokeBA0(chip, BA0_SERBAD, idx);
    3395 
    3396         /*
    3397         * Tell the serial port to load the new value into the FIFO location.
    3398         */
    3399         snd_cs46xx_pokeBA0(chip, BA0_SERBCM, SERBCM_WRC);
    3400     }
    3401 
    3402     /* wait for last command to complete */
    3403     cs46xx_wait_for_fifo(chip,200);
    3404 
    3405     /*
    3406     *  Now, if we powered up the devices, then power them back down again.
    3407     *  This is kinda ugly, but should never happen.
    3408     */
    3409     if (powerdown)
    3410         snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);
    3411 
    3412     return 0;
     3236 
     3237static void amp_none(struct snd_cs46xx *chip, int change)
     3238{       
     3239}
     3240
     3241#ifdef CONFIG_SND_CS46XX_NEW_DSP
     3242static int voyetra_setup_eapd_slot(struct snd_cs46xx *chip)
     3243{
     3244       
     3245        u32 idx, valid_slots,tmp,powerdown = 0;
     3246        u16 modem_power,pin_config,logic_type;
     3247
     3248        snd_printdd ("cs46xx: cs46xx_setup_eapd_slot()+\n");
     3249
     3250        /*
     3251        *  See if the devices are powered down.  If so, we must power them up first
     3252        *  or they will not respond.
     3253        */
     3254        tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1);
     3255
     3256        if (!(tmp & CLKCR1_SWCE)) {
     3257                snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp | CLKCR1_SWCE);
     3258                powerdown = 1;
     3259        }
     3260
     3261        /*
     3262        * Clear PRA.  The Bonzo chip will be used for GPIO not for modem
     3263        * stuff.
     3264        */
     3265        if(chip->nr_ac97_codecs != 2) {
     3266                snd_printk (KERN_ERR "cs46xx: cs46xx_setup_eapd_slot() - no secondary codec configured\n");
     3267                return -EINVAL;
     3268        }
     3269
     3270        modem_power = snd_cs46xx_codec_read (chip,
     3271                                             AC97_EXTENDED_MSTATUS,
     3272                                             CS46XX_SECONDARY_CODEC_INDEX);
     3273        modem_power &=0xFEFF;
     3274
     3275        snd_cs46xx_codec_write(chip,
     3276                               AC97_EXTENDED_MSTATUS, modem_power,
     3277                               CS46XX_SECONDARY_CODEC_INDEX);
     3278
     3279        /*
     3280        * Set GPIO pin's 7 and 8 so that they are configured for output.
     3281        */
     3282        pin_config = snd_cs46xx_codec_read (chip,
     3283                                            AC97_GPIO_CFG,
     3284                                            CS46XX_SECONDARY_CODEC_INDEX);
     3285        pin_config &=0x27F;
     3286
     3287        snd_cs46xx_codec_write(chip,
     3288                               AC97_GPIO_CFG, pin_config,
     3289                               CS46XX_SECONDARY_CODEC_INDEX);
     3290   
     3291        /*
     3292        * Set GPIO pin's 7 and 8 so that they are compatible with CMOS logic.
     3293        */
     3294
     3295        logic_type = snd_cs46xx_codec_read(chip, AC97_GPIO_POLARITY,
     3296                                           CS46XX_SECONDARY_CODEC_INDEX);
     3297        logic_type &=0x27F;
     3298
     3299        snd_cs46xx_codec_write (chip, AC97_GPIO_POLARITY, logic_type,
     3300                                CS46XX_SECONDARY_CODEC_INDEX);
     3301
     3302        valid_slots = snd_cs46xx_peekBA0(chip, BA0_ACOSV);
     3303        valid_slots |= 0x200;
     3304        snd_cs46xx_pokeBA0(chip, BA0_ACOSV, valid_slots);
     3305
     3306        if ( cs46xx_wait_for_fifo(chip,1) ) {
     3307          snd_printdd("FIFO is busy\n");
     3308         
     3309          return -EINVAL;
     3310        }
     3311
     3312        /*
     3313         * Fill slots 12 with the correct value for the GPIO pins.
     3314        */
     3315        for(idx = 0x90; idx <= 0x9F; idx++) {
     3316                /*
     3317                * Initialize the fifo so that bits 7 and 8 are on.
     3318                *
     3319                * Remember that the GPIO pins in bonzo are shifted by 4 bits to
     3320                * the left.  0x1800 corresponds to bits 7 and 8.
     3321                */
     3322                snd_cs46xx_pokeBA0(chip, BA0_SERBWP, 0x1800);
     3323
     3324                /*
     3325                * Wait for command to complete
     3326                */
     3327                if ( cs46xx_wait_for_fifo(chip,200) ) {
     3328                        snd_printdd("failed waiting for FIFO at addr (%02X)\n",idx);
     3329
     3330                        return -EINVAL;
     3331                }
     3332           
     3333                /*
     3334                * Write the serial port FIFO index.
     3335                */
     3336                snd_cs46xx_pokeBA0(chip, BA0_SERBAD, idx);
     3337     
     3338                /*
     3339                * Tell the serial port to load the new value into the FIFO location.
     3340                */
     3341                snd_cs46xx_pokeBA0(chip, BA0_SERBCM, SERBCM_WRC);
     3342        }
     3343
     3344        /* wait for last command to complete */
     3345        cs46xx_wait_for_fifo(chip,200);
     3346
     3347        /*
     3348        *  Now, if we powered up the devices, then power them back down again.
     3349        *  This is kinda ugly, but should never happen.
     3350        */
     3351        if (powerdown)
     3352                snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);
     3353
     3354        return 0;
    34133355}
    34143356#endif
     
    34173359 *      Crystal EAPD mode
    34183360 */
    3419 
    3420 static void amp_voyetra(cs46xx_t *chip, int change)
    3421 {
    3422     /* Manage the EAPD bit on the Crystal 4297
    3423      and the Analog AD1885 */
    3424 
    3425 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    3426     int old = chip->amplifier;
    3427 #endif
    3428     int oval, val;
    3429 
    3430     chip->amplifier += change;
    3431     oval = snd_cs46xx_codec_read(chip, AC97_POWERDOWN,
    3432                                  CS46XX_PRIMARY_CODEC_INDEX);
    3433     val = oval;
    3434     if (chip->amplifier) {
    3435         /* Turn the EAPD amp on */
    3436         val |= 0x8000;
    3437     } else {
    3438         /* Turn the EAPD amp off */
    3439         val &= ~0x8000;
    3440     }
    3441     if (val != oval) {
    3442         snd_cs46xx_codec_write(chip, AC97_POWERDOWN, val,
    3443                                CS46XX_PRIMARY_CODEC_INDEX);
    3444         if (chip->eapd_switch)
    3445             snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
    3446                            &chip->eapd_switch->id);
    3447     }
    3448 
    3449 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    3450     if (chip->amplifier && !old) {
    3451         voyetra_setup_eapd_slot(chip);
    3452     }
    3453 #endif
    3454 }
    3455 
    3456 static void hercules_init(cs46xx_t *chip)
    3457 {
    3458     /* default: AMP off, and SPDIF input optical */
    3459     snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, EGPIODR_GPOE0);
    3460     snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, EGPIODR_GPOE0);
     3361 
     3362static void amp_voyetra(struct snd_cs46xx *chip, int change)
     3363{
     3364        /* Manage the EAPD bit on the Crystal 4297
     3365           and the Analog AD1885 */
     3366           
     3367#ifdef CONFIG_SND_CS46XX_NEW_DSP
     3368        int old = chip->amplifier;
     3369#endif
     3370        int oval, val;
     3371       
     3372        chip->amplifier += change;
     3373        oval = snd_cs46xx_codec_read(chip, AC97_POWERDOWN,
     3374                                     CS46XX_PRIMARY_CODEC_INDEX);
     3375        val = oval;
     3376        if (chip->amplifier) {
     3377                /* Turn the EAPD amp on */
     3378                val |= 0x8000;
     3379        } else {
     3380                /* Turn the EAPD amp off */
     3381                val &= ~0x8000;
     3382        }
     3383        if (val != oval) {
     3384                snd_cs46xx_codec_write(chip, AC97_POWERDOWN, val,
     3385                                       CS46XX_PRIMARY_CODEC_INDEX);
     3386                if (chip->eapd_switch)
     3387                        snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
     3388                                       &chip->eapd_switch->id);
     3389        }
     3390
     3391#ifdef CONFIG_SND_CS46XX_NEW_DSP
     3392        if (chip->amplifier && !old) {
     3393                voyetra_setup_eapd_slot(chip);
     3394        }
     3395#endif
     3396}
     3397
     3398static void hercules_init(struct snd_cs46xx *chip)
     3399{
     3400        /* default: AMP off, and SPDIF input optical */
     3401        snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, EGPIODR_GPOE0);
     3402        snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, EGPIODR_GPOE0);
    34613403}
    34623404
     
    34643406/*
    34653407 *      Game Theatre XP card - EGPIO[2] is used to enable the external amp.
    3466  */
    3467 static void amp_hercules(cs46xx_t *chip, int change)
    3468 {
    3469     int old = chip->amplifier;
    3470     int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR);
    3471     int val2 = snd_cs46xx_peekBA0(chip, BA0_EGPIOPTR);
    3472 
    3473     chip->amplifier += change;
    3474     if (chip->amplifier && !old) {
    3475         snd_printdd ("Hercules amplifier ON\n");
    3476 
    3477         snd_cs46xx_pokeBA0(chip, BA0_EGPIODR,
    3478                            EGPIODR_GPOE2 | val1);     /* enable EGPIO2 output */
    3479         snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR,
    3480                            EGPIOPTR_GPPT2 | val2);   /* open-drain on output */
    3481     } else if (old && !chip->amplifier) {
    3482         snd_printdd ("Hercules amplifier OFF\n");
    3483         snd_cs46xx_pokeBA0(chip, BA0_EGPIODR,  val1 & ~EGPIODR_GPOE2); /* disable */
    3484         snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, val2 & ~EGPIOPTR_GPPT2); /* disable */
    3485     }
    3486 }
    3487 
    3488 static void voyetra_mixer_init (cs46xx_t *chip)
    3489 {
    3490     snd_printdd ("initializing Voyetra mixer\n");
    3491 
    3492     /* Enable SPDIF out */
    3493     snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, EGPIODR_GPOE0);
    3494     snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, EGPIODR_GPOE0);
    3495 }
    3496 
    3497 static void hercules_mixer_init (cs46xx_t *chip)
    3498 {
    3499 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    3500     unsigned int idx;
    3501     int err;
    3502     snd_card_t *card = chip->card;
    3503 #endif
    3504 
    3505     /* set EGPIO to default */
    3506     hercules_init(chip);
    3507 
    3508     snd_printdd ("initializing Hercules mixer\n");
    3509 
    3510 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    3511     for (idx = 0 ; idx < ARRAY_SIZE(snd_hercules_controls); idx++) {
    3512         snd_kcontrol_t *kctl;
    3513 
    3514         kctl = snd_ctl_new1(&snd_hercules_controls[idx], chip);
    3515         if ((err = snd_ctl_add(card, kctl)) < 0) {
    3516             printk (KERN_ERR "cs46xx: failed to initialize Hercules mixer (%d)\n",err);
    3517             break;
    3518         }
    3519     }
     3408 */ 
     3409static void amp_hercules(struct snd_cs46xx *chip, int change)
     3410{
     3411        int old = chip->amplifier;
     3412        int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR);
     3413        int val2 = snd_cs46xx_peekBA0(chip, BA0_EGPIOPTR);
     3414
     3415        chip->amplifier += change;
     3416        if (chip->amplifier && !old) {
     3417                snd_printdd ("Hercules amplifier ON\n");
     3418
     3419                snd_cs46xx_pokeBA0(chip, BA0_EGPIODR,
     3420                                   EGPIODR_GPOE2 | val1);     /* enable EGPIO2 output */
     3421                snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR,
     3422                                   EGPIOPTR_GPPT2 | val2);   /* open-drain on output */
     3423        } else if (old && !chip->amplifier) {
     3424                snd_printdd ("Hercules amplifier OFF\n");
     3425                snd_cs46xx_pokeBA0(chip, BA0_EGPIODR,  val1 & ~EGPIODR_GPOE2); /* disable */
     3426                snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, val2 & ~EGPIOPTR_GPPT2); /* disable */
     3427        }
     3428}
     3429
     3430static void voyetra_mixer_init (struct snd_cs46xx *chip)
     3431{
     3432        snd_printdd ("initializing Voyetra mixer\n");
     3433
     3434        /* Enable SPDIF out */
     3435        snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, EGPIODR_GPOE0);
     3436        snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, EGPIODR_GPOE0);
     3437}
     3438
     3439static void hercules_mixer_init (struct snd_cs46xx *chip)
     3440{
     3441#ifdef CONFIG_SND_CS46XX_NEW_DSP
     3442        unsigned int idx;
     3443        int err;
     3444        struct snd_card *card = chip->card;
     3445#endif
     3446
     3447        /* set EGPIO to default */
     3448        hercules_init(chip);
     3449
     3450        snd_printdd ("initializing Hercules mixer\n");
     3451
     3452#ifdef CONFIG_SND_CS46XX_NEW_DSP
     3453        for (idx = 0 ; idx < ARRAY_SIZE(snd_hercules_controls); idx++) {
     3454                struct snd_kcontrol *kctl;
     3455
     3456                kctl = snd_ctl_new1(&snd_hercules_controls[idx], chip);
     3457                if ((err = snd_ctl_add(card, kctl)) < 0) {
     3458                        printk (KERN_ERR "cs46xx: failed to initialize Hercules mixer (%d)\n",err);
     3459                        break;
     3460                }
     3461        }
    35203462#endif
    35213463}
     
    35263468 *      Untested
    35273469 */
    3528 
    3529 static void amp_voyetra_4294(cs46xx_t *chip, int change)
    3530 {
    3531     chip->amplifier += change;
    3532 
    3533     if (chip->amplifier) {
    3534         /* Switch the GPIO pins 7 and 8 to open drain */
    3535         snd_cs46xx_codec_write(chip, 0x4C,
    3536                                snd_cs46xx_codec_read(chip, 0x4C) & 0xFE7F);
    3537         snd_cs46xx_codec_write(chip, 0x4E,
    3538                                snd_cs46xx_codec_read(chip, 0x4E) | 0x0180);
    3539         /* Now wake the AMP (this might be backwards) */
    3540         snd_cs46xx_codec_write(chip, 0x54,
    3541                                snd_cs46xx_codec_read(chip, 0x54) & ~0x0180);
    3542     } else {
    3543         snd_cs46xx_codec_write(chip, 0x54,
    3544                                snd_cs46xx_codec_read(chip, 0x54) | 0x0180);
    3545     }
    3546 }
    3547 #endif
    3548 
    3549 
    3550 /*
    3551  * piix4 pci ids
    3552  */
    3553 #ifndef PCI_VENDOR_ID_INTEL
    3554 #define PCI_VENDOR_ID_INTEL 0x8086
    3555 #endif /* PCI_VENDOR_ID_INTEL */
    3556 
    3557 #ifndef PCI_DEVICE_ID_INTEL_82371AB_3
    3558 #define PCI_DEVICE_ID_INTEL_82371AB_3 0x7113
    3559 #endif /* PCI_DEVICE_ID_INTEL_82371AB_3 */
     3470 
     3471static void amp_voyetra_4294(struct snd_cs46xx *chip, int change)
     3472{
     3473        chip->amplifier += change;
     3474
     3475        if (chip->amplifier) {
     3476                /* Switch the GPIO pins 7 and 8 to open drain */
     3477                snd_cs46xx_codec_write(chip, 0x4C,
     3478                                       snd_cs46xx_codec_read(chip, 0x4C) & 0xFE7F);
     3479                snd_cs46xx_codec_write(chip, 0x4E,
     3480                                       snd_cs46xx_codec_read(chip, 0x4E) | 0x0180);
     3481                /* Now wake the AMP (this might be backwards) */
     3482                snd_cs46xx_codec_write(chip, 0x54,
     3483                                       snd_cs46xx_codec_read(chip, 0x54) & ~0x0180);
     3484        } else {
     3485                snd_cs46xx_codec_write(chip, 0x54,
     3486                                       snd_cs46xx_codec_read(chip, 0x54) | 0x0180);
     3487        }
     3488}
     3489#endif
     3490
    35603491
    35613492/*
     
    35673498 *      enough to make them useful.
    35683499 */
    3569 
    3570 static void clkrun_hack(cs46xx_t *chip, int change)
    3571 {
    3572     u16 control, nval;
    3573 
    3574     if (chip->acpi_dev == NULL)
    3575         return;
    3576 
    3577     chip->amplifier += change;
    3578 
    3579     /* Read ACPI port */
    3580     nval = control = inw(chip->acpi_port + 0x10);
    3581 
    3582     /* Flip CLKRUN off while running */
    3583     if (! chip->amplifier)
    3584         nval |= 0x2000;
    3585     else
    3586         nval &= ~0x2000;
    3587     if (nval != control)
    3588         outw(nval, chip->acpi_port + 0x10);
    3589 }
    3590 
    3591 
     3500 
     3501static void clkrun_hack(struct snd_cs46xx *chip, int change)
     3502{
     3503        u16 control, nval;
     3504       
     3505        if (!chip->acpi_port)
     3506                return;
     3507
     3508        chip->amplifier += change;
     3509       
     3510        /* Read ACPI port */   
     3511        nval = control = inw(chip->acpi_port + 0x10);
     3512
     3513        /* Flip CLKRUN off while running */
     3514        if (! chip->amplifier)
     3515                nval |= 0x2000;
     3516        else
     3517                nval &= ~0x2000;
     3518        if (nval != control)
     3519                outw(nval, chip->acpi_port + 0x10);
     3520}
     3521
     3522       
    35923523/*
    35933524 * detect intel piix4
    35943525 */
    3595 static void clkrun_init(cs46xx_t *chip)
    3596 {
    3597     u8 pp;
    3598 
    3599     chip->acpi_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
    3600     if (chip->acpi_dev == NULL)
    3601         return;         /* Not a thinkpad thats for sure */
    3602 
    3603     /* Find the control port */
    3604     pci_read_config_byte(chip->acpi_dev, 0x41, &pp);
    3605     chip->acpi_port = pp << 8;
     3526static void clkrun_init(struct snd_cs46xx *chip)
     3527{
     3528        struct pci_dev *pdev;
     3529        u8 pp;
     3530
     3531        chip->acpi_port = 0;
     3532       
     3533        pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
     3534                PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
     3535        if (pdev == NULL)
     3536                return;         /* Not a thinkpad thats for sure */
     3537
     3538        /* Find the control port */             
     3539        pci_read_config_byte(pdev, 0x41, &pp);
     3540        chip->acpi_port = pp << 8;
     3541        pci_dev_put(pdev);
    36063542}
    36073543
     
    36103546 * Card subid table
    36113547 */
    3612 
     3548 
    36133549struct cs_card_type
    36143550{
    3615     u16 vendor;
    3616     u16 id;
    3617     char *name;
    3618     void (*init)(cs46xx_t *);
    3619     void (*amp)(cs46xx_t *, int);
    3620     void (*active)(cs46xx_t *, int);
    3621     void (*mixer_init)(cs46xx_t *);
     3551        u16 vendor;
     3552        u16 id;
     3553        char *name;
     3554        void (*init)(struct snd_cs46xx *);
     3555        void (*amp)(struct snd_cs46xx *, int);
     3556        void (*active)(struct snd_cs46xx *, int);
     3557        void (*mixer_init)(struct snd_cs46xx *);
    36223558};
    36233559
    3624 static struct cs_card_type __initdata cards[] = {
    3625     {0x1489, 0x7001, "Genius Soundmaker 128 value", NULL, NULL, NULL, NULL},
    3626     {0x5053, 0x3357, "Voyetra", NULL, amp_voyetra, NULL, voyetra_mixer_init},
    3627     {0x1071, 0x6003, "Mitac MI6020/21", NULL, amp_voyetra, NULL, NULL},
    3628     {0x14AF, 0x0050, "Hercules Game Theatre XP", NULL, amp_hercules, NULL, hercules_mixer_init},
    3629     {0x1681, 0x0050, "Hercules Game Theatre XP", NULL, amp_hercules, NULL, hercules_mixer_init},
    3630     {0x1681, 0x0051, "Hercules Game Theatre XP", NULL, amp_hercules, NULL, hercules_mixer_init},
    3631     {0x1681, 0x0052, "Hercules Game Theatre XP", NULL, amp_hercules, NULL, hercules_mixer_init},
    3632     {0x1681, 0x0053, "Hercules Game Theatre XP", NULL, amp_hercules, NULL, hercules_mixer_init},
    3633     {0x1681, 0x0054, "Hercules Game Theatre XP", NULL, amp_hercules, NULL, hercules_mixer_init},
    3634     {0x153b, 0x1136, "Terratec SiXPack 5.1", NULL, NULL, NULL, NULL},
    3635     /* Not sure if the 570 needs the clkrun hack */
    3636     {PCI_VENDOR_ID_IBM, 0x0132, "Thinkpad 570", clkrun_init, NULL, clkrun_hack, NULL},
    3637     {PCI_VENDOR_ID_IBM, 0x0153, "Thinkpad 600X/A20/T20", clkrun_init, NULL, clkrun_hack, NULL},
    3638     {PCI_VENDOR_ID_IBM, 0x1010, "Thinkpad 600E (unsupported)", NULL, NULL, NULL, NULL},
    3639     {0, 0, NULL, NULL, NULL, NULL, NULL}
     3560static struct cs_card_type __devinitdata cards[] = {
     3561        {
     3562                .vendor = 0x1489,
     3563                .id = 0x7001,
     3564                .name = "Genius Soundmaker 128 value",
     3565                /* nothing special */
     3566        },
     3567        {
     3568                .vendor = 0x5053,
     3569                .id = 0x3357,
     3570                .name = "Voyetra",
     3571                .amp = amp_voyetra,
     3572                .mixer_init = voyetra_mixer_init,
     3573        },
     3574        {
     3575                .vendor = 0x1071,
     3576                .id = 0x6003,
     3577                .name = "Mitac MI6020/21",
     3578                .amp = amp_voyetra,
     3579        },
     3580        {
     3581                .vendor = 0x14AF,
     3582                .id = 0x0050,
     3583                .name = "Hercules Game Theatre XP",
     3584                .amp = amp_hercules,
     3585                .mixer_init = hercules_mixer_init,
     3586        },
     3587        {
     3588                .vendor = 0x1681,
     3589                .id = 0x0050,
     3590                .name = "Hercules Game Theatre XP",
     3591                .amp = amp_hercules,
     3592                .mixer_init = hercules_mixer_init,
     3593        },
     3594        {
     3595                .vendor = 0x1681,
     3596                .id = 0x0051,
     3597                .name = "Hercules Game Theatre XP",
     3598                .amp = amp_hercules,
     3599                .mixer_init = hercules_mixer_init,
     3600
     3601        },
     3602        {
     3603                .vendor = 0x1681,
     3604                .id = 0x0052,
     3605                .name = "Hercules Game Theatre XP",
     3606                .amp = amp_hercules,
     3607                .mixer_init = hercules_mixer_init,
     3608        },
     3609        {
     3610                .vendor = 0x1681,
     3611                .id = 0x0053,
     3612                .name = "Hercules Game Theatre XP",
     3613                .amp = amp_hercules,
     3614                .mixer_init = hercules_mixer_init,
     3615        },
     3616        {
     3617                .vendor = 0x1681,
     3618                .id = 0x0054,
     3619                .name = "Hercules Game Theatre XP",
     3620                .amp = amp_hercules,
     3621                .mixer_init = hercules_mixer_init,
     3622        },
     3623        /* Teratec */
     3624        {
     3625                .vendor = 0x153b,
     3626                .id = 0x1136,
     3627                .name = "Terratec SiXPack 5.1",
     3628        },
     3629        /* Not sure if the 570 needs the clkrun hack */
     3630        {
     3631                .vendor = PCI_VENDOR_ID_IBM,
     3632                .id = 0x0132,
     3633                .name = "Thinkpad 570",
     3634                .init = clkrun_init,
     3635                .active = clkrun_hack,
     3636        },
     3637        {
     3638                .vendor = PCI_VENDOR_ID_IBM,
     3639                .id = 0x0153,
     3640                .name = "Thinkpad 600X/A20/T20",
     3641                .init = clkrun_init,
     3642                .active = clkrun_hack,
     3643        },
     3644        {
     3645                .vendor = PCI_VENDOR_ID_IBM,
     3646                .id = 0x1010,
     3647                .name = "Thinkpad 600E (unsupported)",
     3648        },
     3649        {0} /* terminator */
    36403650};
    36413651
     
    36453655 */
    36463656#ifdef CONFIG_PM
    3647 static int snd_cs46xx_suspend(snd_card_t *card, unsigned int state)
    3648 {
    3649     cs46xx_t *chip = card->pm_private_data;
    3650     int amp_saved;
    3651 
    3652     snd_pcm_suspend_all(chip->pcm);
    3653     // chip->ac97_powerdown = snd_cs46xx_codec_read(chip, AC97_POWER_CONTROL);
    3654     // chip->ac97_general_purpose = snd_cs46xx_codec_read(chip, BA0_AC97_GENERAL_PURPOSE);
    3655 
    3656     snd_ac97_suspend(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]);
    3657     if (chip->ac97[CS46XX_SECONDARY_CODEC_INDEX])
    3658         snd_ac97_suspend(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]);
    3659 
    3660     amp_saved = chip->amplifier;
    3661     /* turn off amp */
    3662     chip->amplifier_ctrl(chip, -chip->amplifier);
    3663     snd_cs46xx_hw_stop(chip);
    3664     /* disable CLKRUN */
    3665     chip->active_ctrl(chip, -chip->amplifier);
    3666     chip->amplifier = amp_saved; /* restore the status */
    3667     pci_disable_device(chip->pci);
    3668     return 0;
    3669 }
    3670 
    3671 static int snd_cs46xx_resume(snd_card_t *card, unsigned int state)
    3672 {
    3673     cs46xx_t *chip = card->pm_private_data;
    3674     int amp_saved;
    3675 
    3676     pci_enable_device(chip->pci);
    3677     pci_set_master(chip->pci);
    3678     amp_saved = chip->amplifier;
    3679     chip->amplifier = 0;
    3680     chip->active_ctrl(chip, 1); /* force to on */
    3681 
    3682     snd_cs46xx_chip_init(chip);
     3657int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state)
     3658{
     3659        struct snd_card *card = pci_get_drvdata(pci);
     3660        struct snd_cs46xx *chip = card->private_data;
     3661        int amp_saved;
     3662
     3663        snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
     3664        snd_pcm_suspend_all(chip->pcm);
     3665        // chip->ac97_powerdown = snd_cs46xx_codec_read(chip, AC97_POWER_CONTROL);
     3666        // chip->ac97_general_purpose = snd_cs46xx_codec_read(chip, BA0_AC97_GENERAL_PURPOSE);
     3667
     3668        snd_ac97_suspend(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]);
     3669        snd_ac97_suspend(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]);
     3670
     3671        amp_saved = chip->amplifier;
     3672        /* turn off amp */
     3673        chip->amplifier_ctrl(chip, -chip->amplifier);
     3674        snd_cs46xx_hw_stop(chip);
     3675        /* disable CLKRUN */
     3676        chip->active_ctrl(chip, -chip->amplifier);
     3677        chip->amplifier = amp_saved; /* restore the status */
     3678        pci_disable_device(pci);
     3679        pci_save_state(pci);
     3680        return 0;
     3681}
     3682
     3683int snd_cs46xx_resume(struct pci_dev *pci)
     3684{
     3685        struct snd_card *card = pci_get_drvdata(pci);
     3686        struct snd_cs46xx *chip = card->private_data;
     3687        int amp_saved;
     3688
     3689        pci_restore_state(pci);
     3690        pci_enable_device(pci);
     3691        pci_set_master(pci);
     3692        amp_saved = chip->amplifier;
     3693        chip->amplifier = 0;
     3694        chip->active_ctrl(chip, 1); /* force to on */
     3695
     3696        snd_cs46xx_chip_init(chip);
    36833697
    36843698#if 0
    3685     snd_cs46xx_codec_write(chip, BA0_AC97_GENERAL_PURPOSE,
    3686                            chip->ac97_general_purpose);
    3687     snd_cs46xx_codec_write(chip, AC97_POWER_CONTROL,
    3688                            chip->ac97_powerdown);
    3689     mdelay(10);
    3690     snd_cs46xx_codec_write(chip, BA0_AC97_POWERDOWN,
    3691                            chip->ac97_powerdown);
    3692     mdelay(5);
    3693 #endif
    3694 
    3695     snd_ac97_resume(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]);
    3696     if (chip->ac97[CS46XX_SECONDARY_CODEC_INDEX])
    3697         snd_ac97_resume(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]);
    3698 
    3699     if (amp_saved)
    3700         chip->amplifier_ctrl(chip, 1); /* turn amp on */
    3701     else
    3702         chip->active_ctrl(chip, -1); /* disable CLKRUN */
    3703     chip->amplifier = amp_saved;
    3704     return 0;
     3699        snd_cs46xx_codec_write(chip, BA0_AC97_GENERAL_PURPOSE,
     3700                               chip->ac97_general_purpose);
     3701        snd_cs46xx_codec_write(chip, AC97_POWER_CONTROL,
     3702                               chip->ac97_powerdown);
     3703        mdelay(10);
     3704        snd_cs46xx_codec_write(chip, BA0_AC97_POWERDOWN,
     3705                               chip->ac97_powerdown);
     3706        mdelay(5);
     3707#endif
     3708
     3709        snd_ac97_resume(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]);
     3710        snd_ac97_resume(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]);
     3711
     3712        if (amp_saved)
     3713                chip->amplifier_ctrl(chip, 1); /* turn amp on */
     3714        else
     3715                chip->active_ctrl(chip, -1); /* disable CLKRUN */
     3716        chip->amplifier = amp_saved;
     3717        snd_power_change_state(card, SNDRV_CTL_POWER_D0);
     3718        return 0;
    37053719}
    37063720#endif /* CONFIG_PM */
     
    37103724 */
    37113725
    3712 int __devinit snd_cs46xx_create(snd_card_t * card,
    3713                                 struct pci_dev * pci,
    3714                                 int external_amp, int thinkpad,
    3715                                 cs46xx_t ** rchip)
    3716 {
    3717     cs46xx_t *chip;
    3718     int err, idx;
    3719     snd_cs46xx_region_t *region;
    3720     struct cs_card_type *cp;
    3721     u16 ss_card, ss_vendor;
    3722 #ifdef TARGET_OS2
    3723     static snd_device_ops_t ops = {
    3724         snd_cs46xx_dev_free,0,0,0
    3725     };
    3726 #else
    3727     static snd_device_ops_t ops = {
    3728         .dev_free =     snd_cs46xx_dev_free,
    3729     };
    3730 #endif
    3731     *rchip = NULL;
    3732 
    3733     /* enable PCI device */
    3734     if ((err = pci_enable_device(pci)) < 0)
    3735         return err;
    3736 
    3737     chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
    3738     if (chip == NULL)
    3739         return -ENOMEM;
    3740     spin_lock_init(&chip->reg_lock);
    3741 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    3742     init_MUTEX(&chip->spos_mutex);
    3743 #endif
    3744     chip->card = card;
    3745     chip->pci = pci;
    3746     chip->irq = -1;
    3747     chip->ba0_addr = pci_resource_start(pci, 0);
    3748     chip->ba1_addr = pci_resource_start(pci, 1);
    3749     if (chip->ba0_addr == 0 || chip->ba0_addr == (unsigned long)~0 ||
    3750         chip->ba1_addr == 0 || chip->ba1_addr == (unsigned long)~0) {
    3751         snd_printk("wrong address(es) - ba0 = 0x%lx, ba1 = 0x%lx\n", chip->ba0_addr, chip->ba1_addr);
    3752         snd_cs46xx_free(chip);
    3753         return -ENOMEM;
    3754     }
    3755 
    3756     region = &chip->region.name.ba0;
    3757     strcpy(region->name, "CS46xx_BA0");
    3758     region->base = chip->ba0_addr;
    3759     region->size = CS46XX_BA0_SIZE;
    3760 
    3761     region = &chip->region.name.data0;
    3762     strcpy(region->name, "CS46xx_BA1_data0");
    3763     region->base = chip->ba1_addr + BA1_SP_DMEM0;
    3764     region->size = CS46XX_BA1_DATA0_SIZE;
    3765 
    3766     region = &chip->region.name.data1;
    3767     strcpy(region->name, "CS46xx_BA1_data1");
    3768     region->base = chip->ba1_addr + BA1_SP_DMEM1;
    3769     region->size = CS46XX_BA1_DATA1_SIZE;
    3770 
    3771     region = &chip->region.name.pmem;
    3772     strcpy(region->name, "CS46xx_BA1_pmem");
    3773     region->base = chip->ba1_addr + BA1_SP_PMEM;
    3774     region->size = CS46XX_BA1_PRG_SIZE;
    3775 
    3776     region = &chip->region.name.reg;
    3777     strcpy(region->name, "CS46xx_BA1_reg");
    3778     region->base = chip->ba1_addr + BA1_SP_REG;
    3779     region->size = CS46XX_BA1_REG_SIZE;
    3780 
    3781     /* set up amp and clkrun hack */
    3782     pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &ss_vendor);
    3783     pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &ss_card);
    3784 
    3785     for (cp = &cards[0]; cp->name; cp++) {
    3786         if (cp->vendor == ss_vendor && cp->id == ss_card) {
    3787             snd_printdd ("hack for %s enabled\n", cp->name);
    3788 
    3789             chip->amplifier_ctrl = cp->amp;
    3790             chip->active_ctrl = cp->active;
    3791             chip->mixer_init = cp->mixer_init;
    3792 
    3793             if (cp->init)
    3794                 cp->init(chip);
    3795             break;
    3796         }
    3797     }
    3798 
    3799     if (external_amp) {
    3800         snd_printk("Crystal EAPD support forced on.\n");
    3801         chip->amplifier_ctrl = amp_voyetra;
    3802     }
    3803 
    3804     if (thinkpad) {
    3805         snd_printk("Activating CLKRUN hack for Thinkpad.\n");
    3806         chip->active_ctrl = clkrun_hack;
    3807         clkrun_init(chip);
    3808     }
    3809 
    3810     if (chip->amplifier_ctrl == NULL)
    3811         chip->amplifier_ctrl = amp_none;
    3812     if (chip->active_ctrl == NULL)
    3813         chip->active_ctrl = amp_none;
    3814 
    3815     chip->active_ctrl(chip, 1); /* enable CLKRUN */
    3816 
    3817     pci_set_master(pci);
    3818 
    3819     for (idx = 0; idx < 5; idx++) {
    3820         region = &chip->region.idx[idx];
    3821         if ((region->resource = request_mem_region(region->base, region->size, region->name)) == NULL) {
    3822             snd_printk("unable to request memory region 0x%lx-0x%lx\n", region->base, region->base + region->size - 1);
    3823             snd_cs46xx_free(chip);
    3824             return -EBUSY;
    3825         }
    3826         (unsigned long)region->remap_addr = (unsigned long) ioremap_nocache(region->base, region->size);
    3827         if (region->remap_addr == 0) {
    3828             snd_printk("%s ioremap problem\n", region->name);
    3829             snd_cs46xx_free(chip);
    3830             return -ENOMEM;
    3831         }
    3832     }
    3833 
    3834     if (request_irq(pci->irq, snd_cs46xx_interrupt, SA_INTERRUPT|SA_SHIRQ, "CS46XX", (void *) chip)) {
    3835         snd_printk("unable to grab IRQ %d\n", pci->irq);
    3836         snd_cs46xx_free(chip);
    3837         return -EBUSY;
    3838     }
    3839     chip->irq = pci->irq;
    3840 
    3841 #ifdef CONFIG_SND_CS46XX_NEW_DSP
    3842     chip->dsp_spos_instance = cs46xx_dsp_spos_create(chip);
    3843     if (chip->dsp_spos_instance == NULL) {
    3844         snd_cs46xx_free(chip);
    3845         return -ENOMEM;
    3846     }
    3847 #endif
    3848 
    3849     err = snd_cs46xx_chip_init(chip);
    3850     if (err < 0) {
    3851         snd_cs46xx_free(chip);
    3852         return err;
    3853     }
    3854 
    3855     snd_cs46xx_proc_init(card, chip);
    3856 
    3857     snd_card_set_pm_callback(card, snd_cs46xx_suspend, snd_cs46xx_resume, chip);
    3858 
    3859     if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
    3860         snd_cs46xx_free(chip);
    3861         return err;
    3862     }
    3863 
    3864     chip->active_ctrl(chip, -1); /* disable CLKRUN */
    3865 
    3866     *rchip = chip;
    3867     return 0;
    3868 }
     3726int __devinit snd_cs46xx_create(struct snd_card *card,
     3727                      struct pci_dev * pci,
     3728                      int external_amp, int thinkpad,
     3729                      struct snd_cs46xx ** rchip)
     3730{
     3731        struct snd_cs46xx *chip;
     3732        int err, idx;
     3733        struct snd_cs46xx_region *region;
     3734        struct cs_card_type *cp;
     3735        u16 ss_card, ss_vendor;
     3736        static struct snd_device_ops ops = {
     3737                .dev_free =     snd_cs46xx_dev_free,
     3738        };
     3739       
     3740        *rchip = NULL;
     3741
     3742        /* enable PCI device */
     3743        if ((err = pci_enable_device(pci)) < 0)
     3744                return err;
     3745
     3746        chip = (struct snd_cs46xx *)kzalloc(sizeof(*chip), GFP_KERNEL);
     3747        if (chip == NULL) {
     3748                pci_disable_device(pci);
     3749                return -ENOMEM;
     3750        }
     3751        spin_lock_init(&chip->reg_lock);
     3752#ifdef CONFIG_SND_CS46XX_NEW_DSP
     3753        init_MUTEX(&chip->spos_mutex);
     3754#endif
     3755        chip->card = card;
     3756        chip->pci = pci;
     3757        chip->irq = -1;
     3758        chip->ba0_addr = pci_resource_start(pci, 0);
     3759        chip->ba1_addr = pci_resource_start(pci, 1);
     3760        if (chip->ba0_addr == 0 || chip->ba0_addr == (unsigned long)~0 ||
     3761            chip->ba1_addr == 0 || chip->ba1_addr == (unsigned long)~0) {
     3762                snd_printk(KERN_ERR "wrong address(es) - ba0 = 0x%lx, ba1 = 0x%lx\n",
     3763                           chip->ba0_addr, chip->ba1_addr);
     3764                snd_cs46xx_free(chip);
     3765                return -ENOMEM;
     3766        }
     3767
     3768        region = &chip->region.name.ba0;
     3769        strcpy(region->name, "CS46xx_BA0");
     3770        region->base = chip->ba0_addr;
     3771        region->size = CS46XX_BA0_SIZE;
     3772
     3773        region = &chip->region.name.data0;
     3774        strcpy(region->name, "CS46xx_BA1_data0");
     3775        region->base = chip->ba1_addr + BA1_SP_DMEM0;
     3776        region->size = CS46XX_BA1_DATA0_SIZE;
     3777
     3778        region = &chip->region.name.data1;
     3779        strcpy(region->name, "CS46xx_BA1_data1");
     3780        region->base = chip->ba1_addr + BA1_SP_DMEM1;
     3781        region->size = CS46XX_BA1_DATA1_SIZE;
     3782
     3783        region = &chip->region.name.pmem;
     3784        strcpy(region->name, "CS46xx_BA1_pmem");
     3785        region->base = chip->ba1_addr + BA1_SP_PMEM;
     3786        region->size = CS46XX_BA1_PRG_SIZE;
     3787
     3788        region = &chip->region.name.reg;
     3789        strcpy(region->name, "CS46xx_BA1_reg");
     3790        region->base = chip->ba1_addr + BA1_SP_REG;
     3791        region->size = CS46XX_BA1_REG_SIZE;
     3792
     3793        /* set up amp and clkrun hack */
     3794        pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &ss_vendor);
     3795        pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &ss_card);
     3796
     3797        for (cp = &cards[0]; cp->name; cp++) {
     3798                if (cp->vendor == ss_vendor && cp->id == ss_card) {
     3799                        snd_printdd ("hack for %s enabled\n", cp->name);
     3800
     3801                        chip->amplifier_ctrl = cp->amp;
     3802                        chip->active_ctrl = cp->active;
     3803                        chip->mixer_init = cp->mixer_init;
     3804
     3805                        if (cp->init)
     3806                                cp->init(chip);
     3807                        break;
     3808                }
     3809        }
     3810
     3811        if (external_amp) {
     3812                snd_printk(KERN_INFO "Crystal EAPD support forced on.\n");
     3813                chip->amplifier_ctrl = amp_voyetra;
     3814        }
     3815
     3816        if (thinkpad) {
     3817                snd_printk(KERN_INFO "Activating CLKRUN hack for Thinkpad.\n");
     3818                chip->active_ctrl = clkrun_hack;
     3819                clkrun_init(chip);
     3820        }
     3821       
     3822        if (chip->amplifier_ctrl == NULL)
     3823                chip->amplifier_ctrl = amp_none;
     3824        if (chip->active_ctrl == NULL)
     3825                chip->active_ctrl = amp_none;
     3826
     3827        chip->active_ctrl(chip, 1); /* enable CLKRUN */
     3828
     3829        pci_set_master(pci);
     3830
     3831        for (idx = 0; idx < 5; idx++) {
     3832                region = &chip->region.idx[idx];
     3833                if ((region->resource = request_mem_region(region->base, region->size,
     3834                                                           region->name)) == NULL) {
     3835                        snd_printk(KERN_ERR "unable to request memory region 0x%lx-0x%lx\n",
     3836                                   region->base, region->base + region->size - 1);
     3837                        snd_cs46xx_free(chip);
     3838                        return -EBUSY;
     3839                }
     3840                region->remap_addr = ioremap_nocache(region->base, region->size);
     3841                if (region->remap_addr == NULL) {
     3842                        snd_printk(KERN_ERR "%s ioremap problem\n", region->name);
     3843                        snd_cs46xx_free(chip);
     3844                        return -ENOMEM;
     3845                }
     3846        }
     3847
     3848        if (request_irq(pci->irq, snd_cs46xx_interrupt, SA_INTERRUPT|SA_SHIRQ,
     3849                        "CS46XX", chip)) {
     3850                snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
     3851                snd_cs46xx_free(chip);
     3852                return -EBUSY;
     3853        }
     3854        chip->irq = pci->irq;
     3855
     3856#ifdef CONFIG_SND_CS46XX_NEW_DSP
     3857        chip->dsp_spos_instance = cs46xx_dsp_spos_create(chip);
     3858        if (chip->dsp_spos_instance == NULL) {
     3859                snd_cs46xx_free(chip);
     3860                return -ENOMEM;
     3861        }
     3862#endif
     3863
     3864        err = snd_cs46xx_chip_init(chip);
     3865        if (err < 0) {
     3866                snd_cs46xx_free(chip);
     3867                return err;
     3868        }
     3869
     3870        if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
     3871                snd_cs46xx_free(chip);
     3872                return err;
     3873        }
     3874       
     3875        snd_cs46xx_proc_init(card, chip);
     3876
     3877        chip->active_ctrl(chip, -1); /* disable CLKRUN */
     3878
     3879        snd_card_set_dev(card, &pci->dev);
     3880
     3881        *rchip = chip;
     3882        return 0;
     3883}
  • GPL/trunk/alsa-kernel/pci/cs46xx/cs46xx_lib.h

    r33 r34  
    5454#define BA1_MEMORY_COUNT        3
    5555
    56 extern snd_pcm_ops_t snd_cs46xx_playback_ops;
    57 extern snd_pcm_ops_t snd_cs46xx_playback_indirect_ops;
    58 extern snd_pcm_ops_t snd_cs46xx_capture_ops;
    59 extern snd_pcm_ops_t snd_cs46xx_capture_indirect_ops;
    60 extern snd_pcm_ops_t snd_cs46xx_playback_rear_ops;
    61 extern snd_pcm_ops_t snd_cs46xx_playback_indirect_rear_ops;
    62 extern snd_pcm_ops_t snd_cs46xx_playback_iec958_ops;
    63 extern snd_pcm_ops_t snd_cs46xx_playback_indirect_iec958_ops;
    64 extern snd_pcm_ops_t snd_cs46xx_playback_clfe_ops;
    65 extern snd_pcm_ops_t snd_cs46xx_playback_indirect_clfe_ops;
    66 
    67 
    6856/*
    6957 *  common I/O routines
    7058 */
    7159
    72 static inline void snd_cs46xx_poke(cs46xx_t *chip, unsigned long reg, unsigned int val)
     60static inline void snd_cs46xx_poke(struct snd_cs46xx *chip, unsigned long reg, unsigned int val)
    7361{
    7462        unsigned int bank = reg >> 16;
     
    7967}
    8068
    81 static inline unsigned int snd_cs46xx_peek(cs46xx_t *chip, unsigned long reg)
     69static inline unsigned int snd_cs46xx_peek(struct snd_cs46xx *chip, unsigned long reg)
    8270{
    8371        unsigned int bank = reg >> 16;
     
    8674}
    8775
    88 static inline void snd_cs46xx_pokeBA0(cs46xx_t *chip, unsigned long offset, unsigned int val)
     76static inline void snd_cs46xx_pokeBA0(struct snd_cs46xx *chip, unsigned long offset, unsigned int val)
    8977{
    9078        writel(val, (char*)chip->region.name.ba0.remap_addr + offset);
    9179}
    9280
    93 static inline unsigned int snd_cs46xx_peekBA0(cs46xx_t *chip, unsigned long offset)
     81static inline unsigned int snd_cs46xx_peekBA0(struct snd_cs46xx *chip, unsigned long offset)
    9482{
    9583        return readl((char*)chip->region.name.ba0.remap_addr + offset);
    9684}
    9785
    98 dsp_spos_instance_t *  cs46xx_dsp_spos_create (cs46xx_t * chip);
    99 void                   cs46xx_dsp_spos_destroy (cs46xx_t * chip);
    100 int                    cs46xx_dsp_load_module (cs46xx_t * chip,dsp_module_desc_t * module);
    101 symbol_entry_t *       cs46xx_dsp_lookup_symbol (cs46xx_t * chip,char * symbol_name,int symbol_type);
    102 symbol_entry_t *       cs46xx_dsp_lookup_symbol_addr (cs46xx_t * chip,u32 address,int symbol_type);
    103 int                    cs46xx_dsp_proc_init (snd_card_t * card, cs46xx_t *chip);
    104 int                    cs46xx_dsp_proc_done (cs46xx_t *chip);
    105 int                    cs46xx_dsp_scb_and_task_init (cs46xx_t *chip);
    106 int                    cs46xx_dsp_async_init (cs46xx_t *chip,dsp_scb_descriptor_t * fg_entry);
    107 int                    snd_cs46xx_download (cs46xx_t *chip,u32 *src,unsigned long offset,
    108                                             unsigned long len);
    109 int                    snd_cs46xx_clear_BA1(cs46xx_t *chip,unsigned long offset,unsigned long len);
    110 int                    cs46xx_dsp_enable_spdif_out (cs46xx_t *chip);
    111 int                    cs46xx_dsp_enable_spdif_hw (cs46xx_t *chip);
    112 int                    cs46xx_dsp_disable_spdif_out (cs46xx_t *chip);
    113 int                    cs46xx_dsp_enable_spdif_in (cs46xx_t *chip);
    114 int                    cs46xx_dsp_disable_spdif_in (cs46xx_t *chip);
    115 int                    cs46xx_dsp_enable_pcm_capture (cs46xx_t *chip);
    116 int                    cs46xx_dsp_disable_pcm_capture (cs46xx_t *chip);
    117 int                    cs46xx_dsp_enable_adc_capture (cs46xx_t *chip);
    118 int                    cs46xx_dsp_disable_adc_capture (cs46xx_t *chip);
    119 int                    cs46xx_poke_via_dsp (cs46xx_t *chip,u32 address,u32 data);
    120 dsp_scb_descriptor_t * cs46xx_dsp_create_scb (cs46xx_t *chip,char * name, u32 * scb_data,u32 dest);
    121 void                   cs46xx_dsp_proc_free_scb_desc (dsp_scb_descriptor_t * scb);
    122 void                   cs46xx_dsp_proc_register_scb_desc (cs46xx_t *chip,dsp_scb_descriptor_t * scb);
    123 dsp_task_descriptor_t * cs46xx_dsp_create_task_tree (cs46xx_t *chip,char * name,
    124                                                      u32 * task_data,u32 dest,int size);
    125 dsp_scb_descriptor_t * cs46xx_dsp_create_timing_master_scb (cs46xx_t *chip);
    126 dsp_scb_descriptor_t * cs46xx_dsp_create_codec_out_scb(cs46xx_t * chip,char * codec_name,
    127                                                        u16 channel_disp,u16 fifo_addr,
    128                                                        u16 child_scb_addr,
    129                                                        u32 dest,
    130                                                        dsp_scb_descriptor_t * parent_scb,
    131                                                        int scb_child_type);
    132 dsp_scb_descriptor_t * cs46xx_dsp_create_codec_in_scb(cs46xx_t * chip,char * codec_name,
    133                                                       u16 channel_disp,u16 fifo_addr,
    134                                                       u16 sample_buffer_addr,
    135                                                       u32 dest,
    136                                                       dsp_scb_descriptor_t * parent_scb,
    137                                                       int scb_child_type);
    138 void                   cs46xx_dsp_remove_scb (cs46xx_t *chip,dsp_scb_descriptor_t * scb);
    139 dsp_scb_descriptor_t * cs46xx_dsp_create_generic_scb (cs46xx_t *chip,char * name,
    140                                                       u32 * scb_data,u32 dest,
    141                                                       char * task_entry_name,
    142                                                       dsp_scb_descriptor_t * parent_scb,
    143                                                       int scb_child_type);
    144 dsp_scb_descriptor_t *  cs46xx_dsp_create_codec_in_scb(cs46xx_t * chip,char * codec_name,
    145                                                        u16 channel_disp,u16 fifo_addr,
    146                                                        u16 sample_buffer_addr,
    147                                                        u32 dest,dsp_scb_descriptor_t * parent_scb,
    148                                                        int scb_child_type);
    149 dsp_scb_descriptor_t * cs46xx_dsp_create_pcm_reader_scb(cs46xx_t * chip,char * scb_name,
    150                                                         u16 sample_buffer_addr,u32 dest,
    151                                                         int virtual_channel,u32 playback_hw_addr,
    152                                                         dsp_scb_descriptor_t * parent_scb,
    153                                                         int scb_child_type);
    154 dsp_scb_descriptor_t *  cs46xx_dsp_create_src_task_scb(cs46xx_t * chip,char * scb_name,
    155                                                        int sample_rate,
    156                                                        u16 src_buffer_addr,
    157                                                        u16 src_delay_buffer_addr,u32 dest,
    158                                                        dsp_scb_descriptor_t * parent_scb,
    159                                                        int scb_child_type,
    160                                                        int pass_through);
    161 dsp_scb_descriptor_t *  cs46xx_dsp_create_mix_only_scb(cs46xx_t * chip,char * scb_name,
    162                                                        u16 mix_buffer_addr,u32 dest,
    163                                                        dsp_scb_descriptor_t * parent_scb,
    164                                                        int scb_child_type);
     86struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip);
     87void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip);
     88int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module);
     89struct dsp_symbol_entry *cs46xx_dsp_lookup_symbol (struct snd_cs46xx * chip, char * symbol_name,
     90                                                   int symbol_type);
     91int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip);
     92int cs46xx_dsp_proc_done (struct snd_cs46xx *chip);
     93int cs46xx_dsp_scb_and_task_init (struct snd_cs46xx *chip);
     94int snd_cs46xx_download (struct snd_cs46xx *chip, u32 *src, unsigned long offset,
     95                         unsigned long len);
     96int snd_cs46xx_clear_BA1(struct snd_cs46xx *chip, unsigned long offset, unsigned long len);
     97int cs46xx_dsp_enable_spdif_out (struct snd_cs46xx *chip);
     98int cs46xx_dsp_enable_spdif_hw (struct snd_cs46xx *chip);
     99int cs46xx_dsp_disable_spdif_out (struct snd_cs46xx *chip);
     100int cs46xx_dsp_enable_spdif_in (struct snd_cs46xx *chip);
     101int cs46xx_dsp_disable_spdif_in (struct snd_cs46xx *chip);
     102int cs46xx_dsp_enable_pcm_capture (struct snd_cs46xx *chip);
     103int cs46xx_dsp_disable_pcm_capture (struct snd_cs46xx *chip);
     104int cs46xx_dsp_enable_adc_capture (struct snd_cs46xx *chip);
     105int cs46xx_dsp_disable_adc_capture (struct snd_cs46xx *chip);
     106int cs46xx_poke_via_dsp (struct snd_cs46xx *chip, u32 address, u32 data);
     107struct dsp_scb_descriptor * cs46xx_dsp_create_scb (struct snd_cs46xx *chip, char * name,
     108                                                   u32 * scb_data, u32 dest);
     109void cs46xx_dsp_proc_free_scb_desc (struct dsp_scb_descriptor * scb);
     110void cs46xx_dsp_proc_register_scb_desc (struct snd_cs46xx *chip,
     111                                        struct dsp_scb_descriptor * scb);
     112struct dsp_scb_descriptor * cs46xx_dsp_create_timing_master_scb (struct snd_cs46xx *chip);
     113struct dsp_scb_descriptor *
     114cs46xx_dsp_create_codec_out_scb(struct snd_cs46xx * chip,
     115                                char * codec_name, u16 channel_disp, u16 fifo_addr,
     116                                u16 child_scb_addr, u32 dest,
     117                                struct dsp_scb_descriptor * parent_scb,
     118                                int scb_child_type);
     119struct dsp_scb_descriptor *
     120cs46xx_dsp_create_codec_in_scb(struct snd_cs46xx * chip, char * codec_name,
     121                               u16 channel_disp, u16 fifo_addr,
     122                               u16 sample_buffer_addr, u32 dest,
     123                               struct dsp_scb_descriptor * parent_scb,
     124                               int scb_child_type);
     125void cs46xx_dsp_remove_scb (struct snd_cs46xx *chip,
     126                            struct dsp_scb_descriptor * scb);
     127struct dsp_scb_descriptor *
     128cs46xx_dsp_create_codec_in_scb(struct snd_cs46xx * chip, char * codec_name,
     129                               u16 channel_disp, u16 fifo_addr,
     130                               u16 sample_buffer_addr, u32 dest,
     131                               struct dsp_scb_descriptor * parent_scb,
     132                               int scb_child_type);
     133struct dsp_scb_descriptor *
     134cs46xx_dsp_create_src_task_scb(struct snd_cs46xx * chip, char * scb_name,
     135                               int sample_rate, u16 src_buffer_addr,
     136                               u16 src_delay_buffer_addr, u32 dest,
     137                               struct dsp_scb_descriptor * parent_scb,
     138                               int scb_child_type, int pass_through);
     139struct dsp_scb_descriptor *
     140cs46xx_dsp_create_mix_only_scb(struct snd_cs46xx * chip, char * scb_name,
     141                               u16 mix_buffer_addr, u32 dest,
     142                               struct dsp_scb_descriptor * parent_scb,
     143                               int scb_child_type);
    165144
    166 dsp_scb_descriptor_t *  cs46xx_dsp_create_vari_decimate_scb(cs46xx_t * chip,char * scb_name,
    167                                                             u16 vari_buffer_addr0,
    168                                                             u16 vari_buffer_addr1,
    169                                                             u32 dest,
    170                                                             dsp_scb_descriptor_t * parent_scb,
    171                                                             int scb_child_type);
    172 dsp_scb_descriptor_t *  cs46xx_dsp_create_pcm_serial_input_scb(cs46xx_t * chip,char * scb_name,u32 dest,
    173                                                                dsp_scb_descriptor_t * input_scb,
    174                                                                dsp_scb_descriptor_t * parent_scb,
    175                                                                int scb_child_type);
    176 dsp_scb_descriptor_t * cs46xx_dsp_create_asynch_fg_tx_scb(cs46xx_t * chip,char * scb_name,u32 dest,
    177                                                           u16 hfg_scb_address,
    178                                                           u16 asynch_buffer_address,
    179                                                           dsp_scb_descriptor_t * parent_scb,
    180                                                           int scb_child_type);
    181 dsp_scb_descriptor_t * cs46xx_dsp_create_asynch_fg_rx_scb(cs46xx_t * chip,char * scb_name,u32 dest,
    182                                                           u16 hfg_scb_address,
    183                                                           u16 asynch_buffer_address,
    184                                                           dsp_scb_descriptor_t * parent_scb,
    185                                                           int scb_child_type);
    186 dsp_scb_descriptor_t *  cs46xx_dsp_create_spio_write_scb(cs46xx_t * chip,char * scb_name,u32 dest,
    187                                                          dsp_scb_descriptor_t * parent_scb,
    188                                                          int scb_child_type);
    189 dsp_scb_descriptor_t *  cs46xx_dsp_create_mix_to_ostream_scb(cs46xx_t * chip,char * scb_name,
    190                                                              u16 mix_buffer_addr,u16 writeback_spb,u32 dest,
    191                                                              dsp_scb_descriptor_t * parent_scb,
    192                                                              int scb_child_type);
    193 dsp_scb_descriptor_t *  cs46xx_dsp_create_output_snoop_scb(cs46xx_t * chip,char * scb_name,u32 dest,
    194                                                            u16 snoop_buffer_address,
    195                                                            dsp_scb_descriptor_t * snoop_scb,
    196                                                            dsp_scb_descriptor_t * parent_scb,
    197                                                            int scb_child_type);
    198 dsp_scb_descriptor_t *  cs46xx_dsp_create_magic_snoop_scb(cs46xx_t * chip,char * scb_name,u32 dest,
    199                                                           u16 snoop_buffer_address,
    200                                                           dsp_scb_descriptor_t * snoop_scb,
    201                                                           dsp_scb_descriptor_t * parent_scb,
    202                                                           int scb_child_type);
    203 pcm_channel_descriptor_t * cs46xx_dsp_create_pcm_channel (cs46xx_t * chip,u32 sample_rate, void * private_data, u32 hw_dma_addr,
    204                                                           int pcm_channel_id);
    205 void                       cs46xx_dsp_destroy_pcm_channel (cs46xx_t * chip,
    206                                                            pcm_channel_descriptor_t * pcm_channel);
    207 int                        cs46xx_dsp_pcm_unlink (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel);
    208 int                        cs46xx_dsp_pcm_link (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel);
    209 dsp_scb_descriptor_t *     cs46xx_add_record_source (cs46xx_t *chip,dsp_scb_descriptor_t * source,
    210                                                      u16 addr,char * scb_name);
    211 int                         cs46xx_src_unlink(cs46xx_t *chip,dsp_scb_descriptor_t * src);
    212 int                         cs46xx_src_link(cs46xx_t *chip,dsp_scb_descriptor_t * src);
    213 int                        cs46xx_iec958_pre_open (cs46xx_t *chip);
    214 int                        cs46xx_iec958_post_close (cs46xx_t *chip);
    215 int                        cs46xx_dsp_pcm_channel_set_period (cs46xx_t * chip,
    216                                                                pcm_channel_descriptor_t * pcm_channel,
    217                                                                int period_size);
    218 int                        cs46xx_dsp_pcm_ostream_set_period (cs46xx_t * chip,
    219                                                               int period_size);
    220 int                        cs46xx_dsp_set_dac_volume (cs46xx_t * chip,u16 left,u16 right);
    221 int                        cs46xx_dsp_set_iec958_volume (cs46xx_t * chip,u16 left,u16 right);
     145struct dsp_scb_descriptor *
     146cs46xx_dsp_create_vari_decimate_scb(struct snd_cs46xx * chip, char * scb_name,
     147                                    u16 vari_buffer_addr0, u16 vari_buffer_addr1, u32 dest,
     148                                    struct dsp_scb_descriptor * parent_scb,
     149                                    int scb_child_type);
     150struct dsp_scb_descriptor *
     151cs46xx_dsp_create_asynch_fg_rx_scb(struct snd_cs46xx * chip, char * scb_name,
     152                                   u32 dest, u16 hfg_scb_address, u16 asynch_buffer_address,
     153                                   struct dsp_scb_descriptor * parent_scb,
     154                                   int scb_child_type);
     155struct dsp_scb_descriptor *
     156cs46xx_dsp_create_spio_write_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
     157                                 struct dsp_scb_descriptor * parent_scb,
     158                                 int scb_child_type);
     159struct dsp_scb_descriptor *
     160cs46xx_dsp_create_mix_to_ostream_scb(struct snd_cs46xx * chip, char * scb_name,
     161                                     u16 mix_buffer_addr, u16 writeback_spb, u32 dest,
     162                                     struct dsp_scb_descriptor * parent_scb,
     163                                     int scb_child_type);
     164struct dsp_scb_descriptor *
     165cs46xx_dsp_create_magic_snoop_scb(struct snd_cs46xx * chip, char * scb_name,
     166                                  u32 dest, u16 snoop_buffer_address,
     167                                  struct dsp_scb_descriptor * snoop_scb,
     168                                  struct dsp_scb_descriptor * parent_scb,
     169                                  int scb_child_type);
     170struct dsp_pcm_channel_descriptor *
     171cs46xx_dsp_create_pcm_channel (struct snd_cs46xx * chip, u32 sample_rate,
     172                               void * private_data, u32 hw_dma_addr,
     173                               int pcm_channel_id);
     174void cs46xx_dsp_destroy_pcm_channel (struct snd_cs46xx * chip,
     175                                     struct dsp_pcm_channel_descriptor * pcm_channel);
     176int cs46xx_dsp_pcm_unlink (struct snd_cs46xx * chip,
     177                           struct dsp_pcm_channel_descriptor * pcm_channel);
     178int cs46xx_dsp_pcm_link (struct snd_cs46xx * chip,
     179                         struct dsp_pcm_channel_descriptor * pcm_channel);
     180struct dsp_scb_descriptor *
     181cs46xx_add_record_source (struct snd_cs46xx *chip, struct dsp_scb_descriptor * source,
     182                          u16 addr, char * scb_name);
     183int cs46xx_src_unlink(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src);
     184int cs46xx_src_link(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src);
     185int cs46xx_iec958_pre_open (struct snd_cs46xx *chip);
     186int cs46xx_iec958_post_close (struct snd_cs46xx *chip);
     187int cs46xx_dsp_pcm_channel_set_period (struct snd_cs46xx * chip,
     188                                       struct dsp_pcm_channel_descriptor * pcm_channel,
     189                                       int period_size);
     190int cs46xx_dsp_pcm_ostream_set_period (struct snd_cs46xx * chip, int period_size);
     191int cs46xx_dsp_set_dac_volume (struct snd_cs46xx * chip, u16 left, u16 right);
     192int cs46xx_dsp_set_iec958_volume (struct snd_cs46xx * chip, u16 left, u16 right);
    222193#endif /* __CS46XX_LIB_H__ */
  • GPL/trunk/alsa-kernel/pci/cs46xx/dsp_spos.c

    r33 r34  
    3838#include "dsp_spos.h"
    3939
    40 static wide_opcode_t wide_opcodes[] = {
    41     WIDE_FOR_BEGIN_LOOP,
    42     WIDE_FOR_BEGIN_LOOP2,
    43     WIDE_COND_GOTO_ADDR,
    44     WIDE_COND_GOTO_CALL,
    45     WIDE_TBEQ_COND_GOTO_ADDR,
    46     WIDE_TBEQ_COND_CALL_ADDR,
    47     WIDE_TBEQ_NCOND_GOTO_ADDR,
    48     WIDE_TBEQ_NCOND_CALL_ADDR,
    49     WIDE_TBEQ_COND_GOTO1_ADDR,
    50     WIDE_TBEQ_COND_CALL1_ADDR,
    51     WIDE_TBEQ_NCOND_GOTOI_ADDR,
    52     WIDE_TBEQ_NCOND_CALL1_ADDR
     40static int cs46xx_dsp_async_init (struct snd_cs46xx *chip,
     41                                  struct dsp_scb_descriptor * fg_entry);
     42
     43static enum wide_opcode wide_opcodes[] = {
     44        WIDE_FOR_BEGIN_LOOP,
     45        WIDE_FOR_BEGIN_LOOP2,
     46        WIDE_COND_GOTO_ADDR,
     47        WIDE_COND_GOTO_CALL,
     48        WIDE_TBEQ_COND_GOTO_ADDR,
     49        WIDE_TBEQ_COND_CALL_ADDR,
     50        WIDE_TBEQ_NCOND_GOTO_ADDR,
     51        WIDE_TBEQ_NCOND_CALL_ADDR,
     52        WIDE_TBEQ_COND_GOTO1_ADDR,
     53        WIDE_TBEQ_COND_CALL1_ADDR,
     54        WIDE_TBEQ_NCOND_GOTOI_ADDR,
     55        WIDE_TBEQ_NCOND_CALL1_ADDR
    5356};
    5457
    55 static int shadow_and_reallocate_code (cs46xx_t * chip,u32 * data,u32 size, u32 overlay_begin_address)
    56 {
    57     unsigned int i = 0, j, nreallocated = 0;
    58     u32 hival,loval,address;
    59     u32 mop_operands,mop_type,wide_op;
    60     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    61 
    62     snd_assert( ((size % 2) == 0), return -EINVAL);
    63 
    64     while (i < size) {
    65         loval = data[i++];
    66         hival = data[i++];
    67 
    68         if (ins->code.offset > 0) {
    69             mop_operands = (hival >> 6) & 0x03fff;
    70             mop_type = mop_operands >> 10;
    71 
    72             /* check for wide type instruction */
    73             if (mop_type == 0 &&
    74                 (mop_operands & WIDE_LADD_INSTR_MASK) == 0 &&
    75                 (mop_operands & WIDE_INSTR_MASK) != 0) {
    76                 wide_op = loval & 0x7f;
    77                 for (j = 0;j < sizeof(wide_opcodes) / sizeof(wide_opcode_t); ++j) {
    78                     if (wide_opcodes[j] == wide_op) {
    79                         /* need to reallocate instruction */
    80                         address  = (hival & 0x00FFF) << 5;
    81                         address |=  loval >> 15;
    82 
    83                         snd_printdd("handle_wideop[1]: %05x:%05x addr %04x\n",hival,loval,address);
    84 
    85                         if ( !(address & 0x8000) ) {
    86                             address += (ins->code.offset / 2) - overlay_begin_address;
    87                         } else {
    88                             snd_printdd("handle_wideop[1]: ROM symbol not reallocated\n");
    89                         }
    90 
    91                         hival &= 0xFF000;
    92                         loval &= 0x07FFF;
    93 
    94                         hival |= ( (address >> 5)  & 0x00FFF);
    95                         loval |= ( (address << 15) & 0xF8000);
    96 
    97                         address  = (hival & 0x00FFF) << 5;
    98                         address |=  loval >> 15;
    99 
    100                         snd_printdd("handle_wideop:[2] %05x:%05x addr %04x\n",hival,loval,address);
    101                         nreallocated ++;
    102                     } /* wide_opcodes[j] == wide_op */
    103                 } /* for */
    104             } /* mod_type == 0 ... */
    105         } /* ins->code.offset > 0 */
    106 
    107         ins->code.data[ins->code.size++] = loval;
    108         ins->code.data[ins->code.size++] = hival;
    109     }
    110 
    111     snd_printdd("dsp_spos: %d instructions reallocated\n",nreallocated);
    112     return nreallocated;
    113 }
    114 
    115 static segment_desc_t * get_segment_desc (dsp_module_desc_t * module, int seg_type)
    116 {
    117     int i;
    118     for (i = 0;i < module->nsegments; ++i) {
    119         if (module->segments[i].segment_type == seg_type) {
    120             return (module->segments + i);
    121         }
    122     }
    123 
    124     return NULL;
     58static int shadow_and_reallocate_code (struct snd_cs46xx * chip, u32 * data, u32 size,
     59                                       u32 overlay_begin_address)
     60{
     61        unsigned int i = 0, j, nreallocated = 0;
     62        u32 hival,loval,address;
     63        u32 mop_operands,mop_type,wide_op;
     64        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     65
     66        snd_assert( ((size % 2) == 0), return -EINVAL);
     67 
     68        while (i < size) {
     69                loval = data[i++];
     70                hival = data[i++];
     71
     72                if (ins->code.offset > 0) {
     73                        mop_operands = (hival >> 6) & 0x03fff;
     74                        mop_type = mop_operands >> 10;
     75     
     76                        /* check for wide type instruction */
     77                        if (mop_type == 0 &&
     78                            (mop_operands & WIDE_LADD_INSTR_MASK) == 0 &&
     79                            (mop_operands & WIDE_INSTR_MASK) != 0) {
     80                                wide_op = loval & 0x7f;
     81                                for (j = 0;j < ARRAY_SIZE(wide_opcodes); ++j) {
     82                                        if (wide_opcodes[j] == wide_op) {
     83                                                /* need to reallocate instruction */
     84                                                address  = (hival & 0x00FFF) << 5;
     85                                                address |=  loval >> 15;
     86           
     87                                                snd_printdd("handle_wideop[1]: %05x:%05x addr %04x\n",hival,loval,address);
     88           
     89                                                if ( !(address & 0x8000) ) {
     90                                                        address += (ins->code.offset / 2) - overlay_begin_address;
     91                                                } else {
     92                                                        snd_printdd("handle_wideop[1]: ROM symbol not reallocated\n");
     93                                                }
     94           
     95                                                hival &= 0xFF000;
     96                                                loval &= 0x07FFF;
     97           
     98                                                hival |= ( (address >> 5)  & 0x00FFF);
     99                                                loval |= ( (address << 15) & 0xF8000);
     100           
     101                                                address  = (hival & 0x00FFF) << 5;
     102                                                address |=  loval >> 15;
     103           
     104                                                snd_printdd("handle_wideop:[2] %05x:%05x addr %04x\n",hival,loval,address);           
     105                                                nreallocated ++;
     106                                        } /* wide_opcodes[j] == wide_op */
     107                                } /* for */
     108                        } /* mod_type == 0 ... */
     109                } /* ins->code.offset > 0 */
     110
     111                ins->code.data[ins->code.size++] = loval;
     112                ins->code.data[ins->code.size++] = hival;
     113        }
     114
     115        snd_printdd("dsp_spos: %d instructions reallocated\n",nreallocated);
     116        return nreallocated;
     117}
     118
     119static struct dsp_segment_desc * get_segment_desc (struct dsp_module_desc * module, int seg_type)
     120{
     121        int i;
     122        for (i = 0;i < module->nsegments; ++i) {
     123                if (module->segments[i].segment_type == seg_type) {
     124                        return (module->segments + i);
     125                }
     126        }
     127
     128        return NULL;
    125129};
    126130
    127 static int find_free_symbol_index (dsp_spos_instance_t * ins)
    128 {
    129     int index = ins->symbol_table.nsymbols,i;
    130 
    131     for (i = ins->symbol_table.highest_frag_index; i < ins->symbol_table.nsymbols; ++i) {
    132         if (ins->symbol_table.symbols[i].deleted) {
    133             index = i;
    134             break;
    135         }
    136     }
    137 
    138     return index;
    139 }
    140 
    141 static int add_symbols (cs46xx_t * chip, dsp_module_desc_t * module)
    142 {
    143     int i;
    144     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    145 
    146     if (module->symbol_table.nsymbols > 0) {
    147         if (!strcmp(module->symbol_table.symbols[0].symbol_name, "OVERLAYBEGINADDRESS") &&
    148             module->symbol_table.symbols[0].symbol_type == SYMBOL_CONSTANT ) {
    149             module->overlay_begin_address = module->symbol_table.symbols[0].address;
    150         }
    151     }
    152 
    153     for (i = 0;i < module->symbol_table.nsymbols; ++i) {
    154         if (ins->symbol_table.nsymbols == (DSP_MAX_SYMBOLS - 1)) {
    155             snd_printk(KERN_ERR "dsp_spos: symbol table is full\n");
    156             return -ENOMEM;
    157         }
    158 
    159 
    160         if (cs46xx_dsp_lookup_symbol(chip,
    161                                      module->symbol_table.symbols[i].symbol_name,
    162                                      module->symbol_table.symbols[i].symbol_type) == NULL) {
    163 
    164             ins->symbol_table.symbols[ins->symbol_table.nsymbols] = module->symbol_table.symbols[i];
    165             ins->symbol_table.symbols[ins->symbol_table.nsymbols].address += ((ins->code.offset / 2) - module->overlay_begin_address);
    166             ins->symbol_table.symbols[ins->symbol_table.nsymbols].module = module;
    167             ins->symbol_table.symbols[ins->symbol_table.nsymbols].deleted = 0;
    168 
    169             if (ins->symbol_table.nsymbols > ins->symbol_table.highest_frag_index)
    170                 ins->symbol_table.highest_frag_index = ins->symbol_table.nsymbols;
    171 
    172             ins->symbol_table.nsymbols++;
    173         } else {
    174             /* if (0) printk ("dsp_spos: symbol <%s> duplicated, probably nothing wrong with that (Cirrus?)\n",
    175              module->symbol_table.symbols[i].symbol_name); */
    176         }
    177     }
    178 
    179     return 0;
    180 }
    181 
    182 static symbol_entry_t * add_symbol (cs46xx_t * chip, char * symbol_name, u32 address, int type)
    183 {
    184     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    185     symbol_entry_t * symbol = NULL;
    186     int index;
    187 
    188     if (ins->symbol_table.nsymbols == (DSP_MAX_SYMBOLS - 1)) {
    189         snd_printk(KERN_ERR "dsp_spos: symbol table is full\n");
    190         return NULL;
    191     }
    192 
    193     if (cs46xx_dsp_lookup_symbol(chip,
    194                                  symbol_name,
    195                                  type) != NULL) {
    196         snd_printk(KERN_ERR "dsp_spos: symbol <%s> duplicated\n", symbol_name);
    197         return NULL;
    198     }
    199 
    200     index = find_free_symbol_index (ins);
    201 
    202     strcpy (ins->symbol_table.symbols[index].symbol_name, symbol_name);
    203     ins->symbol_table.symbols[index].address = address;
    204     ins->symbol_table.symbols[index].symbol_type = type;
    205     ins->symbol_table.symbols[index].module = NULL;
    206     ins->symbol_table.symbols[index].deleted = 0;
    207     symbol = (ins->symbol_table.symbols + index);
    208 
    209     if (index > ins->symbol_table.highest_frag_index)
    210         ins->symbol_table.highest_frag_index = index;
    211 
    212     if (index == ins->symbol_table.nsymbols)
    213         ins->symbol_table.nsymbols++; /* no frag. in list */
    214 
    215     return symbol;
    216 }
    217 
    218 dsp_spos_instance_t *  cs46xx_dsp_spos_create (cs46xx_t * chip)
    219 {
    220     dsp_spos_instance_t * ins = kmalloc(sizeof(dsp_spos_instance_t), GFP_KERNEL);
    221 
    222     if (ins == NULL)
    223         return NULL;
    224     memset(ins, 0, sizeof(*ins));
    225 
    226     /* better to use vmalloc for this big table */
    227     ins->symbol_table.nsymbols = 0;
    228     ins->symbol_table.symbols = vmalloc(sizeof(symbol_entry_t) * DSP_MAX_SYMBOLS);
    229     ins->symbol_table.highest_frag_index = 0;
    230 
    231     if (ins->symbol_table.symbols == NULL) {
    232         cs46xx_dsp_spos_destroy(chip);
    233         return NULL;
    234     }
    235 
    236     ins->code.offset = 0;
    237     ins->code.size = 0;
    238     ins->code.data = kmalloc(DSP_CODE_BYTE_SIZE, GFP_KERNEL);
    239 
    240     if (ins->code.data == NULL) {
    241         cs46xx_dsp_spos_destroy(chip);
    242         return NULL;
    243     }
    244 
    245     ins->nscb = 0;
    246     ins->ntask = 0;
    247 
    248     ins->nmodules = 0;
    249     ins->modules = kmalloc(sizeof(dsp_module_desc_t) * DSP_MAX_MODULES, GFP_KERNEL);
    250 
    251     if (ins->modules == NULL) {
    252         cs46xx_dsp_spos_destroy(chip);
    253         return NULL;
    254     }
    255 
    256     /* default SPDIF input sample rate
    257      to 48000 khz */
    258     ins->spdif_in_sample_rate = 48000;
    259 
    260     /* maximize volume */
    261     ins->dac_volume_right = 0x8000;
    262     ins->dac_volume_left = 0x8000;
    263     ins->spdif_input_volume_right = 0x8000;
    264     ins->spdif_input_volume_left = 0x8000;
    265 
    266     /* set left and right validity bits and
    267      default channel status */
    268     ins->spdif_csuv_default =
    269         ins->spdif_csuv_stream =
    270         /* byte 0 */  ((unsigned int)_wrap_all_bits(  (SNDRV_PCM_DEFAULT_CON_SPDIF        & 0xff)) << 24) |
    271         /* byte 1 */  ((unsigned int)_wrap_all_bits( ((SNDRV_PCM_DEFAULT_CON_SPDIF >> 8) & 0xff)) << 16) |
    272         /* byte 3 */   (unsigned int)_wrap_all_bits(  (SNDRV_PCM_DEFAULT_CON_SPDIF >> 24) & 0xff) |
    273         /* left and right validity bits */ (1 << 13) | (1 << 12);
    274 
    275     return ins;
    276 }
    277 
    278 void  cs46xx_dsp_spos_destroy (cs46xx_t * chip)
    279 {
    280     int i;
    281     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    282 
    283     snd_assert(ins != NULL, return);
    284 
    285     down(&chip->spos_mutex);
    286     for (i = 0; i < ins->nscb; ++i) {
    287         if (ins->scbs[i].deleted) continue;
    288 
    289         cs46xx_dsp_proc_free_scb_desc ( (ins->scbs + i) );
    290     }
    291 
    292     if (ins->code.data)
    293         kfree(ins->code.data);
    294 
    295     if (ins->symbol_table.symbols)
    296         vfree(ins->symbol_table.symbols);
    297 
    298     if (ins->modules)
    299         kfree(ins->modules);
    300 
    301     kfree(ins);
    302     up(&chip->spos_mutex);
    303 }
    304 
    305 int cs46xx_dsp_load_module (cs46xx_t * chip, dsp_module_desc_t * module)
    306 {
    307     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    308     segment_desc_t * code = get_segment_desc (module,SEGTYPE_SP_PROGRAM);
    309     segment_desc_t * parameter = get_segment_desc (module,SEGTYPE_SP_PARAMETER);
    310     segment_desc_t * sample = get_segment_desc (module,SEGTYPE_SP_SAMPLE);
    311     u32 doffset, dsize;
    312 
    313     if (ins->nmodules == DSP_MAX_MODULES - 1) {
    314         snd_printk(KERN_ERR "dsp_spos: to many modules loaded into DSP\n");
    315         return -ENOMEM;
    316     }
    317 
    318     snd_printdd("dsp_spos: loading module %s into DSP\n", module->module_name);
    319 
    320     if (ins->nmodules == 0) {
    321         snd_printdd("dsp_spos: clearing parameter area\n");
    322         snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET, DSP_PARAMETER_BYTE_SIZE);
    323     }
    324 
    325     if (parameter == NULL) {
    326         snd_printdd("dsp_spos: module got no parameter segment\n");
    327     } else {
    328         if (ins->nmodules > 0) {
    329             snd_printk(KERN_WARNING "dsp_spos: WARNING current parameter data may be overwriten!\n");
    330         }
    331 
    332         doffset = (parameter->offset * 4 + DSP_PARAMETER_BYTE_OFFSET);
    333         dsize   = parameter->size * 4;
    334 
    335         snd_printdd("dsp_spos: downloading parameter data to chip (%08x-%08x)\n",
    336                     doffset,doffset + dsize);
    337 
    338         if (snd_cs46xx_download (chip, parameter->data, doffset, dsize)) {
    339             snd_printk(KERN_ERR "dsp_spos: failed to download parameter data to DSP\n");
    340             return -EINVAL;
    341         }
    342     }
    343 
    344     if (ins->nmodules == 0) {
    345         snd_printdd("dsp_spos: clearing sample area\n");
    346         snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET, DSP_SAMPLE_BYTE_SIZE);
    347     }
    348 
    349     if (sample == NULL) {
    350         snd_printdd("dsp_spos: module got no sample segment\n");
    351     } else {
    352         if (ins->nmodules > 0) {
    353             snd_printk(KERN_WARNING "dsp_spos: WARNING current sample data may be overwriten\n");
    354         }
    355 
    356         doffset = (sample->offset * 4  + DSP_SAMPLE_BYTE_OFFSET);
    357         dsize   =  sample->size * 4;
    358 
    359         snd_printdd("dsp_spos: downloading sample data to chip (%08x-%08x)\n",
    360                     doffset,doffset + dsize);
    361 
    362         if (snd_cs46xx_download (chip,sample->data,doffset,dsize)) {
    363             snd_printk(KERN_ERR "dsp_spos: failed to sample data to DSP\n");
    364             return -EINVAL;
    365         }
    366     }
    367 
    368 
    369     if (ins->nmodules == 0) {
    370         snd_printdd("dsp_spos: clearing code area\n");
    371         snd_cs46xx_clear_BA1(chip, DSP_CODE_BYTE_OFFSET, DSP_CODE_BYTE_SIZE);
    372     }
    373 
    374     if (code == NULL) {
    375         snd_printdd("dsp_spos: module got no code segment\n");
    376     } else {
    377         if (ins->code.offset + code->size > DSP_CODE_BYTE_SIZE) {
    378             snd_printk(KERN_ERR "dsp_spos: no space available in DSP\n");
    379             return -ENOMEM;
    380         }
    381 
    382         module->load_address = ins->code.offset;
    383         module->overlay_begin_address = 0x000;
    384 
    385         /* if module has a code segment it must have
    386          symbol table */
    387         snd_assert(module->symbol_table.symbols != NULL ,return -ENOMEM);
    388         if (add_symbols(chip,module)) {
    389             snd_printk(KERN_ERR "dsp_spos: failed to load symbol table\n");
    390             return -ENOMEM;
    391         }
    392 
    393         doffset = (code->offset * 4 + ins->code.offset * 4 + DSP_CODE_BYTE_OFFSET);
    394         dsize   = code->size * 4;
    395         snd_printdd("dsp_spos: downloading code to chip (%08x-%08x)\n",
    396                     doffset,doffset + dsize);
    397 
    398         module->nfixups = shadow_and_reallocate_code(chip,code->data,code->size,module->overlay_begin_address);
    399 
    400         if (snd_cs46xx_download (chip,(ins->code.data + ins->code.offset),doffset,dsize)) {
    401             snd_printk(KERN_ERR "dsp_spos: failed to download code to DSP\n");
    402             return -EINVAL;
    403         }
    404 
    405         ins->code.offset += code->size;
    406     }
    407 
    408     /* NOTE: module segments and symbol table must be
    409      statically allocated. Case that module data is
    410      not generated by the ospparser */
    411     ins->modules[ins->nmodules] = *module;
    412     ins->nmodules++;
    413 
    414     return 0;
    415 }
    416 
    417 symbol_entry_t * cs46xx_dsp_lookup_symbol (cs46xx_t * chip, char * symbol_name, int symbol_type)
    418 {
    419     int i;
    420     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    421 
    422     for ( i = 0; i < ins->symbol_table.nsymbols; ++i ) {
    423 
    424         if (ins->symbol_table.symbols[i].deleted)
    425             continue;
    426 
    427         if (!strcmp(ins->symbol_table.symbols[i].symbol_name,symbol_name) &&
    428             ins->symbol_table.symbols[i].symbol_type == symbol_type) {
    429             return (ins->symbol_table.symbols + i);
    430         }
    431     }
     131static int find_free_symbol_index (struct dsp_spos_instance * ins)
     132{
     133        int index = ins->symbol_table.nsymbols,i;
     134
     135        for (i = ins->symbol_table.highest_frag_index; i < ins->symbol_table.nsymbols; ++i) {
     136                if (ins->symbol_table.symbols[i].deleted) {
     137                        index = i;
     138                        break;
     139                }
     140        }
     141
     142        return index;
     143}
     144
     145static int add_symbols (struct snd_cs46xx * chip, struct dsp_module_desc * module)
     146{
     147        int i;
     148        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     149
     150        if (module->symbol_table.nsymbols > 0) {
     151                if (!strcmp(module->symbol_table.symbols[0].symbol_name, "OVERLAYBEGINADDRESS") &&
     152                    module->symbol_table.symbols[0].symbol_type == SYMBOL_CONSTANT ) {
     153                        module->overlay_begin_address = module->symbol_table.symbols[0].address;
     154                }
     155        }
     156
     157        for (i = 0;i < module->symbol_table.nsymbols; ++i) {
     158                if (ins->symbol_table.nsymbols == (DSP_MAX_SYMBOLS - 1)) {
     159                        snd_printk(KERN_ERR "dsp_spos: symbol table is full\n");
     160                        return -ENOMEM;
     161                }
     162
     163
     164                if (cs46xx_dsp_lookup_symbol(chip,
     165                                             module->symbol_table.symbols[i].symbol_name,
     166                                             module->symbol_table.symbols[i].symbol_type) == NULL) {
     167
     168                        ins->symbol_table.symbols[ins->symbol_table.nsymbols] = module->symbol_table.symbols[i];
     169                        ins->symbol_table.symbols[ins->symbol_table.nsymbols].address += ((ins->code.offset / 2) - module->overlay_begin_address);
     170                        ins->symbol_table.symbols[ins->symbol_table.nsymbols].module = module;
     171                        ins->symbol_table.symbols[ins->symbol_table.nsymbols].deleted = 0;
     172
     173                        if (ins->symbol_table.nsymbols > ins->symbol_table.highest_frag_index)
     174                                ins->symbol_table.highest_frag_index = ins->symbol_table.nsymbols;
     175
     176                        ins->symbol_table.nsymbols++;
     177                } else {
     178          /* if (0) printk ("dsp_spos: symbol <%s> duplicated, probably nothing wrong with that (Cirrus?)\n",
     179                             module->symbol_table.symbols[i].symbol_name); */
     180                }
     181        }
     182
     183        return 0;
     184}
     185
     186static struct dsp_symbol_entry *
     187add_symbol (struct snd_cs46xx * chip, char * symbol_name, u32 address, int type)
     188{
     189        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     190        struct dsp_symbol_entry * symbol = NULL;
     191        int index;
     192
     193        if (ins->symbol_table.nsymbols == (DSP_MAX_SYMBOLS - 1)) {
     194                snd_printk(KERN_ERR "dsp_spos: symbol table is full\n");
     195                return NULL;
     196        }
     197 
     198        if (cs46xx_dsp_lookup_symbol(chip,
     199                                     symbol_name,
     200                                     type) != NULL) {
     201                snd_printk(KERN_ERR "dsp_spos: symbol <%s> duplicated\n", symbol_name);
     202                return NULL;
     203        }
     204
     205        index = find_free_symbol_index (ins);
     206
     207        strcpy (ins->symbol_table.symbols[index].symbol_name, symbol_name);
     208        ins->symbol_table.symbols[index].address = address;
     209        ins->symbol_table.symbols[index].symbol_type = type;
     210        ins->symbol_table.symbols[index].module = NULL;
     211        ins->symbol_table.symbols[index].deleted = 0;
     212        symbol = (ins->symbol_table.symbols + index);
     213
     214        if (index > ins->symbol_table.highest_frag_index)
     215                ins->symbol_table.highest_frag_index = index;
     216
     217        if (index == ins->symbol_table.nsymbols)
     218                ins->symbol_table.nsymbols++; /* no frag. in list */
     219
     220        return symbol;
     221}
     222
     223struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip)
     224{
     225        struct dsp_spos_instance * ins = kzalloc(sizeof(struct dsp_spos_instance), GFP_KERNEL);
     226
     227        if (ins == NULL)
     228                return NULL;
     229
     230        /* better to use vmalloc for this big table */
     231        ins->symbol_table.nsymbols = 0;
     232        ins->symbol_table.symbols = vmalloc(sizeof(struct dsp_symbol_entry) *
     233                                            DSP_MAX_SYMBOLS);
     234        ins->symbol_table.highest_frag_index = 0;
     235
     236        if (ins->symbol_table.symbols == NULL) {
     237                cs46xx_dsp_spos_destroy(chip);
     238                return NULL;
     239        }
     240
     241        ins->code.offset = 0;
     242        ins->code.size = 0;
     243        ins->code.data = kmalloc(DSP_CODE_BYTE_SIZE, GFP_KERNEL);
     244
     245        if (ins->code.data == NULL) {
     246                cs46xx_dsp_spos_destroy(chip);
     247                return NULL;
     248        }
     249
     250        ins->nscb = 0;
     251        ins->ntask = 0;
     252
     253        ins->nmodules = 0;
     254        ins->modules = kmalloc(sizeof(struct dsp_module_desc) * DSP_MAX_MODULES, GFP_KERNEL);
     255
     256        if (ins->modules == NULL) {
     257                cs46xx_dsp_spos_destroy(chip);
     258                return NULL;
     259        }
     260
     261        /* default SPDIF input sample rate
     262           to 48000 khz */
     263        ins->spdif_in_sample_rate = 48000;
     264
     265        /* maximize volume */
     266        ins->dac_volume_right = 0x8000;
     267        ins->dac_volume_left = 0x8000;
     268        ins->spdif_input_volume_right = 0x8000;
     269        ins->spdif_input_volume_left = 0x8000;
     270
     271        /* set left and right validity bits and
     272           default channel status */
     273        ins->spdif_csuv_default =
     274                ins->spdif_csuv_stream = 
     275         /* byte 0 */  ((unsigned int)_wrap_all_bits(  (SNDRV_PCM_DEFAULT_CON_SPDIF        & 0xff)) << 24) |
     276         /* byte 1 */  ((unsigned int)_wrap_all_bits( ((SNDRV_PCM_DEFAULT_CON_SPDIF >> 8) & 0xff)) << 16) |
     277         /* byte 3 */   (unsigned int)_wrap_all_bits(  (SNDRV_PCM_DEFAULT_CON_SPDIF >> 24) & 0xff) |
     278         /* left and right validity bits */ (1 << 13) | (1 << 12);
     279
     280        return ins;
     281}
     282
     283void  cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip)
     284{
     285        int i;
     286        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     287
     288        snd_assert(ins != NULL, return);
     289
     290        down(&chip->spos_mutex);
     291        for (i = 0; i < ins->nscb; ++i) {
     292                if (ins->scbs[i].deleted) continue;
     293
     294                cs46xx_dsp_proc_free_scb_desc ( (ins->scbs + i) );
     295        }
     296
     297        kfree(ins->code.data);
     298        vfree(ins->symbol_table.symbols);
     299        kfree(ins->modules);
     300        kfree(ins);
     301        up(&chip->spos_mutex);
     302}
     303
     304int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module)
     305{
     306        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     307        struct dsp_segment_desc * code = get_segment_desc (module,SEGTYPE_SP_PROGRAM);
     308        struct dsp_segment_desc * parameter = get_segment_desc (module,SEGTYPE_SP_PARAMETER);
     309        struct dsp_segment_desc * sample = get_segment_desc (module,SEGTYPE_SP_SAMPLE);
     310        u32 doffset, dsize;
     311
     312        if (ins->nmodules == DSP_MAX_MODULES - 1) {
     313                snd_printk(KERN_ERR "dsp_spos: to many modules loaded into DSP\n");
     314                return -ENOMEM;
     315        }
     316
     317        snd_printdd("dsp_spos: loading module %s into DSP\n", module->module_name);
     318 
     319        if (ins->nmodules == 0) {
     320                snd_printdd("dsp_spos: clearing parameter area\n");
     321                snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET, DSP_PARAMETER_BYTE_SIZE);
     322        }
     323 
     324        if (parameter == NULL) {
     325                snd_printdd("dsp_spos: module got no parameter segment\n");
     326        } else {
     327                if (ins->nmodules > 0) {
     328                        snd_printk(KERN_WARNING "dsp_spos: WARNING current parameter data may be overwriten!\n");
     329                }
     330
     331                doffset = (parameter->offset * 4 + DSP_PARAMETER_BYTE_OFFSET);
     332                dsize   = parameter->size * 4;
     333
     334                snd_printdd("dsp_spos: downloading parameter data to chip (%08x-%08x)\n",
     335                            doffset,doffset + dsize);
     336
     337                if (snd_cs46xx_download (chip, parameter->data, doffset, dsize)) {
     338                        snd_printk(KERN_ERR "dsp_spos: failed to download parameter data to DSP\n");
     339                        return -EINVAL;
     340                }
     341        }
     342
     343        if (ins->nmodules == 0) {
     344                snd_printdd("dsp_spos: clearing sample area\n");
     345                snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET, DSP_SAMPLE_BYTE_SIZE);
     346        }
     347
     348        if (sample == NULL) {
     349                snd_printdd("dsp_spos: module got no sample segment\n");
     350        } else {
     351                if (ins->nmodules > 0) {
     352                        snd_printk(KERN_WARNING "dsp_spos: WARNING current sample data may be overwriten\n");
     353                }
     354
     355                doffset = (sample->offset * 4  + DSP_SAMPLE_BYTE_OFFSET);
     356                dsize   =  sample->size * 4;
     357
     358                snd_printdd("dsp_spos: downloading sample data to chip (%08x-%08x)\n",
     359                            doffset,doffset + dsize);
     360
     361                if (snd_cs46xx_download (chip,sample->data,doffset,dsize)) {
     362                        snd_printk(KERN_ERR "dsp_spos: failed to sample data to DSP\n");
     363                        return -EINVAL;
     364                }
     365        }
     366
     367
     368        if (ins->nmodules == 0) {
     369                snd_printdd("dsp_spos: clearing code area\n");
     370                snd_cs46xx_clear_BA1(chip, DSP_CODE_BYTE_OFFSET, DSP_CODE_BYTE_SIZE);
     371        }
     372
     373        if (code == NULL) {
     374                snd_printdd("dsp_spos: module got no code segment\n");
     375        } else {
     376                if (ins->code.offset + code->size > DSP_CODE_BYTE_SIZE) {
     377                        snd_printk(KERN_ERR "dsp_spos: no space available in DSP\n");
     378                        return -ENOMEM;
     379                }
     380
     381                module->load_address = ins->code.offset;
     382                module->overlay_begin_address = 0x000;
     383
     384                /* if module has a code segment it must have
     385                   symbol table */
     386                snd_assert(module->symbol_table.symbols != NULL ,return -ENOMEM);
     387                if (add_symbols(chip,module)) {
     388                        snd_printk(KERN_ERR "dsp_spos: failed to load symbol table\n");
     389                        return -ENOMEM;
     390                }
     391   
     392                doffset = (code->offset * 4 + ins->code.offset * 4 + DSP_CODE_BYTE_OFFSET);
     393                dsize   = code->size * 4;
     394                snd_printdd("dsp_spos: downloading code to chip (%08x-%08x)\n",
     395                            doffset,doffset + dsize);   
     396
     397                module->nfixups = shadow_and_reallocate_code(chip,code->data,code->size,module->overlay_begin_address);
     398
     399                if (snd_cs46xx_download (chip,(ins->code.data + ins->code.offset),doffset,dsize)) {
     400                        snd_printk(KERN_ERR "dsp_spos: failed to download code to DSP\n");
     401                        return -EINVAL;
     402                }
     403
     404                ins->code.offset += code->size;
     405        }
     406
     407        /* NOTE: module segments and symbol table must be
     408           statically allocated. Case that module data is
     409           not generated by the ospparser */
     410        ins->modules[ins->nmodules] = *module;
     411        ins->nmodules++;
     412
     413        return 0;
     414}
     415
     416struct dsp_symbol_entry *
     417cs46xx_dsp_lookup_symbol (struct snd_cs46xx * chip, char * symbol_name, int symbol_type)
     418{
     419        int i;
     420        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     421
     422        for ( i = 0; i < ins->symbol_table.nsymbols; ++i ) {
     423
     424                if (ins->symbol_table.symbols[i].deleted)
     425                        continue;
     426
     427                if (!strcmp(ins->symbol_table.symbols[i].symbol_name,symbol_name) &&
     428                    ins->symbol_table.symbols[i].symbol_type == symbol_type) {
     429                        return (ins->symbol_table.symbols + i);
     430                }
     431        }
    432432
    433433#if 0
    434     printk ("dsp_spos: symbol <%s> type %02x not found\n",
    435             symbol_name,symbol_type);
     434        printk ("dsp_spos: symbol <%s> type %02x not found\n",
     435                symbol_name,symbol_type);
    436436#endif
    437437
    438     return NULL;
    439 }
    440 
    441 
    442 symbol_entry_t * cs46xx_dsp_lookup_symbol_addr (cs46xx_t * chip, u32 address, int symbol_type)
    443 {
    444     int i;
    445     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    446 
    447     for ( i = 0; i < ins->symbol_table.nsymbols; ++i ) {
    448 
    449         if (ins->symbol_table.symbols[i].deleted)
    450             continue;
    451 
    452         if (ins->symbol_table.symbols[i].address == address &&
    453             ins->symbol_table.symbols[i].symbol_type == symbol_type) {
    454             return (ins->symbol_table.symbols + i);
    455         }
    456     }
    457 
    458 
    459     return NULL;
    460 }
    461 
    462 
    463 static void cs46xx_dsp_proc_symbol_table_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
    464 {
    465     cs46xx_t *chip = entry->private_data;
    466     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    467     int i;
    468 
    469     snd_iprintf(buffer, "SYMBOLS:\n");
    470     for ( i = 0; i < ins->symbol_table.nsymbols; ++i ) {
    471         char *module_str = "system";
    472 
    473         if (ins->symbol_table.symbols[i].deleted)
    474             continue;
    475 
    476         if (ins->symbol_table.symbols[i].module != NULL) {
    477             module_str = ins->symbol_table.symbols[i].module->module_name;
    478         }
    479 
    480 
    481         snd_iprintf(buffer, "%04X <%02X> %s [%s]\n",
    482                     ins->symbol_table.symbols[i].address,
    483                     ins->symbol_table.symbols[i].symbol_type,
    484                     ins->symbol_table.symbols[i].symbol_name,
    485                     module_str);
    486     }
    487 }
    488 
    489 
    490 static void cs46xx_dsp_proc_modules_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
    491 {
    492     cs46xx_t *chip = entry->private_data;
    493     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    494     int i,j;
    495 
    496     down(&chip->spos_mutex);
    497     snd_iprintf(buffer, "MODULES:\n");
    498     for ( i = 0; i < ins->nmodules; ++i ) {
    499         snd_iprintf(buffer, "\n%s:\n", ins->modules[i].module_name);
    500         snd_iprintf(buffer, "   %d symbols\n", ins->modules[i].symbol_table.nsymbols);
    501         snd_iprintf(buffer, "   %d fixups\n", ins->modules[i].nfixups);
    502 
    503         for (j = 0; j < ins->modules[i].nsegments; ++ j) {
    504             segment_desc_t * desc = (ins->modules[i].segments + j);
    505             snd_iprintf(buffer, "   segment %02x offset %08x size %08x\n",
    506                         desc->segment_type,desc->offset, desc->size);
    507         }
    508     }
    509     up(&chip->spos_mutex);
    510 }
    511 
    512 static void cs46xx_dsp_proc_task_tree_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
    513 {
    514     cs46xx_t *chip = entry->private_data;
    515     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    516     int i,j,col;
    517     unsigned long dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
    518 
    519     down(&chip->spos_mutex);
    520     snd_iprintf(buffer, "TASK TREES:\n");
    521     for ( i = 0; i < ins->ntask; ++i) {
    522         snd_iprintf(buffer,"\n%04x %s:\n",ins->tasks[i].address,ins->tasks[i].task_name);
    523 
    524         for (col = 0,j = 0;j < ins->tasks[i].size; j++,col++) {
    525             u32 val;
    526             if (col == 4) {
    527                 snd_iprintf(buffer,"\n");
    528                 col = 0;
    529             }
    530             val = readl(dst + (ins->tasks[i].address + j) * sizeof(u32));
    531             snd_iprintf(buffer,"%08x ",val);
    532         }
    533     }
    534 
    535     snd_iprintf(buffer,"\n");
    536     up(&chip->spos_mutex);
    537 }
    538 
    539 static void cs46xx_dsp_proc_scb_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
    540 {
    541     cs46xx_t *chip = entry->private_data;
    542     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    543     int i;
    544 
    545     down(&chip->spos_mutex);
    546     snd_iprintf(buffer, "SCB's:\n");
    547     for ( i = 0; i < ins->nscb; ++i) {
    548         if (ins->scbs[i].deleted)
    549             continue;
    550         snd_iprintf(buffer,"\n%04x %s:\n\n",ins->scbs[i].address,ins->scbs[i].scb_name);
    551 
    552         if (ins->scbs[i].parent_scb_ptr != NULL) {
    553             snd_iprintf(buffer,"parent [%s:%04x] ",
    554                         ins->scbs[i].parent_scb_ptr->scb_name,
    555                         ins->scbs[i].parent_scb_ptr->address);
    556         } else snd_iprintf(buffer,"parent [none] ");
    557 
    558         snd_iprintf(buffer,"sub_list_ptr [%s:%04x]\nnext_scb_ptr [%s:%04x]  task_entry [%s:%04x]\n",
    559                     ins->scbs[i].sub_list_ptr->scb_name,
    560                     ins->scbs[i].sub_list_ptr->address,
    561                     ins->scbs[i].next_scb_ptr->scb_name,
    562                     ins->scbs[i].next_scb_ptr->address,
    563                     ins->scbs[i].task_entry->symbol_name,
    564                     ins->scbs[i].task_entry->address);
    565     }
    566 
    567     snd_iprintf(buffer,"\n");
    568     up(&chip->spos_mutex);
    569 }
    570 
    571 static void cs46xx_dsp_proc_parameter_dump_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
    572 {
    573     cs46xx_t *chip = entry->private_data;
    574     /*dsp_spos_instance_t * ins = chip->dsp_spos_instance; */
    575     unsigned int i,col = 0;
    576     unsigned long dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
    577     symbol_entry_t * symbol;
    578 
    579     for (i = 0;i < DSP_PARAMETER_BYTE_SIZE; i += sizeof(u32),col ++) {
    580         if (col == 4) {
    581             snd_iprintf(buffer,"\n");
    582             col = 0;
    583         }
    584 
    585         if ( (symbol = cs46xx_dsp_lookup_symbol_addr (chip,i / sizeof(u32), SYMBOL_PARAMETER)) != NULL) {
    586             col = 0;
    587             snd_iprintf (buffer,"\n%s:\n",symbol->symbol_name);
    588         }
    589 
    590         if (col == 0) {
    591             snd_iprintf(buffer, "%04X ", i / (unsigned int)sizeof(u32));
    592         }
    593 
    594         snd_iprintf(buffer,"%08X ",readl(dst + i));
    595     }
    596 }
    597 
    598 static void cs46xx_dsp_proc_sample_dump_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
    599 {
    600     cs46xx_t *chip = entry->private_data;
    601     int i,col = 0;
    602     unsigned long dst = chip->region.idx[2].remap_addr;
    603 
    604     snd_iprintf(buffer,"PCMREADER:\n");
    605     for (i = PCM_READER_BUF1;i < PCM_READER_BUF1 + 0x30; i += sizeof(u32),col ++) {
    606         if (col == 4) {
    607             snd_iprintf(buffer,"\n");
    608             col = 0;
    609         }
    610 
    611         if (col == 0) {
    612             snd_iprintf(buffer, "%04X ",i);
    613         }
    614 
    615         snd_iprintf(buffer,"%08X ",readl(dst + i));
    616     }
    617 
    618     snd_iprintf(buffer,"\nMIX_SAMPLE_BUF1:\n");
    619 
    620     col = 0;
    621     for (i = MIX_SAMPLE_BUF1;i < MIX_SAMPLE_BUF1 + 0x40; i += sizeof(u32),col ++) {
    622         if (col == 4) {
    623             snd_iprintf(buffer,"\n");
    624             col = 0;
    625         }
    626 
    627         if (col == 0) {
    628             snd_iprintf(buffer, "%04X ",i);
    629         }
    630 
    631         snd_iprintf(buffer,"%08X ",readl(dst + i));
    632     }
    633 
    634     snd_iprintf(buffer,"\nSRC_TASK_SCB1:\n");
    635     col = 0;
    636     for (i = 0x2480 ; i < 0x2480 + 0x40 ; i += sizeof(u32),col ++) {
    637         if (col == 4) {
    638             snd_iprintf(buffer,"\n");
    639             col = 0;
    640         }
    641 
    642         if (col == 0) {
    643             snd_iprintf(buffer, "%04X ",i);
    644         }
    645 
    646         snd_iprintf(buffer,"%08X ",readl(dst + i));
    647     }
    648 
    649 
    650     snd_iprintf(buffer,"\nSPDIFO_BUFFER:\n");
    651     col = 0;
    652     for (i = SPDIFO_IP_OUTPUT_BUFFER1;i < SPDIFO_IP_OUTPUT_BUFFER1 + 0x30; i += sizeof(u32),col ++) {
    653         if (col == 4) {
    654             snd_iprintf(buffer,"\n");
    655             col = 0;
    656         }
    657 
    658         if (col == 0) {
    659             snd_iprintf(buffer, "%04X ",i);
    660         }
    661 
    662         snd_iprintf(buffer,"%08X ",readl(dst + i));
    663     }
    664 
    665     snd_iprintf(buffer,"\n...\n");
    666     col = 0;
    667 
    668     for (i = SPDIFO_IP_OUTPUT_BUFFER1+0xD0;i < SPDIFO_IP_OUTPUT_BUFFER1 + 0x110; i += sizeof(u32),col ++) {
    669         if (col == 4) {
    670             snd_iprintf(buffer,"\n");
    671             col = 0;
    672         }
    673 
    674         if (col == 0) {
    675             snd_iprintf(buffer, "%04X ",i);
    676         }
    677 
    678         snd_iprintf(buffer,"%08X ",readl(dst + i));
    679     }
    680 
    681 
    682     snd_iprintf(buffer,"\nOUTPUT_SNOOP:\n");
    683     col = 0;
    684     for (i = OUTPUT_SNOOP_BUFFER;i < OUTPUT_SNOOP_BUFFER + 0x40; i += sizeof(u32),col ++) {
    685         if (col == 4) {
    686             snd_iprintf(buffer,"\n");
    687             col = 0;
    688         }
    689 
    690         if (col == 0) {
    691             snd_iprintf(buffer, "%04X ",i);
    692         }
    693 
    694         snd_iprintf(buffer,"%08X ",readl(dst + i));
    695     }
    696 
    697     snd_iprintf(buffer,"\nCODEC_INPUT_BUF1: \n");
    698     col = 0;
    699     for (i = CODEC_INPUT_BUF1;i < CODEC_INPUT_BUF1 + 0x40; i += sizeof(u32),col ++) {
    700         if (col == 4) {
    701             snd_iprintf(buffer,"\n");
    702             col = 0;
    703         }
    704 
    705         if (col == 0) {
    706             snd_iprintf(buffer, "%04X ",i);
    707         }
    708 
    709         snd_iprintf(buffer,"%08X ",readl(dst + i));
    710     }
     438        return NULL;
     439}
     440
     441
     442static struct dsp_symbol_entry *
     443cs46xx_dsp_lookup_symbol_addr (struct snd_cs46xx * chip, u32 address, int symbol_type)
     444{
     445        int i;
     446        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     447
     448        for ( i = 0; i < ins->symbol_table.nsymbols; ++i ) {
     449
     450                if (ins->symbol_table.symbols[i].deleted)
     451                        continue;
     452
     453                if (ins->symbol_table.symbols[i].address == address &&
     454                    ins->symbol_table.symbols[i].symbol_type == symbol_type) {
     455                        return (ins->symbol_table.symbols + i);
     456                }
     457        }
     458
     459
     460        return NULL;
     461}
     462
     463
     464static void cs46xx_dsp_proc_symbol_table_read (struct snd_info_entry *entry,
     465                                               struct snd_info_buffer *buffer)
     466{
     467        struct snd_cs46xx *chip = entry->private_data;
     468        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     469        int i;
     470
     471        snd_iprintf(buffer, "SYMBOLS:\n");
     472        for ( i = 0; i < ins->symbol_table.nsymbols; ++i ) {
     473                char *module_str = "system";
     474
     475                if (ins->symbol_table.symbols[i].deleted)
     476                        continue;
     477
     478                if (ins->symbol_table.symbols[i].module != NULL) {
     479                        module_str = ins->symbol_table.symbols[i].module->module_name;
     480                }
     481
     482   
     483                snd_iprintf(buffer, "%04X <%02X> %s [%s]\n",
     484                            ins->symbol_table.symbols[i].address,
     485                            ins->symbol_table.symbols[i].symbol_type,
     486                            ins->symbol_table.symbols[i].symbol_name,
     487                            module_str);   
     488        }
     489}
     490
     491
     492static void cs46xx_dsp_proc_modules_read (struct snd_info_entry *entry,
     493                                          struct snd_info_buffer *buffer)
     494{
     495        struct snd_cs46xx *chip = entry->private_data;
     496        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     497        int i,j;
     498
     499        down(&chip->spos_mutex);
     500        snd_iprintf(buffer, "MODULES:\n");
     501        for ( i = 0; i < ins->nmodules; ++i ) {
     502                snd_iprintf(buffer, "\n%s:\n", ins->modules[i].module_name);
     503                snd_iprintf(buffer, "   %d symbols\n", ins->modules[i].symbol_table.nsymbols);
     504                snd_iprintf(buffer, "   %d fixups\n", ins->modules[i].nfixups);
     505
     506                for (j = 0; j < ins->modules[i].nsegments; ++ j) {
     507                        struct dsp_segment_desc * desc = (ins->modules[i].segments + j);
     508                        snd_iprintf(buffer, "   segment %02x offset %08x size %08x\n",
     509                                    desc->segment_type,desc->offset, desc->size);
     510                }
     511        }
     512        up(&chip->spos_mutex);
     513}
     514
     515static void cs46xx_dsp_proc_task_tree_read (struct snd_info_entry *entry,
     516                                            struct snd_info_buffer *buffer)
     517{
     518        struct snd_cs46xx *chip = entry->private_data;
     519        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     520        int i, j, col;
     521        void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
     522
     523        down(&chip->spos_mutex);
     524        snd_iprintf(buffer, "TASK TREES:\n");
     525        for ( i = 0; i < ins->ntask; ++i) {
     526                snd_iprintf(buffer,"\n%04x %s:\n",ins->tasks[i].address,ins->tasks[i].task_name);
     527
     528                for (col = 0,j = 0;j < ins->tasks[i].size; j++,col++) {
     529                        u32 val;
     530                        if (col == 4) {
     531                                snd_iprintf(buffer,"\n");
     532                                col = 0;
     533                        }
     534                        val = readl(dst + (ins->tasks[i].address + j) * sizeof(u32));
     535                        snd_iprintf(buffer,"%08x ",val);
     536                }
     537        }
     538
     539        snd_iprintf(buffer,"\n"); 
     540        up(&chip->spos_mutex);
     541}
     542
     543static void cs46xx_dsp_proc_scb_read (struct snd_info_entry *entry,
     544                                      struct snd_info_buffer *buffer)
     545{
     546        struct snd_cs46xx *chip = entry->private_data;
     547        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     548        int i;
     549
     550        down(&chip->spos_mutex);
     551        snd_iprintf(buffer, "SCB's:\n");
     552        for ( i = 0; i < ins->nscb; ++i) {
     553                if (ins->scbs[i].deleted)
     554                        continue;
     555                snd_iprintf(buffer,"\n%04x %s:\n\n",ins->scbs[i].address,ins->scbs[i].scb_name);
     556
     557                if (ins->scbs[i].parent_scb_ptr != NULL) {
     558                        snd_iprintf(buffer,"parent [%s:%04x] ",
     559                                    ins->scbs[i].parent_scb_ptr->scb_name,
     560                                    ins->scbs[i].parent_scb_ptr->address);
     561                } else snd_iprintf(buffer,"parent [none] ");
     562
     563                snd_iprintf(buffer,"sub_list_ptr [%s:%04x]\nnext_scb_ptr [%s:%04x]  task_entry [%s:%04x]\n",
     564                            ins->scbs[i].sub_list_ptr->scb_name,
     565                            ins->scbs[i].sub_list_ptr->address,
     566                            ins->scbs[i].next_scb_ptr->scb_name,
     567                            ins->scbs[i].next_scb_ptr->address,
     568                            ins->scbs[i].task_entry->symbol_name,
     569                            ins->scbs[i].task_entry->address);
     570        }
     571
     572        snd_iprintf(buffer,"\n");
     573        up(&chip->spos_mutex);
     574}
     575
     576static void cs46xx_dsp_proc_parameter_dump_read (struct snd_info_entry *entry,
     577                                                 struct snd_info_buffer *buffer)
     578{
     579        struct snd_cs46xx *chip = entry->private_data;
     580        /*struct dsp_spos_instance * ins = chip->dsp_spos_instance; */
     581        unsigned int i, col = 0;
     582        void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
     583        struct dsp_symbol_entry * symbol;
     584
     585        for (i = 0;i < DSP_PARAMETER_BYTE_SIZE; i += sizeof(u32),col ++) {
     586                if (col == 4) {
     587                        snd_iprintf(buffer,"\n");
     588                        col = 0;
     589                }
     590
     591                if ( (symbol = cs46xx_dsp_lookup_symbol_addr (chip,i / sizeof(u32), SYMBOL_PARAMETER)) != NULL) {
     592                        col = 0;
     593                        snd_iprintf (buffer,"\n%s:\n",symbol->symbol_name);
     594                }
     595
     596                if (col == 0) {
     597                        snd_iprintf(buffer, "%04X ", i / (unsigned int)sizeof(u32));
     598                }
     599
     600                snd_iprintf(buffer,"%08X ",readl(dst + i));
     601        }
     602}
     603
     604static void cs46xx_dsp_proc_sample_dump_read (struct snd_info_entry *entry,
     605                                              struct snd_info_buffer *buffer)
     606{
     607        struct snd_cs46xx *chip = entry->private_data;
     608        int i,col = 0;
     609        void __iomem *dst = chip->region.idx[2].remap_addr;
     610
     611        snd_iprintf(buffer,"PCMREADER:\n");
     612        for (i = PCM_READER_BUF1;i < PCM_READER_BUF1 + 0x30; i += sizeof(u32),col ++) {
     613                if (col == 4) {
     614                        snd_iprintf(buffer,"\n");
     615                        col = 0;
     616                }
     617
     618                if (col == 0) {
     619                        snd_iprintf(buffer, "%04X ",i);
     620                }
     621
     622                snd_iprintf(buffer,"%08X ",readl(dst + i));
     623        }
     624
     625        snd_iprintf(buffer,"\nMIX_SAMPLE_BUF1:\n");
     626
     627        col = 0;
     628        for (i = MIX_SAMPLE_BUF1;i < MIX_SAMPLE_BUF1 + 0x40; i += sizeof(u32),col ++) {
     629                if (col == 4) {
     630                        snd_iprintf(buffer,"\n");
     631                        col = 0;
     632                }
     633
     634                if (col == 0) {
     635                        snd_iprintf(buffer, "%04X ",i);
     636                }
     637
     638                snd_iprintf(buffer,"%08X ",readl(dst + i));
     639        }
     640
     641        snd_iprintf(buffer,"\nSRC_TASK_SCB1:\n");
     642        col = 0;
     643        for (i = 0x2480 ; i < 0x2480 + 0x40 ; i += sizeof(u32),col ++) {
     644                if (col == 4) {
     645                        snd_iprintf(buffer,"\n");
     646                        col = 0;
     647                }
     648               
     649                if (col == 0) {
     650                        snd_iprintf(buffer, "%04X ",i);
     651                }
     652
     653                snd_iprintf(buffer,"%08X ",readl(dst + i));
     654        }
     655
     656
     657        snd_iprintf(buffer,"\nSPDIFO_BUFFER:\n");
     658        col = 0;
     659        for (i = SPDIFO_IP_OUTPUT_BUFFER1;i < SPDIFO_IP_OUTPUT_BUFFER1 + 0x30; i += sizeof(u32),col ++) {
     660                if (col == 4) {
     661                        snd_iprintf(buffer,"\n");
     662                        col = 0;
     663                }
     664
     665                if (col == 0) {
     666                        snd_iprintf(buffer, "%04X ",i);
     667                }
     668
     669                snd_iprintf(buffer,"%08X ",readl(dst + i));
     670        }
     671
     672        snd_iprintf(buffer,"\n...\n");
     673        col = 0;
     674
     675        for (i = SPDIFO_IP_OUTPUT_BUFFER1+0xD0;i < SPDIFO_IP_OUTPUT_BUFFER1 + 0x110; i += sizeof(u32),col ++) {
     676                if (col == 4) {
     677                        snd_iprintf(buffer,"\n");
     678                        col = 0;
     679                }
     680
     681                if (col == 0) {
     682                        snd_iprintf(buffer, "%04X ",i);
     683                }
     684
     685                snd_iprintf(buffer,"%08X ",readl(dst + i));
     686        }
     687
     688
     689        snd_iprintf(buffer,"\nOUTPUT_SNOOP:\n");
     690        col = 0;
     691        for (i = OUTPUT_SNOOP_BUFFER;i < OUTPUT_SNOOP_BUFFER + 0x40; i += sizeof(u32),col ++) {
     692                if (col == 4) {
     693                        snd_iprintf(buffer,"\n");
     694                        col = 0;
     695                }
     696
     697                if (col == 0) {
     698                        snd_iprintf(buffer, "%04X ",i);
     699                }
     700
     701                snd_iprintf(buffer,"%08X ",readl(dst + i));
     702        }
     703
     704        snd_iprintf(buffer,"\nCODEC_INPUT_BUF1: \n");
     705        col = 0;
     706        for (i = CODEC_INPUT_BUF1;i < CODEC_INPUT_BUF1 + 0x40; i += sizeof(u32),col ++) {
     707                if (col == 4) {
     708                        snd_iprintf(buffer,"\n");
     709                        col = 0;
     710                }
     711
     712                if (col == 0) {
     713                        snd_iprintf(buffer, "%04X ",i);
     714                }
     715
     716                snd_iprintf(buffer,"%08X ",readl(dst + i));
     717        }
    711718#if 0
    712     snd_iprintf(buffer,"\nWRITE_BACK_BUF1: \n");
    713     col = 0;
    714     for (i = WRITE_BACK_BUF1;i < WRITE_BACK_BUF1 + 0x40; i += sizeof(u32),col ++) {
    715         if (col == 4) {
    716             snd_iprintf(buffer,"\n");
    717             col = 0;
    718         }
    719 
    720         if (col == 0) {
    721             snd_iprintf(buffer, "%04X ",i);
    722         }
    723 
    724         snd_iprintf(buffer,"%08X ",readl(dst + i));
    725     }
     719        snd_iprintf(buffer,"\nWRITE_BACK_BUF1: \n");
     720        col = 0;
     721        for (i = WRITE_BACK_BUF1;i < WRITE_BACK_BUF1 + 0x40; i += sizeof(u32),col ++) {
     722                if (col == 4) {
     723                        snd_iprintf(buffer,"\n");
     724                        col = 0;
     725                }
     726
     727                if (col == 0) {
     728                        snd_iprintf(buffer, "%04X ",i);
     729                }
     730
     731                snd_iprintf(buffer,"%08X ",readl(dst + i));
     732        }
    726733#endif
    727734
    728     snd_iprintf(buffer,"\nSPDIFI_IP_OUTPUT_BUFFER1: \n");
    729     col = 0;
    730     for (i = SPDIFI_IP_OUTPUT_BUFFER1;i < SPDIFI_IP_OUTPUT_BUFFER1 + 0x80; i += sizeof(u32),col ++) {
    731         if (col == 4) {
    732             snd_iprintf(buffer,"\n");
    733             col = 0;
    734         }
    735 
    736         if (col == 0) {
    737             snd_iprintf(buffer, "%04X ",i);
    738         }
    739 
    740         snd_iprintf(buffer,"%08X ",readl(dst + i));
    741     }
    742     snd_iprintf(buffer,"\n");
    743 }
    744 
    745 int cs46xx_dsp_proc_init (snd_card_t * card, cs46xx_t *chip)
    746 {
    747     snd_info_entry_t *entry;
    748     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    749     int i;
    750 
    751     ins->snd_card = card;
    752 
    753     if ((entry = snd_info_create_card_entry(card, "dsp", card->proc_root)) != NULL) {
    754         entry->content = SNDRV_INFO_CONTENT_TEXT;
    755         entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
    756         entry->c.text.read_size = 512;
    757 
    758         if (snd_info_register(entry) < 0) {
    759             snd_info_free_entry(entry);
    760             entry = NULL;
    761         }
    762     }
    763 
    764     ins->proc_dsp_dir = entry;
    765 
    766     if (!ins->proc_dsp_dir)
    767         return -ENOMEM;
    768 
    769     if ((entry = snd_info_create_card_entry(card, "spos_symbols", ins->proc_dsp_dir)) != NULL) {
    770         entry->content = SNDRV_INFO_CONTENT_TEXT;
    771         entry->private_data = chip;
    772         entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
    773         entry->c.text.read_size = 512;
    774         entry->c.text.read = cs46xx_dsp_proc_symbol_table_read;
    775         if (snd_info_register(entry) < 0) {
    776             snd_info_free_entry(entry);
    777             entry = NULL;
    778         }
    779     }
    780     ins->proc_sym_info_entry = entry;
    781 
    782     if ((entry = snd_info_create_card_entry(card, "spos_modules", ins->proc_dsp_dir)) != NULL) {
    783         entry->content = SNDRV_INFO_CONTENT_TEXT;
    784         entry->private_data = chip;
    785         entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
    786         entry->c.text.read_size = 512;
    787         entry->c.text.read = cs46xx_dsp_proc_modules_read;
    788         if (snd_info_register(entry) < 0) {
    789             snd_info_free_entry(entry);
    790             entry = NULL;
    791         }
    792     }
    793     ins->proc_modules_info_entry = entry;
    794 
    795     if ((entry = snd_info_create_card_entry(card, "parameter", ins->proc_dsp_dir)) != NULL) {
    796         entry->content = SNDRV_INFO_CONTENT_TEXT;
    797         entry->private_data = chip;
    798         entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
    799         entry->c.text.read_size = 512;
    800         entry->c.text.read = cs46xx_dsp_proc_parameter_dump_read;
    801         if (snd_info_register(entry) < 0) {
    802             snd_info_free_entry(entry);
    803             entry = NULL;
    804         }
    805     }
    806     ins->proc_parameter_dump_info_entry = entry;
    807 
    808     if ((entry = snd_info_create_card_entry(card, "sample", ins->proc_dsp_dir)) != NULL) {
    809         entry->content = SNDRV_INFO_CONTENT_TEXT;
    810         entry->private_data = chip;
    811         entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
    812         entry->c.text.read_size = 512;
    813         entry->c.text.read = cs46xx_dsp_proc_sample_dump_read;
    814         if (snd_info_register(entry) < 0) {
    815             snd_info_free_entry(entry);
    816             entry = NULL;
    817         }
    818     }
    819     ins->proc_sample_dump_info_entry = entry;
    820 
    821     if ((entry = snd_info_create_card_entry(card, "task_tree", ins->proc_dsp_dir)) != NULL) {
    822         entry->content = SNDRV_INFO_CONTENT_TEXT;
    823         entry->private_data = chip;
    824         entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
    825         entry->c.text.read_size = 512;
    826         entry->c.text.read = cs46xx_dsp_proc_task_tree_read;
    827         if (snd_info_register(entry) < 0) {
    828             snd_info_free_entry(entry);
    829             entry = NULL;
    830         }
    831     }
    832     ins->proc_task_info_entry = entry;
    833 
    834     if ((entry = snd_info_create_card_entry(card, "scb_info", ins->proc_dsp_dir)) != NULL) {
    835         entry->content = SNDRV_INFO_CONTENT_TEXT;
    836         entry->private_data = chip;
    837         entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
    838         entry->c.text.read_size = 1024;
    839         entry->c.text.read = cs46xx_dsp_proc_scb_read;
    840         if (snd_info_register(entry) < 0) {
    841             snd_info_free_entry(entry);
    842             entry = NULL;
    843         }
    844     }
    845     ins->proc_scb_info_entry = entry;
    846 
    847     down(&chip->spos_mutex);
    848     /* register/update SCB's entries on proc */
    849     for (i = 0; i < ins->nscb; ++i) {
    850         if (ins->scbs[i].deleted) continue;
    851 
    852         cs46xx_dsp_proc_register_scb_desc (chip, (ins->scbs + i));
    853     }
    854     up(&chip->spos_mutex);
    855 
    856     return 0;
    857 }
    858 
    859 int cs46xx_dsp_proc_done (cs46xx_t *chip)
    860 {
    861     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    862     int i;
    863 
    864     if (ins->proc_sym_info_entry) {
    865         snd_info_unregister(ins->proc_sym_info_entry);
    866         ins->proc_sym_info_entry = NULL;
    867     }
    868 
    869     if (ins->proc_modules_info_entry) {
    870         snd_info_unregister(ins->proc_modules_info_entry);
    871         ins->proc_modules_info_entry = NULL;
    872     }
    873 
    874     if (ins->proc_parameter_dump_info_entry) {
    875         snd_info_unregister(ins->proc_parameter_dump_info_entry);
    876         ins->proc_parameter_dump_info_entry = NULL;
    877     }
    878 
    879     if (ins->proc_sample_dump_info_entry) {
    880         snd_info_unregister(ins->proc_sample_dump_info_entry);
    881         ins->proc_sample_dump_info_entry = NULL;
    882     }
    883 
    884     if (ins->proc_scb_info_entry) {
    885         snd_info_unregister(ins->proc_scb_info_entry);
    886         ins->proc_scb_info_entry = NULL;
    887     }
    888 
    889     if (ins->proc_task_info_entry) {
    890         snd_info_unregister(ins->proc_task_info_entry);
    891         ins->proc_task_info_entry = NULL;
    892     }
    893 
    894     down(&chip->spos_mutex);
    895     for (i = 0; i < ins->nscb; ++i) {
    896         if (ins->scbs[i].deleted) continue;
    897         cs46xx_dsp_proc_free_scb_desc ( (ins->scbs + i) );
    898     }
    899     up(&chip->spos_mutex);
    900 
    901     if (ins->proc_dsp_dir) {
    902         snd_info_unregister (ins->proc_dsp_dir);
    903         ins->proc_dsp_dir = NULL;
    904     }
    905 
    906     return 0;
    907 }
    908 
    909 static int debug_tree = 0;
    910 static void _dsp_create_task_tree (cs46xx_t *chip,u32 * task_data, u32  dest, int size)
    911 {
    912     unsigned long spdst = chip->region.idx[1].remap_addr +
    913         DSP_PARAMETER_BYTE_OFFSET + dest * sizeof(u32);
    914     int i;
    915 
    916     for (i = 0; i < size; ++i) {
    917         if (debug_tree) printk ("addr %08x, val %08x\n",(int)spdst,task_data[i]);
    918         writel(task_data[i],spdst);
    919         spdst += sizeof(u32);
    920     }
    921 }
    922 
    923 static int debug_scb = 0;
    924 static void _dsp_create_scb (cs46xx_t *chip,u32 * scb_data, u32  dest)
    925 {
    926     unsigned long spdst = chip->region.idx[1].remap_addr +
    927         DSP_PARAMETER_BYTE_OFFSET + dest * sizeof(u32);
    928     int i;
    929 
    930     for (i = 0; i < 0x10; ++i) {
    931         if (debug_scb) printk ("addr %08x, val %08x\n",(int)spdst,scb_data[i]);
    932         writel(scb_data[i],spdst);
    933         spdst += sizeof(u32);
    934     }
    935 }
    936 
    937 static int find_free_scb_index (dsp_spos_instance_t * ins)
    938 {
    939     int index = ins->nscb, i;
    940 
    941     for (i = ins->scb_highest_frag_index; i < ins->nscb; ++i) {
    942         if (ins->scbs[i].deleted) {
    943             index = i;
    944             break;
    945         }
    946     }
    947 
    948     return index;
    949 }
    950 
    951 static dsp_scb_descriptor_t * _map_scb (cs46xx_t *chip,char * name,u32 dest)
    952 {
    953     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    954     dsp_scb_descriptor_t * desc = NULL;
    955     int index;
    956 
    957     if (ins->nscb == DSP_MAX_SCB_DESC - 1) {
    958         snd_printk(KERN_ERR "dsp_spos: got no place for other SCB\n");
    959         return NULL;
    960     }
    961 
    962     index = find_free_scb_index (ins);
    963 
    964     strcpy(ins->scbs[index].scb_name, name);
    965     ins->scbs[index].address = dest;
    966     ins->scbs[index].index = index;
    967     ins->scbs[index].proc_info = NULL;
    968     ins->scbs[index].ref_count = 1;
    969     ins->scbs[index].deleted = 0;
    970     spin_lock_init(&ins->scbs[index].lock);
    971 
    972     desc = (ins->scbs + index);
    973     ins->scbs[index].scb_symbol = add_symbol (chip, name, dest, SYMBOL_PARAMETER);
    974 
    975     if (index > ins->scb_highest_frag_index)
    976         ins->scb_highest_frag_index = index;
    977 
    978     if (index == ins->nscb)
    979         ins->nscb++;
    980 
    981     return desc;
    982 }
    983 
    984 static dsp_task_descriptor_t * _map_task_tree (cs46xx_t *chip,char * name,u32 dest,u32 size)
    985 {
    986     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    987     dsp_task_descriptor_t * desc = NULL;
    988 
    989     if (ins->ntask == DSP_MAX_TASK_DESC - 1) {
    990         snd_printk(KERN_ERR "dsp_spos: got no place for other TASK\n");
    991         return NULL;
    992     }
    993 
    994     strcpy(ins->tasks[ins->ntask].task_name,name);
    995     ins->tasks[ins->ntask].address = dest;
    996     ins->tasks[ins->ntask].size = size;
    997 
    998     /* quick find in list */
    999     ins->tasks[ins->ntask].index = ins->ntask;
    1000     desc = (ins->tasks + ins->ntask);
    1001     ins->ntask++;
    1002 
    1003     add_symbol (chip,name,dest,SYMBOL_PARAMETER);
    1004     return desc;
    1005 }
    1006 
    1007 dsp_scb_descriptor_t * cs46xx_dsp_create_scb (cs46xx_t *chip,char * name, u32 * scb_data,u32 dest)
    1008 {
    1009     dsp_scb_descriptor_t * desc;
    1010 
    1011     desc = _map_scb (chip,name,dest);
    1012     if (desc) {
    1013         _dsp_create_scb(chip,scb_data,dest);
    1014     } else {
    1015         snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n");
    1016     }
    1017 
    1018     return desc;
    1019 }
    1020 
    1021 
    1022 dsp_task_descriptor_t *  cs46xx_dsp_create_task_tree (cs46xx_t *chip,char * name, u32 * task_data,u32 dest,int size)
    1023 {
    1024     dsp_task_descriptor_t * desc;
    1025 
    1026     desc = _map_task_tree (chip,name,dest,size);
    1027     if (desc) {
    1028         _dsp_create_task_tree(chip,task_data,dest,size);
    1029     } else {
    1030         snd_printk(KERN_ERR "dsp_spos: failed to map TASK\n");
    1031     }
    1032 
    1033     return desc;
    1034 }
    1035 
    1036 int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
    1037 {
    1038     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    1039     symbol_entry_t * fg_task_tree_header_code;
    1040     symbol_entry_t * task_tree_header_code;
    1041     symbol_entry_t * task_tree_thread;
    1042     symbol_entry_t * null_algorithm;
    1043     symbol_entry_t * magic_snoop_task;
    1044 
    1045     dsp_scb_descriptor_t * timing_master_scb;
    1046     dsp_scb_descriptor_t * codec_out_scb;
    1047     dsp_scb_descriptor_t * codec_in_scb;
    1048     dsp_scb_descriptor_t * src_task_scb;
    1049     dsp_scb_descriptor_t * master_mix_scb;
    1050     dsp_scb_descriptor_t * rear_mix_scb;
    1051     dsp_scb_descriptor_t * record_mix_scb;
    1052     dsp_scb_descriptor_t * write_back_scb;
    1053     dsp_scb_descriptor_t * vari_decimate_scb;
    1054     dsp_scb_descriptor_t * rear_codec_out_scb;
    1055     dsp_scb_descriptor_t * clfe_codec_out_scb;
    1056     dsp_scb_descriptor_t * magic_snoop_scb;
    1057 
    1058     int fifo_addr,fifo_span,valid_slots;
    1059 
    1060     static spos_control_block_t sposcb = {
    1061         /* 0 */ HFG_TREE_SCB,HFG_STACK,
    1062         /* 1 */ SPOSCB_ADDR,BG_TREE_SCB_ADDR,
    1063         /* 2 */ DSP_SPOS_DC,0,
    1064         /* 3 */ DSP_SPOS_DC,DSP_SPOS_DC,
    1065         /* 4 */ 0,0,
    1066         /* 5 */ DSP_SPOS_UU,0,
    1067         /* 6 */ FG_TASK_HEADER_ADDR,0,
    1068         /* 7 */ 0,0,
    1069         /* 8 */ DSP_SPOS_UU,DSP_SPOS_DC,
    1070         /* 9 */ 0,
    1071         /* A */ 0,HFG_FIRST_EXECUTE_MODE,
    1072         /* B */ DSP_SPOS_UU,DSP_SPOS_UU,
    1073         /* C */ DSP_SPOS_DC_DC,
    1074         /* D */ DSP_SPOS_DC_DC,
    1075         /* E */ DSP_SPOS_DC_DC,
    1076         /* F */ DSP_SPOS_DC_DC
    1077     };
    1078 
    1079     cs46xx_dsp_create_task_tree(chip, "sposCB", (u32 *)&sposcb, SPOSCB_ADDR, 0x10);
    1080 
    1081     null_algorithm  = cs46xx_dsp_lookup_symbol(chip, "NULLALGORITHM", SYMBOL_CODE);
    1082     if (null_algorithm == NULL) {
    1083         snd_printk(KERN_ERR "dsp_spos: symbol NULLALGORITHM not found\n");
    1084         return -EIO;
    1085     }
    1086 
    1087     fg_task_tree_header_code = cs46xx_dsp_lookup_symbol(chip, "FGTASKTREEHEADERCODE", SYMBOL_CODE);
    1088     if (fg_task_tree_header_code == NULL) {
    1089         snd_printk(KERN_ERR "dsp_spos: symbol FGTASKTREEHEADERCODE not found\n");
    1090         return -EIO;
    1091     }
    1092 
    1093     task_tree_header_code = cs46xx_dsp_lookup_symbol(chip, "TASKTREEHEADERCODE", SYMBOL_CODE);
    1094     if (task_tree_header_code == NULL) {
    1095         snd_printk(KERN_ERR "dsp_spos: symbol TASKTREEHEADERCODE not found\n");
    1096         return -EIO;
    1097     }
    1098 
    1099     task_tree_thread = cs46xx_dsp_lookup_symbol(chip, "TASKTREETHREAD", SYMBOL_CODE);
    1100     if (task_tree_thread == NULL) {
    1101         snd_printk(KERN_ERR "dsp_spos: symbol TASKTREETHREAD not found\n");
    1102         return -EIO;
    1103     }
    1104 
    1105     magic_snoop_task = cs46xx_dsp_lookup_symbol(chip, "MAGICSNOOPTASK", SYMBOL_CODE);
    1106     if (magic_snoop_task == NULL) {
    1107         snd_printk(KERN_ERR "dsp_spos: symbol MAGICSNOOPTASK not found\n");
    1108         return -EIO;
    1109     }
    1110 
    1111     {
    1112         /* create the null SCB */
    1113         static generic_scb_t null_scb = {
    1114             { 0, 0, 0, 0 },
    1115             { 0, 0, 0, 0, 0 },
    1116             NULL_SCB_ADDR, NULL_SCB_ADDR,
    1117             0,0,
    1118             0,0,0,
    1119             {
    1120                 0,0,
    1121                 0,0,
    1122             }
    1123         };
    1124 
    1125         null_scb.entry_point = null_algorithm->address;
    1126 
    1127         ins->the_null_scb = cs46xx_dsp_create_scb(chip, "nullSCB", (u32 *)&null_scb, NULL_SCB_ADDR);
    1128         ins->the_null_scb->task_entry = null_algorithm;
    1129         ins->the_null_scb->sub_list_ptr = ins->the_null_scb;
    1130         ins->the_null_scb->next_scb_ptr = ins->the_null_scb;
    1131         ins->the_null_scb->parent_scb_ptr = NULL;
    1132         cs46xx_dsp_proc_register_scb_desc (chip,ins->the_null_scb);
    1133     }
    1134 
    1135     {
    1136         /* setup foreground task tree */
    1137         static task_tree_control_block_t fg_task_tree_hdr =  {
    1138             { FG_TASK_HEADER_ADDR | (DSP_SPOS_DC << 0x10),
    1139             DSP_SPOS_DC_DC,
    1140             DSP_SPOS_DC_DC,
    1141             0x0000,DSP_SPOS_DC,
    1142             DSP_SPOS_DC, DSP_SPOS_DC,
    1143             DSP_SPOS_DC_DC,
    1144             DSP_SPOS_DC_DC,
    1145             DSP_SPOS_DC_DC,
    1146             DSP_SPOS_DC,DSP_SPOS_DC },
    1147 
    1148             {
    1149                 BG_TREE_SCB_ADDR,TIMINGMASTER_SCB_ADDR,
    1150                 /*fg_task_tree_header_code->address*/0,
    1151                 FG_TASK_HEADER_ADDR + TCBData,
    1152             },
    1153 
    1154             {
    1155                 4,0,
    1156                 1,0,
    1157                 2,SPOSCB_ADDR + HFGFlags,
    1158                 0,0,
    1159                 FG_TASK_HEADER_ADDR + TCBContextBlk,FG_STACK
    1160             },
    1161 
    1162             {
    1163                 DSP_SPOS_DC,/*task_tree_thread->address*/0,
    1164                 DSP_SPOS_DC,DSP_SPOS_DC,
    1165                 DSP_SPOS_DC,DSP_SPOS_DC,
    1166                 DSP_SPOS_DC,DSP_SPOS_DC,
    1167                 DSP_SPOS_DC,DSP_SPOS_DC,
    1168                 DSP_SPOS_DCDC,
    1169                 DSP_SPOS_UU,1,
    1170                 DSP_SPOS_DCDC,
    1171                 DSP_SPOS_DCDC,
    1172                 DSP_SPOS_DCDC,
    1173                 DSP_SPOS_DCDC,
    1174                 DSP_SPOS_DCDC,
    1175                 DSP_SPOS_DCDC,
    1176                 DSP_SPOS_DCDC,
    1177                 DSP_SPOS_DCDC,
    1178                 DSP_SPOS_DCDC,
    1179                 DSP_SPOS_DCDC,
    1180                 DSP_SPOS_DCDC,
    1181                 DSP_SPOS_DCDC,
    1182                 DSP_SPOS_DCDC,
    1183                 DSP_SPOS_DCDC,
    1184                 DSP_SPOS_DCDC,
    1185                 DSP_SPOS_DCDC,
    1186                 DSP_SPOS_DCDC,
    1187                 DSP_SPOS_DCDC,
    1188                 DSP_SPOS_DCDC,
    1189                 DSP_SPOS_DCDC,
    1190                 DSP_SPOS_DCDC,
    1191                 DSP_SPOS_DCDC,
    1192                 DSP_SPOS_DCDC,
    1193                 DSP_SPOS_DCDC,
    1194                 DSP_SPOS_DCDC,
    1195                 DSP_SPOS_DCDC,
    1196                 DSP_SPOS_DCDC,
    1197                 DSP_SPOS_DCDC
    1198             },
    1199             {
    1200                 FG_INTERVAL_TIMER_PERIOD,DSP_SPOS_UU,
    1201                 0,0
    1202             }
    1203         };
    1204         fg_task_tree_hdr.links.entry_point = fg_task_tree_header_code->address;
    1205         fg_task_tree_hdr.context_blk.stack0 = task_tree_thread->address;
    1206         cs46xx_dsp_create_task_tree(chip,"FGtaskTreeHdr",(u32 *)&fg_task_tree_hdr,FG_TASK_HEADER_ADDR,0x35);
    1207     }
    1208 
    1209 
    1210     {
    1211         /* setup foreground task tree */
    1212         task_tree_control_block_t bg_task_tree_hdr =  {
    1213             { DSP_SPOS_DC_DC,
    1214             DSP_SPOS_DC_DC,
    1215             DSP_SPOS_DC_DC,
    1216             DSP_SPOS_DC, DSP_SPOS_DC,
    1217             DSP_SPOS_DC, DSP_SPOS_DC,
    1218             DSP_SPOS_DC_DC,
    1219             DSP_SPOS_DC_DC,
    1220             DSP_SPOS_DC_DC,
    1221             DSP_SPOS_DC,DSP_SPOS_DC },
    1222 
    1223             {
    1224                 NULL_SCB_ADDR,NULL_SCB_ADDR,  /* Set up the background to do nothing */
    1225                 /*task_tree_header_code->address*/0,
    1226                 BG_TREE_SCB_ADDR + TCBData,
    1227             },
    1228 
    1229             {
    1230                 9999,0,
    1231                 0,1,
    1232                 0,SPOSCB_ADDR + HFGFlags,
    1233                 0,0,
    1234                 BG_TREE_SCB_ADDR + TCBContextBlk,BG_STACK
    1235             },
    1236 
    1237             {
    1238                 DSP_SPOS_DC,/*task_tree_thread->address*/0,
    1239                 DSP_SPOS_DC,DSP_SPOS_DC,
    1240                 DSP_SPOS_DC,DSP_SPOS_DC,
    1241                 DSP_SPOS_DC,DSP_SPOS_DC,
    1242                 DSP_SPOS_DC,DSP_SPOS_DC,
    1243                 DSP_SPOS_DCDC,
    1244                 DSP_SPOS_UU,1,
    1245                 DSP_SPOS_DCDC,
    1246                 DSP_SPOS_DCDC,
    1247                 DSP_SPOS_DCDC,
    1248                 DSP_SPOS_DCDC,
    1249                 DSP_SPOS_DCDC,
    1250                 DSP_SPOS_DCDC,
    1251                 DSP_SPOS_DCDC,
    1252                 DSP_SPOS_DCDC,
    1253                 DSP_SPOS_DCDC,
    1254                 DSP_SPOS_DCDC,
    1255                 DSP_SPOS_DCDC,
    1256                 DSP_SPOS_DCDC,
    1257                 DSP_SPOS_DCDC,
    1258                 DSP_SPOS_DCDC,
    1259                 DSP_SPOS_DCDC,
    1260                 DSP_SPOS_DCDC,
    1261                 DSP_SPOS_DCDC,
    1262                 DSP_SPOS_DCDC,
    1263                 DSP_SPOS_DCDC,
    1264                 DSP_SPOS_DCDC,
    1265                 DSP_SPOS_DCDC,
    1266                 DSP_SPOS_DCDC,
    1267                 DSP_SPOS_DCDC,
    1268                 DSP_SPOS_DCDC,
    1269                 DSP_SPOS_DCDC,
    1270                 DSP_SPOS_DCDC,
    1271                 DSP_SPOS_DCDC,
    1272                 DSP_SPOS_DCDC
    1273             },
    1274             {
    1275                 BG_INTERVAL_TIMER_PERIOD,DSP_SPOS_UU,
    1276                 0,0
    1277             }
    1278         };
    1279         bg_task_tree_hdr.links.entry_point = task_tree_header_code->address;
    1280         bg_task_tree_hdr.context_blk.stack0 = task_tree_thread->address;
    1281         cs46xx_dsp_create_task_tree(chip,"BGtaskTreeHdr",(u32 *)&bg_task_tree_hdr,BG_TREE_SCB_ADDR,0x35);
    1282     }
    1283 
    1284     /* create timing master SCB */
    1285     timing_master_scb = cs46xx_dsp_create_timing_master_scb(chip);
    1286 
    1287     /* create the CODEC output task */
    1288     codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_I",0x0010,0x0000,
    1289                                                     MASTERMIX_SCB_ADDR,
    1290                                                     CODECOUT_SCB_ADDR,timing_master_scb,
    1291                                                     SCB_ON_PARENT_SUBLIST_SCB);
    1292 
    1293     if (!codec_out_scb) goto _fail_end;
    1294     /* create the master mix SCB */
    1295     master_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"MasterMixSCB",
    1296                                                     MIX_SAMPLE_BUF1,MASTERMIX_SCB_ADDR,
    1297                                                     codec_out_scb,
    1298                                                     SCB_ON_PARENT_SUBLIST_SCB);
    1299     ins->master_mix_scb = master_mix_scb;
    1300 
    1301     if (!master_mix_scb) goto _fail_end;
    1302 
    1303     /* create codec in */
    1304     codec_in_scb = cs46xx_dsp_create_codec_in_scb(chip,"CodecInSCB",0x0010,0x00A0,
    1305                                                   CODEC_INPUT_BUF1,
    1306                                                   CODECIN_SCB_ADDR,codec_out_scb,
    1307                                                   SCB_ON_PARENT_NEXT_SCB);
    1308     if (!codec_in_scb) goto _fail_end;
    1309     ins->codec_in_scb = codec_in_scb;
    1310 
    1311     /* create write back scb */
    1312     write_back_scb = cs46xx_dsp_create_mix_to_ostream_scb(chip,"WriteBackSCB",
    1313                                                           WRITE_BACK_BUF1,WRITE_BACK_SPB,
    1314                                                           WRITEBACK_SCB_ADDR,
    1315                                                           timing_master_scb,
    1316                                                           SCB_ON_PARENT_NEXT_SCB);
    1317     if (!write_back_scb) goto _fail_end;
    1318 
    1319     {
    1320         mix2_ostream_spb_t mix2_ostream_spb = {
    1321             0x00020000,
    1322             0x0000ffff
    1323         };
    1324 
    1325         /* dirty hack ... */
    1326         _dsp_create_task_tree (chip,(u32 *)&mix2_ostream_spb,WRITE_BACK_SPB,2);
    1327     }
    1328 
    1329     /* input sample converter */
    1330     vari_decimate_scb = cs46xx_dsp_create_vari_decimate_scb(chip,"VariDecimateSCB",
    1331                                                             VARI_DECIMATE_BUF0,
    1332                                                             VARI_DECIMATE_BUF1,
    1333                                                             VARIDECIMATE_SCB_ADDR,
    1334                                                             write_back_scb,
    1335                                                             SCB_ON_PARENT_SUBLIST_SCB);
    1336     if (!vari_decimate_scb) goto _fail_end;
    1337 
    1338     /* create the record mixer SCB */
    1339     record_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"RecordMixerSCB",
    1340                                                     MIX_SAMPLE_BUF2,
    1341                                                     RECORD_MIXER_SCB_ADDR,
    1342                                                     vari_decimate_scb,
    1343                                                     SCB_ON_PARENT_SUBLIST_SCB);
    1344     ins->record_mixer_scb = record_mix_scb;
    1345 
    1346     if (!record_mix_scb) goto _fail_end;
    1347 
    1348     valid_slots = snd_cs46xx_peekBA0(chip, BA0_ACOSV);
    1349 
    1350     //  snd_assert (chip->nr_ac97_codecs == 1 || chip->nr_ac97_codecs == 2);
    1351 
    1352     if (chip->nr_ac97_codecs == 1) {
    1353         /* output on slot 5 and 11
    1354          on primary CODEC */
    1355         fifo_addr = 0x20;
    1356         fifo_span = 0x60;
    1357 
    1358         /* enable slot 5 and 11 */
    1359         valid_slots |= ACOSV_SLV5 | ACOSV_SLV11;
    1360     } else {
    1361         /* output on slot 7 and 8
    1362          on secondary CODEC */
    1363         fifo_addr = 0x40;
    1364         fifo_span = 0x10;
    1365 
    1366         /* enable slot 7 and 8 */
    1367         valid_slots |= ACOSV_SLV7 | ACOSV_SLV8;
    1368     }
    1369     /* create CODEC tasklet for rear speakers output*/
    1370     rear_codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_Rear",fifo_span,fifo_addr,
    1371                                                          REAR_MIXER_SCB_ADDR,
    1372                                                          REAR_CODECOUT_SCB_ADDR,codec_in_scb,
    1373                                                          SCB_ON_PARENT_NEXT_SCB);
    1374     if (!rear_codec_out_scb) goto _fail_end;
    1375 
    1376 
    1377     /* create the rear PCM channel  mixer SCB */
    1378     rear_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"RearMixerSCB",
    1379                                                   MIX_SAMPLE_BUF3,
    1380                                                   REAR_MIXER_SCB_ADDR,
    1381                                                   rear_codec_out_scb,
    1382                                                   SCB_ON_PARENT_SUBLIST_SCB);
    1383     ins->rear_mix_scb = rear_mix_scb;
    1384     if (!rear_mix_scb) goto _fail_end;
    1385 
    1386     if (chip->nr_ac97_codecs == 2) {
    1387         /* create CODEC tasklet for rear Center/LFE output
    1388          slot 6 and 9 on seconadry CODEC */
    1389         clfe_codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_CLFE",0x0030,0x0030,
    1390                                                              CLFE_MIXER_SCB_ADDR,
    1391                                                              CLFE_CODEC_SCB_ADDR,
    1392                                                              rear_codec_out_scb,
    1393                                                              SCB_ON_PARENT_NEXT_SCB);
    1394         if (!clfe_codec_out_scb) goto _fail_end;
    1395 
    1396 
    1397         /* create the rear PCM channel  mixer SCB */
    1398         ins->center_lfe_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"CLFEMixerSCB",
    1399                                                                  MIX_SAMPLE_BUF4,
    1400                                                                  CLFE_MIXER_SCB_ADDR,
    1401                                                                  clfe_codec_out_scb,
    1402                                                                  SCB_ON_PARENT_SUBLIST_SCB);
    1403         if (!ins->center_lfe_mix_scb) goto _fail_end;
    1404 
    1405         /* enable slot 6 and 9 */
    1406         valid_slots |= ACOSV_SLV6 | ACOSV_SLV9;
    1407     } else {
    1408         clfe_codec_out_scb = rear_codec_out_scb;
    1409         ins->center_lfe_mix_scb = rear_mix_scb;
    1410     }
    1411 
    1412     /* enable slots depending on CODEC configuration */
    1413     snd_cs46xx_pokeBA0(chip, BA0_ACOSV, valid_slots);
    1414 
    1415     /* the magic snooper */
    1416     magic_snoop_scb = cs46xx_dsp_create_magic_snoop_scb (chip,"MagicSnoopSCB_I",OUTPUTSNOOP_SCB_ADDR,
    1417                                                          OUTPUT_SNOOP_BUFFER,
    1418                                                          codec_out_scb,
    1419                                                          clfe_codec_out_scb,
    1420                                                          SCB_ON_PARENT_NEXT_SCB);
    1421 
    1422 
    1423     if (!magic_snoop_scb) goto _fail_end;
    1424     ins->ref_snoop_scb = magic_snoop_scb;
    1425 
    1426     /* SP IO access */
    1427     if (!cs46xx_dsp_create_spio_write_scb(chip,"SPIOWriteSCB",SPIOWRITE_SCB_ADDR,
    1428                                           magic_snoop_scb,
    1429                                           SCB_ON_PARENT_NEXT_SCB))
    1430         goto _fail_end;
    1431 
    1432     /* SPDIF input sampel rate converter */
    1433     src_task_scb = cs46xx_dsp_create_src_task_scb(chip,"SrcTaskSCB_SPDIFI",
    1434                                                   ins->spdif_in_sample_rate,
    1435                                                   SRC_OUTPUT_BUF1,
    1436                                                   SRC_DELAY_BUF1,SRCTASK_SCB_ADDR,
    1437                                                   master_mix_scb,
    1438                                                   SCB_ON_PARENT_SUBLIST_SCB,1);
    1439 
    1440     if (!src_task_scb) goto _fail_end;
    1441     cs46xx_src_unlink(chip,src_task_scb);
    1442 
    1443     /* NOTE: when we now how to detect the SPDIF input
    1444      sample rate we will use this SRC to adjust it */
    1445     ins->spdif_in_src = src_task_scb;
    1446 
    1447     cs46xx_dsp_async_init(chip,timing_master_scb);
    1448     return 0;
    1449 
    1450     _fail_end:
    1451         snd_printk(KERN_ERR "dsp_spos: failed to setup SCB's in DSP\n");
    1452         return -EINVAL;
    1453 }
    1454 
    1455 int cs46xx_dsp_async_init (cs46xx_t *chip, dsp_scb_descriptor_t * fg_entry)
    1456 {
    1457     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    1458     symbol_entry_t * s16_async_codec_input_task;
    1459     symbol_entry_t * spdifo_task;
    1460     symbol_entry_t * spdifi_task;
    1461     dsp_scb_descriptor_t * spdifi_scb_desc,* spdifo_scb_desc,* async_codec_scb_desc;
    1462 
    1463     s16_async_codec_input_task = cs46xx_dsp_lookup_symbol(chip, "S16_ASYNCCODECINPUTTASK", SYMBOL_CODE);
    1464     if (s16_async_codec_input_task == NULL) {
    1465         snd_printk(KERN_ERR "dsp_spos: symbol S16_ASYNCCODECINPUTTASK not found\n");
    1466         return -EIO;
    1467     }
    1468     spdifo_task = cs46xx_dsp_lookup_symbol(chip, "SPDIFOTASK", SYMBOL_CODE);
    1469     if (spdifo_task == NULL) {
    1470         snd_printk(KERN_ERR "dsp_spos: symbol SPDIFOTASK not found\n");
    1471         return -EIO;
    1472     }
    1473 
    1474     spdifi_task = cs46xx_dsp_lookup_symbol(chip, "SPDIFITASK", SYMBOL_CODE);
    1475     if (spdifi_task == NULL) {
    1476         snd_printk(KERN_ERR "dsp_spos: symbol SPDIFITASK not found\n");
    1477         return -EIO;
    1478     }
    1479 
    1480     {
    1481         /* 0xBC0 */
    1482         spdifoscb_t spdifo_scb = {
    1483             /* 0 */ DSP_SPOS_UUUU,
    1484             {
    1485                 /* 1 */ 0xb0,
    1486                 /* 2 */ 0,
    1487                 /* 3 */ 0,
    1488                 /* 4 */ 0,
    1489             },
    1490             /* NOTE: the SPDIF output task read samples in mono
    1491              format, the AsynchFGTxSCB task writes to buffer
    1492              in stereo format
    1493              */
    1494             /* 5 */ RSCONFIG_SAMPLE_16MONO + RSCONFIG_MODULO_256,
    1495             /* 6 */ ( SPDIFO_IP_OUTPUT_BUFFER1 << 0x10 )  |  0xFFFC,
    1496             /* 7 */ 0,0,
    1497             /* 8 */ 0,
    1498             /* 9 */ FG_TASK_HEADER_ADDR, NULL_SCB_ADDR,
    1499             /* A */ /*spdifo_task->address*/0,
    1500             SPDIFO_SCB_INST + SPDIFOFIFOPointer,
    1501             {
    1502                 /* B */ 0x0040, /*DSP_SPOS_UUUU,*/
    1503                 /* C */ 0x20ff, /*DSP_SPOS_UUUU,*/
    1504             },
    1505             /* D */ 0x804c,0,                                                     /* SPDIFOFIFOPointer:SPDIFOStatRegAddr; */
    1506             /* E */ 0x0108,0x0001,                                        /* SPDIFOStMoFormat:SPDIFOFIFOBaseAddr; */
    1507             /* F */ DSP_SPOS_UUUU                                         /* SPDIFOFree; */
    1508         };
    1509 
    1510         /* 0xBB0 */
    1511         spdifiscb_t spdifi_scb = {
    1512             /* 0 */ DSP_SPOS_UULO,DSP_SPOS_UUHI,
    1513             /* 1 */ 0,
    1514             /* 2 */ 0,
    1515             /* 3 */ 1,4000,        /* SPDIFICountLimit SPDIFICount */
    1516             /* 4 */ DSP_SPOS_UUUU, /* SPDIFIStatusData */
    1517             /* 5 */ 0,DSP_SPOS_UUHI, /* StatusData, Free4 */
    1518             /* 6 */ DSP_SPOS_UUUU,  /* Free3 */
    1519             /* 7 */ DSP_SPOS_UU,DSP_SPOS_DC,  /* Free2 BitCount*/
    1520             /* 8 */ DSP_SPOS_UUUU,      /* TempStatus */
    1521             /* 9 */ SPDIFO_SCB_INST, NULL_SCB_ADDR,
    1522             /* A */ /*spdifi_task->address*/0,
    1523             SPDIFI_SCB_INST + SPDIFIFIFOPointer,
    1524             /* NOTE: The SPDIF input task write the sample in mono
    1525              format from the HW FIFO, the AsynchFGRxSCB task  reads
    1526              them in stereo
    1527              */
    1528             /* B */ RSCONFIG_SAMPLE_16MONO + RSCONFIG_MODULO_128,
    1529             /* C */ (SPDIFI_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC,
    1530             /* D */ 0x8048,0,
    1531             /* E */ 0x01f0,0x0001,
    1532             /* F */ DSP_SPOS_UUUU /* SPDIN_STATUS monitor */
    1533         };
    1534 
    1535         /* 0xBA0 */
    1536         async_codec_input_scb_t async_codec_input_scb = {
    1537             /* 0 */ DSP_SPOS_UUUU,
    1538             /* 1 */ 0,
    1539             /* 2 */ 0,
    1540             /* 3 */ 1,4000,
    1541             /* 4 */ 0x0118,0x0001,
    1542             /* 5 */ RSCONFIG_SAMPLE_16MONO + RSCONFIG_MODULO_64,
    1543             /* 6 */ (ASYNC_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC,
    1544             /* 7 */ DSP_SPOS_UU,0x3,
    1545             /* 8 */ DSP_SPOS_UUUU,
    1546             /* 9 */ SPDIFI_SCB_INST,NULL_SCB_ADDR,
    1547             /* A */ /*s16_async_codec_input_task->address*/0,
    1548             HFG_TREE_SCB + AsyncCIOFIFOPointer,
    1549 
    1550             /* B */ RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64,
    1551             /* C */ (ASYNC_IP_OUTPUT_BUFFER1 << 0x10),  /*(ASYNC_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC,*/
    1552 
     735        snd_iprintf(buffer,"\nSPDIFI_IP_OUTPUT_BUFFER1: \n");
     736        col = 0;
     737        for (i = SPDIFI_IP_OUTPUT_BUFFER1;i < SPDIFI_IP_OUTPUT_BUFFER1 + 0x80; i += sizeof(u32),col ++) {
     738                if (col == 4) {
     739                        snd_iprintf(buffer,"\n");
     740                        col = 0;
     741                }
     742
     743                if (col == 0) {
     744                        snd_iprintf(buffer, "%04X ",i);
     745                }
     746               
     747                snd_iprintf(buffer,"%08X ",readl(dst + i));
     748        }
     749        snd_iprintf(buffer,"\n");
     750}
     751
     752int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip)
     753{
     754        struct snd_info_entry *entry;
     755        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     756        int i;
     757
     758        ins->snd_card = card;
     759
     760        if ((entry = snd_info_create_card_entry(card, "dsp", card->proc_root)) != NULL) {
     761                entry->content = SNDRV_INFO_CONTENT_TEXT;
     762                entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
     763                entry->c.text.read_size = 512;
     764     
     765                if (snd_info_register(entry) < 0) {
     766                        snd_info_free_entry(entry);
     767                        entry = NULL;
     768                }
     769        }
     770
     771        ins->proc_dsp_dir = entry;
     772
     773        if (!ins->proc_dsp_dir)
     774                return -ENOMEM;
     775
     776        if ((entry = snd_info_create_card_entry(card, "spos_symbols", ins->proc_dsp_dir)) != NULL) {
     777                entry->content = SNDRV_INFO_CONTENT_TEXT;
     778                entry->private_data = chip;
     779                entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
     780                entry->c.text.read_size = 512;
     781                entry->c.text.read = cs46xx_dsp_proc_symbol_table_read;
     782                if (snd_info_register(entry) < 0) {
     783                        snd_info_free_entry(entry);
     784                        entry = NULL;
     785                }
     786        }
     787        ins->proc_sym_info_entry = entry;
     788   
     789        if ((entry = snd_info_create_card_entry(card, "spos_modules", ins->proc_dsp_dir)) != NULL) {
     790                entry->content = SNDRV_INFO_CONTENT_TEXT;
     791                entry->private_data = chip;
     792                entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
     793                entry->c.text.read_size = 512;
     794                entry->c.text.read = cs46xx_dsp_proc_modules_read;
     795                if (snd_info_register(entry) < 0) {
     796                        snd_info_free_entry(entry);
     797                        entry = NULL;
     798                }
     799        }
     800        ins->proc_modules_info_entry = entry;
     801
     802        if ((entry = snd_info_create_card_entry(card, "parameter", ins->proc_dsp_dir)) != NULL) {
     803                entry->content = SNDRV_INFO_CONTENT_TEXT;
     804                entry->private_data = chip;
     805                entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
     806                entry->c.text.read_size = 512;
     807                entry->c.text.read = cs46xx_dsp_proc_parameter_dump_read;
     808                if (snd_info_register(entry) < 0) {
     809                        snd_info_free_entry(entry);
     810                        entry = NULL;
     811                }
     812        }
     813        ins->proc_parameter_dump_info_entry = entry;
     814
     815        if ((entry = snd_info_create_card_entry(card, "sample", ins->proc_dsp_dir)) != NULL) {
     816                entry->content = SNDRV_INFO_CONTENT_TEXT;
     817                entry->private_data = chip;
     818                entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
     819                entry->c.text.read_size = 512;
     820                entry->c.text.read = cs46xx_dsp_proc_sample_dump_read;
     821                if (snd_info_register(entry) < 0) {
     822                        snd_info_free_entry(entry);
     823                        entry = NULL;
     824                }
     825        }
     826        ins->proc_sample_dump_info_entry = entry;
     827
     828        if ((entry = snd_info_create_card_entry(card, "task_tree", ins->proc_dsp_dir)) != NULL) {
     829                entry->content = SNDRV_INFO_CONTENT_TEXT;
     830                entry->private_data = chip;
     831                entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
     832                entry->c.text.read_size = 512;
     833                entry->c.text.read = cs46xx_dsp_proc_task_tree_read;
     834                if (snd_info_register(entry) < 0) {
     835                        snd_info_free_entry(entry);
     836                        entry = NULL;
     837                }
     838        }
     839        ins->proc_task_info_entry = entry;
     840
     841        if ((entry = snd_info_create_card_entry(card, "scb_info", ins->proc_dsp_dir)) != NULL) {
     842                entry->content = SNDRV_INFO_CONTENT_TEXT;
     843                entry->private_data = chip;
     844                entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
     845                entry->c.text.read_size = 1024;
     846                entry->c.text.read = cs46xx_dsp_proc_scb_read;
     847                if (snd_info_register(entry) < 0) {
     848                        snd_info_free_entry(entry);
     849                        entry = NULL;
     850                }
     851        }
     852        ins->proc_scb_info_entry = entry;
     853
     854        down(&chip->spos_mutex);
     855        /* register/update SCB's entries on proc */
     856        for (i = 0; i < ins->nscb; ++i) {
     857                if (ins->scbs[i].deleted) continue;
     858
     859                cs46xx_dsp_proc_register_scb_desc (chip, (ins->scbs + i));
     860        }
     861        up(&chip->spos_mutex);
     862
     863        return 0;
     864}
     865
     866int cs46xx_dsp_proc_done (struct snd_cs46xx *chip)
     867{
     868        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     869        int i;
     870
     871        if (ins->proc_sym_info_entry) {
     872                snd_info_unregister(ins->proc_sym_info_entry);
     873                ins->proc_sym_info_entry = NULL;
     874        }
     875 
     876        if (ins->proc_modules_info_entry) {
     877                snd_info_unregister(ins->proc_modules_info_entry);
     878                ins->proc_modules_info_entry = NULL;
     879        }
     880 
     881        if (ins->proc_parameter_dump_info_entry) {
     882                snd_info_unregister(ins->proc_parameter_dump_info_entry);
     883                ins->proc_parameter_dump_info_entry = NULL;
     884        }
     885 
     886        if (ins->proc_sample_dump_info_entry) {
     887                snd_info_unregister(ins->proc_sample_dump_info_entry);
     888                ins->proc_sample_dump_info_entry = NULL;
     889        }
     890 
     891        if (ins->proc_scb_info_entry) {
     892                snd_info_unregister(ins->proc_scb_info_entry);
     893                ins->proc_scb_info_entry = NULL;
     894        }
     895 
     896        if (ins->proc_task_info_entry) {
     897                snd_info_unregister(ins->proc_task_info_entry);
     898                ins->proc_task_info_entry = NULL;
     899        }
     900
     901        down(&chip->spos_mutex);
     902        for (i = 0; i < ins->nscb; ++i) {
     903                if (ins->scbs[i].deleted) continue;
     904                cs46xx_dsp_proc_free_scb_desc ( (ins->scbs + i) );
     905        }
     906        up(&chip->spos_mutex);
     907
     908        if (ins->proc_dsp_dir) {
     909                snd_info_unregister (ins->proc_dsp_dir);
     910                ins->proc_dsp_dir = NULL;
     911        }
     912
     913        return 0;
     914}
     915
     916static int debug_tree;
     917static void _dsp_create_task_tree (struct snd_cs46xx *chip, u32 * task_data,
     918                                   u32  dest, int size)
     919{
     920        void __iomem *spdst = chip->region.idx[1].remap_addr +
     921                DSP_PARAMETER_BYTE_OFFSET + dest * sizeof(u32);
     922        int i;
     923
     924        for (i = 0; i < size; ++i) {
     925                if (debug_tree) printk ("addr %p, val %08x\n",spdst,task_data[i]);
     926                writel(task_data[i],spdst);
     927                spdst += sizeof(u32);
     928        }
     929}
     930
     931static int debug_scb;
     932static void _dsp_create_scb (struct snd_cs46xx *chip, u32 * scb_data, u32 dest)
     933{
     934        void __iomem *spdst = chip->region.idx[1].remap_addr +
     935                DSP_PARAMETER_BYTE_OFFSET + dest * sizeof(u32);
     936        int i;
     937
     938        for (i = 0; i < 0x10; ++i) {
     939                if (debug_scb) printk ("addr %p, val %08x\n",spdst,scb_data[i]);
     940                writel(scb_data[i],spdst);
     941                spdst += sizeof(u32);
     942        }
     943}
     944
     945static int find_free_scb_index (struct dsp_spos_instance * ins)
     946{
     947        int index = ins->nscb, i;
     948
     949        for (i = ins->scb_highest_frag_index; i < ins->nscb; ++i) {
     950                if (ins->scbs[i].deleted) {
     951                        index = i;
     952                        break;
     953                }
     954        }
     955
     956        return index;
     957}
     958
     959static struct dsp_scb_descriptor * _map_scb (struct snd_cs46xx *chip, char * name, u32 dest)
     960{
     961        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     962        struct dsp_scb_descriptor * desc = NULL;
     963        int index;
     964
     965        if (ins->nscb == DSP_MAX_SCB_DESC - 1) {
     966                snd_printk(KERN_ERR "dsp_spos: got no place for other SCB\n");
     967                return NULL;
     968        }
     969
     970        index = find_free_scb_index (ins);
     971
     972        strcpy(ins->scbs[index].scb_name, name);
     973        ins->scbs[index].address = dest;
     974        ins->scbs[index].index = index;
     975        ins->scbs[index].proc_info = NULL;
     976        ins->scbs[index].ref_count = 1;
     977        ins->scbs[index].deleted = 0;
     978        spin_lock_init(&ins->scbs[index].lock);
     979
     980        desc = (ins->scbs + index);
     981        ins->scbs[index].scb_symbol = add_symbol (chip, name, dest, SYMBOL_PARAMETER);
     982
     983        if (index > ins->scb_highest_frag_index)
     984                ins->scb_highest_frag_index = index;
     985
     986        if (index == ins->nscb)
     987                ins->nscb++;
     988
     989        return desc;
     990}
     991
     992static struct dsp_task_descriptor *
     993_map_task_tree (struct snd_cs46xx *chip, char * name, u32 dest, u32 size)
     994{
     995        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     996        struct dsp_task_descriptor * desc = NULL;
     997
     998        if (ins->ntask == DSP_MAX_TASK_DESC - 1) {
     999                snd_printk(KERN_ERR "dsp_spos: got no place for other TASK\n");
     1000                return NULL;
     1001        }
     1002
     1003        strcpy(ins->tasks[ins->ntask].task_name,name);
     1004        ins->tasks[ins->ntask].address = dest;
     1005        ins->tasks[ins->ntask].size = size;
     1006
     1007        /* quick find in list */
     1008        ins->tasks[ins->ntask].index = ins->ntask;
     1009        desc = (ins->tasks + ins->ntask);
     1010        ins->ntask++;
     1011
     1012        add_symbol (chip,name,dest,SYMBOL_PARAMETER);
     1013        return desc;
     1014}
     1015
     1016struct dsp_scb_descriptor *
     1017cs46xx_dsp_create_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32 dest)
     1018{
     1019        struct dsp_scb_descriptor * desc;
     1020
     1021        desc = _map_scb (chip,name,dest);
     1022        if (desc) {
     1023                _dsp_create_scb(chip,scb_data,dest);
     1024        } else {
     1025                snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n");
     1026        }
     1027
     1028        return desc;
     1029}
     1030
     1031
     1032static struct dsp_task_descriptor *
     1033cs46xx_dsp_create_task_tree (struct snd_cs46xx *chip, char * name, u32 * task_data,
     1034                             u32 dest, int size)
     1035{
     1036        struct dsp_task_descriptor * desc;
     1037
     1038        desc = _map_task_tree (chip,name,dest,size);
     1039        if (desc) {
     1040                _dsp_create_task_tree(chip,task_data,dest,size);
     1041        } else {
     1042                snd_printk(KERN_ERR "dsp_spos: failed to map TASK\n");
     1043        }
     1044
     1045        return desc;
     1046}
     1047
     1048int cs46xx_dsp_scb_and_task_init (struct snd_cs46xx *chip)
     1049{
     1050        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     1051        struct dsp_symbol_entry * fg_task_tree_header_code;
     1052        struct dsp_symbol_entry * task_tree_header_code;
     1053        struct dsp_symbol_entry * task_tree_thread;
     1054        struct dsp_symbol_entry * null_algorithm;
     1055        struct dsp_symbol_entry * magic_snoop_task;
     1056
     1057        struct dsp_scb_descriptor * timing_master_scb;
     1058        struct dsp_scb_descriptor * codec_out_scb;
     1059        struct dsp_scb_descriptor * codec_in_scb;
     1060        struct dsp_scb_descriptor * src_task_scb;
     1061        struct dsp_scb_descriptor * master_mix_scb;
     1062        struct dsp_scb_descriptor * rear_mix_scb;
     1063        struct dsp_scb_descriptor * record_mix_scb;
     1064        struct dsp_scb_descriptor * write_back_scb;
     1065        struct dsp_scb_descriptor * vari_decimate_scb;
     1066        struct dsp_scb_descriptor * rear_codec_out_scb;
     1067        struct dsp_scb_descriptor * clfe_codec_out_scb;
     1068        struct dsp_scb_descriptor * magic_snoop_scb;
     1069       
     1070        int fifo_addr, fifo_span, valid_slots;
     1071
     1072        static struct dsp_spos_control_block sposcb = {
     1073                /* 0 */ HFG_TREE_SCB,HFG_STACK,
     1074                /* 1 */ SPOSCB_ADDR,BG_TREE_SCB_ADDR,
     1075                /* 2 */ DSP_SPOS_DC,0,
     1076                /* 3 */ DSP_SPOS_DC,DSP_SPOS_DC,
     1077                /* 4 */ 0,0,
     1078                /* 5 */ DSP_SPOS_UU,0,
     1079                /* 6 */ FG_TASK_HEADER_ADDR,0,
     1080                /* 7 */ 0,0,
     1081                /* 8 */ DSP_SPOS_UU,DSP_SPOS_DC,
     1082                /* 9 */ 0,
     1083                /* A */ 0,HFG_FIRST_EXECUTE_MODE,
     1084                /* B */ DSP_SPOS_UU,DSP_SPOS_UU,
     1085                /* C */ DSP_SPOS_DC_DC,
     1086                /* D */ DSP_SPOS_DC_DC,
     1087                /* E */ DSP_SPOS_DC_DC,
     1088                /* F */ DSP_SPOS_DC_DC
     1089        };
     1090
     1091        cs46xx_dsp_create_task_tree(chip, "sposCB", (u32 *)&sposcb, SPOSCB_ADDR, 0x10);
     1092
     1093        null_algorithm  = cs46xx_dsp_lookup_symbol(chip, "NULLALGORITHM", SYMBOL_CODE);
     1094        if (null_algorithm == NULL) {
     1095                snd_printk(KERN_ERR "dsp_spos: symbol NULLALGORITHM not found\n");
     1096                return -EIO;
     1097        }
     1098
     1099        fg_task_tree_header_code = cs46xx_dsp_lookup_symbol(chip, "FGTASKTREEHEADERCODE", SYMBOL_CODE); 
     1100        if (fg_task_tree_header_code == NULL) {
     1101                snd_printk(KERN_ERR "dsp_spos: symbol FGTASKTREEHEADERCODE not found\n");
     1102                return -EIO;
     1103        }
     1104
     1105        task_tree_header_code = cs46xx_dsp_lookup_symbol(chip, "TASKTREEHEADERCODE", SYMBOL_CODE); 
     1106        if (task_tree_header_code == NULL) {
     1107                snd_printk(KERN_ERR "dsp_spos: symbol TASKTREEHEADERCODE not found\n");
     1108                return -EIO;
     1109        }
     1110 
     1111        task_tree_thread = cs46xx_dsp_lookup_symbol(chip, "TASKTREETHREAD", SYMBOL_CODE);
     1112        if (task_tree_thread == NULL) {
     1113                snd_printk(KERN_ERR "dsp_spos: symbol TASKTREETHREAD not found\n");
     1114                return -EIO;
     1115        }
     1116
     1117        magic_snoop_task = cs46xx_dsp_lookup_symbol(chip, "MAGICSNOOPTASK", SYMBOL_CODE);
     1118        if (magic_snoop_task == NULL) {
     1119                snd_printk(KERN_ERR "dsp_spos: symbol MAGICSNOOPTASK not found\n");
     1120                return -EIO;
     1121        }
     1122 
     1123        {
     1124                /* create the null SCB */
     1125                static struct dsp_generic_scb null_scb = {
     1126                        { 0, 0, 0, 0 },
     1127                        { 0, 0, 0, 0, 0 },
     1128                        NULL_SCB_ADDR, NULL_SCB_ADDR,
     1129                        0, 0, 0, 0, 0,
     1130                        {
     1131                                0,0,
     1132                                0,0,
     1133                        }
     1134                };
     1135
     1136                null_scb.entry_point = null_algorithm->address;
     1137                ins->the_null_scb = cs46xx_dsp_create_scb(chip, "nullSCB", (u32 *)&null_scb, NULL_SCB_ADDR);
     1138                ins->the_null_scb->task_entry = null_algorithm;
     1139                ins->the_null_scb->sub_list_ptr = ins->the_null_scb;
     1140                ins->the_null_scb->next_scb_ptr = ins->the_null_scb;
     1141                ins->the_null_scb->parent_scb_ptr = NULL;
     1142                cs46xx_dsp_proc_register_scb_desc (chip,ins->the_null_scb);
     1143        }
     1144
     1145        {
     1146                /* setup foreground task tree */
     1147                static struct dsp_task_tree_control_block fg_task_tree_hdr =  {
     1148                        { FG_TASK_HEADER_ADDR | (DSP_SPOS_DC << 0x10),
     1149                          DSP_SPOS_DC_DC,
     1150                          DSP_SPOS_DC_DC,
     1151                          0x0000,DSP_SPOS_DC,
     1152                          DSP_SPOS_DC, DSP_SPOS_DC,
     1153                          DSP_SPOS_DC_DC,
     1154                          DSP_SPOS_DC_DC,
     1155                          DSP_SPOS_DC_DC,
     1156                          DSP_SPOS_DC,DSP_SPOS_DC },
     1157   
     1158                        {
     1159                                BG_TREE_SCB_ADDR,TIMINGMASTER_SCB_ADDR,
     1160                                0,
     1161                                FG_TASK_HEADER_ADDR + TCBData,                 
     1162                        },
     1163
     1164                        {   
     1165                                4,0,
     1166                                1,0,
     1167                                2,SPOSCB_ADDR + HFGFlags,
     1168                                0,0,
     1169                                FG_TASK_HEADER_ADDR + TCBContextBlk,FG_STACK
     1170                        },
     1171
     1172                        {
     1173                                DSP_SPOS_DC,0,
     1174                                DSP_SPOS_DC,DSP_SPOS_DC,
     1175                                DSP_SPOS_DC,DSP_SPOS_DC,
     1176                                DSP_SPOS_DC,DSP_SPOS_DC,
     1177                                DSP_SPOS_DC,DSP_SPOS_DC,
     1178                                DSP_SPOS_DCDC,
     1179                                DSP_SPOS_UU,1,
     1180                                DSP_SPOS_DCDC,
     1181                                DSP_SPOS_DCDC,
     1182                                DSP_SPOS_DCDC,
     1183                                DSP_SPOS_DCDC,
     1184                                DSP_SPOS_DCDC,
     1185                                DSP_SPOS_DCDC,
     1186                                DSP_SPOS_DCDC,
     1187                                DSP_SPOS_DCDC,
     1188                                DSP_SPOS_DCDC,
     1189                                DSP_SPOS_DCDC,
     1190                                DSP_SPOS_DCDC,
     1191                                DSP_SPOS_DCDC,
     1192                                DSP_SPOS_DCDC,
     1193                                DSP_SPOS_DCDC,
     1194                                DSP_SPOS_DCDC,
     1195                                DSP_SPOS_DCDC,
     1196                                DSP_SPOS_DCDC,
     1197                                DSP_SPOS_DCDC,
     1198                                DSP_SPOS_DCDC,
     1199                                DSP_SPOS_DCDC,
     1200                                DSP_SPOS_DCDC,
     1201                                DSP_SPOS_DCDC,
     1202                                DSP_SPOS_DCDC,
     1203                                DSP_SPOS_DCDC,
     1204                                DSP_SPOS_DCDC,
     1205                                DSP_SPOS_DCDC,
     1206                                DSP_SPOS_DCDC,
     1207                                DSP_SPOS_DCDC
     1208                        },                                               
     1209                        {
     1210                                FG_INTERVAL_TIMER_PERIOD,DSP_SPOS_UU,
     1211                                0,0
     1212                        }
     1213                };
     1214
     1215                fg_task_tree_hdr.links.entry_point = fg_task_tree_header_code->address;
     1216                fg_task_tree_hdr.context_blk.stack0 = task_tree_thread->address;
     1217                cs46xx_dsp_create_task_tree(chip,"FGtaskTreeHdr",(u32 *)&fg_task_tree_hdr,FG_TASK_HEADER_ADDR,0x35);
     1218        }
     1219
     1220
     1221        {
     1222                /* setup foreground task tree */
     1223                static struct dsp_task_tree_control_block bg_task_tree_hdr =  {
     1224                        { DSP_SPOS_DC_DC,
     1225                          DSP_SPOS_DC_DC,
     1226                          DSP_SPOS_DC_DC,
     1227                          DSP_SPOS_DC, DSP_SPOS_DC,
     1228                          DSP_SPOS_DC, DSP_SPOS_DC,
     1229                          DSP_SPOS_DC_DC,
     1230                          DSP_SPOS_DC_DC,
     1231                          DSP_SPOS_DC_DC,
     1232                          DSP_SPOS_DC,DSP_SPOS_DC },
     1233   
     1234                        {
     1235                                NULL_SCB_ADDR,NULL_SCB_ADDR,  /* Set up the background to do nothing */
     1236                                0,
     1237                                BG_TREE_SCB_ADDR + TCBData,
     1238                        },
     1239
     1240                        {   
     1241                                9999,0,
     1242                                0,1,
     1243                                0,SPOSCB_ADDR + HFGFlags,
     1244                                0,0,
     1245                                BG_TREE_SCB_ADDR + TCBContextBlk,BG_STACK
     1246                        },
     1247
     1248                        {
     1249                                DSP_SPOS_DC,0,
     1250                                DSP_SPOS_DC,DSP_SPOS_DC,
     1251                                DSP_SPOS_DC,DSP_SPOS_DC,
     1252                                DSP_SPOS_DC,DSP_SPOS_DC,
     1253                                DSP_SPOS_DC,DSP_SPOS_DC,
     1254                                DSP_SPOS_DCDC,
     1255                                DSP_SPOS_UU,1,
     1256                                DSP_SPOS_DCDC,
     1257                                DSP_SPOS_DCDC,
     1258                                DSP_SPOS_DCDC,
     1259                                DSP_SPOS_DCDC,
     1260                                DSP_SPOS_DCDC,
     1261                                DSP_SPOS_DCDC,
     1262                                DSP_SPOS_DCDC,
     1263                                DSP_SPOS_DCDC,
     1264                                DSP_SPOS_DCDC,
     1265                                DSP_SPOS_DCDC,
     1266                                DSP_SPOS_DCDC,
     1267                                DSP_SPOS_DCDC,
     1268                                DSP_SPOS_DCDC,
     1269                                DSP_SPOS_DCDC,
     1270                                DSP_SPOS_DCDC,
     1271                                DSP_SPOS_DCDC,
     1272                                DSP_SPOS_DCDC,
     1273                                DSP_SPOS_DCDC,
     1274                                DSP_SPOS_DCDC,
     1275                                DSP_SPOS_DCDC,
     1276                                DSP_SPOS_DCDC,
     1277                                DSP_SPOS_DCDC,
     1278                                DSP_SPOS_DCDC,
     1279                                DSP_SPOS_DCDC,
     1280                                DSP_SPOS_DCDC,
     1281                                DSP_SPOS_DCDC,
     1282                                DSP_SPOS_DCDC,
     1283                                DSP_SPOS_DCDC
     1284                        },                                               
     1285                        {
     1286                                BG_INTERVAL_TIMER_PERIOD,DSP_SPOS_UU,
     1287                                0,0
     1288                        }
     1289                };
     1290
     1291                bg_task_tree_hdr.links.entry_point = task_tree_header_code->address;
     1292                bg_task_tree_hdr.context_blk.stack0 = task_tree_thread->address;
     1293                cs46xx_dsp_create_task_tree(chip,"BGtaskTreeHdr",(u32 *)&bg_task_tree_hdr,BG_TREE_SCB_ADDR,0x35);
     1294        }
     1295
     1296        /* create timing master SCB */
     1297        timing_master_scb = cs46xx_dsp_create_timing_master_scb(chip);
     1298
     1299        /* create the CODEC output task */
     1300        codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_I",0x0010,0x0000,
     1301                                                        MASTERMIX_SCB_ADDR,
     1302                                                        CODECOUT_SCB_ADDR,timing_master_scb,
     1303                                                        SCB_ON_PARENT_SUBLIST_SCB);
     1304
     1305        if (!codec_out_scb) goto _fail_end;
     1306        /* create the master mix SCB */
     1307        master_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"MasterMixSCB",
     1308                                                        MIX_SAMPLE_BUF1,MASTERMIX_SCB_ADDR,
     1309                                                        codec_out_scb,
     1310                                                        SCB_ON_PARENT_SUBLIST_SCB);
     1311        ins->master_mix_scb = master_mix_scb;
     1312
     1313        if (!master_mix_scb) goto _fail_end;
     1314
     1315        /* create codec in */
     1316        codec_in_scb = cs46xx_dsp_create_codec_in_scb(chip,"CodecInSCB",0x0010,0x00A0,
     1317                                                      CODEC_INPUT_BUF1,
     1318                                                      CODECIN_SCB_ADDR,codec_out_scb,
     1319                                                      SCB_ON_PARENT_NEXT_SCB);
     1320        if (!codec_in_scb) goto _fail_end;
     1321        ins->codec_in_scb = codec_in_scb;
     1322
     1323        /* create write back scb */
     1324        write_back_scb = cs46xx_dsp_create_mix_to_ostream_scb(chip,"WriteBackSCB",
     1325                                                              WRITE_BACK_BUF1,WRITE_BACK_SPB,
     1326                                                              WRITEBACK_SCB_ADDR,
     1327                                                              timing_master_scb,
     1328                                                              SCB_ON_PARENT_NEXT_SCB);
     1329        if (!write_back_scb) goto _fail_end;
     1330
     1331        {
     1332                static struct dsp_mix2_ostream_spb mix2_ostream_spb = {
     1333                        0x00020000,
     1334                        0x0000ffff
     1335                };
     1336   
     1337                /* dirty hack ... */
     1338                _dsp_create_task_tree (chip,(u32 *)&mix2_ostream_spb,WRITE_BACK_SPB,2);
     1339        }
     1340
     1341        /* input sample converter */
     1342        vari_decimate_scb = cs46xx_dsp_create_vari_decimate_scb(chip,"VariDecimateSCB",
     1343                                                                VARI_DECIMATE_BUF0,
     1344                                                                VARI_DECIMATE_BUF1,
     1345                                                                VARIDECIMATE_SCB_ADDR,
     1346                                                                write_back_scb,
     1347                                                                SCB_ON_PARENT_SUBLIST_SCB);
     1348        if (!vari_decimate_scb) goto _fail_end;
     1349
     1350        /* create the record mixer SCB */
     1351        record_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"RecordMixerSCB",
     1352                                                        MIX_SAMPLE_BUF2,
     1353                                                        RECORD_MIXER_SCB_ADDR,
     1354                                                        vari_decimate_scb,
     1355                                                        SCB_ON_PARENT_SUBLIST_SCB);
     1356        ins->record_mixer_scb = record_mix_scb;
     1357
     1358        if (!record_mix_scb) goto _fail_end;
     1359
     1360        valid_slots = snd_cs46xx_peekBA0(chip, BA0_ACOSV);
     1361
     1362        snd_assert (chip->nr_ac97_codecs == 1 || chip->nr_ac97_codecs == 2);
     1363
     1364        if (chip->nr_ac97_codecs == 1) {
     1365                /* output on slot 5 and 11
     1366                   on primary CODEC */
     1367                fifo_addr = 0x20;
     1368                fifo_span = 0x60;
     1369
     1370                /* enable slot 5 and 11 */
     1371                valid_slots |= ACOSV_SLV5 | ACOSV_SLV11;
     1372        } else {
     1373                /* output on slot 7 and 8
     1374                   on secondary CODEC */
     1375                fifo_addr = 0x40;
     1376                fifo_span = 0x10;
     1377
     1378                /* enable slot 7 and 8 */
     1379                valid_slots |= ACOSV_SLV7 | ACOSV_SLV8;
     1380        }
     1381        /* create CODEC tasklet for rear speakers output*/
     1382        rear_codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_Rear",fifo_span,fifo_addr,
     1383                                                             REAR_MIXER_SCB_ADDR,
     1384                                                             REAR_CODECOUT_SCB_ADDR,codec_in_scb,
     1385                                                             SCB_ON_PARENT_NEXT_SCB);
     1386        if (!rear_codec_out_scb) goto _fail_end;
     1387       
     1388       
     1389        /* create the rear PCM channel  mixer SCB */
     1390        rear_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"RearMixerSCB",
     1391                                                      MIX_SAMPLE_BUF3,
     1392                                                      REAR_MIXER_SCB_ADDR,
     1393                                                      rear_codec_out_scb,
     1394                                                      SCB_ON_PARENT_SUBLIST_SCB);
     1395        ins->rear_mix_scb = rear_mix_scb;
     1396        if (!rear_mix_scb) goto _fail_end;
     1397       
     1398        if (chip->nr_ac97_codecs == 2) {
     1399                /* create CODEC tasklet for rear Center/LFE output
     1400                   slot 6 and 9 on seconadry CODEC */
     1401                clfe_codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_CLFE",0x0030,0x0030,
     1402                                                                     CLFE_MIXER_SCB_ADDR,
     1403                                                                     CLFE_CODEC_SCB_ADDR,
     1404                                                                     rear_codec_out_scb,
     1405                                                                     SCB_ON_PARENT_NEXT_SCB);
     1406                if (!clfe_codec_out_scb) goto _fail_end;
     1407               
     1408               
     1409                /* create the rear PCM channel  mixer SCB */
     1410                ins->center_lfe_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"CLFEMixerSCB",
     1411                                                                         MIX_SAMPLE_BUF4,
     1412                                                                         CLFE_MIXER_SCB_ADDR,
     1413                                                                         clfe_codec_out_scb,
     1414                                                                         SCB_ON_PARENT_SUBLIST_SCB);
     1415                if (!ins->center_lfe_mix_scb) goto _fail_end;
     1416
     1417                /* enable slot 6 and 9 */
     1418                valid_slots |= ACOSV_SLV6 | ACOSV_SLV9;
     1419        } else {
     1420                clfe_codec_out_scb = rear_codec_out_scb;
     1421                ins->center_lfe_mix_scb = rear_mix_scb;
     1422        }
     1423
     1424        /* enable slots depending on CODEC configuration */
     1425        snd_cs46xx_pokeBA0(chip, BA0_ACOSV, valid_slots);
     1426
     1427        /* the magic snooper */
     1428        magic_snoop_scb = cs46xx_dsp_create_magic_snoop_scb (chip,"MagicSnoopSCB_I",OUTPUTSNOOP_SCB_ADDR,
     1429                                                             OUTPUT_SNOOP_BUFFER,
     1430                                                             codec_out_scb,
     1431                                                             clfe_codec_out_scb,
     1432                                                             SCB_ON_PARENT_NEXT_SCB);
     1433
     1434   
     1435        if (!magic_snoop_scb) goto _fail_end;
     1436        ins->ref_snoop_scb = magic_snoop_scb;
     1437
     1438        /* SP IO access */
     1439        if (!cs46xx_dsp_create_spio_write_scb(chip,"SPIOWriteSCB",SPIOWRITE_SCB_ADDR,
     1440                                              magic_snoop_scb,
     1441                                              SCB_ON_PARENT_NEXT_SCB))
     1442                goto _fail_end;
     1443
     1444        /* SPDIF input sampel rate converter */
     1445        src_task_scb = cs46xx_dsp_create_src_task_scb(chip,"SrcTaskSCB_SPDIFI",
     1446                                                      ins->spdif_in_sample_rate,
     1447                                                      SRC_OUTPUT_BUF1,
     1448                                                      SRC_DELAY_BUF1,SRCTASK_SCB_ADDR,
     1449                                                      master_mix_scb,
     1450                                                      SCB_ON_PARENT_SUBLIST_SCB,1);
     1451
     1452        if (!src_task_scb) goto _fail_end;
     1453        cs46xx_src_unlink(chip,src_task_scb);
     1454
     1455        /* NOTE: when we now how to detect the SPDIF input
     1456           sample rate we will use this SRC to adjust it */
     1457        ins->spdif_in_src = src_task_scb;
     1458
     1459        cs46xx_dsp_async_init(chip,timing_master_scb);
     1460        return 0;
     1461
     1462 _fail_end:
     1463        snd_printk(KERN_ERR "dsp_spos: failed to setup SCB's in DSP\n");
     1464        return -EINVAL;
     1465}
     1466
     1467static int cs46xx_dsp_async_init (struct snd_cs46xx *chip,
     1468                                  struct dsp_scb_descriptor * fg_entry)
     1469{
     1470        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     1471        struct dsp_symbol_entry * s16_async_codec_input_task;
     1472        struct dsp_symbol_entry * spdifo_task;
     1473        struct dsp_symbol_entry * spdifi_task;
     1474        struct dsp_scb_descriptor * spdifi_scb_desc, * spdifo_scb_desc, * async_codec_scb_desc;
     1475
     1476        s16_async_codec_input_task = cs46xx_dsp_lookup_symbol(chip, "S16_ASYNCCODECINPUTTASK", SYMBOL_CODE);
     1477        if (s16_async_codec_input_task == NULL) {
     1478                snd_printk(KERN_ERR "dsp_spos: symbol S16_ASYNCCODECINPUTTASK not found\n");
     1479                return -EIO;
     1480        }
     1481        spdifo_task = cs46xx_dsp_lookup_symbol(chip, "SPDIFOTASK", SYMBOL_CODE);
     1482        if (spdifo_task == NULL) {
     1483                snd_printk(KERN_ERR "dsp_spos: symbol SPDIFOTASK not found\n");
     1484                return -EIO;
     1485        }
     1486
     1487        spdifi_task = cs46xx_dsp_lookup_symbol(chip, "SPDIFITASK", SYMBOL_CODE);
     1488        if (spdifi_task == NULL) {
     1489                snd_printk(KERN_ERR "dsp_spos: symbol SPDIFITASK not found\n");
     1490                return -EIO;
     1491        }
     1492
     1493        {
     1494                /* 0xBC0 */
     1495                struct dsp_spdifoscb spdifo_scb = {
     1496                        /* 0 */ DSP_SPOS_UUUU,
     1497                        {
     1498                                /* 1 */ 0xb0,
     1499                                /* 2 */ 0,
     1500                                /* 3 */ 0,
     1501                                /* 4 */ 0,
     1502                        },
     1503                        /* NOTE: the SPDIF output task read samples in mono
     1504                           format, the AsynchFGTxSCB task writes to buffer
     1505                           in stereo format
     1506                        */
     1507                        /* 5 */ RSCONFIG_SAMPLE_16MONO + RSCONFIG_MODULO_256,
     1508                        /* 6 */ ( SPDIFO_IP_OUTPUT_BUFFER1 << 0x10 )  |  0xFFFC,
     1509                        /* 7 */ 0,0,
     1510                        /* 8 */ 0,
     1511                        /* 9 */ FG_TASK_HEADER_ADDR, NULL_SCB_ADDR,
     1512                        /* A */ spdifo_task->address,
     1513                        SPDIFO_SCB_INST + SPDIFOFIFOPointer,
     1514                        {
     1515                                /* B */ 0x0040, /*DSP_SPOS_UUUU,*/
     1516                                /* C */ 0x20ff, /*DSP_SPOS_UUUU,*/
     1517                        },
     1518                        /* D */ 0x804c,0,                                                         /* SPDIFOFIFOPointer:SPDIFOStatRegAddr; */
     1519                        /* E */ 0x0108,0x0001,                                    /* SPDIFOStMoFormat:SPDIFOFIFOBaseAddr; */
     1520                        /* F */ DSP_SPOS_UUUU                                     /* SPDIFOFree; */
     1521                };
     1522
     1523                /* 0xBB0 */
     1524                struct dsp_spdifiscb spdifi_scb = {
     1525                        /* 0 */ DSP_SPOS_UULO,DSP_SPOS_UUHI,
     1526                        /* 1 */ 0,
     1527                        /* 2 */ 0,
     1528                        /* 3 */ 1,4000,        /* SPDIFICountLimit SPDIFICount */
     1529                        /* 4 */ DSP_SPOS_UUUU, /* SPDIFIStatusData */
     1530                        /* 5 */ 0,DSP_SPOS_UUHI, /* StatusData, Free4 */
     1531                        /* 6 */ DSP_SPOS_UUUU,  /* Free3 */
     1532                        /* 7 */ DSP_SPOS_UU,DSP_SPOS_DC,  /* Free2 BitCount*/
     1533                        /* 8 */ DSP_SPOS_UUUU,  /* TempStatus */
     1534                        /* 9 */ SPDIFO_SCB_INST, NULL_SCB_ADDR,
     1535                        /* A */ spdifi_task->address,
     1536                        SPDIFI_SCB_INST + SPDIFIFIFOPointer,
     1537                        /* NOTE: The SPDIF input task write the sample in mono
     1538                           format from the HW FIFO, the AsynchFGRxSCB task  reads
     1539                           them in stereo
     1540                        */
     1541                        /* B */ RSCONFIG_SAMPLE_16MONO + RSCONFIG_MODULO_128,
     1542                        /* C */ (SPDIFI_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC,
     1543                        /* D */ 0x8048,0,
     1544                        /* E */ 0x01f0,0x0001,
     1545                        /* F */ DSP_SPOS_UUUU /* SPDIN_STATUS monitor */
     1546                };
     1547
     1548                /* 0xBA0 */
     1549                struct dsp_async_codec_input_scb async_codec_input_scb = {
     1550                        /* 0 */ DSP_SPOS_UUUU,
     1551                        /* 1 */ 0,
     1552                        /* 2 */ 0,
     1553                        /* 3 */ 1,4000,
     1554                        /* 4 */ 0x0118,0x0001,
     1555                        /* 5 */ RSCONFIG_SAMPLE_16MONO + RSCONFIG_MODULO_64,
     1556                        /* 6 */ (ASYNC_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC,
     1557                        /* 7 */ DSP_SPOS_UU,0x3,
     1558                        /* 8 */ DSP_SPOS_UUUU,
     1559                        /* 9 */ SPDIFI_SCB_INST,NULL_SCB_ADDR,
     1560                        /* A */ s16_async_codec_input_task->address,
     1561                        HFG_TREE_SCB + AsyncCIOFIFOPointer,
     1562             
     1563                        /* B */ RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64,
     1564                        /* C */ (ASYNC_IP_OUTPUT_BUFFER1 << 0x10),  /*(ASYNC_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC,*/
     1565     
    15531566#ifdef UseASER1Input
    1554             /* short AsyncCIFIFOPointer:AsyncCIStatRegAddr;
    1555              Init. 0000:8042: for ASER1
    1556              0000:8044: for ASER2 */
    1557             /* D */ 0x8042,0,
    1558 
    1559             /* short AsyncCIStMoFormat:AsyncCIFIFOBaseAddr;
    1560              Init 1 stero:8050 ASER1
    1561              Init 0  mono:8070 ASER2
    1562              Init 1 Stereo : 0100 ASER1 (Set by script) */
    1563             /* E */ 0x0100,0x0001,
    1564 
     1567                        /* short AsyncCIFIFOPointer:AsyncCIStatRegAddr;       
     1568                           Init. 0000:8042: for ASER1
     1569                           0000:8044: for ASER2 */
     1570                        /* D */ 0x8042,0,
     1571     
     1572                        /* short AsyncCIStMoFormat:AsyncCIFIFOBaseAddr;
     1573                           Init 1 stero:8050 ASER1
     1574                           Init 0  mono:8070 ASER2
     1575                           Init 1 Stereo : 0100 ASER1 (Set by script) */
     1576                        /* E */ 0x0100,0x0001,
     1577     
    15651578#endif
    1566 
     1579     
    15671580#ifdef UseASER2Input
    1568             /* short AsyncCIFIFOPointer:AsyncCIStatRegAddr;
    1569              Init. 0000:8042: for ASER1
    1570              0000:8044: for ASER2 */
    1571             /* D */ 0x8044,0,
    1572 
    1573             /* short AsyncCIStMoFormat:AsyncCIFIFOBaseAddr;
    1574              Init 1 stero:8050 ASER1
    1575              Init 0  mono:8070 ASER2
    1576              Init 1 Stereo : 0100 ASER1 (Set by script) */
    1577             /* E */ 0x0110,0x0001,
    1578 
     1581                        /* short AsyncCIFIFOPointer:AsyncCIStatRegAddr;
     1582                           Init. 0000:8042: for ASER1
     1583                           0000:8044: for ASER2 */
     1584                        /* D */ 0x8044,0,
     1585     
     1586                        /* short AsyncCIStMoFormat:AsyncCIFIFOBaseAddr;
     1587                           Init 1 stero:8050 ASER1
     1588                           Init 0  mono:8070 ASER2
     1589                           Init 1 Stereo : 0100 ASER1 (Set by script) */
     1590                        /* E */ 0x0110,0x0001,
     1591     
    15791592#endif
    1580 
    1581             /* short AsyncCIOutputBufModulo:AsyncCIFree;
    1582              AsyncCIOutputBufModulo: The modulo size for
    1583              the output buffer of this task */
    1584             /* F */ 0, /* DSP_SPOS_UUUU */
    1585         };
    1586 
    1587         spdifi_scb.entry_point = spdifi_task->address;
    1588         spdifo_scb.entry_point = spdifo_task->address;
    1589         async_codec_input_scb.io_entry_point = s16_async_codec_input_task->address;
    1590         spdifo_scb_desc = cs46xx_dsp_create_scb(chip,"SPDIFOSCB",(u32 *)&spdifo_scb,SPDIFO_SCB_INST);
    1591 
    1592         snd_assert(spdifo_scb_desc, return -EIO);
    1593         spdifi_scb_desc = cs46xx_dsp_create_scb(chip,"SPDIFISCB",(u32 *)&spdifi_scb,SPDIFI_SCB_INST);
    1594         snd_assert(spdifi_scb_desc, return -EIO);
    1595         async_codec_scb_desc = cs46xx_dsp_create_scb(chip,"AsynCodecInputSCB",(u32 *)&async_codec_input_scb, HFG_TREE_SCB);
    1596         snd_assert(async_codec_scb_desc, return -EIO);
    1597 
    1598         async_codec_scb_desc->parent_scb_ptr = NULL;
    1599         async_codec_scb_desc->next_scb_ptr = spdifi_scb_desc;
    1600         async_codec_scb_desc->sub_list_ptr = ins->the_null_scb;
    1601         async_codec_scb_desc->task_entry = s16_async_codec_input_task;
    1602 
    1603         spdifi_scb_desc->parent_scb_ptr = async_codec_scb_desc;
    1604         spdifi_scb_desc->next_scb_ptr = spdifo_scb_desc;
    1605         spdifi_scb_desc->sub_list_ptr = ins->the_null_scb;
    1606         spdifi_scb_desc->task_entry = spdifi_task;
    1607 
    1608         spdifo_scb_desc->parent_scb_ptr = spdifi_scb_desc;
    1609         spdifo_scb_desc->next_scb_ptr = fg_entry;
    1610         spdifo_scb_desc->sub_list_ptr = ins->the_null_scb;
    1611         spdifo_scb_desc->task_entry = spdifo_task;
    1612 
    1613         /* this one is faked, as the parnet of SPDIFO task
    1614          is the FG task tree */
    1615         fg_entry->parent_scb_ptr = spdifo_scb_desc;
    1616 
    1617         /* for proc fs */
    1618         cs46xx_dsp_proc_register_scb_desc (chip,spdifo_scb_desc);
    1619         cs46xx_dsp_proc_register_scb_desc (chip,spdifi_scb_desc);
    1620         cs46xx_dsp_proc_register_scb_desc (chip,async_codec_scb_desc);
    1621 
    1622         /* Async MASTER ENABLE, affects both SPDIF input and output */
    1623         snd_cs46xx_pokeBA0(chip, BA0_ASER_MASTER, 0x1 );
    1624     }
    1625 
    1626     return 0;
    1627 }
    1628 
    1629 
    1630 static void cs46xx_dsp_disable_spdif_hw (cs46xx_t *chip)
    1631 {
    1632     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    1633 
    1634     /* set SPDIF output FIFO slot */
    1635     snd_cs46xx_pokeBA0(chip, BA0_ASER_FADDR, 0);
    1636 
    1637     /* SPDIF output MASTER ENABLE */
    1638     cs46xx_poke_via_dsp (chip,SP_SPDOUT_CONTROL, 0);
    1639 
    1640     /* right and left validate bit */
    1641     /*cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, ins->spdif_csuv_default);*/
    1642     cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, 0x0);
    1643 
    1644     /* clear fifo pointer */
    1645     cs46xx_poke_via_dsp (chip,SP_SPDIN_FIFOPTR, 0x0);
    1646 
    1647     /* monitor state */
    1648     ins->spdif_status_out &= ~DSP_SPDIF_STATUS_HW_ENABLED;
    1649 }
    1650 
    1651 int cs46xx_dsp_enable_spdif_hw (cs46xx_t *chip)
    1652 {
    1653     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    1654 
    1655     /* if hw-ctrl already enabled, turn off to reset logic ... */
    1656     cs46xx_dsp_disable_spdif_hw (chip);
    1657     udelay(50);
    1658 
    1659     /* set SPDIF output FIFO slot */
    1660     snd_cs46xx_pokeBA0(chip, BA0_ASER_FADDR, ( 0x8000 | ((SP_SPDOUT_FIFO >> 4) << 4) ));
    1661 
    1662     /* SPDIF output MASTER ENABLE */
    1663     cs46xx_poke_via_dsp (chip,SP_SPDOUT_CONTROL, 0x80000000);
    1664 
    1665     /* right and left validate bit */
    1666     cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, ins->spdif_csuv_default);
    1667 
    1668     /* monitor state */
    1669     ins->spdif_status_out |= DSP_SPDIF_STATUS_HW_ENABLED;
    1670 
    1671     return 0;
    1672 }
    1673 
    1674 int cs46xx_dsp_enable_spdif_in (cs46xx_t *chip)
    1675 {
    1676     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    1677 
    1678     /* turn on amplifier */
    1679     chip->active_ctrl(chip, 1);
    1680     chip->amplifier_ctrl(chip, 1);
    1681 
    1682     snd_assert (ins->asynch_rx_scb == NULL,return -EINVAL);
    1683     snd_assert (ins->spdif_in_src != NULL,return -EINVAL);
    1684 
    1685     down(&chip->spos_mutex);
    1686 
    1687     if ( ! (ins->spdif_status_out & DSP_SPDIF_STATUS_INPUT_CTRL_ENABLED) ) {
    1688         /* time countdown enable */
    1689         cs46xx_poke_via_dsp (chip,SP_ASER_COUNTDOWN, 0x80000005);
    1690         /* NOTE: 80000005 value is just magic. With all values
    1691          that I've tested this one seem to give the best result.
    1692          Got no explication why. (Benny) */
    1693 
    1694         /* SPDIF input MASTER ENABLE */
    1695         cs46xx_poke_via_dsp (chip,SP_SPDIN_CONTROL, 0x800003ff);
    1696 
    1697         ins->spdif_status_out |= DSP_SPDIF_STATUS_INPUT_CTRL_ENABLED;
    1698     }
    1699 
    1700     /* create and start the asynchronous receiver SCB */
    1701     ins->asynch_rx_scb = cs46xx_dsp_create_asynch_fg_rx_scb(chip,"AsynchFGRxSCB",
    1702                                                             ASYNCRX_SCB_ADDR,
    1703                                                             SPDIFI_SCB_INST,
    1704                                                             SPDIFI_IP_OUTPUT_BUFFER1,
    1705                                                             ins->spdif_in_src,
    1706                                                             SCB_ON_PARENT_SUBLIST_SCB);
    1707 
    1708     spin_lock_irq(&chip->reg_lock);
    1709 
    1710     /* reset SPDIF input sample buffer pointer */
    1711     /*snd_cs46xx_poke (chip, (SPDIFI_SCB_INST + 0x0c) << 2,
    1712      (SPDIFI_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC);*/
    1713 
    1714     /* reset FIFO ptr */
    1715     /*cs46xx_poke_via_dsp (chip,SP_SPDIN_FIFOPTR, 0x0);*/
    1716     cs46xx_src_link(chip,ins->spdif_in_src);
    1717 
    1718     /* unmute SRC volume */
    1719     cs46xx_dsp_scb_set_volume (chip,ins->spdif_in_src,0x7fff,0x7fff);
    1720 
    1721     spin_unlock_irq(&chip->reg_lock);
    1722 
    1723     /* set SPDIF input sample rate and unmute
    1724      NOTE: only 48khz support for SPDIF input this time */
    1725     /* cs46xx_dsp_set_src_sample_rate(chip,ins->spdif_in_src,48000); */
    1726 
    1727     /* monitor state */
    1728     ins->spdif_status_in = 1;
    1729     up(&chip->spos_mutex);
    1730 
    1731     return 0;
    1732 }
    1733 
    1734 int cs46xx_dsp_disable_spdif_in (cs46xx_t *chip)
    1735 {
    1736     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    1737 
    1738     snd_assert (ins->asynch_rx_scb != NULL, return -EINVAL);
    1739     snd_assert (ins->spdif_in_src != NULL,return -EINVAL);
    1740 
    1741     down(&chip->spos_mutex);
    1742 
    1743     /* Remove the asynchronous receiver SCB */
    1744     cs46xx_dsp_remove_scb (chip,ins->asynch_rx_scb);
    1745     ins->asynch_rx_scb = NULL;
    1746 
    1747     cs46xx_src_unlink(chip,ins->spdif_in_src);
    1748 
    1749     /* monitor state */
    1750     ins->spdif_status_in = 0;
    1751     up(&chip->spos_mutex);
    1752 
    1753     /* restore amplifier */
    1754     chip->active_ctrl(chip, -1);
    1755     chip->amplifier_ctrl(chip, -1);
    1756 
    1757     return 0;
    1758 }
    1759 
    1760 int cs46xx_dsp_enable_pcm_capture (cs46xx_t *chip)
    1761 {
    1762     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    1763 
    1764     snd_assert (ins->pcm_input == NULL,return -EINVAL);
    1765     snd_assert (ins->ref_snoop_scb != NULL,return -EINVAL);
    1766 
    1767     down(&chip->spos_mutex);
    1768     ins->pcm_input = cs46xx_add_record_source(chip,ins->ref_snoop_scb,PCMSERIALIN_PCM_SCB_ADDR,
    1769                                               "PCMSerialInput_Wave");
    1770     up(&chip->spos_mutex);
    1771 
    1772     return 0;
    1773 }
    1774 
    1775 int cs46xx_dsp_disable_pcm_capture (cs46xx_t *chip)
    1776 {
    1777     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    1778 
    1779     snd_assert (ins->pcm_input != NULL,return -EINVAL);
    1780 
    1781     down(&chip->spos_mutex);
    1782     cs46xx_dsp_remove_scb (chip,ins->pcm_input);
    1783     ins->pcm_input = NULL;
    1784     up(&chip->spos_mutex);
    1785 
    1786     return 0;
    1787 }
    1788 
    1789 int cs46xx_dsp_enable_adc_capture (cs46xx_t *chip)
    1790 {
    1791     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    1792 
    1793     snd_assert (ins->adc_input == NULL,return -EINVAL);
    1794     snd_assert (ins->codec_in_scb != NULL,return -EINVAL);
    1795 
    1796     down(&chip->spos_mutex);
    1797     ins->adc_input = cs46xx_add_record_source(chip,ins->codec_in_scb,PCMSERIALIN_SCB_ADDR,
    1798                                               "PCMSerialInput_ADC");
    1799     up(&chip->spos_mutex);
    1800 
    1801     return 0;
    1802 }
    1803 
    1804 int cs46xx_dsp_disable_adc_capture (cs46xx_t *chip)
    1805 {
    1806     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    1807 
    1808     snd_assert (ins->adc_input != NULL,return -EINVAL);
    1809 
    1810     down(&chip->spos_mutex);
    1811     cs46xx_dsp_remove_scb (chip,ins->adc_input);
    1812     ins->adc_input = NULL;
    1813     up(&chip->spos_mutex);
    1814 
    1815     return 0;
    1816 }
    1817 
    1818 int cs46xx_poke_via_dsp (cs46xx_t *chip,u32 address,u32 data)
    1819 {
    1820     u32 temp;
    1821     int  i;
    1822 
    1823     /* santiy check the parameters.  (These numbers are not 100% correct.  They are
    1824      a rough guess from looking at the controller spec.) */
    1825     if (address < 0x8000 || address >= 0x9000)
    1826         return -EINVAL;
    1827 
    1828     /* initialize the SP_IO_WRITE SCB with the data. */
    1829     temp = ( address << 16 ) | ( address & 0x0000FFFF);   /* offset 0 <-- address2 : address1 */
    1830 
    1831     snd_cs46xx_poke(chip,( SPIOWRITE_SCB_ADDR      << 2), temp);
    1832     snd_cs46xx_poke(chip,((SPIOWRITE_SCB_ADDR + 1) << 2), data); /* offset 1 <-- data1 */
    1833     snd_cs46xx_poke(chip,((SPIOWRITE_SCB_ADDR + 2) << 2), data); /* offset 1 <-- data2 */
    1834 
    1835     /* Poke this location to tell the task to start */
    1836     snd_cs46xx_poke(chip,((SPIOWRITE_SCB_ADDR + 6) << 2), SPIOWRITE_SCB_ADDR << 0x10);
    1837 
    1838     /* Verify that the task ran */
    1839     for (i=0; i<25; i++) {
    1840         udelay(125);
    1841 
    1842         temp =  snd_cs46xx_peek(chip,((SPIOWRITE_SCB_ADDR + 6) << 2));
    1843         if (temp == 0x00000000)
    1844             break;
    1845     }
    1846 
    1847     if (i == 25) {
    1848         snd_printk(KERN_ERR "dsp_spos: SPIOWriteTask not responding\n");
    1849         return -EBUSY;
    1850     }
    1851 
    1852     return 0;
    1853 }
    1854 
    1855 int cs46xx_dsp_set_dac_volume (cs46xx_t * chip,u16 left,u16 right)
    1856 {
    1857     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    1858     dsp_scb_descriptor_t * scb;
    1859 
    1860     down(&chip->spos_mutex);
    1861 
    1862     /* main output */
    1863     scb = ins->master_mix_scb->sub_list_ptr;
    1864     while (scb != ins->the_null_scb) {
    1865         cs46xx_dsp_scb_set_volume (chip,scb,left,right);
    1866         scb = scb->next_scb_ptr;
    1867     }
    1868 
    1869     /* rear output */
    1870     scb = ins->rear_mix_scb->sub_list_ptr;
    1871     while (scb != ins->the_null_scb) {
    1872         cs46xx_dsp_scb_set_volume (chip,scb,left,right);
    1873         scb = scb->next_scb_ptr;
    1874     }
    1875 
    1876     ins->dac_volume_left = left;
    1877     ins->dac_volume_right = right;
    1878 
    1879     up(&chip->spos_mutex);
    1880 
    1881     return 0;
    1882 }
    1883 
    1884 int cs46xx_dsp_set_iec958_volume (cs46xx_t * chip,u16 left,u16 right) {
    1885     dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    1886 
    1887     down(&chip->spos_mutex);
    1888 
    1889     if (ins->asynch_rx_scb != NULL)
    1890         cs46xx_dsp_scb_set_volume (chip,ins->asynch_rx_scb,
    1891                                    left,right);
    1892 
    1893     ins->spdif_input_volume_left = left;
    1894     ins->spdif_input_volume_right = right;
    1895 
    1896     up(&chip->spos_mutex);
    1897 
    1898     return 0;
    1899 }
     1593     
     1594                        /* short AsyncCIOutputBufModulo:AsyncCIFree;
     1595                           AsyncCIOutputBufModulo: The modulo size for   
     1596                           the output buffer of this task */
     1597                        /* F */ 0, /* DSP_SPOS_UUUU */
     1598                };
     1599
     1600                spdifo_scb_desc = cs46xx_dsp_create_scb(chip,"SPDIFOSCB",(u32 *)&spdifo_scb,SPDIFO_SCB_INST);
     1601
     1602                snd_assert(spdifo_scb_desc, return -EIO);
     1603                spdifi_scb_desc = cs46xx_dsp_create_scb(chip,"SPDIFISCB",(u32 *)&spdifi_scb,SPDIFI_SCB_INST);
     1604                snd_assert(spdifi_scb_desc, return -EIO);
     1605                async_codec_scb_desc = cs46xx_dsp_create_scb(chip,"AsynCodecInputSCB",(u32 *)&async_codec_input_scb, HFG_TREE_SCB);
     1606                snd_assert(async_codec_scb_desc, return -EIO);
     1607
     1608                async_codec_scb_desc->parent_scb_ptr = NULL;
     1609                async_codec_scb_desc->next_scb_ptr = spdifi_scb_desc;
     1610                async_codec_scb_desc->sub_list_ptr = ins->the_null_scb;
     1611                async_codec_scb_desc->task_entry = s16_async_codec_input_task;
     1612
     1613                spdifi_scb_desc->parent_scb_ptr = async_codec_scb_desc;
     1614                spdifi_scb_desc->next_scb_ptr = spdifo_scb_desc;
     1615                spdifi_scb_desc->sub_list_ptr = ins->the_null_scb;
     1616                spdifi_scb_desc->task_entry = spdifi_task;
     1617
     1618                spdifo_scb_desc->parent_scb_ptr = spdifi_scb_desc;
     1619                spdifo_scb_desc->next_scb_ptr = fg_entry;
     1620                spdifo_scb_desc->sub_list_ptr = ins->the_null_scb;
     1621                spdifo_scb_desc->task_entry = spdifo_task;
     1622
     1623                /* this one is faked, as the parnet of SPDIFO task
     1624                   is the FG task tree */
     1625                fg_entry->parent_scb_ptr = spdifo_scb_desc;
     1626
     1627                /* for proc fs */
     1628                cs46xx_dsp_proc_register_scb_desc (chip,spdifo_scb_desc);
     1629                cs46xx_dsp_proc_register_scb_desc (chip,spdifi_scb_desc);
     1630                cs46xx_dsp_proc_register_scb_desc (chip,async_codec_scb_desc);
     1631
     1632                /* Async MASTER ENABLE, affects both SPDIF input and output */
     1633                snd_cs46xx_pokeBA0(chip, BA0_ASER_MASTER, 0x1 );
     1634        }
     1635
     1636        return 0;
     1637}
     1638
     1639
     1640static void cs46xx_dsp_disable_spdif_hw (struct snd_cs46xx *chip)
     1641{
     1642        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     1643
     1644        /* set SPDIF output FIFO slot */
     1645        snd_cs46xx_pokeBA0(chip, BA0_ASER_FADDR, 0);
     1646
     1647        /* SPDIF output MASTER ENABLE */
     1648        cs46xx_poke_via_dsp (chip,SP_SPDOUT_CONTROL, 0);
     1649
     1650        /* right and left validate bit */
     1651        /*cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, ins->spdif_csuv_default);*/
     1652        cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, 0x0);
     1653
     1654        /* clear fifo pointer */
     1655        cs46xx_poke_via_dsp (chip,SP_SPDIN_FIFOPTR, 0x0);
     1656
     1657        /* monitor state */
     1658        ins->spdif_status_out &= ~DSP_SPDIF_STATUS_HW_ENABLED;
     1659}
     1660
     1661int cs46xx_dsp_enable_spdif_hw (struct snd_cs46xx *chip)
     1662{
     1663        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     1664
     1665        /* if hw-ctrl already enabled, turn off to reset logic ... */
     1666        cs46xx_dsp_disable_spdif_hw (chip);
     1667        udelay(50);
     1668
     1669        /* set SPDIF output FIFO slot */
     1670        snd_cs46xx_pokeBA0(chip, BA0_ASER_FADDR, ( 0x8000 | ((SP_SPDOUT_FIFO >> 4) << 4) ));
     1671
     1672        /* SPDIF output MASTER ENABLE */
     1673        cs46xx_poke_via_dsp (chip,SP_SPDOUT_CONTROL, 0x80000000);
     1674
     1675        /* right and left validate bit */
     1676        cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, ins->spdif_csuv_default);
     1677
     1678        /* monitor state */
     1679        ins->spdif_status_out |= DSP_SPDIF_STATUS_HW_ENABLED;
     1680
     1681        return 0;
     1682}
     1683
     1684int cs46xx_dsp_enable_spdif_in (struct snd_cs46xx *chip)
     1685{
     1686        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     1687
     1688        /* turn on amplifier */
     1689        chip->active_ctrl(chip, 1);
     1690        chip->amplifier_ctrl(chip, 1);
     1691
     1692        snd_assert (ins->asynch_rx_scb == NULL,return -EINVAL);
     1693        snd_assert (ins->spdif_in_src != NULL,return -EINVAL);
     1694
     1695        down(&chip->spos_mutex);
     1696
     1697        if ( ! (ins->spdif_status_out & DSP_SPDIF_STATUS_INPUT_CTRL_ENABLED) ) {
     1698                /* time countdown enable */
     1699                cs46xx_poke_via_dsp (chip,SP_ASER_COUNTDOWN, 0x80000005);
     1700                /* NOTE: 80000005 value is just magic. With all values
     1701                   that I've tested this one seem to give the best result.
     1702                   Got no explication why. (Benny) */
     1703
     1704                /* SPDIF input MASTER ENABLE */
     1705                cs46xx_poke_via_dsp (chip,SP_SPDIN_CONTROL, 0x800003ff);
     1706
     1707                ins->spdif_status_out |= DSP_SPDIF_STATUS_INPUT_CTRL_ENABLED;
     1708        }
     1709
     1710        /* create and start the asynchronous receiver SCB */
     1711        ins->asynch_rx_scb = cs46xx_dsp_create_asynch_fg_rx_scb(chip,"AsynchFGRxSCB",
     1712                                                                ASYNCRX_SCB_ADDR,
     1713                                                                SPDIFI_SCB_INST,
     1714                                                                SPDIFI_IP_OUTPUT_BUFFER1,
     1715                                                                ins->spdif_in_src,
     1716                                                                SCB_ON_PARENT_SUBLIST_SCB);
     1717
     1718        spin_lock_irq(&chip->reg_lock);
     1719
     1720        /* reset SPDIF input sample buffer pointer */
     1721        /*snd_cs46xx_poke (chip, (SPDIFI_SCB_INST + 0x0c) << 2,
     1722          (SPDIFI_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC);*/
     1723
     1724        /* reset FIFO ptr */
     1725        /*cs46xx_poke_via_dsp (chip,SP_SPDIN_FIFOPTR, 0x0);*/
     1726        cs46xx_src_link(chip,ins->spdif_in_src);
     1727
     1728        /* unmute SRC volume */
     1729        cs46xx_dsp_scb_set_volume (chip,ins->spdif_in_src,0x7fff,0x7fff);
     1730
     1731        spin_unlock_irq(&chip->reg_lock);
     1732
     1733        /* set SPDIF input sample rate and unmute
     1734           NOTE: only 48khz support for SPDIF input this time */
     1735        /* cs46xx_dsp_set_src_sample_rate(chip,ins->spdif_in_src,48000); */
     1736
     1737        /* monitor state */
     1738        ins->spdif_status_in = 1;
     1739        up(&chip->spos_mutex);
     1740
     1741        return 0;
     1742}
     1743
     1744int cs46xx_dsp_disable_spdif_in (struct snd_cs46xx *chip)
     1745{
     1746        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     1747
     1748        snd_assert (ins->asynch_rx_scb != NULL, return -EINVAL);
     1749        snd_assert (ins->spdif_in_src != NULL,return -EINVAL); 
     1750
     1751        down(&chip->spos_mutex);
     1752
     1753        /* Remove the asynchronous receiver SCB */
     1754        cs46xx_dsp_remove_scb (chip,ins->asynch_rx_scb);
     1755        ins->asynch_rx_scb = NULL;
     1756
     1757        cs46xx_src_unlink(chip,ins->spdif_in_src);
     1758
     1759        /* monitor state */
     1760        ins->spdif_status_in = 0;
     1761        up(&chip->spos_mutex);
     1762
     1763        /* restore amplifier */
     1764        chip->active_ctrl(chip, -1);
     1765        chip->amplifier_ctrl(chip, -1);
     1766
     1767        return 0;
     1768}
     1769
     1770int cs46xx_dsp_enable_pcm_capture (struct snd_cs46xx *chip)
     1771{
     1772        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     1773
     1774        snd_assert (ins->pcm_input == NULL,return -EINVAL);
     1775        snd_assert (ins->ref_snoop_scb != NULL,return -EINVAL);
     1776
     1777        down(&chip->spos_mutex);
     1778        ins->pcm_input = cs46xx_add_record_source(chip,ins->ref_snoop_scb,PCMSERIALIN_PCM_SCB_ADDR,
     1779                                                  "PCMSerialInput_Wave");
     1780        up(&chip->spos_mutex);
     1781
     1782        return 0;
     1783}
     1784
     1785int cs46xx_dsp_disable_pcm_capture (struct snd_cs46xx *chip)
     1786{
     1787        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     1788
     1789        snd_assert (ins->pcm_input != NULL,return -EINVAL);
     1790
     1791        down(&chip->spos_mutex);
     1792        cs46xx_dsp_remove_scb (chip,ins->pcm_input);
     1793        ins->pcm_input = NULL;
     1794        up(&chip->spos_mutex);
     1795
     1796        return 0;
     1797}
     1798
     1799int cs46xx_dsp_enable_adc_capture (struct snd_cs46xx *chip)
     1800{
     1801        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     1802
     1803        snd_assert (ins->adc_input == NULL,return -EINVAL);
     1804        snd_assert (ins->codec_in_scb != NULL,return -EINVAL);
     1805
     1806        down(&chip->spos_mutex);
     1807        ins->adc_input = cs46xx_add_record_source(chip,ins->codec_in_scb,PCMSERIALIN_SCB_ADDR,
     1808                                                  "PCMSerialInput_ADC");
     1809        up(&chip->spos_mutex);
     1810
     1811        return 0;
     1812}
     1813
     1814int cs46xx_dsp_disable_adc_capture (struct snd_cs46xx *chip)
     1815{
     1816        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     1817
     1818        snd_assert (ins->adc_input != NULL,return -EINVAL);
     1819
     1820        down(&chip->spos_mutex);
     1821        cs46xx_dsp_remove_scb (chip,ins->adc_input);
     1822        ins->adc_input = NULL;
     1823        up(&chip->spos_mutex);
     1824
     1825        return 0;
     1826}
     1827
     1828int cs46xx_poke_via_dsp (struct snd_cs46xx *chip, u32 address, u32 data)
     1829{
     1830        u32 temp;
     1831        int  i;
     1832
     1833        /* santiy check the parameters.  (These numbers are not 100% correct.  They are
     1834           a rough guess from looking at the controller spec.) */
     1835        if (address < 0x8000 || address >= 0x9000)
     1836                return -EINVAL;
     1837       
     1838        /* initialize the SP_IO_WRITE SCB with the data. */
     1839        temp = ( address << 16 ) | ( address & 0x0000FFFF);   /* offset 0 <-- address2 : address1 */
     1840
     1841        snd_cs46xx_poke(chip,( SPIOWRITE_SCB_ADDR      << 2), temp);
     1842        snd_cs46xx_poke(chip,((SPIOWRITE_SCB_ADDR + 1) << 2), data); /* offset 1 <-- data1 */
     1843        snd_cs46xx_poke(chip,((SPIOWRITE_SCB_ADDR + 2) << 2), data); /* offset 1 <-- data2 */
     1844   
     1845        /* Poke this location to tell the task to start */
     1846        snd_cs46xx_poke(chip,((SPIOWRITE_SCB_ADDR + 6) << 2), SPIOWRITE_SCB_ADDR << 0x10);
     1847
     1848        /* Verify that the task ran */
     1849        for (i=0; i<25; i++) {
     1850                udelay(125);
     1851
     1852                temp =  snd_cs46xx_peek(chip,((SPIOWRITE_SCB_ADDR + 6) << 2));
     1853                if (temp == 0x00000000)
     1854                        break;
     1855        }
     1856
     1857        if (i == 25) {
     1858                snd_printk(KERN_ERR "dsp_spos: SPIOWriteTask not responding\n");
     1859                return -EBUSY;
     1860        }
     1861
     1862        return 0;
     1863}
     1864
     1865int cs46xx_dsp_set_dac_volume (struct snd_cs46xx * chip, u16 left, u16 right)
     1866{
     1867        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     1868        struct dsp_scb_descriptor * scb;
     1869
     1870        down(&chip->spos_mutex);
     1871       
     1872        /* main output */
     1873        scb = ins->master_mix_scb->sub_list_ptr;
     1874        while (scb != ins->the_null_scb) {
     1875                cs46xx_dsp_scb_set_volume (chip,scb,left,right);
     1876                scb = scb->next_scb_ptr;
     1877        }
     1878
     1879        /* rear output */
     1880        scb = ins->rear_mix_scb->sub_list_ptr;
     1881        while (scb != ins->the_null_scb) {
     1882                cs46xx_dsp_scb_set_volume (chip,scb,left,right);
     1883                scb = scb->next_scb_ptr;
     1884        }
     1885
     1886        ins->dac_volume_left = left;
     1887        ins->dac_volume_right = right;
     1888
     1889        up(&chip->spos_mutex);
     1890
     1891        return 0;
     1892}
     1893
     1894int cs46xx_dsp_set_iec958_volume (struct snd_cs46xx * chip, u16 left, u16 right)
     1895{
     1896        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     1897
     1898        down(&chip->spos_mutex);
     1899
     1900        if (ins->asynch_rx_scb != NULL)
     1901                cs46xx_dsp_scb_set_volume (chip,ins->asynch_rx_scb,
     1902                                           left,right);
     1903
     1904        ins->spdif_input_volume_left = left;
     1905        ins->spdif_input_volume_right = right;
     1906
     1907        up(&chip->spos_mutex);
     1908
     1909        return 0;
     1910}
  • GPL/trunk/alsa-kernel/pci/cs46xx/dsp_spos.h

    r33 r34  
    4444   needs to be reallocated when load
    4545   code into DSP */
    46 typedef enum {
     46enum wide_opcode {
    4747        WIDE_FOR_BEGIN_LOOP = 0x20,
    4848        WIDE_FOR_BEGIN_LOOP2,
     
    5959        WIDE_TBEQ_NCOND_GOTOI_ADDR,
    6060        WIDE_TBEQ_NCOND_CALL1_ADDR,
    61 } wide_opcode_t;
     61};
    6262
    6363/* SAMPLE segment */
     
    187187#define SP_SPDOUT_CSUV    0x808E
    188188
    189 static inline u8 _wrap_all_bits (u8 val) {
     189static inline u8 _wrap_all_bits (u8 val)
     190{
    190191        u8 wrapped;
    191192       
     
    202203
    203204        return wrapped;
    204 
    205205}
    206206
    207 
    208 static inline void cs46xx_dsp_spos_update_scb (cs46xx_t * chip,dsp_scb_descriptor_t * scb)
     207static inline void cs46xx_dsp_spos_update_scb (struct snd_cs46xx * chip,
     208                                               struct dsp_scb_descriptor * scb)
    209209{
    210210        /* update nextSCB and subListPtr in SCB */
     
    215215}
    216216
    217 static inline void cs46xx_dsp_scb_set_volume (cs46xx_t * chip,dsp_scb_descriptor_t * scb,
    218                                               u16 left,u16 right) {
     217static inline void cs46xx_dsp_scb_set_volume (struct snd_cs46xx * chip,
     218                                              struct dsp_scb_descriptor * scb,
     219                                              u16 left, u16 right)
     220{
    219221        unsigned int val = ((0xffff - left) << 16 | (0xffff - right));
    220222
  • GPL/trunk/alsa-kernel/pci/cs46xx/dsp_spos_scb_lib.c

    r33 r34  
    3737#include "dsp_spos.h"
    3838
    39 typedef struct _proc_scb_info_t {
    40         dsp_scb_descriptor_t * scb_desc;
    41         cs46xx_t *chip;
    42 } proc_scb_info_t;
    43 
    44 static void remove_symbol (cs46xx_t * chip,symbol_entry_t * symbol)
    45 {
    46         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
     39struct proc_scb_info {
     40        struct dsp_scb_descriptor * scb_desc;
     41        struct snd_cs46xx *chip;
     42};
     43
     44static void remove_symbol (struct snd_cs46xx * chip, struct dsp_symbol_entry * symbol)
     45{
     46        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
    4747        int symbol_index = (int)(symbol - ins->symbol_table.symbols);
    4848
     
    6565}
    6666
    67 static void cs46xx_dsp_proc_scb_info_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
    68 {
    69         proc_scb_info_t * scb_info  = (proc_scb_info_t *)entry->private_data;
    70         dsp_scb_descriptor_t * scb = scb_info->scb_desc;
    71         dsp_spos_instance_t * ins;
    72         cs46xx_t *chip = scb_info->chip;
     67static void cs46xx_dsp_proc_scb_info_read (struct snd_info_entry *entry,
     68                                           struct snd_info_buffer *buffer)
     69{
     70        struct proc_scb_info * scb_info  = entry->private_data;
     71        struct dsp_scb_descriptor * scb = scb_info->scb_desc;
     72        struct dsp_spos_instance * ins;
     73        struct snd_cs46xx *chip = scb_info->chip;
    7374        int j,col;
    74         unsigned long dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
     75        void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
    7576
    7677        ins = chip->dsp_spos_instance;
     
    107108}
    108109
    109 static void _dsp_unlink_scb (cs46xx_t *chip,dsp_scb_descriptor_t * scb)
    110 {
    111         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
     110static void _dsp_unlink_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor * scb)
     111{
     112        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
    112113        unsigned long flags;
    113114
     
    161162}
    162163
    163 static void _dsp_clear_sample_buffer (cs46xx_t *chip, u32 sample_buffer_addr, int dword_count)
    164 {
    165         unsigned long dst = chip->region.idx[2].remap_addr + sample_buffer_addr;
     164static void _dsp_clear_sample_buffer (struct snd_cs46xx *chip, u32 sample_buffer_addr,
     165                                      int dword_count)
     166{
     167        void __iomem *dst = chip->region.idx[2].remap_addr + sample_buffer_addr;
    166168        int i;
    167169 
     
    172174}
    173175
    174 void cs46xx_dsp_remove_scb (cs46xx_t *chip, dsp_scb_descriptor_t * scb)
    175 {
    176         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
     176void cs46xx_dsp_remove_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor * scb)
     177{
     178        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
    177179
    178180        /* check integrety */
     
    219221
    220222
    221 void cs46xx_dsp_proc_free_scb_desc (dsp_scb_descriptor_t * scb)
     223void cs46xx_dsp_proc_free_scb_desc (struct dsp_scb_descriptor * scb)
    222224{
    223225        if (scb->proc_info) {
    224                 proc_scb_info_t * scb_info  = (proc_scb_info_t *)scb->proc_info->private_data;
     226                struct proc_scb_info * scb_info = scb->proc_info->private_data;
    225227
    226228                snd_printdd("cs46xx_dsp_proc_free_scb_desc: freeing %s\n",scb->scb_name);
     
    234236}
    235237
    236 void cs46xx_dsp_proc_register_scb_desc (cs46xx_t *chip,dsp_scb_descriptor_t * scb)
    237 {
    238         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    239         snd_info_entry_t * entry;
    240         proc_scb_info_t * scb_info;
     238void cs46xx_dsp_proc_register_scb_desc (struct snd_cs46xx *chip,
     239                                        struct dsp_scb_descriptor * scb)
     240{
     241        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     242        struct snd_info_entry * entry;
     243        struct proc_scb_info * scb_info;
    241244
    242245        /* register to proc */
     
    246249                if ((entry = snd_info_create_card_entry(ins->snd_card, scb->scb_name,
    247250                                                        ins->proc_dsp_dir)) != NULL) {
    248                     scb_info = kmalloc(sizeof(proc_scb_info_t), GFP_KERNEL);
    249                     if (!scb_info) {
    250                         snd_info_free_entry(entry);
    251                         entry = NULL;
    252                         goto out;
    253                     }
    254          
     251                        scb_info = kmalloc(sizeof(struct proc_scb_info), GFP_KERNEL);
     252                        if (!scb_info) {
     253                                snd_info_free_entry(entry);
     254                                entry = NULL;
     255                                goto out;
     256                        }
     257
    255258                        scb_info->chip = chip;
    256259                        scb_info->scb_desc = scb;
     
    268271                                entry = NULL;
    269272                        }
    270                 }
    271             out:
     273                }
     274out:
    272275                scb->proc_info = entry;
    273276        }
    274277}
    275278
    276 static dsp_scb_descriptor_t *
    277 _dsp_create_generic_scb (cs46xx_t *chip,char * name, u32 * scb_data,u32 dest,
    278                          symbol_entry_t * task_entry,
    279                          dsp_scb_descriptor_t * parent_scb,
     279static struct dsp_scb_descriptor *
     280_dsp_create_generic_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32 dest,
     281                         struct dsp_symbol_entry * task_entry,
     282                         struct dsp_scb_descriptor * parent_scb,
    280283                         int scb_child_type)
    281284{
    282         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    283         dsp_scb_descriptor_t * scb;
     285        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     286        struct dsp_scb_descriptor * scb;
    284287 
    285288        unsigned long flags;
     
    343346}
    344347
    345 dsp_scb_descriptor_t *
    346 cs46xx_dsp_create_generic_scb (cs46xx_t *chip,char * name, u32 * scb_data,u32 dest,
    347                               char * task_entry_name,
    348                                dsp_scb_descriptor_t * parent_scb,
     348static struct dsp_scb_descriptor *
     349cs46xx_dsp_create_generic_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data,
     350                               u32 dest, char * task_entry_name,
     351                               struct dsp_scb_descriptor * parent_scb,
    349352                               int scb_child_type)
    350353{
    351         symbol_entry_t * task_entry;
     354        struct dsp_symbol_entry * task_entry;
    352355
    353356        task_entry = cs46xx_dsp_lookup_symbol (chip,task_entry_name,
     
    363366}
    364367
    365 dsp_scb_descriptor_t *
    366 cs46xx_dsp_create_timing_master_scb (cs46xx_t *chip)
    367 {
    368         dsp_scb_descriptor_t * scb;
    369  
    370         timing_master_scb_t timing_master_scb = {
     368struct dsp_scb_descriptor *
     369cs46xx_dsp_create_timing_master_scb (struct snd_cs46xx *chip)
     370{
     371        struct dsp_scb_descriptor * scb;
     372 
     373        struct dsp_timing_master_scb timing_master_scb = {
    371374                { 0,
    372375                  0,
     
    397400
    398401
    399 dsp_scb_descriptor_t *
    400 cs46xx_dsp_create_codec_out_scb(cs46xx_t * chip,char * codec_name,
    401                                 u16 channel_disp,u16 fifo_addr,
    402                                 u16 child_scb_addr,
    403                                 u32 dest,dsp_scb_descriptor_t * parent_scb,
     402struct dsp_scb_descriptor *
     403cs46xx_dsp_create_codec_out_scb(struct snd_cs46xx * chip, char * codec_name,
     404                                u16 channel_disp, u16 fifo_addr, u16 child_scb_addr,
     405                                u32 dest, struct dsp_scb_descriptor * parent_scb,
    404406                                int scb_child_type)
    405407{
    406     dsp_scb_descriptor_t * scb;
    407 
    408         codec_output_scb_t codec_out_scb = {
     408        struct dsp_scb_descriptor * scb;
     409 
     410        struct dsp_codec_output_scb codec_out_scb = {
    409411                { 0,
    410412                  0,
     
    423425                0,                      /* COstrmRsConfig */
    424426                0,                      /* COstrmBufPtr */
    425                 /*channel_disp*/0,
    426                 /*fifo_addr*/0, /* leftChanBaseIOaddr:rightChanIOdisp */
     427                channel_disp,fifo_addr, /* leftChanBaseIOaddr:rightChanIOdisp */
    427428                0x0000,0x0080,          /* (!AC97!) COexpVolChangeRate:COscaleShiftCount */
    428                 0,/*child_scb_addr*/0        /* COreserved - need child scb to work with rom code */
    429         };
    430 
    431         codec_out_scb.left_chan_base_IO_addr = channel_disp;
    432         codec_out_scb.right_chan_IO_disp = fifo_addr;
    433         codec_out_scb.last_sub_ptr = child_scb_addr;
    434 
     429                0,child_scb_addr        /* COreserved - need child scb to work with rom code */
     430        };
     431 
     432 
    435433        scb = cs46xx_dsp_create_generic_scb(chip,codec_name,(u32 *)&codec_out_scb,
    436434                                            dest,"S16_CODECOUTPUTTASK",parent_scb,
     
    440438}
    441439
    442 dsp_scb_descriptor_t *
    443 cs46xx_dsp_create_codec_in_scb(cs46xx_t * chip,char * codec_name,
    444                                 u16 channel_disp,u16 fifo_addr,
    445                                 u16 sample_buffer_addr,
    446                                 u32 dest,dsp_scb_descriptor_t * parent_scb,
    447                                 int scb_child_type)
    448 {
    449 
    450         dsp_scb_descriptor_t * scb;
    451         codec_input_scb_t codec_input_scb = {
     440struct dsp_scb_descriptor *
     441cs46xx_dsp_create_codec_in_scb(struct snd_cs46xx * chip, char * codec_name,
     442                               u16 channel_disp, u16 fifo_addr, u16 sample_buffer_addr,
     443                               u32 dest, struct dsp_scb_descriptor * parent_scb,
     444                               int scb_child_type)
     445{
     446
     447        struct dsp_scb_descriptor * scb;
     448        struct dsp_codec_input_scb codec_input_scb = {
    452449                { 0,
    453450                  0,
     
    471468
    472469                RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64,  /* strmRsConfig */
    473                 /*sample_buffer_addr << 0x10*/0,       /* strmBufPtr; defined as a dword ptr, used as a byte ptr */
    474                 /*channel_disp*/0,/*fifo_addr*/0,           /* (!AC97!) leftChanBaseINaddr=AC97primary
     470                sample_buffer_addr << 0x10,       /* strmBufPtr; defined as a dword ptr, used as a byte ptr */
     471                channel_disp,fifo_addr,           /* (!AC97!) leftChanBaseINaddr=AC97primary
    475472                                                     link input slot 3 :rightChanINdisp=""slot 4 */
    476473                0x0000,0x0000,                    /* (!AC97!) ????:scaleShiftCount; no shift needed
     
    478475                0x80008000                        /* ??clw cwcgame.scb has 0 */
    479476        };
    480 
    481         codec_input_scb.strm_buf_ptr = sample_buffer_addr << 0x10;
    482         codec_input_scb.rightChanINdisp = channel_disp;
    483         codec_input_scb.left_chan_base_IN_addr = fifo_addr;
     477 
    484478        scb = cs46xx_dsp_create_generic_scb(chip,codec_name,(u32 *)&codec_input_scb,
    485479                                            dest,"S16_CODECINPUTTASK",parent_scb,
     
    489483
    490484
    491 dsp_scb_descriptor_t *
    492 cs46xx_dsp_create_pcm_reader_scb(cs46xx_t * chip,char * scb_name,
    493                                  u16 sample_buffer_addr,u32 dest,
     485static struct dsp_scb_descriptor *
     486cs46xx_dsp_create_pcm_reader_scb(struct snd_cs46xx * chip, char * scb_name,
     487                                 u16 sample_buffer_addr, u32 dest,
    494488                                 int virtual_channel, u32 playback_hw_addr,
    495                                  dsp_scb_descriptor_t * parent_scb,
    496 
     489                                 struct dsp_scb_descriptor * parent_scb,
    497490                                 int scb_child_type)
    498491{
    499         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    500         dsp_scb_descriptor_t * scb;
    501  
    502         generic_scb_t pcm_reader_scb = {
     492        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     493        struct dsp_scb_descriptor * scb;
     494 
     495        struct dsp_generic_scb pcm_reader_scb = {
    503496   
    504497                /*
     
    534527                  /*        Barnette said that is what we should use since */
    535528                  /*        we are not running in optimized mode? */
    536                   /*DMA_RQ_C2_AC_NONE + */
    537                   /*DMA_RQ_C2_SIGNAL_SOURCE_PINGPONG +*/ /* set play interrupt (bit0) in HISR when source */
     529                  DMA_RQ_C2_AC_NONE +
     530                  DMA_RQ_C2_SIGNAL_SOURCE_PINGPONG + /* set play interrupt (bit0) in HISR when source */
    538531                  /*   buffer (on host) crosses half-way point */
    539                   /*virtual_channel*/0,                   /* Play DMA channel arbitrarily set to 0 */
    540                   /*playback_hw_addr*/0,                  /* HostBuffAddr (source) */
    541                   /*DMA_RQ_SD_SP_SAMPLE_ADDR + */        /* destination buffer is in SP Sample Memory */
    542                   /*sample_buffer_addr */0                /* SP Buffer Address (destination) */
     532                  virtual_channel,                   /* Play DMA channel arbitrarily set to 0 */
     533                  playback_hw_addr,                  /* HostBuffAddr (source) */
     534                  DMA_RQ_SD_SP_SAMPLE_ADDR +         /* destination buffer is in SP Sample Memory */
     535                  sample_buffer_addr                 /* SP Buffer Address (destination) */
    543536                },
    544537                /* Scatter/gather DMA requestor extension   (5 ints) */
     
    556549                /* rsConfig register for stream buffer (rsDMA reg. is loaded from basicReq.daw */
    557550                /*   for incoming streams, or basicReq.saw, for outgoing streams) */
    558                 /*RSCONFIG_DMA_ENABLE +    */             /* enable DMA */
    559                 /*(19 << RSCONFIG_MAX_DMA_SIZE_SHIFT) + *//* MAX_DMA_SIZE picked to be 19 since SPUD  */
     551                RSCONFIG_DMA_ENABLE +                 /* enable DMA */
     552                (19 << RSCONFIG_MAX_DMA_SIZE_SHIFT) + /* MAX_DMA_SIZE picked to be 19 since SPUD  */
    560553                /*  uses it for some reason */
    561                 /*((dest >> 4) << RSCONFIG_STREAM_NUM_SHIFT) +*/ /* stream number = SCBaddr/16 */
    562                 /*RSCONFIG_SAMPLE_16STEREO + */
    563                 /*RSCONFIG_MODULO_32*/0,             /* dest buffer(PCMreaderBuf) is 32 dwords (256 bytes) */
     554                ((dest >> 4) << RSCONFIG_STREAM_NUM_SHIFT) + /* stream number = SCBaddr/16 */
     555                RSCONFIG_SAMPLE_16STEREO +
     556                RSCONFIG_MODULO_32,             /* dest buffer(PCMreaderBuf) is 32 dwords (256 bytes) */
    564557                /* Stream sample pointer & MAC-unit mode for this stream */
    565                 /*(sample_buffer_addr << 0x10)*/0,
     558                (sample_buffer_addr << 0x10),
    566559                /* Fractional increment per output sample in the input sample buffer */
    567560                0,
     
    574567        };
    575568
    576         pcm_reader_scb.basic_req.dmw = DMA_RQ_C2_AC_NONE +
    577             DMA_RQ_C2_SIGNAL_SOURCE_PINGPONG +
    578             virtual_channel;
    579         pcm_reader_scb.basic_req.saw = playback_hw_addr;
    580         pcm_reader_scb.basic_req.daw = DMA_RQ_SD_SP_SAMPLE_ADDR + sample_buffer_addr;
    581         pcm_reader_scb.strm_rs_config = RSCONFIG_DMA_ENABLE +
    582             (19 << RSCONFIG_MAX_DMA_SIZE_SHIFT) +
    583             ((dest >> 4) << RSCONFIG_STREAM_NUM_SHIFT) +
    584             RSCONFIG_SAMPLE_16STEREO +
    585             RSCONFIG_MODULO_32;
    586         pcm_reader_scb.strm_buf_ptr = sample_buffer_addr << 0x10;
    587569        if (ins->null_algorithm == NULL) {
    588570                ins->null_algorithm =  cs46xx_dsp_lookup_symbol (chip,"NULLALGORITHM",
     
    604586#define GOF_PER_SEC 200
    605587
    606 dsp_scb_descriptor_t *
    607 cs46xx_dsp_create_src_task_scb(cs46xx_t * chip,char * scb_name,
     588struct dsp_scb_descriptor *
     589cs46xx_dsp_create_src_task_scb(struct snd_cs46xx * chip, char * scb_name,
    608590                               int rate,
    609591                               u16 src_buffer_addr,
    610                                u16 src_delay_buffer_addr,u32 dest,
    611                                dsp_scb_descriptor_t * parent_scb,
     592                               u16 src_delay_buffer_addr, u32 dest,
     593                               struct dsp_scb_descriptor * parent_scb,
    612594                               int scb_child_type,
    613595                               int pass_through)
    614596{
    615597
    616         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    617         dsp_scb_descriptor_t * scb;
     598        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     599        struct dsp_scb_descriptor * scb;
    618600        unsigned int tmp1, tmp2;
    619601        unsigned int phiIncr;
     
    652634
    653635        {
    654                 src_task_scb_t src_task_scb = {
     636                struct dsp_src_task_scb src_task_scb = {
    655637                        0x0028,0x00c8,
    656638                        0x5555,0x0000,
    657639                        0x0000,0x0000,
    658                         /*src_buffer_addr*/0,1,
    659                         /*correctionPerGOF*/0,/*correctionPerSec*/0,
     640                        src_buffer_addr,1,
     641                        correctionPerGOF,correctionPerSec,
    660642                        RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_32, 
    661                         0x0000,/*src_delay_buffer_addr*/0,
     643                        0x0000,src_delay_buffer_addr,                 
    662644                        0x0,                                           
    663                         0x080,/*(src_delay_buffer_addr + (24 * 4))*/0,
     645                        0x080,(src_delay_buffer_addr + (24 * 4)),
    664646                        0,0, /* next_scb, sub_list_ptr */
    665647                        0,0, /* entry, this_spb */
    666648                        RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_8,
    667                         /*src_buffer_addr << 0x10*/0,
    668                         /*phiIncr*/0,
     649                        src_buffer_addr << 0x10,
     650                        phiIncr,
    669651                        {
    670                                 /*0xffff - ins->dac_volume_right*/0,/*0xffff - ins->dac_volume_left*/0,
    671                                 /*0xffff - ins->dac_volume_right*/0,/*0xffff - ins->dac_volume_left*/0
     652                                0xffff - ins->dac_volume_right,0xffff - ins->dac_volume_left,
     653                                0xffff - ins->dac_volume_right,0xffff - ins->dac_volume_left
    672654                        }
    673655                };
    674 
    675                 src_task_scb.output_buf_producer_ptr = src_buffer_addr;
    676                 src_task_scb.gof_length = correctionPerGOF;
    677                 src_task_scb.gofs_per_sec = correctionPerSec;
    678                 src_task_scb.input_buf_consumer_ptr = src_delay_buffer_addr;
    679                 src_task_scb.input_buf_producer_ptr = (src_delay_buffer_addr + (24 * 4));
    680                 src_task_scb.src_strm_buf_ptr = src_buffer_addr << 0x10;
    681                 src_task_scb.phiIncr6int_26frac = phiIncr;
    682                 src_task_scb.src_vol_ctrl.rightTarg = 0xffff - ins->dac_volume_right;
    683                 src_task_scb.src_vol_ctrl.leftTarg = 0xffff - ins->dac_volume_left;
    684                 src_task_scb.src_vol_ctrl.rightVol = 0xffff - ins->dac_volume_right;
    685                 src_task_scb.src_vol_ctrl.leftVol = 0xffff - ins->dac_volume_left;
    686 
     656               
    687657                if (ins->s16_up == NULL) {
    688658                        ins->s16_up =  cs46xx_dsp_lookup_symbol (chip,"S16_UPSRC",
     
    702672                        /* wont work with any other rate than
    703673                           the native DSP rate */
    704                         //snd_assert (rate == 48000);
     674                        snd_assert (rate = 48000);
    705675
    706676                        scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&src_task_scb,
     
    719689}
    720690
    721 dsp_scb_descriptor_t *
    722 cs46xx_dsp_create_filter_scb(cs46xx_t * chip,char * scb_name,
    723                              u16 buffer_addr,u32 dest,
    724                              dsp_scb_descriptor_t * parent_scb,
     691#if 0 /* not used */
     692struct dsp_scb_descriptor *
     693cs46xx_dsp_create_filter_scb(struct snd_cs46xx * chip, char * scb_name,
     694                             u16 buffer_addr, u32 dest,
     695                             struct dsp_scb_descriptor * parent_scb,
    725696                             int scb_child_type) {
    726         dsp_scb_descriptor_t * scb;
     697        struct dsp_scb_descriptor * scb;
    727698       
    728         filter_scb_t filter_scb = {
    729                /* .a0_right            = */0x41a9,
    730                /* .a0_left             = */0x41a9,
    731                /* .a1_right            = */0xb8e4,
    732                /* .a1_left             = */0xb8e4,
    733                /* .a2_right            = */0x3e55,
    734                /* .a2_left             = */0x3e55,
    735 
    736                /* .filter_unused3      = */0x0000,
    737                /* .filter_unused2      = */0x0000,
    738 
    739                /* .output_buf_ptr      = *//*buffer_addr*/0,
    740                /* .init                = */0x000,
    741 
    742                /* .prev_sample_output1 = */0x00000000,
    743                /* .prev_sample_output2 = */0x00000000,
    744 
    745                /* .prev_sample_input1  = */0x00000000,
    746                /* .prev_sample_input2  = */0x00000000,
    747 
    748                /* .next_scb_ptr        = */0x0000,
    749                /* .sub_list_ptr        = */0x0000,
    750 
    751                /* .entry_point         = */0x0000,
    752                /* .spb_ptr             = */0x0000,
    753 
    754                /* .b0_right            = */0x0e38,
    755                /* .b0_left             = */0x0e38,
    756                /* .b1_right            = */0x1c71,
    757                /* .b1_left             = */0x1c71,
    758                /* .b2_right            = */0x0e38,
    759                /* .b2_left             = */0x0e38,
     699        struct dsp_filter_scb filter_scb = {
     700                .a0_right            = 0x41a9,
     701                .a0_left             = 0x41a9,
     702                .a1_right            = 0xb8e4,
     703                .a1_left             = 0xb8e4,
     704                .a2_right            = 0x3e55,
     705                .a2_left             = 0x3e55,
     706               
     707                .filter_unused3      = 0x0000,
     708                .filter_unused2      = 0x0000,
     709
     710                .output_buf_ptr      = buffer_addr,
     711                .init                = 0x000,
     712
     713                .prev_sample_output1 = 0x00000000,
     714                .prev_sample_output2 = 0x00000000,
     715
     716                .prev_sample_input1  = 0x00000000,
     717                .prev_sample_input2  = 0x00000000,
     718
     719                .next_scb_ptr        = 0x0000,
     720                .sub_list_ptr        = 0x0000,
     721
     722                .entry_point         = 0x0000,
     723                .spb_ptr             = 0x0000,
     724
     725                .b0_right            = 0x0e38,
     726                .b0_left             = 0x0e38,
     727                .b1_right            = 0x1c71,
     728                .b1_left             = 0x1c71,
     729                .b2_right            = 0x0e38,
     730                .b2_left             = 0x0e38,
    760731        };
    761732
    762         filter_scb.output_buf_ptr  = buffer_addr;
    763733
    764734        scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&filter_scb,
     
    768738        return scb;
    769739}
    770 
    771 dsp_scb_descriptor_t *
    772 cs46xx_dsp_create_mix_only_scb(cs46xx_t * chip,char * scb_name,
    773                                u16 mix_buffer_addr,u32 dest,
    774                                dsp_scb_descriptor_t * parent_scb,
     740#endif /* not used */
     741
     742struct dsp_scb_descriptor *
     743cs46xx_dsp_create_mix_only_scb(struct snd_cs46xx * chip, char * scb_name,
     744                               u16 mix_buffer_addr, u32 dest,
     745                               struct dsp_scb_descriptor * parent_scb,
    775746                               int scb_child_type)
    776747{
    777         dsp_scb_descriptor_t * scb;
    778  
    779         mix_only_scb_t master_mix_scb = {
     748        struct dsp_scb_descriptor * scb;
     749 
     750        struct dsp_mix_only_scb master_mix_scb = {
    780751                /* 0 */ { 0,
    781752                          /* 1 */   0,
    782                           /* 2 */  /*mix_buffer_addr*/0,
     753                          /* 2 */  mix_buffer_addr,
    783754                          /* 3 */  0
    784755                          /*   */ },
     
    793764                /* A */ 0,0,
    794765                /* B */ RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_32,
    795                 /* C */ /*(mix_buffer_addr  + (16 * 4)) << 0x10*/0,
     766                /* C */ (mix_buffer_addr  + (16 * 4)) << 0x10,
    796767                /* D */ 0,
    797768                {
     
    801772        };
    802773
    803         master_mix_scb.basic_req.saw = mix_buffer_addr;
    804         master_mix_scb.strm_buf_ptr = (mix_buffer_addr  + (16 * 4)) << 0x10;
    805774
    806775        scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&master_mix_scb,
     
    811780
    812781
    813 dsp_scb_descriptor_t *
    814 cs46xx_dsp_create_mix_to_ostream_scb(cs46xx_t * chip,char * scb_name,
    815                                      u16 mix_buffer_addr,u16 writeback_spb,u32 dest,
    816                                      dsp_scb_descriptor_t * parent_scb,
     782struct dsp_scb_descriptor *
     783cs46xx_dsp_create_mix_to_ostream_scb(struct snd_cs46xx * chip, char * scb_name,
     784                                     u16 mix_buffer_addr, u16 writeback_spb, u32 dest,
     785                                     struct dsp_scb_descriptor * parent_scb,
    817786                                     int scb_child_type)
    818787{
    819         dsp_scb_descriptor_t * scb;
    820 
    821         mix2_ostream_scb_t mix2_ostream_scb = {
     788        struct dsp_scb_descriptor * scb;
     789
     790        struct dsp_mix2_ostream_scb mix2_ostream_scb = {
    822791                /* Basic (non scatter/gather) DMA requestor (4 ints) */
    823792                {
     
    833802     
    834803                        CS46XX_DSP_CAPTURE_CHANNEL,                                 
    835                         /*DMA_RQ_SD_SP_SAMPLE_ADDR +
    836                         mix_buffer_addr*/0,
     804                        DMA_RQ_SD_SP_SAMPLE_ADDR +
     805                        mix_buffer_addr,
    837806                        0x0                   
    838807                },
     
    840809                { 0, 0, 0, 0, 0, },
    841810                0,0,
    842                 0,/*writeback_spb*/0,
    843    
    844                 /*RSCONFIG_DMA_ENABLE +
     811                0,writeback_spb,
     812   
     813                RSCONFIG_DMA_ENABLE +
    845814                (19 << RSCONFIG_MAX_DMA_SIZE_SHIFT) +
    846815   
     
    848817                RSCONFIG_DMA_TO_HOST +
    849818                RSCONFIG_SAMPLE_16STEREO +
    850                 RSCONFIG_MODULO_64*/0,
    851                 /*(mix_buffer_addr + (32 * 4)) << 0x10*/0,
     819                RSCONFIG_MODULO_64,   
     820                (mix_buffer_addr + (32 * 4)) << 0x10,
    852821                1,0,           
    853822                0x0001,0x0080,
    854823                0xFFFF,0
    855         };
    856 
    857         mix2_ostream_scb.basic_req.saw = DMA_RQ_SD_SP_SAMPLE_ADDR + mix_buffer_addr;
    858         mix2_ostream_scb.this_spb = writeback_spb;
    859         mix2_ostream_scb.strm_rs_config = RSCONFIG_DMA_ENABLE +
    860             (19 << RSCONFIG_MAX_DMA_SIZE_SHIFT) +
    861             ((dest >> 4) << RSCONFIG_STREAM_NUM_SHIFT) +
    862             RSCONFIG_DMA_TO_HOST +
    863             RSCONFIG_SAMPLE_16STEREO +
    864             RSCONFIG_MODULO_64;
    865         mix2_ostream_scb.strm_buf_ptr = (mix_buffer_addr + (32 * 4)) << 0x10;
     824        };
    866825
    867826
     
    875834
    876835
    877 dsp_scb_descriptor_t *
    878 cs46xx_dsp_create_vari_decimate_scb(cs46xx_t * chip,char * scb_name,
     836struct dsp_scb_descriptor *
     837cs46xx_dsp_create_vari_decimate_scb(struct snd_cs46xx * chip,char * scb_name,
    879838                                    u16 vari_buffer_addr0,
    880839                                    u16 vari_buffer_addr1,
    881840                                    u32 dest,
    882                                     dsp_scb_descriptor_t * parent_scb,
     841                                    struct dsp_scb_descriptor * parent_scb,
    883842                                    int scb_child_type)
    884843{
    885844
    886         dsp_scb_descriptor_t * scb;
    887  
    888         vari_decimate_scb_t vari_decimate_scb = {
     845        struct dsp_scb_descriptor * scb;
     846 
     847        struct dsp_vari_decimate_scb vari_decimate_scb = {
    889848                0x0028,0x00c8,
    890849                0x5555,0x0000,
    891850                0x0000,0x0000,
    892                 /*vari_buffer_addr0*/0,/*vari_buffer_addr1*/0,
     851                vari_buffer_addr0,vari_buffer_addr1,
    893852   
    894853                0x0028,0x00c8,
     
    897856                0xFF800000,   
    898857                0,
    899                 0x0080,/*vari_buffer_addr1 + (25 * 4)*/0,
     858                0x0080,vari_buffer_addr1 + (25 * 4),
    900859   
    901860                0,0,
     
    903862
    904863                RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_8,
    905                 /*vari_buffer_addr0 << 0x10*/0,
     864                vari_buffer_addr0 << 0x10,   
    906865                0x04000000,                   
    907866                {
     
    911870        };
    912871
    913         vari_decimate_scb.vdec_output_buf_producer_ptr = vari_buffer_addr0;
    914         vari_decimate_scb.vdec_input_buf_consumer_ptr = vari_buffer_addr1;
    915         vari_decimate_scb.vdec_input_buf_producer_ptr = vari_buffer_addr1 + (25 * 4);
    916         vari_decimate_scb.vdec_strm_buf_ptr = vari_buffer_addr0 << 0x10;
    917 
    918872        scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&vari_decimate_scb,
    919873                                            dest,"VARIDECIMATE",parent_scb,
     
    924878
    925879
    926 dsp_scb_descriptor_t *
    927 cs46xx_dsp_create_pcm_serial_input_scb(cs46xx_t * chip,char * scb_name,u32 dest,
    928                                        dsp_scb_descriptor_t * input_scb,
    929                                        dsp_scb_descriptor_t * parent_scb,
     880static struct dsp_scb_descriptor *
     881cs46xx_dsp_create_pcm_serial_input_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
     882                                       struct dsp_scb_descriptor * input_scb,
     883                                       struct dsp_scb_descriptor * parent_scb,
    930884                                       int scb_child_type)
    931885{
    932886
    933         dsp_scb_descriptor_t * scb;
    934 
    935 
    936         pcm_serial_input_scb_t pcm_serial_input_scb = {
     887        struct dsp_scb_descriptor * scb;
     888
     889
     890        struct dsp_pcm_serial_input_scb pcm_serial_input_scb = {
    937891                { 0,
    938892                  0,
     
    953907                RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_16,
    954908                0,
    955       /* 0xD */ 0,/*input_scb->address*/0,
     909      /* 0xD */ 0,input_scb->address,
    956910                {
    957911      /* 0xE */   0x8000,0x8000,
     
    960914        };
    961915
    962         pcm_serial_input_scb.codec_input_buf_scb = input_scb->address;
    963 
    964916        scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&pcm_serial_input_scb,
    965917                                            dest,"PCMSERIALINPUTTASK",parent_scb,
     
    969921
    970922
    971 dsp_scb_descriptor_t *
    972 cs46xx_dsp_create_asynch_fg_tx_scb(cs46xx_t * chip,char * scb_name,u32 dest,
     923static struct dsp_scb_descriptor *
     924cs46xx_dsp_create_asynch_fg_tx_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
    973925                                   u16 hfg_scb_address,
    974926                                   u16 asynch_buffer_address,
    975                                    dsp_scb_descriptor_t * parent_scb,
     927                                   struct dsp_scb_descriptor * parent_scb,
    976928                                   int scb_child_type)
    977929{
    978930
    979         dsp_scb_descriptor_t * scb;
    980 
    981         asynch_fg_tx_scb_t asynch_fg_tx_scb = {
     931        struct dsp_scb_descriptor * scb;
     932
     933        struct dsp_asynch_fg_tx_scb asynch_fg_tx_scb = {
    982934                0xfc00,0x03ff,      /*  Prototype sample buffer size of 256 dwords */
    983935                0x0058,0x0028,      /* Min Delta 7 dwords == 28 bytes */
    984936                /* : Max delta 25 dwords == 100 bytes */
    985                 0,/*hfg_scb_address*/0,  /* Point to HFG task SCB */
     937                0,hfg_scb_address,  /* Point to HFG task SCB */
    986938                0,0,                /* Initialize current Delta and Consumer ptr adjustment count */
    987939                0,                  /* Initialize accumulated Phi to 0 */
     
    995947   
    996948                0,0,
    997                 0,/*dest + AFGTxAccumPhi*/0,
     949                0,dest + AFGTxAccumPhi,
    998950   
    999951                RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_256, /* Stereo, 256 dword */
    1000                 /*(asynch_buffer_address) << 0x10*/0,  /* This should be automagically synchronized
     952                (asynch_buffer_address) << 0x10,  /* This should be automagically synchronized
    1001953                                                     to the producer pointer */
    1002954   
     
    1006958                0x8000,0x8000,                  /* Volume controls are unused at this time */
    1007959                0x8000,0x8000
    1008         };
    1009         asynch_fg_tx_scb.hfg_scb_ptr = hfg_scb_address;
    1010         asynch_fg_tx_scb.this_ptr = dest + AFGTxAccumPhi;
    1011         asynch_fg_tx_scb.strm_buf_ptr = (asynch_buffer_address) << 0x10;
     960        };
    1012961 
    1013962        scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&asynch_fg_tx_scb,
     
    1019968
    1020969
    1021 dsp_scb_descriptor_t *
    1022 cs46xx_dsp_create_asynch_fg_rx_scb(cs46xx_t * chip,char * scb_name,u32 dest,
     970struct dsp_scb_descriptor *
     971cs46xx_dsp_create_asynch_fg_rx_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
    1023972                                   u16 hfg_scb_address,
    1024973                                   u16 asynch_buffer_address,
    1025                                    dsp_scb_descriptor_t * parent_scb,
     974                                   struct dsp_scb_descriptor * parent_scb,
    1026975                                   int scb_child_type)
    1027976{
    1028         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    1029         dsp_scb_descriptor_t * scb;
    1030 
    1031         asynch_fg_rx_scb_t asynch_fg_rx_scb = {
     977        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     978        struct dsp_scb_descriptor * scb;
     979
     980        struct dsp_asynch_fg_rx_scb asynch_fg_rx_scb = {
    1032981                0xfe00,0x01ff,      /*  Prototype sample buffer size of 128 dwords */
    1033982                0x0064,0x001c,      /* Min Delta 7 dwords == 28 bytes */
    1034983                                    /* : Max delta 25 dwords == 100 bytes */
    1035                 0,/*hfg_scb_address*/0,  /* Point to HFG task SCB */
     984                0,hfg_scb_address,  /* Point to HFG task SCB */
    1036985                0,0,                            /* Initialize current Delta and Consumer ptr adjustment count */
    1037986                {
     
    1044993     
    1045994                0,0,
    1046                 0,/*dest*/0,
     995                0,dest,
    1047996   
    1048997                RSCONFIG_MODULO_128 |
    1049998        RSCONFIG_SAMPLE_16STEREO,                         /* Stereo, 128 dword */
    1050                 /*( (asynch_buffer_address + (16 * 4))  << 0x10)*/0,   /* This should be automagically
     999                ( (asynch_buffer_address + (16 * 4))  << 0x10),   /* This should be automagically
    10511000                                                                                          synchrinized to the producer pointer */
    10521001   
     
    10561005
    10571006                /* Set IEC958 input volume */
    1058                 /*0xffff - ins->spdif_input_volume_right*/0,/*0xffff - ins->spdif_input_volume_left*/0,
    1059                 /*0xffff - ins->spdif_input_volume_right*/0,/*0xffff - ins->spdif_input_volume_left*/0,
    1060         };
    1061 
    1062         asynch_fg_rx_scb.hfg_scb_ptr = hfg_scb_address;
    1063         asynch_fg_rx_scb.this_ptr = dest;
    1064         asynch_fg_rx_scb.strm_buf_ptr = ( (asynch_buffer_address + (16 * 4))  << 0x10);
    1065         asynch_fg_rx_scb.right_targ = 0xffff - ins->spdif_input_volume_right;
    1066         asynch_fg_rx_scb.left_targ = 0xffff - ins->spdif_input_volume_left;
    1067         asynch_fg_rx_scb.right_vol = 0xffff - ins->spdif_input_volume_right;
    1068         asynch_fg_rx_scb.left_vol = 0xffff - ins->spdif_input_volume_left;
     1007                0xffff - ins->spdif_input_volume_right,0xffff - ins->spdif_input_volume_left,
     1008                0xffff - ins->spdif_input_volume_right,0xffff - ins->spdif_input_volume_left,
     1009        };
    10691010
    10701011        scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&asynch_fg_rx_scb,
     
    10761017
    10771018
    1078 dsp_scb_descriptor_t *
    1079 cs46xx_dsp_create_output_snoop_scb(cs46xx_t * chip,char * scb_name,u32 dest,
     1019#if 0 /* not used */
     1020struct dsp_scb_descriptor *
     1021cs46xx_dsp_create_output_snoop_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
    10801022                                   u16 snoop_buffer_address,
    1081                                    dsp_scb_descriptor_t * snoop_scb,
    1082                                    dsp_scb_descriptor_t * parent_scb,
     1023                                   struct dsp_scb_descriptor * snoop_scb,
     1024                                   struct dsp_scb_descriptor * parent_scb,
    10831025                                   int scb_child_type)
    10841026{
    10851027
    1086         dsp_scb_descriptor_t * scb;
    1087  
    1088         output_snoop_scb_t output_snoop_scb = {
     1028        struct dsp_scb_descriptor * scb;
     1029 
     1030        struct dsp_output_snoop_scb output_snoop_scb = {
    10891031                { 0,    /*  not used.  Zero */
    10901032                  0,
     
    11041046   
    11051047                RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64,
    1106                 /*snoop_buffer_address << 0x10*/0,
     1048                snoop_buffer_address << 0x10, 
    11071049                0,0,
    11081050                0,
    1109                 0,/*snoop_scb->address*/0
     1051                0,snoop_scb->address
    11101052        };
    1111 
    1112         output_snoop_scb.strm_buf_ptr = snoop_buffer_address << 0x10;
    1113         output_snoop_scb.input_scb = snoop_scb->address;
     1053 
    11141054        scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&output_snoop_scb,
    11151055                                            dest,"OUTPUTSNOOP",parent_scb,
     
    11171057        return scb;
    11181058}
    1119 
    1120 
    1121 dsp_scb_descriptor_t *
    1122 cs46xx_dsp_create_spio_write_scb(cs46xx_t * chip,char * scb_name,u32 dest,
    1123                                  dsp_scb_descriptor_t * parent_scb,
     1059#endif /* not used */
     1060
     1061
     1062struct dsp_scb_descriptor *
     1063cs46xx_dsp_create_spio_write_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
     1064                                 struct dsp_scb_descriptor * parent_scb,
    11241065                                 int scb_child_type)
    11251066{
    1126         dsp_scb_descriptor_t * scb;
    1127  
    1128         spio_write_scb_t spio_write_scb = {
     1067        struct dsp_scb_descriptor * scb;
     1068 
     1069        struct dsp_spio_write_scb spio_write_scb = {
    11291070                0,0,         /*   SPIOWAddress2:SPIOWAddress1; */
    11301071                0,           /*   SPIOWData1; */
     
    11551096}
    11561097
    1157 dsp_scb_descriptor_t *  cs46xx_dsp_create_magic_snoop_scb(cs46xx_t * chip,char * scb_name,u32 dest,
    1158                                                           u16 snoop_buffer_address,
    1159                                                           dsp_scb_descriptor_t * snoop_scb,
    1160                                                           dsp_scb_descriptor_t * parent_scb,
    1161                                                           int scb_child_type)
    1162 {
    1163         dsp_scb_descriptor_t * scb;
    1164  
    1165         magic_snoop_task_t magic_snoop_scb = {
     1098struct dsp_scb_descriptor *
     1099cs46xx_dsp_create_magic_snoop_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
     1100                                  u16 snoop_buffer_address,
     1101                                  struct dsp_scb_descriptor * snoop_scb,
     1102                                  struct dsp_scb_descriptor * parent_scb,
     1103                                  int scb_child_type)
     1104{
     1105        struct dsp_scb_descriptor * scb;
     1106 
     1107        struct dsp_magic_snoop_task magic_snoop_scb = {
    11661108                /* 0 */ 0, /* i0 */
    11671109                /* 1 */ 0, /* i1 */
    1168                 /* 2 */ /*snoop_buffer_address << 0x10*/0,
    1169                 /* 3 */ 0,/*snoop_scb->address*/0,
     1110                /* 2 */ snoop_buffer_address << 0x10,
     1111                /* 3 */ 0,snoop_scb->address,
    11701112                /* 4 */ 0, /* i3 */
    11711113                /* 5 */ 0, /* i4 */
     
    11761118                /* A */ 0,0, /* entry_point, this_ptr */
    11771119                /* B */ RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64,
    1178                 /* C */ /*snoop_buffer_address  << 0x10*/0,
     1120                /* C */ snoop_buffer_address  << 0x10,
    11791121                /* D */ 0,
    11801122                /* E */ { 0x8000,0x8000,
     
    11831125        };
    11841126
    1185         magic_snoop_scb.strm_buf_ptr1 = snoop_buffer_address << 0x10;
    1186         magic_snoop_scb.snoop_scb = snoop_scb->address;
    1187         magic_snoop_scb.strm_buf_ptr2 = snoop_buffer_address  << 0x10;
    11881127        scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&magic_snoop_scb,
    11891128                                            dest,"MAGICSNOOPTASK",parent_scb,
     
    11931132}
    11941133
    1195 static dsp_scb_descriptor_t * find_next_free_scb (cs46xx_t * chip,dsp_scb_descriptor_t * from)
    1196 {
    1197         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    1198         dsp_scb_descriptor_t * scb = from;
     1134static struct dsp_scb_descriptor *
     1135find_next_free_scb (struct snd_cs46xx * chip, struct dsp_scb_descriptor * from)
     1136{
     1137        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     1138        struct dsp_scb_descriptor * scb = from;
    11991139
    12001140        while (scb->next_scb_ptr != ins->the_null_scb) {
     
    12761216};
    12771217
    1278 pcm_channel_descriptor_t * cs46xx_dsp_create_pcm_channel (cs46xx_t * chip,
    1279                                                           u32 sample_rate, void * private_data,
    1280                                                           u32 hw_dma_addr,
    1281                                                           int pcm_channel_id)
    1282 {
    1283         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    1284         dsp_scb_descriptor_t * src_scb = NULL,* pcm_scb, * mixer_scb = NULL;
    1285         dsp_scb_descriptor_t * src_parent_scb = NULL;
    1286 
    1287         /* dsp_scb_descriptor_t * pcm_parent_scb; */
     1218struct dsp_pcm_channel_descriptor *
     1219cs46xx_dsp_create_pcm_channel (struct snd_cs46xx * chip,
     1220                               u32 sample_rate, void * private_data,
     1221                               u32 hw_dma_addr,
     1222                               int pcm_channel_id)
     1223{
     1224        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     1225        struct dsp_scb_descriptor * src_scb = NULL, * pcm_scb, * mixer_scb = NULL;
     1226        struct dsp_scb_descriptor * src_parent_scb = NULL;
     1227
     1228        /* struct dsp_scb_descriptor * pcm_parent_scb; */
    12881229        char scb_name[DSP_MAX_SCB_NAME];
    1289         int i,pcm_index = -1, insert_point, src_index = -1,pass_through = 0;
     1230        int i, pcm_index = -1, insert_point, src_index = -1, pass_through = 0;
    12901231        unsigned long flags;
    12911232
     
    13021243        case DSP_PCM_S71_CHANNEL:
    13031244                /* TODO */
    1304                 //snd_assert(0);
     1245                snd_assert(0);
    13051246                break;
    13061247        case DSP_IEC958_CHANNEL:
     
    13181259                break;
    13191260        default:
    1320                 //snd_assert (0);
     1261                snd_assert (0);
    13211262                return NULL;
    13221263        }
     
    13751316                }
    13761317
    1377                 sprintf (scb_name,/*DSP_MAX_SCB_NAME,*/"SrcTask_SCB%d",src_index);
     1318                sprintf (scb_name,"SrcTask_SCB%d",src_index);
    13781319               
    13791320                snd_printdd( "dsp_spos: creating SRC \"%s\"\n",scb_name);
     
    13991340 
    14001341 
    1401         sprintf (scb_name,/*DSP_MAX_SCB_NAME,*/"PCMReader_SCB%d",pcm_index);
     1342        sprintf (scb_name,"PCMReader_SCB%d",pcm_index);
    14021343
    14031344        snd_printdd( "dsp_spos: creating PCM \"%s\" (%d)\n",scb_name,
     
    14351376}
    14361377
    1437 int cs46xx_dsp_pcm_channel_set_period (cs46xx_t * chip,
    1438                                        pcm_channel_descriptor_t * pcm_channel,
     1378int cs46xx_dsp_pcm_channel_set_period (struct snd_cs46xx * chip,
     1379                                       struct dsp_pcm_channel_descriptor * pcm_channel,
    14391380                                       int period_size)
    14401381{
     
    14741415}
    14751416
    1476 int cs46xx_dsp_pcm_ostream_set_period (cs46xx_t * chip,
     1417int cs46xx_dsp_pcm_ostream_set_period (struct snd_cs46xx * chip,
    14771418                                       int period_size)
    14781419{
     
    15121453}
    15131454
    1514 void cs46xx_dsp_destroy_pcm_channel (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel)
    1515 {
    1516         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
     1455void cs46xx_dsp_destroy_pcm_channel (struct snd_cs46xx * chip,
     1456                                     struct dsp_pcm_channel_descriptor * pcm_channel)
     1457{
     1458        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
    15171459        unsigned long flags;
    15181460
     
    15421484}
    15431485
    1544 int cs46xx_dsp_pcm_unlink (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel)
    1545 {
    1546         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
     1486int cs46xx_dsp_pcm_unlink (struct snd_cs46xx * chip,
     1487                           struct dsp_pcm_channel_descriptor * pcm_channel)
     1488{
     1489        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
    15471490        unsigned long flags;
    15481491
     
    15671510}
    15681511
    1569 int cs46xx_dsp_pcm_link (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel)
    1570 {
    1571         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    1572         dsp_scb_descriptor_t * parent_scb;
    1573         dsp_scb_descriptor_t * src_scb = pcm_channel->src_scb;
     1512int cs46xx_dsp_pcm_link (struct snd_cs46xx * chip,
     1513                         struct dsp_pcm_channel_descriptor * pcm_channel)
     1514{
     1515        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     1516        struct dsp_scb_descriptor * parent_scb;
     1517        struct dsp_scb_descriptor * src_scb = pcm_channel->src_scb;
    15741518        unsigned long flags;
    15751519
     
    16081552}
    16091553
    1610 dsp_scb_descriptor_t * cs46xx_add_record_source (cs46xx_t *chip,dsp_scb_descriptor_t * source,
    1611                                                  u16 addr,char * scb_name)
    1612 {
    1613         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    1614         dsp_scb_descriptor_t * parent;
    1615         dsp_scb_descriptor_t * pcm_input;
     1554struct dsp_scb_descriptor *
     1555cs46xx_add_record_source (struct snd_cs46xx *chip, struct dsp_scb_descriptor * source,
     1556                          u16 addr, char * scb_name)
     1557{
     1558        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     1559        struct dsp_scb_descriptor * parent;
     1560        struct dsp_scb_descriptor * pcm_input;
    16161561        int insert_point;
    16171562
     
    16331578}
    16341579
    1635 int cs46xx_src_unlink(cs46xx_t *chip,dsp_scb_descriptor_t * src)
     1580int cs46xx_src_unlink(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src)
    16361581{
    16371582        snd_assert (src->parent_scb_ptr != NULL,  return -EINVAL );
     
    16451590}
    16461591
    1647 int cs46xx_src_link(cs46xx_t *chip,dsp_scb_descriptor_t * src)
    1648 {
    1649         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
    1650         dsp_scb_descriptor_t * parent_scb;
     1592int cs46xx_src_link(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src)
     1593{
     1594        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
     1595        struct dsp_scb_descriptor * parent_scb;
    16511596
    16521597        snd_assert (src->parent_scb_ptr == NULL,   return -EINVAL );
     
    16691614}
    16701615
    1671 int cs46xx_dsp_enable_spdif_out (cs46xx_t *chip)
    1672 {
    1673         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
     1616int cs46xx_dsp_enable_spdif_out (struct snd_cs46xx *chip)
     1617{
     1618        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
    16741619
    16751620        if ( ! (ins->spdif_status_out & DSP_SPDIF_STATUS_HW_ENABLED) ) {
     
    17171662}
    17181663
    1719 int  cs46xx_dsp_disable_spdif_out (cs46xx_t *chip)
    1720 {
    1721         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
     1664int  cs46xx_dsp_disable_spdif_out (struct snd_cs46xx *chip)
     1665{
     1666        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
    17221667
    17231668        /* dont touch anything if SPDIF is open */
     
    17491694}
    17501695
    1751 int cs46xx_iec958_pre_open (cs46xx_t *chip)
    1752 {
    1753         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
     1696int cs46xx_iec958_pre_open (struct snd_cs46xx *chip)
     1697{
     1698        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
    17541699
    17551700        if ( ins->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED ) {
     
    17821727}
    17831728
    1784 int cs46xx_iec958_post_close (cs46xx_t *chip)
    1785 {
    1786         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
     1729int cs46xx_iec958_post_close (struct snd_cs46xx *chip)
     1730{
     1731        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
    17871732
    17881733        snd_assert (ins->asynch_tx_scb != NULL, return -EINVAL);
  • GPL/trunk/alsa-kernel/pci/cs46xx/imgs/cwc4630.h

    r33 r34  
    44#define __HEADER_cwc4630_H__
    55
    6 static symbol_entry_t cwc4630_symbols[] = {
     6static struct dsp_symbol_entry cwc4630_symbols[] = {
    77  { 0x0000, "BEGINADDRESS",0x00 },
    88  { 0x8000, "EXECCHILD",0x03 },
     
    303303
    304304
    305 static segment_desc_t cwc4630_segments[] = {
     305static struct dsp_segment_desc cwc4630_segments[] = {
    306306  { SEGTYPE_SP_PROGRAM, 0x00000000, 0x00000328, cwc4630_code },
    307307  { SEGTYPE_SP_PARAMETER, 0x00000000, 0x00000080, cwc4630_parameter },
    308308};
    309309
    310 static dsp_module_desc_t cwc4630_module = {
     310static struct dsp_module_desc cwc4630_module = {
    311311  "cwc4630",
    312312  {
  • GPL/trunk/alsa-kernel/pci/cs46xx/imgs/cwcasync.h

    r33 r34  
    44#define __HEADER_cwcasync_H__
    55
    6 static symbol_entry_t cwcasync_symbols[] = {
     6static struct dsp_symbol_entry cwcasync_symbols[] = {
    77  { 0x8000, "EXECCHILD",0x03 },
    88  { 0x8001, "EXECCHILD_98",0x03 },
     
    160160/* #CODE_END */
    161161
    162 static segment_desc_t cwcasync_segments[] = {
     162static struct dsp_segment_desc cwcasync_segments[] = {
    163163  { SEGTYPE_SP_PROGRAM, 0x00000000, 0x000001b6, cwcasync_code },
    164164};
    165165
    166 static dsp_module_desc_t cwcasync_module = {
     166static struct dsp_module_desc cwcasync_module = {
    167167  "cwcasync",
    168168  {
  • GPL/trunk/alsa-kernel/pci/cs46xx/imgs/cwcbinhack.h

    r33 r34  
    55#define __HEADER_cwcbinhack_H__
    66
    7 static symbol_entry_t cwcbinhack_symbols[] = {
     7static struct dsp_symbol_entry cwcbinhack_symbols[] = {
    88  { 0x02c8, "OVERLAYBEGINADDRESS",0x00 },
    99  { 0x02c8, "MAGICSNOOPTASK",0x03 },
     
    3232/* #CODE_END */
    3333
    34 static segment_desc_t cwcbinhack_segments[] = {
     34static struct dsp_segment_desc cwcbinhack_segments[] = {
    3535  { SEGTYPE_SP_PROGRAM, 0x00000000, 64, cwcbinhack_code },
    3636};
    3737
    38 static dsp_module_desc_t cwcbinhack_module = {
     38static struct dsp_module_desc cwcbinhack_module = {
    3939  "cwcbinhack",
    4040  {
  • GPL/trunk/alsa-kernel/pci/cs46xx/imgs/cwcdma.h

    r33 r34  
    44#define __HEADER_cwcdma_H__
    55
    6 symbol_entry_t cwcdma_symbols[] = {
     6static struct dsp_symbol_entry cwcdma_symbols[] = {
    77  { 0x8000, "EXECCHILD",0x03 },
    88  { 0x8001, "EXECCHILD_98",0x03 },
     
    3434}; /* cwcdma symbols */
    3535
    36 u32 cwcdma_code[] = {
     36static u32 cwcdma_code[] = {
    3737/* OVERLAYBEGINADDRESS */
    3838/* 0000 */ 0x00002731,0x00001400,0x0004c108,0x000e5044,
     
    5252/* #CODE_END */
    5353
    54 segment_desc_t cwcdma_segments[] = {
     54static struct dsp_segment_desc cwcdma_segments[] = {
    5555  { SEGTYPE_SP_PROGRAM, 0x00000000, 0x00000030, cwcdma_code },
    5656};
    5757
    58 dsp_module_desc_t cwcdma_module = {
     58static struct dsp_module_desc cwcdma_module = {
    5959  "cwcdma",
    6060  {
  • GPL/trunk/alsa-kernel/pci/cs46xx/imgs/cwcemb80.h

    r33 r34  
    44#define __HEADER_cwcemb80_H__
    55
    6 static symbol_entry_t cwcemb80_symbols[] = {
     6static struct dsp_symbol_entry cwcemb80_symbols[] = {
    77  { 0x0000, "BEGINADDRESS",0x00 },
    88  { 0x8000, "EXECCHILD",0x03 },
     
    15891589
    15901590
    1591 static segment_desc_t cwcemb80_segments[] = {
     1591static struct dsp_segment_desc cwcemb80_segments[] = {
    15921592  { SEGTYPE_SP_PROGRAM, 0x00000000, 0x0000031c, cwcemb80_code },
    15931593  { SEGTYPE_SP_PARAMETER, 0x00000000, 0x00000697, cwcemb80_parameter },
     
    15951595};
    15961596
    1597 static dsp_module_desc_t cwcemb80_module = {
     1597static struct dsp_module_desc cwcemb80_module = {
    15981598  "cwcemb80",
    15991599  {
  • GPL/trunk/alsa-kernel/pci/cs46xx/imgs/cwcsnoop.h

    r33 r34  
    44#define __HEADER_cwcsnoop_H__
    55
    6 static symbol_entry_t cwcsnoop_symbols[] = {
     6static struct dsp_symbol_entry cwcsnoop_symbols[] = {
    77  { 0x0500, "OVERLAYBEGINADDRESS",0x00 },
    88  { 0x0500, "OUTPUTSNOOP",0x03 },
     
    3030/* #CODE_END */
    3131
    32 static segment_desc_t cwcsnoop_segments[] = {
     32static struct dsp_segment_desc cwcsnoop_segments[] = {
    3333  { SEGTYPE_SP_PROGRAM, 0x00000000, 0x0000003e, cwcsnoop_code },
    3434};
    3535
    36 static dsp_module_desc_t cwcsnoop_module = {
     36static struct dsp_module_desc cwcsnoop_module = {
    3737  "cwcsnoop",
    3838  {
Note: See TracChangeset for help on using the changeset viewer.