Ignore:
Timestamp:
Apr 19, 2025, 8:08:37 PM (4 months ago)
Author:
David Azarewicz
Message:

Merge in changes from 6.6-LTS branch.
Fixed additional 25+ problems.

Location:
GPL/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • GPL/trunk

  • GPL/trunk/alsa-kernel/pci/emu10k1/voice.c

    r679 r772  
    22/*
    33 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
     4 *                   Lee Revell <rlrevell@joe-job.com>
     5 *                   Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
    46 *                   Creative Labs, Inc.
    5  *                   Lee Revell <rlrevell@joe-job.com>
     7 *
    68 *  Routines for control of EMU10K1 chips - voice manager
    7  *
    8  *  Rewrote voice allocator for multichannel support - rlrevell 12/2004
    9  *
    10  *  BUGS:
    11  *    --
    12  *
    13  *  TODO:
    14  *    --
    159 */
    1610
     
    2418 * the card record and each allocation begins where the last left off.  The
    2519 * hardware requires stereo interleaved voices be aligned to an even/odd
    26  * boundary.  For multichannel voice allocation we ensure than the block of
    27  * voices does not cross the 32 voice boundary.  This simplifies the
    28  * multichannel support and ensures we can use a single write to the
    29  * (set|clear)_loop_stop registers.  Otherwise (for example) the voices would
    30  * get out of sync when pausing/resuming a stream.
     20 * boundary.
    3121 *                                                      --rlrevell
    3222 */
    3323
    3424static int voice_alloc(struct snd_emu10k1 *emu, int type, int number,
    35                        struct snd_emu10k1_voice **rvoice)
     25                       struct snd_emu10k1_pcm *epcm, struct snd_emu10k1_voice **rvoice)
    3626{
    3727        struct snd_emu10k1_voice *voice;
    38         int i, j, k, first_voice, last_voice, skip;
     28        int i, j, k, skip;
    3929
    40         *rvoice = NULL;
    41         first_voice = last_voice = 0;
    42         for (i = emu->next_free_voice, j = 0; j < NUM_G ; i += number, j += number) {
     30        for (i = emu->next_free_voice, j = 0; j < NUM_G; i = (i + skip) % NUM_G, j += skip) {
    4331                /*
    4432                dev_dbg(emu->card->dev, "i %d j %d next free %d!\n",
    4533                       i, j, emu->next_free_voice);
    4634                */
    47                 i %= NUM_G;
    4835
    4936                /* stereo voices must be even/odd */
    50                 if ((number == 2) && (i % 2)) {
    51                         i++;
     37                if ((number > 1) && (i % 2)) {
     38                        skip = 1;
    5239                        continue;
    5340                }
    54                        
    55                 skip = 0;
     41
    5642                for (k = 0; k < number; k++) {
    57                         voice = &emu->voices[(i+k) % NUM_G];
     43                        voice = &emu->voices[i + k];
    5844                        if (voice->use) {
    59                                 skip = 1;
    60                                 break;
     45                                skip = k + 1;
     46                                goto next;
    6147                        }
    6248                }
    63                 if (!skip) {
    64                         /* dev_dbg(emu->card->dev, "allocated voice %d\n", i); */
    65                         first_voice = i;
    66                         last_voice = (i + number) % NUM_G;
    67                         emu->next_free_voice = last_voice;
    68                         break;
     49
     50                for (k = 0; k < number; k++) {
     51                        voice = &emu->voices[i + k];
     52                        voice->use = type;
     53                        voice->epcm = epcm;
     54                        /* dev_dbg(emu->card->dev, "allocated voice %d\n", i + k); */
    6955                }
     56                voice->last = 1;
     57
     58                *rvoice = &emu->voices[i];
     59                emu->next_free_voice = (i + number) % NUM_G;
     60                return 0;
     61
     62        next: ;
    7063        }
    71        
    72         if (first_voice == last_voice)
    73                 return -ENOMEM;
    74        
    75         for (i = 0; i < number; i++) {
    76                 voice = &emu->voices[(first_voice + i) % NUM_G];
    77                 /*
    78                 dev_dbg(emu->card->dev, "voice alloc - %i, %i of %i\n",
    79                        voice->number, idx-first_voice+1, number);
    80                 */
    81                 voice->use = 1;
    82                 switch (type) {
    83                 case EMU10K1_PCM:
    84                         voice->pcm = 1;
    85                         break;
    86                 case EMU10K1_SYNTH:
    87                         voice->synth = 1;
    88                         break;
    89                 case EMU10K1_MIDI:
    90                         voice->midi = 1;
    91                         break;
    92                 case EMU10K1_EFX:
    93                         voice->efx = 1;
    94                         break;
    95                 }
    96         }
    97         *rvoice = &emu->voices[first_voice];
    98         return 0;
     64        return -ENOMEM;  // -EBUSY would have been better
    9965}
    10066
    101 int snd_emu10k1_voice_alloc(struct snd_emu10k1 *emu, int type, int number,
    102                             struct snd_emu10k1_voice **rvoice)
     67static void voice_free(struct snd_emu10k1 *emu,
     68                       struct snd_emu10k1_voice *pvoice)
     69{
     70        if (pvoice->dirty)
     71                snd_emu10k1_voice_init(emu, pvoice->number);
     72        pvoice->interrupt = NULL;
     73        pvoice->use = pvoice->dirty = pvoice->last = 0;
     74        pvoice->epcm = NULL;
     75}
     76
     77int snd_emu10k1_voice_alloc(struct snd_emu10k1 *emu, int type, int count, int channels,
     78                            struct snd_emu10k1_pcm *epcm, struct snd_emu10k1_voice **rvoice)
    10379{
    10480        unsigned long flags;
     
    10783        if (snd_BUG_ON(!rvoice))
    10884                return -EINVAL;
    109         if (snd_BUG_ON(!number))
     85        if (snd_BUG_ON(!count))
     86                return -EINVAL;
     87        if (snd_BUG_ON(!channels))
    11088                return -EINVAL;
    11189
    11290        spin_lock_irqsave(&emu->voice_lock, flags);
    113         for (;;) {
    114                 result = voice_alloc(emu, type, number, rvoice);
    115                 if (result == 0 || type == EMU10K1_SYNTH || type == EMU10K1_MIDI)
    116                         break;
    117 
    118                 /* free a voice from synth */
    119                 if (emu->get_synth_voice) {
     91        for (int got = 0; got < channels; ) {
     92                result = voice_alloc(emu, type, count, epcm, &rvoice[got]);
     93                if (result == 0) {
     94                        got++;
     95                        /*
     96                        dev_dbg(emu->card->dev, "voice alloc - %i, %i of %i\n",
     97                                rvoice[got - 1]->number, got, want);
     98                        */
     99                        continue;
     100                }
     101                if (type != EMU10K1_SYNTH && emu->get_synth_voice) {
     102                        /* free a voice from synth */
    120103                        result = emu->get_synth_voice(emu);
    121104                        if (result >= 0) {
    122                                 struct snd_emu10k1_voice *pvoice = &emu->voices[result];
    123                                 pvoice->interrupt = NULL;
    124                                 pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = pvoice->efx = 0;
    125                                 pvoice->epcm = NULL;
     105                                voice_free(emu, &emu->voices[result]);
     106                                continue;
    126107                        }
    127108                }
    128                 if (result < 0)
    129                         break;
     109                for (int i = 0; i < got; i++) {
     110                        for (int j = 0; j < count; j++)
     111                                voice_free(emu, rvoice[i] + j);
     112                        rvoice[i] = NULL;
     113                }
     114                break;
    130115        }
    131116        spin_unlock_irqrestore(&emu->voice_lock, flags);
     
    140125{
    141126        unsigned long flags;
     127        int last;
    142128
    143129        if (snd_BUG_ON(!pvoice))
    144130                return -EINVAL;
    145131        spin_lock_irqsave(&emu->voice_lock, flags);
    146         pvoice->interrupt = NULL;
    147         pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = pvoice->efx = 0;
    148         pvoice->epcm = NULL;
    149         snd_emu10k1_voice_init(emu, pvoice->number);
     132        do {
     133                last = pvoice->last;
     134                voice_free(emu, pvoice++);
     135        } while (!last);
    150136        spin_unlock_irqrestore(&emu->voice_lock, flags);
    151137        return 0;
Note: See TracChangeset for help on using the changeset viewer.