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