^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) * ALSA modem driver for VIA VT82xx (South Bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * VT82C686A/B/C, VT8233A/C, VT8235
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Tjeerd.Mulder <Tjeerd.Mulder@fujitsu-siemens.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * 2002 Takashi Iwai <tiwai@suse.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Changes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Sep. 2, 2004 Sasha Khapyorsky <sashak@alsa-project.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Modified from original audio driver 'via82xx.c' to support AC97
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * modems.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <sound/pcm_params.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <sound/info.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <sound/ac97_codec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <sound/initval.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define POINTER_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) MODULE_DESCRIPTION("VIA VT82xx modem");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C modem,pci}}");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static int index = -2; /* Exclude the first card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static int ac97_clock = 48000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) module_param(index, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) MODULE_PARM_DESC(index, "Index value for VIA 82xx bridge.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) module_param(id, charp, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) MODULE_PARM_DESC(id, "ID string for VIA 82xx bridge.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) module_param(ac97_clock, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz).");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /* just for backward compatibility */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static bool enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) module_param(enable, bool, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^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) * Direct registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define VIAREG(via, x) ((via)->port + VIA_REG_##x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define VIADEV_REG(viadev, x) ((viadev)->port + VIA_REG_##x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* common offsets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define VIA_REG_OFFSET_STATUS 0x00 /* byte - channel status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define VIA_REG_STAT_ACTIVE 0x80 /* RO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define VIA_REG_STAT_PAUSED 0x40 /* RO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define VIA_REG_STAT_TRIGGER_QUEUED 0x08 /* RO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define VIA_REG_STAT_STOPPED 0x04 /* RWC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define VIA_REG_STAT_EOL 0x02 /* RWC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define VIA_REG_STAT_FLAG 0x01 /* RWC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define VIA_REG_OFFSET_CONTROL 0x01 /* byte - channel control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define VIA_REG_CTRL_START 0x80 /* WO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define VIA_REG_CTRL_TERMINATE 0x40 /* WO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define VIA_REG_CTRL_AUTOSTART 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define VIA_REG_CTRL_PAUSE 0x08 /* RW */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define VIA_REG_CTRL_INT_STOP 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define VIA_REG_CTRL_INT_EOL 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define VIA_REG_CTRL_INT_FLAG 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define VIA_REG_CTRL_RESET 0x01 /* RW - probably reset? undocumented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define VIA_REG_CTRL_INT (VIA_REG_CTRL_INT_FLAG | VIA_REG_CTRL_INT_EOL | VIA_REG_CTRL_AUTOSTART)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define VIA_REG_OFFSET_TYPE 0x02 /* byte - channel type (686 only) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define VIA_REG_TYPE_AUTOSTART 0x80 /* RW - autostart at EOL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define VIA_REG_TYPE_16BIT 0x20 /* RW */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define VIA_REG_TYPE_STEREO 0x10 /* RW */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define VIA_REG_TYPE_INT_LLINE 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define VIA_REG_TYPE_INT_LSAMPLE 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define VIA_REG_TYPE_INT_LESSONE 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define VIA_REG_TYPE_INT_MASK 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define VIA_REG_TYPE_INT_EOL 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define VIA_REG_TYPE_INT_FLAG 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define VIA_REG_OFFSET_TABLE_PTR 0x04 /* dword - channel table pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define VIA_REG_OFFSET_CURR_PTR 0x04 /* dword - channel current pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define VIA_REG_OFFSET_STOP_IDX 0x08 /* dword - stop index, channel type, sample rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define VIA_REG_OFFSET_CURR_COUNT 0x0c /* dword - channel current count (24 bit) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define VIA_REG_OFFSET_CURR_INDEX 0x0f /* byte - channel current index (for via8233 only) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define DEFINE_VIA_REGSET(name,val) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) enum {\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) VIA_REG_##name##_STATUS = (val),\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) VIA_REG_##name##_CONTROL = (val) + 0x01,\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) VIA_REG_##name##_TYPE = (val) + 0x02,\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) VIA_REG_##name##_TABLE_PTR = (val) + 0x04,\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) VIA_REG_##name##_CURR_PTR = (val) + 0x04,\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) VIA_REG_##name##_STOP_IDX = (val) + 0x08,\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) VIA_REG_##name##_CURR_COUNT = (val) + 0x0c,\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* modem block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) DEFINE_VIA_REGSET(MO, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) DEFINE_VIA_REGSET(MI, 0x50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /* AC'97 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define VIA_REG_AC97 0x80 /* dword */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define VIA_REG_AC97_CODEC_ID_MASK (3<<30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define VIA_REG_AC97_CODEC_ID_SHIFT 30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define VIA_REG_AC97_CODEC_ID_PRIMARY 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define VIA_REG_AC97_CODEC_ID_SECONDARY 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define VIA_REG_AC97_SECONDARY_VALID (1<<27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #define VIA_REG_AC97_PRIMARY_VALID (1<<25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define VIA_REG_AC97_BUSY (1<<24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define VIA_REG_AC97_READ (1<<23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define VIA_REG_AC97_CMD_SHIFT 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #define VIA_REG_AC97_CMD_MASK 0x7e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define VIA_REG_AC97_DATA_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define VIA_REG_AC97_DATA_MASK 0xffff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define VIA_REG_SGD_SHADOW 0x84 /* dword */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define VIA_REG_SGD_STAT_PB_FLAG (1<<0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define VIA_REG_SGD_STAT_CP_FLAG (1<<1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define VIA_REG_SGD_STAT_FM_FLAG (1<<2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define VIA_REG_SGD_STAT_PB_EOL (1<<4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define VIA_REG_SGD_STAT_CP_EOL (1<<5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define VIA_REG_SGD_STAT_FM_EOL (1<<6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define VIA_REG_SGD_STAT_PB_STOP (1<<8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define VIA_REG_SGD_STAT_CP_STOP (1<<9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define VIA_REG_SGD_STAT_FM_STOP (1<<10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #define VIA_REG_SGD_STAT_PB_ACTIVE (1<<12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #define VIA_REG_SGD_STAT_CP_ACTIVE (1<<13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #define VIA_REG_SGD_STAT_FM_ACTIVE (1<<14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define VIA_REG_SGD_STAT_MR_FLAG (1<<16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define VIA_REG_SGD_STAT_MW_FLAG (1<<17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #define VIA_REG_SGD_STAT_MR_EOL (1<<20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define VIA_REG_SGD_STAT_MW_EOL (1<<21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define VIA_REG_SGD_STAT_MR_STOP (1<<24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #define VIA_REG_SGD_STAT_MW_STOP (1<<25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define VIA_REG_SGD_STAT_MR_ACTIVE (1<<28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #define VIA_REG_SGD_STAT_MW_ACTIVE (1<<29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define VIA_REG_GPI_STATUS 0x88
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #define VIA_REG_GPI_INTR 0x8c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #define VIA_TBL_BIT_FLAG 0x40000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #define VIA_TBL_BIT_EOL 0x80000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /* pci space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #define VIA_ACLINK_STAT 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #define VIA_ACLINK_C11_READY 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #define VIA_ACLINK_C10_READY 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #define VIA_ACLINK_C01_READY 0x04 /* secondary codec ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #define VIA_ACLINK_LOWPOWER 0x02 /* low-power state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #define VIA_ACLINK_C00_READY 0x01 /* primary codec ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) #define VIA_ACLINK_CTRL 0x41
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #define VIA_ACLINK_CTRL_ENABLE 0x80 /* 0: disable, 1: enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) #define VIA_ACLINK_CTRL_RESET 0x40 /* 0: assert, 1: de-assert */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) #define VIA_ACLINK_CTRL_SYNC 0x20 /* 0: release SYNC, 1: force SYNC hi */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) #define VIA_ACLINK_CTRL_SDO 0x10 /* 0: release SDO, 1: force SDO hi */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) #define VIA_ACLINK_CTRL_VRA 0x08 /* 0: disable VRA, 1: enable VRA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #define VIA_ACLINK_CTRL_PCM 0x04 /* 0: disable PCM, 1: enable PCM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) #define VIA_ACLINK_CTRL_FM 0x02 /* via686 only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #define VIA_ACLINK_CTRL_SB 0x01 /* via686 only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #define VIA_ACLINK_CTRL_INIT (VIA_ACLINK_CTRL_ENABLE|\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) VIA_ACLINK_CTRL_RESET|\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) VIA_ACLINK_CTRL_PCM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) #define VIA_FUNC_ENABLE 0x42
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) #define VIA_FUNC_MIDI_PNP 0x80 /* FIXME: it's 0x40 in the datasheet! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) #define VIA_FUNC_MIDI_IRQMASK 0x40 /* FIXME: not documented! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #define VIA_FUNC_RX2C_WRITE 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #define VIA_FUNC_SB_FIFO_EMPTY 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) #define VIA_FUNC_ENABLE_GAME 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #define VIA_FUNC_ENABLE_FM 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #define VIA_FUNC_ENABLE_MIDI 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) #define VIA_FUNC_ENABLE_SB 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) #define VIA_PNP_CONTROL 0x43
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) #define VIA_MC97_CTRL 0x44
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) #define VIA_MC97_CTRL_ENABLE 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) #define VIA_MC97_CTRL_SECONDARY 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) #define VIA_MC97_CTRL_INIT (VIA_MC97_CTRL_ENABLE|\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) VIA_MC97_CTRL_SECONDARY)
^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) * pcm stream
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct snd_via_sg_table {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) unsigned int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) unsigned int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) } ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) #define VIA_TABLE_SIZE 255
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct viadev {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) unsigned int reg_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) unsigned long port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) int direction; /* playback = 0, capture = 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct snd_pcm_substream *substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) int running;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) unsigned int tbl_entries; /* # descriptors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct snd_dma_buffer table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct snd_via_sg_table *idx_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) /* for recovery from the unexpected pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) unsigned int lastpos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) unsigned int bufsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) unsigned int bufsize2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) enum { TYPE_CARD_VIA82XX_MODEM = 1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) #define VIA_MAX_MODEM_DEVS 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct via82xx_modem {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) unsigned long port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) unsigned int intr_mask; /* SGD_SHADOW mask to check interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct pci_dev *pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) struct snd_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) unsigned int num_devs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) unsigned int playback_devno, capture_devno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct viadev devs[VIA_MAX_MODEM_DEVS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) struct snd_pcm *pcms[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct snd_ac97_bus *ac97_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) struct snd_ac97 *ac97;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) unsigned int ac97_clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) unsigned int ac97_secondary; /* secondary AC'97 codec is present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) spinlock_t reg_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct snd_info_entry *proc_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) static const struct pci_device_id snd_via82xx_modem_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) { PCI_VDEVICE(VIA, 0x3068), TYPE_CARD_VIA82XX_MODEM, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) { 0, }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) MODULE_DEVICE_TABLE(pci, snd_via82xx_modem_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * allocate and initialize the descriptor buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * periods = number of periods
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * fragsize = period size in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) struct pci_dev *pci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) unsigned int periods, unsigned int fragsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) unsigned int i, idx, ofs, rest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) struct via82xx_modem *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) __le32 *pgtbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (dev->table.area == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* the start of each lists must be aligned to 8 bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * but the kernel pages are much bigger, so we don't care
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &chip->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) PAGE_ALIGN(VIA_TABLE_SIZE * 2 * 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) &dev->table) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (! dev->idx_table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) dev->idx_table = kmalloc_array(VIA_TABLE_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) sizeof(*dev->idx_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (! dev->idx_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /* fill the entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) ofs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) pgtbl = (__le32 *)dev->table.area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) for (i = 0; i < periods; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) rest = fragsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) /* fill descriptors for a period.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * a period can be split to several descriptors if it's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * over page boundary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) unsigned int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) unsigned int flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) unsigned int addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (idx >= VIA_TABLE_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) dev_err(&pci->dev, "too much table size!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) addr = snd_pcm_sgbuf_get_addr(substream, ofs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) pgtbl[idx << 1] = cpu_to_le32(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) r = PAGE_SIZE - (ofs % PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (rest < r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) r = rest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) rest -= r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (! rest) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (i == periods - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) flag = VIA_TBL_BIT_EOL; /* buffer boundary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) flag = VIA_TBL_BIT_FLAG; /* period boundary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) flag = 0; /* period continues to the next */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) dev_dbg(&pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) "tbl %d: at %d size %d (rest %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) idx, ofs, r, rest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) pgtbl[(idx<<1) + 1] = cpu_to_le32(r | flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) dev->idx_table[idx].offset = ofs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) dev->idx_table[idx].size = r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) ofs += r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) } while (rest > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) dev->tbl_entries = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) dev->bufsize = periods * fragsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) dev->bufsize2 = dev->bufsize / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static int clean_via_table(struct viadev *dev, struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) struct pci_dev *pci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (dev->table.area) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) snd_dma_free_pages(&dev->table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) dev->table.area = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) kfree(dev->idx_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) dev->idx_table = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * Basic I/O
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static inline unsigned int snd_via82xx_codec_xread(struct via82xx_modem *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) return inl(VIAREG(chip, AC97));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) static inline void snd_via82xx_codec_xwrite(struct via82xx_modem *chip, unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) outl(val, VIAREG(chip, AC97));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) static int snd_via82xx_codec_ready(struct via82xx_modem *chip, int secondary)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) unsigned int timeout = 1000; /* 1ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) while (timeout-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (!((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) return val & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) dev_err(chip->card->dev, "codec_ready: codec %i is not ready [0x%x]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) secondary, snd_via82xx_codec_xread(chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) static int snd_via82xx_codec_valid(struct via82xx_modem *chip, int secondary)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) unsigned int timeout = 1000; /* 1ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) unsigned int val, val1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) unsigned int stat = !secondary ? VIA_REG_AC97_PRIMARY_VALID :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) VIA_REG_AC97_SECONDARY_VALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) while (timeout-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) val = snd_via82xx_codec_xread(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) val1 = val & (VIA_REG_AC97_BUSY | stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (val1 == stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return val & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) static void snd_via82xx_codec_wait(struct snd_ac97 *ac97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) struct via82xx_modem *chip = ac97->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) __always_unused int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) err = snd_via82xx_codec_ready(chip, ac97->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) /* here we need to wait fairly for long time.. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) msleep(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) static void snd_via82xx_codec_write(struct snd_ac97 *ac97,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) unsigned short reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) unsigned short val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) struct via82xx_modem *chip = ac97->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) unsigned int xval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if(reg == AC97_GPIO_STATUS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) outl(val, VIAREG(chip, GPI_STATUS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) xval = !ac97->num ? VIA_REG_AC97_CODEC_ID_PRIMARY : VIA_REG_AC97_CODEC_ID_SECONDARY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) xval <<= VIA_REG_AC97_CODEC_ID_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) xval |= reg << VIA_REG_AC97_CMD_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) xval |= val << VIA_REG_AC97_DATA_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) snd_via82xx_codec_xwrite(chip, xval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) snd_via82xx_codec_ready(chip, ac97->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static unsigned short snd_via82xx_codec_read(struct snd_ac97 *ac97, unsigned short reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) struct via82xx_modem *chip = ac97->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) unsigned int xval, val = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) int again = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) xval = ac97->num << VIA_REG_AC97_CODEC_ID_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) xval |= ac97->num ? VIA_REG_AC97_SECONDARY_VALID : VIA_REG_AC97_PRIMARY_VALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) xval |= VIA_REG_AC97_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) xval |= (reg & 0x7f) << VIA_REG_AC97_CMD_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (again++ > 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) "codec_read: codec %i is not valid [0x%x]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) ac97->num, snd_via82xx_codec_xread(chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) return 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) snd_via82xx_codec_xwrite(chip, xval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) udelay (20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (snd_via82xx_codec_valid(chip, ac97->num) >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) udelay(25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) val = snd_via82xx_codec_xread(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) return val & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) static void snd_via82xx_channel_reset(struct via82xx_modem *chip, struct viadev *viadev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) outb(VIA_REG_CTRL_PAUSE | VIA_REG_CTRL_TERMINATE | VIA_REG_CTRL_RESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) VIADEV_REG(viadev, OFFSET_CONTROL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) inb(VIADEV_REG(viadev, OFFSET_CONTROL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) udelay(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) /* disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) outb(0x00, VIADEV_REG(viadev, OFFSET_CONTROL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) /* clear interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) outb(0x03, VIADEV_REG(viadev, OFFSET_STATUS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) outb(0x00, VIADEV_REG(viadev, OFFSET_TYPE)); /* for via686 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) // outl(0, VIADEV_REG(viadev, OFFSET_CURR_PTR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) viadev->lastpos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) * Interrupt handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) struct via82xx_modem *chip = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) unsigned int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) status = inl(VIAREG(chip, SGD_SHADOW));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if (! (status & chip->intr_mask)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) // _skip_sgd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) /* check status for each stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) spin_lock(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) for (i = 0; i < chip->num_devs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) struct viadev *viadev = &chip->devs[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) unsigned char c_status = inb(VIADEV_REG(viadev, OFFSET_STATUS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) c_status &= (VIA_REG_STAT_EOL|VIA_REG_STAT_FLAG|VIA_REG_STAT_STOPPED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (! c_status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (viadev->substream && viadev->running) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) spin_unlock(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) snd_pcm_period_elapsed(viadev->substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) spin_lock(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) outb(c_status, VIADEV_REG(viadev, OFFSET_STATUS)); /* ack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) spin_unlock(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) * PCM callbacks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) * trigger callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) static int snd_via82xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) struct via82xx_modem *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) struct viadev *viadev = substream->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) unsigned char val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) case SNDRV_PCM_TRIGGER_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) val |= VIA_REG_CTRL_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) viadev->running = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) val = VIA_REG_CTRL_TERMINATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) viadev->running = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) val |= VIA_REG_CTRL_PAUSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) viadev->running = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) viadev->running = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) outb(val, VIADEV_REG(viadev, OFFSET_CONTROL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (cmd == SNDRV_PCM_TRIGGER_STOP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) snd_via82xx_channel_reset(chip, viadev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) * pointer callbacks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) * calculate the linear position at the given sg-buffer index and the rest count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) #define check_invalid_pos(viadev,pos) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) ((pos) < viadev->lastpos && ((pos) >= viadev->bufsize2 ||\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) viadev->lastpos < viadev->bufsize2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) static inline unsigned int calc_linear_pos(struct via82xx_modem *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) struct viadev *viadev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) unsigned int idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) unsigned int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) unsigned int size, res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) size = viadev->idx_table[idx].size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) res = viadev->idx_table[idx].offset + size - count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) /* check the validity of the calculated position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (size < count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) "invalid via82xx_cur_ptr (size = %d, count = %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) (int)size, (int)count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) res = viadev->lastpos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) } else if (check_invalid_pos(viadev, res)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) #ifdef POINTER_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) dev_dbg(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) "fail: idx = %i/%i, lastpos = 0x%x, bufsize2 = 0x%x, offsize = 0x%x, size = 0x%x, count = 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) idx, viadev->tbl_entries, viadev->lastpos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) viadev->bufsize2, viadev->idx_table[idx].offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) viadev->idx_table[idx].size, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (count && size < count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) dev_dbg(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) "invalid via82xx_cur_ptr, using last valid pointer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) res = viadev->lastpos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (! count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) /* bogus count 0 on the DMA boundary? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) res = viadev->idx_table[idx].offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) /* count register returns full size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * when end of buffer is reached
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) res = viadev->idx_table[idx].offset + size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (check_invalid_pos(viadev, res)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) dev_dbg(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) "invalid via82xx_cur_ptr (2), using last valid pointer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) res = viadev->lastpos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) viadev->lastpos = res; /* remember the last position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (res >= viadev->bufsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) res -= viadev->bufsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) * get the current pointer on via686
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) static snd_pcm_uframes_t snd_via686_pcm_pointer(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) struct via82xx_modem *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) struct viadev *viadev = substream->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) unsigned int idx, ptr, count, res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) if (snd_BUG_ON(!viadev->tbl_entries))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (!(inb(VIADEV_REG(viadev, OFFSET_STATUS)) & VIA_REG_STAT_ACTIVE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) spin_lock(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) count = inl(VIADEV_REG(viadev, OFFSET_CURR_COUNT)) & 0xffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) /* The via686a does not have the current index register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) * so we need to calculate the index from CURR_PTR.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) ptr = inl(VIADEV_REG(viadev, OFFSET_CURR_PTR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (ptr <= (unsigned int)viadev->table.addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) else /* CURR_PTR holds the address + 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) idx = ((ptr - (unsigned int)viadev->table.addr) / 8 - 1) %
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) viadev->tbl_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) res = calc_linear_pos(chip, viadev, idx, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) spin_unlock(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) return bytes_to_frames(substream->runtime, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) * hw_params callback:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) * allocate the buffer and build up the buffer description table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) static int snd_via82xx_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) struct snd_pcm_hw_params *hw_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) struct via82xx_modem *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) struct viadev *viadev = substream->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) err = build_via_table(viadev, substream, chip->pci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) params_periods(hw_params),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) params_period_bytes(hw_params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) snd_ac97_write(chip->ac97, AC97_LINE1_RATE, params_rate(hw_params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) snd_ac97_write(chip->ac97, AC97_LINE1_LEVEL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) * hw_free callback:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) * clean up the buffer description table and release the buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) static int snd_via82xx_hw_free(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) struct via82xx_modem *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) struct viadev *viadev = substream->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) clean_via_table(viadev, substream, chip->pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * set up the table pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) static void snd_via82xx_set_table_ptr(struct via82xx_modem *chip, struct viadev *viadev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) snd_via82xx_codec_ready(chip, chip->ac97_secondary);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) outl((u32)viadev->table.addr, VIADEV_REG(viadev, OFFSET_TABLE_PTR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) udelay(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) snd_via82xx_codec_ready(chip, chip->ac97_secondary);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * prepare callback for playback and capture
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) static int snd_via82xx_pcm_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) struct via82xx_modem *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) struct viadev *viadev = substream->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) snd_via82xx_channel_reset(chip, viadev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) /* this must be set after channel_reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) snd_via82xx_set_table_ptr(chip, viadev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) outb(VIA_REG_TYPE_AUTOSTART|VIA_REG_TYPE_INT_EOL|VIA_REG_TYPE_INT_FLAG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) VIADEV_REG(viadev, OFFSET_TYPE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) * pcm hardware definition, identical for both playback and capture
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) static const struct snd_pcm_hardware snd_via82xx_hw =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) SNDRV_PCM_INFO_BLOCK_TRANSFER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) SNDRV_PCM_INFO_MMAP_VALID |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) /* SNDRV_PCM_INFO_RESUME | */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) SNDRV_PCM_INFO_PAUSE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_KNOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) .rate_min = 8000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) .rate_max = 16000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) .channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) .channels_max = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) .buffer_bytes_max = 128 * 1024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) .period_bytes_min = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) .period_bytes_max = 128 * 1024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) .periods_min = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) .periods_max = VIA_TABLE_SIZE / 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) .fifo_size = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) * open callback skeleton
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) static int snd_via82xx_modem_pcm_open(struct via82xx_modem *chip, struct viadev *viadev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) static const unsigned int rates[] = { 8000, 9600, 12000, 16000 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) static const struct snd_pcm_hw_constraint_list hw_constraints_rates = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) .count = ARRAY_SIZE(rates),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) .list = rates,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) .mask = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) runtime->hw = snd_via82xx_hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if ((err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) &hw_constraints_rates)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) /* we may remove following constaint when we modify table entries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) in interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) runtime->private_data = viadev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) viadev->substream = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) * open callback for playback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) static int snd_via82xx_playback_open(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) struct via82xx_modem *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) struct viadev *viadev = &chip->devs[chip->playback_devno + substream->number];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) return snd_via82xx_modem_pcm_open(chip, viadev, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) * open callback for capture
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) static int snd_via82xx_capture_open(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) struct via82xx_modem *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) struct viadev *viadev = &chip->devs[chip->capture_devno + substream->pcm->device];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) return snd_via82xx_modem_pcm_open(chip, viadev, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) * close callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) static int snd_via82xx_pcm_close(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) struct viadev *viadev = substream->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) viadev->substream = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) /* via686 playback callbacks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) static const struct snd_pcm_ops snd_via686_playback_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) .open = snd_via82xx_playback_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) .close = snd_via82xx_pcm_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) .hw_params = snd_via82xx_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) .hw_free = snd_via82xx_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) .prepare = snd_via82xx_pcm_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) .trigger = snd_via82xx_pcm_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) .pointer = snd_via686_pcm_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) /* via686 capture callbacks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) static const struct snd_pcm_ops snd_via686_capture_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) .open = snd_via82xx_capture_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) .close = snd_via82xx_pcm_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) .hw_params = snd_via82xx_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) .hw_free = snd_via82xx_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) .prepare = snd_via82xx_pcm_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) .trigger = snd_via82xx_pcm_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) .pointer = snd_via686_pcm_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) static void init_viadev(struct via82xx_modem *chip, int idx, unsigned int reg_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) int direction)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) chip->devs[idx].reg_offset = reg_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) chip->devs[idx].direction = direction;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) chip->devs[idx].port = chip->port + reg_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) * create a pcm instance for via686a/b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) static int snd_via686_pcm_new(struct via82xx_modem *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) struct snd_pcm *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) chip->playback_devno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) chip->capture_devno = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) chip->num_devs = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) chip->intr_mask = 0x330000; /* FLAGS | EOL for MR, MW */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) err = snd_pcm_new(chip->card, chip->card->shortname, 0, 1, 1, &pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_via686_playback_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_via686_capture_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) pcm->dev_class = SNDRV_PCM_CLASS_MODEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) pcm->private_data = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) strcpy(pcm->name, chip->card->shortname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) chip->pcms[0] = pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) init_viadev(chip, 0, VIA_REG_MO_STATUS, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) init_viadev(chip, 1, VIA_REG_MI_STATUS, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) &chip->pci->dev, 64*1024, 128*1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) * Mixer part
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) static void snd_via82xx_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) struct via82xx_modem *chip = bus->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) chip->ac97_bus = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) static void snd_via82xx_mixer_free_ac97(struct snd_ac97 *ac97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) struct via82xx_modem *chip = ac97->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) chip->ac97 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) static int snd_via82xx_mixer_new(struct via82xx_modem *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) struct snd_ac97_template ac97;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) static const struct snd_ac97_bus_ops ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) .write = snd_via82xx_codec_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) .read = snd_via82xx_codec_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) .wait = snd_via82xx_codec_wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) chip->ac97_bus->private_free = snd_via82xx_mixer_free_ac97_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) chip->ac97_bus->clock = chip->ac97_clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) memset(&ac97, 0, sizeof(ac97));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) ac97.private_data = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) ac97.private_free = snd_via82xx_mixer_free_ac97;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) ac97.pci = chip->pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) ac97.num = chip->ac97_secondary;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) * proc interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) static void snd_via82xx_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) struct via82xx_modem *chip = entry->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) snd_iprintf(buffer, "%s\n\n", chip->card->longname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) for (i = 0; i < 0xa0; i += 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) snd_iprintf(buffer, "%02x: %08x\n", i, inl(chip->port + i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) static void snd_via82xx_proc_init(struct via82xx_modem *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) snd_card_ro_proc_new(chip->card, "via82xx", chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) snd_via82xx_proc_read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) static int snd_via82xx_chip_init(struct via82xx_modem *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) unsigned long end_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) unsigned char pval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) pci_read_config_byte(chip->pci, VIA_MC97_CTRL, &pval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) if((pval & VIA_MC97_CTRL_INIT) != VIA_MC97_CTRL_INIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) pci_write_config_byte(chip->pci, 0x44, pval|VIA_MC97_CTRL_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) if (! (pval & VIA_ACLINK_C00_READY)) { /* codec not ready? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) /* deassert ACLink reset, force SYNC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) VIA_ACLINK_CTRL_ENABLE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) VIA_ACLINK_CTRL_RESET |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) VIA_ACLINK_CTRL_SYNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) #if 1 /* FIXME: should we do full reset here for all chip models? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) /* deassert ACLink reset, force SYNC (warm AC'97 reset) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) VIA_ACLINK_CTRL_RESET|VIA_ACLINK_CTRL_SYNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) udelay(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) /* ACLink on, deassert ACLink reset, VSR, SGD data out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, VIA_ACLINK_CTRL_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) pci_read_config_byte(chip->pci, VIA_ACLINK_CTRL, &pval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) if ((pval & VIA_ACLINK_CTRL_INIT) != VIA_ACLINK_CTRL_INIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) /* ACLink on, deassert ACLink reset, VSR, SGD data out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, VIA_ACLINK_CTRL_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) /* wait until codec ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) end_time = jiffies + msecs_to_jiffies(750);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) schedule_timeout_uninterruptible(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) } while (time_before(jiffies, end_time));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) "AC'97 codec is not ready [0x%x]\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) VIA_REG_AC97_SECONDARY_VALID |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) end_time = jiffies + msecs_to_jiffies(750);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) VIA_REG_AC97_SECONDARY_VALID |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_SECONDARY_VALID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) chip->ac97_secondary = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) goto __ac97_ok2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) schedule_timeout_uninterruptible(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) } while (time_before(jiffies, end_time));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) /* This is ok, the most of motherboards have only one codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) __ac97_ok2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) /* route FM trap to IRQ, disable FM trap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) // pci_write_config_byte(chip->pci, VIA_FM_NMI_CTRL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) /* disable all GPI interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) outl(0, VIAREG(chip, GPI_INTR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) * power management
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) static int snd_via82xx_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) struct snd_card *card = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) struct via82xx_modem *chip = card->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) for (i = 0; i < chip->num_devs; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) snd_via82xx_channel_reset(chip, &chip->devs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) snd_ac97_suspend(chip->ac97);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) static int snd_via82xx_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) struct snd_card *card = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) struct via82xx_modem *chip = card->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) snd_via82xx_chip_init(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) snd_ac97_resume(chip->ac97);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) for (i = 0; i < chip->num_devs; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) snd_via82xx_channel_reset(chip, &chip->devs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) snd_power_change_state(card, SNDRV_CTL_POWER_D0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) static SIMPLE_DEV_PM_OPS(snd_via82xx_pm, snd_via82xx_suspend, snd_via82xx_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) #define SND_VIA82XX_PM_OPS &snd_via82xx_pm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) #define SND_VIA82XX_PM_OPS NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) #endif /* CONFIG_PM_SLEEP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) static int snd_via82xx_free(struct via82xx_modem *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) if (chip->irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) goto __end_hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) /* disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) for (i = 0; i < chip->num_devs; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) snd_via82xx_channel_reset(chip, &chip->devs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) __end_hw:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) if (chip->irq >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) free_irq(chip->irq, chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) pci_release_regions(chip->pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) pci_disable_device(chip->pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) kfree(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) static int snd_via82xx_dev_free(struct snd_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) struct via82xx_modem *chip = device->device_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) return snd_via82xx_free(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) static int snd_via82xx_create(struct snd_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) struct pci_dev *pci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) int chip_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) int revision,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) unsigned int ac97_clock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) struct via82xx_modem **r_via)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) struct via82xx_modem *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) static const struct snd_device_ops ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) .dev_free = snd_via82xx_dev_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) if ((err = pci_enable_device(pci)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) if ((chip = kzalloc(sizeof(*chip), GFP_KERNEL)) == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) pci_disable_device(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) spin_lock_init(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) chip->card = card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) chip->pci = pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) chip->irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) if ((err = pci_request_regions(pci, card->driver)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) kfree(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) pci_disable_device(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) chip->port = pci_resource_start(pci, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) if (request_irq(pci->irq, snd_via82xx_interrupt, IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) KBUILD_MODNAME, chip)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) snd_via82xx_free(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) chip->irq = pci->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) card->sync_irq = chip->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) if (ac97_clock >= 8000 && ac97_clock <= 48000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) chip->ac97_clock = ac97_clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) if ((err = snd_via82xx_chip_init(chip)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) snd_via82xx_free(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) snd_via82xx_free(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) /* The 8233 ac97 controller does not implement the master bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) * in the pci command register. IMHO this is a violation of the PCI spec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) * We call pci_set_master here because it does not hurt. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) pci_set_master(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) *r_via = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) static int snd_via82xx_probe(struct pci_dev *pci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) const struct pci_device_id *pci_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) struct snd_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) struct via82xx_modem *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) int chip_type = 0, card_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) card_type = pci_id->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) switch (card_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) case TYPE_CARD_VIA82XX_MODEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) strcpy(card->driver, "VIA82XX-MODEM");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) sprintf(card->shortname, "VIA 82XX modem");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) dev_err(card->dev, "invalid card type %d\n", card_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) goto __error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) if ((err = snd_via82xx_create(card, pci, chip_type, pci->revision,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) ac97_clock, &chip)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) goto __error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) card->private_data = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) if ((err = snd_via82xx_mixer_new(chip)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) goto __error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) if ((err = snd_via686_pcm_new(chip)) < 0 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) goto __error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) /* disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) for (i = 0; i < chip->num_devs; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) snd_via82xx_channel_reset(chip, &chip->devs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) sprintf(card->longname, "%s at 0x%lx, irq %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) card->shortname, chip->port, chip->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) snd_via82xx_proc_init(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) if ((err = snd_card_register(card)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) pci_set_drvdata(pci, card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) __error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) static void snd_via82xx_remove(struct pci_dev *pci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) snd_card_free(pci_get_drvdata(pci));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) static struct pci_driver via82xx_modem_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) .name = KBUILD_MODNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) .id_table = snd_via82xx_modem_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) .probe = snd_via82xx_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) .remove = snd_via82xx_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) .pm = SND_VIA82XX_PM_OPS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) module_pci_driver(via82xx_modem_driver);