root/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pdacf_interrupt
  2. pdacf_transfer_mono16
  3. pdacf_transfer_mono32
  4. pdacf_transfer_stereo16
  5. pdacf_transfer_stereo32
  6. pdacf_transfer_mono16sw
  7. pdacf_transfer_mono32sw
  8. pdacf_transfer_stereo16sw
  9. pdacf_transfer_stereo32sw
  10. pdacf_transfer_mono24le
  11. pdacf_transfer_mono24be
  12. pdacf_transfer_stereo24le
  13. pdacf_transfer_stereo24be
  14. pdacf_transfer
  15. pdacf_threaded_irq

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Driver for Sound Core PDAudioCF soundcard
   4  *
   5  * Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz>
   6  */
   7 
   8 #include <sound/core.h>
   9 #include "pdaudiocf.h"
  10 #include <sound/initval.h>
  11 #include <asm/irq_regs.h>
  12 
  13 /*
  14  *
  15  */
  16 irqreturn_t pdacf_interrupt(int irq, void *dev)
  17 {
  18         struct snd_pdacf *chip = dev;
  19         unsigned short stat;
  20         bool wake_thread = false;
  21 
  22         if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|
  23                                   PDAUDIOCF_STAT_IS_CONFIGURED|
  24                                   PDAUDIOCF_STAT_IS_SUSPENDED)) != PDAUDIOCF_STAT_IS_CONFIGURED)
  25                 return IRQ_HANDLED;     /* IRQ_NONE here? */
  26 
  27         stat = inw(chip->port + PDAUDIOCF_REG_ISR);
  28         if (stat & (PDAUDIOCF_IRQLVL|PDAUDIOCF_IRQOVR)) {
  29                 if (stat & PDAUDIOCF_IRQOVR)    /* should never happen */
  30                         snd_printk(KERN_ERR "PDAUDIOCF SRAM buffer overrun detected!\n");
  31                 if (chip->pcm_substream)
  32                         wake_thread = true;
  33                 if (!(stat & PDAUDIOCF_IRQAKM))
  34                         stat |= PDAUDIOCF_IRQAKM;       /* check rate */
  35         }
  36         if (get_irq_regs() != NULL)
  37                 snd_ak4117_check_rate_and_errors(chip->ak4117, 0);
  38         return wake_thread ? IRQ_WAKE_THREAD : IRQ_HANDLED;
  39 }
  40 
  41 static inline void pdacf_transfer_mono16(u16 *dst, u16 xor, unsigned int size, unsigned long rdp_port)
  42 {
  43         while (size-- > 0) {
  44                 *dst++ = inw(rdp_port) ^ xor;
  45                 inw(rdp_port);
  46         }
  47 }
  48 
  49 static inline void pdacf_transfer_mono32(u32 *dst, u32 xor, unsigned int size, unsigned long rdp_port)
  50 {
  51         register u16 val1, val2;
  52 
  53         while (size-- > 0) {
  54                 val1 = inw(rdp_port);
  55                 val2 = inw(rdp_port);
  56                 inw(rdp_port);
  57                 *dst++ = ((((u32)val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor;
  58         }
  59 }
  60 
  61 static inline void pdacf_transfer_stereo16(u16 *dst, u16 xor, unsigned int size, unsigned long rdp_port)
  62 {
  63         while (size-- > 0) {
  64                 *dst++ = inw(rdp_port) ^ xor;
  65                 *dst++ = inw(rdp_port) ^ xor;
  66         }
  67 }
  68 
  69 static inline void pdacf_transfer_stereo32(u32 *dst, u32 xor, unsigned int size, unsigned long rdp_port)
  70 {
  71         register u16 val1, val2, val3;
  72 
  73         while (size-- > 0) {
  74                 val1 = inw(rdp_port);
  75                 val2 = inw(rdp_port);
  76                 val3 = inw(rdp_port);
  77                 *dst++ = ((((u32)val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor;
  78                 *dst++ = (((u32)val3 << 16) | (val2 & 0xff00)) ^ xor;
  79         }
  80 }
  81 
  82 static inline void pdacf_transfer_mono16sw(u16 *dst, u16 xor, unsigned int size, unsigned long rdp_port)
  83 {
  84         while (size-- > 0) {
  85                 *dst++ = swab16(inw(rdp_port) ^ xor);
  86                 inw(rdp_port);
  87         }
  88 }
  89 
  90 static inline void pdacf_transfer_mono32sw(u32 *dst, u32 xor, unsigned int size, unsigned long rdp_port)
  91 {
  92         register u16 val1, val2;
  93 
  94         while (size-- > 0) {
  95                 val1 = inw(rdp_port);
  96                 val2 = inw(rdp_port);
  97                 inw(rdp_port);
  98                 *dst++ = swab32((((val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor);
  99         }
 100 }
 101 
 102 static inline void pdacf_transfer_stereo16sw(u16 *dst, u16 xor, unsigned int size, unsigned long rdp_port)
 103 {
 104         while (size-- > 0) {
 105                 *dst++ = swab16(inw(rdp_port) ^ xor);
 106                 *dst++ = swab16(inw(rdp_port) ^ xor);
 107         }
 108 }
 109 
 110 static inline void pdacf_transfer_stereo32sw(u32 *dst, u32 xor, unsigned int size, unsigned long rdp_port)
 111 {
 112         register u16 val1, val2, val3;
 113 
 114         while (size-- > 0) {
 115                 val1 = inw(rdp_port);
 116                 val2 = inw(rdp_port);
 117                 val3 = inw(rdp_port);
 118                 *dst++ = swab32((((val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor);
 119                 *dst++ = swab32((((u32)val3 << 16) | (val2 & 0xff00)) ^ xor);
 120         }
 121 }
 122 
 123 static inline void pdacf_transfer_mono24le(u8 *dst, u16 xor, unsigned int size, unsigned long rdp_port)
 124 {
 125         register u16 val1, val2;
 126         register u32 xval1;
 127 
 128         while (size-- > 0) {
 129                 val1 = inw(rdp_port);
 130                 val2 = inw(rdp_port);
 131                 inw(rdp_port);
 132                 xval1 = (((val2 & 0xff) << 8) | (val1 << 16)) ^ xor;
 133                 *dst++ = (u8)(xval1 >> 8);
 134                 *dst++ = (u8)(xval1 >> 16);
 135                 *dst++ = (u8)(xval1 >> 24);
 136         }
 137 }
 138 
 139 static inline void pdacf_transfer_mono24be(u8 *dst, u16 xor, unsigned int size, unsigned long rdp_port)
 140 {
 141         register u16 val1, val2;
 142         register u32 xval1;
 143 
 144         while (size-- > 0) {
 145                 val1 = inw(rdp_port);
 146                 val2 = inw(rdp_port);
 147                 inw(rdp_port);
 148                 xval1 = (((val2 & 0xff) << 8) | (val1 << 16)) ^ xor;
 149                 *dst++ = (u8)(xval1 >> 24);
 150                 *dst++ = (u8)(xval1 >> 16);
 151                 *dst++ = (u8)(xval1 >> 8);
 152         }
 153 }
 154 
 155 static inline void pdacf_transfer_stereo24le(u8 *dst, u32 xor, unsigned int size, unsigned long rdp_port)
 156 {
 157         register u16 val1, val2, val3;
 158         register u32 xval1, xval2;
 159 
 160         while (size-- > 0) {
 161                 val1 = inw(rdp_port);
 162                 val2 = inw(rdp_port);
 163                 val3 = inw(rdp_port);
 164                 xval1 = ((((u32)val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor;
 165                 xval2 = (((u32)val3 << 16) | (val2 & 0xff00)) ^ xor;
 166                 *dst++ = (u8)(xval1 >> 8);
 167                 *dst++ = (u8)(xval1 >> 16);
 168                 *dst++ = (u8)(xval1 >> 24);
 169                 *dst++ = (u8)(xval2 >> 8);
 170                 *dst++ = (u8)(xval2 >> 16);
 171                 *dst++ = (u8)(xval2 >> 24);
 172         }
 173 }
 174 
 175 static inline void pdacf_transfer_stereo24be(u8 *dst, u32 xor, unsigned int size, unsigned long rdp_port)
 176 {
 177         register u16 val1, val2, val3;
 178         register u32 xval1, xval2;
 179 
 180         while (size-- > 0) {
 181                 val1 = inw(rdp_port);
 182                 val2 = inw(rdp_port);
 183                 val3 = inw(rdp_port);
 184                 xval1 = ((((u32)val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor;
 185                 xval2 = (((u32)val3 << 16) | (val2 & 0xff00)) ^ xor;
 186                 *dst++ = (u8)(xval1 >> 24);
 187                 *dst++ = (u8)(xval1 >> 16);
 188                 *dst++ = (u8)(xval1 >> 8);
 189                 *dst++ = (u8)(xval2 >> 24);
 190                 *dst++ = (u8)(xval2 >> 16);
 191                 *dst++ = (u8)(xval2 >> 8);
 192         }
 193 }
 194 
 195 static void pdacf_transfer(struct snd_pdacf *chip, unsigned int size, unsigned int off)
 196 {
 197         unsigned long rdp_port = chip->port + PDAUDIOCF_REG_MD;
 198         unsigned int xor = chip->pcm_xor;
 199 
 200         if (chip->pcm_sample == 3) {
 201                 if (chip->pcm_little) {
 202                         if (chip->pcm_channels == 1) {
 203                                 pdacf_transfer_mono24le((char *)chip->pcm_area + (off * 3), xor, size, rdp_port);
 204                         } else {
 205                                 pdacf_transfer_stereo24le((char *)chip->pcm_area + (off * 6), xor, size, rdp_port);
 206                         }
 207                 } else {
 208                         if (chip->pcm_channels == 1) {
 209                                 pdacf_transfer_mono24be((char *)chip->pcm_area + (off * 3), xor, size, rdp_port);
 210                         } else {
 211                                 pdacf_transfer_stereo24be((char *)chip->pcm_area + (off * 6), xor, size, rdp_port);
 212                         }                       
 213                 }
 214                 return;
 215         }
 216         if (chip->pcm_swab == 0) {
 217                 if (chip->pcm_channels == 1) {
 218                         if (chip->pcm_frame == 2) {
 219                                 pdacf_transfer_mono16((u16 *)chip->pcm_area + off, xor, size, rdp_port);
 220                         } else {
 221                                 pdacf_transfer_mono32((u32 *)chip->pcm_area + off, xor, size, rdp_port);
 222                         }
 223                 } else {
 224                         if (chip->pcm_frame == 2) {
 225                                 pdacf_transfer_stereo16((u16 *)chip->pcm_area + (off * 2), xor, size, rdp_port);
 226                         } else {
 227                                 pdacf_transfer_stereo32((u32 *)chip->pcm_area + (off * 2), xor, size, rdp_port);
 228                         }
 229                 }
 230         } else {
 231                 if (chip->pcm_channels == 1) {
 232                         if (chip->pcm_frame == 2) {
 233                                 pdacf_transfer_mono16sw((u16 *)chip->pcm_area + off, xor, size, rdp_port);
 234                         } else {
 235                                 pdacf_transfer_mono32sw((u32 *)chip->pcm_area + off, xor, size, rdp_port);
 236                         }
 237                 } else {
 238                         if (chip->pcm_frame == 2) {
 239                                 pdacf_transfer_stereo16sw((u16 *)chip->pcm_area + (off * 2), xor, size, rdp_port);
 240                         } else {
 241                                 pdacf_transfer_stereo32sw((u32 *)chip->pcm_area + (off * 2), xor, size, rdp_port);
 242                         }
 243                 }
 244         }
 245 }
 246 
 247 irqreturn_t pdacf_threaded_irq(int irq, void *dev)
 248 {
 249         struct snd_pdacf *chip = dev;
 250         int size, off, cont, rdp, wdp;
 251 
 252         if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|PDAUDIOCF_STAT_IS_CONFIGURED)) != PDAUDIOCF_STAT_IS_CONFIGURED)
 253                 return IRQ_HANDLED;
 254         
 255         if (chip->pcm_substream == NULL || chip->pcm_substream->runtime == NULL || !snd_pcm_running(chip->pcm_substream))
 256                 return IRQ_HANDLED;
 257 
 258         rdp = inw(chip->port + PDAUDIOCF_REG_RDP);
 259         wdp = inw(chip->port + PDAUDIOCF_REG_WDP);
 260         /* printk(KERN_DEBUG "TASKLET: rdp = %x, wdp = %x\n", rdp, wdp); */
 261         size = wdp - rdp;
 262         if (size < 0)
 263                 size += 0x10000;
 264         if (size == 0)
 265                 size = 0x10000;
 266         size /= chip->pcm_frame;
 267         if (size > 64)
 268                 size -= 32;
 269 
 270 #if 0
 271         chip->pcm_hwptr += size;
 272         chip->pcm_hwptr %= chip->pcm_size;
 273         chip->pcm_tdone += size;
 274         if (chip->pcm_frame == 2) {
 275                 unsigned long rdp_port = chip->port + PDAUDIOCF_REG_MD;
 276                 while (size-- > 0) {
 277                         inw(rdp_port);
 278                         inw(rdp_port);
 279                 }
 280         } else {
 281                 unsigned long rdp_port = chip->port + PDAUDIOCF_REG_MD;
 282                 while (size-- > 0) {
 283                         inw(rdp_port);
 284                         inw(rdp_port);
 285                         inw(rdp_port);
 286                 }
 287         }
 288 #else
 289         off = chip->pcm_hwptr + chip->pcm_tdone;
 290         off %= chip->pcm_size;
 291         chip->pcm_tdone += size;
 292         while (size > 0) {
 293                 cont = chip->pcm_size - off;
 294                 if (cont > size)
 295                         cont = size;
 296                 pdacf_transfer(chip, cont, off);
 297                 off += cont;
 298                 off %= chip->pcm_size;
 299                 size -= cont;
 300         }
 301 #endif
 302         mutex_lock(&chip->reg_lock);
 303         while (chip->pcm_tdone >= chip->pcm_period) {
 304                 chip->pcm_hwptr += chip->pcm_period;
 305                 chip->pcm_hwptr %= chip->pcm_size;
 306                 chip->pcm_tdone -= chip->pcm_period;
 307                 mutex_unlock(&chip->reg_lock);
 308                 snd_pcm_period_elapsed(chip->pcm_substream);
 309                 mutex_lock(&chip->reg_lock);
 310         }
 311         mutex_unlock(&chip->reg_lock);
 312         return IRQ_HANDLED;
 313 }

/* [<][>][^][v][top][bottom][index][help] */