^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 Digigram pcxhr compatible soundcards
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * mixer interface for stereo cards
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (c) 2004 by Digigram <alsa@digigram.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <sound/control.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <sound/tlv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <sound/asoundef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "pcxhr.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "pcxhr_core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "pcxhr_mix22.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /* registers used on the DSP and Xilinx (port 2) : HR stereo cards only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define PCXHR_DSP_RESET 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define PCXHR_XLX_CFG 0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define PCXHR_XLX_RUER 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define PCXHR_XLX_DATA 0x2C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define PCXHR_XLX_STATUS 0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define PCXHR_XLX_LOFREQ 0x34
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define PCXHR_XLX_HIFREQ 0x38
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define PCXHR_XLX_CSUER 0x3C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define PCXHR_XLX_SELMIC 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define PCXHR_DSP 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /* byte access only ! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define PCXHR_INPB(mgr, x) inb((mgr)->port[PCXHR_DSP] + (x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define PCXHR_OUTPB(mgr, x, data) outb((data), (mgr)->port[PCXHR_DSP] + (x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* values for PCHR_DSP_RESET register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define PCXHR_DSP_RESET_DSP 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define PCXHR_DSP_RESET_MUTE 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define PCXHR_DSP_RESET_CODEC 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define PCXHR_DSP_RESET_SMPTE 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define PCXHR_DSP_RESET_GPO_OFFSET 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define PCXHR_DSP_RESET_GPO_MASK 0x60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* values for PCHR_XLX_CFG register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define PCXHR_CFG_SYNCDSP_MASK 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define PCXHR_CFG_DEPENDENCY_MASK 0x60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define PCXHR_CFG_INDEPENDANT_SEL 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define PCXHR_CFG_MASTER_SEL 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define PCXHR_CFG_SLAVE_SEL 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define PCXHR_CFG_DATA_UER1_SEL_MASK 0x10 /* 0 (UER0), 1(UER1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define PCXHR_CFG_DATAIN_SEL_MASK 0x08 /* 0 (ana), 1 (UER) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define PCXHR_CFG_SRC_MASK 0x04 /* 0 (Bypass), 1 (SRC Actif) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define PCXHR_CFG_CLOCK_UER1_SEL_MASK 0x02 /* 0 (UER0), 1(UER1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define PCXHR_CFG_CLOCKIN_SEL_MASK 0x01 /* 0 (internal), 1 (AES/EBU) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /* values for PCHR_XLX_DATA register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define PCXHR_DATA_CODEC 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define AKM_POWER_CONTROL_CMD 0xA007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define AKM_RESET_ON_CMD 0xA100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define AKM_RESET_OFF_CMD 0xA103
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define AKM_CLOCK_INF_55K_CMD 0xA240
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define AKM_CLOCK_SUP_55K_CMD 0xA24D
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define AKM_MUTE_CMD 0xA38D
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define AKM_UNMUTE_CMD 0xA30D
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define AKM_LEFT_LEVEL_CMD 0xA600
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define AKM_RIGHT_LEVEL_CMD 0xA700
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /* values for PCHR_XLX_STATUS register - READ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define PCXHR_STAT_SRC_LOCK 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define PCXHR_STAT_LEVEL_IN 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define PCXHR_STAT_GPI_OFFSET 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define PCXHR_STAT_GPI_MASK 0x0C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define PCXHR_STAT_MIC_CAPS 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* values for PCHR_XLX_STATUS register - WRITE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define PCXHR_STAT_FREQ_SYNC_MASK 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define PCXHR_STAT_FREQ_UER1_MASK 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define PCXHR_STAT_FREQ_SAVE_MASK 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* values for PCHR_XLX_CSUER register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define PCXHR_SUER1_BIT_U_READ_MASK 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define PCXHR_SUER1_BIT_C_READ_MASK 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define PCXHR_SUER1_DATA_PRESENT_MASK 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define PCXHR_SUER1_CLOCK_PRESENT_MASK 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define PCXHR_SUER_BIT_U_READ_MASK 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define PCXHR_SUER_BIT_C_READ_MASK 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define PCXHR_SUER_DATA_PRESENT_MASK 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define PCXHR_SUER_CLOCK_PRESENT_MASK 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define PCXHR_SUER_BIT_U_WRITE_MASK 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define PCXHR_SUER_BIT_C_WRITE_MASK 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /* values for PCXHR_XLX_SELMIC register - WRITE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define PCXHR_SELMIC_PREAMPLI_OFFSET 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define PCXHR_SELMIC_PREAMPLI_MASK 0x0C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define PCXHR_SELMIC_PHANTOM_ALIM 0x80
^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 const unsigned char g_hr222_p_level[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 0x00, /* [000] -49.5 dB: AKM[000] = -1.#INF dB (mute) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 0x01, /* [001] -49.0 dB: AKM[001] = -48.131 dB (diff=0.86920 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 0x01, /* [002] -48.5 dB: AKM[001] = -48.131 dB (diff=0.36920 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 0x01, /* [003] -48.0 dB: AKM[001] = -48.131 dB (diff=0.13080 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 0x01, /* [004] -47.5 dB: AKM[001] = -48.131 dB (diff=0.63080 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 0x01, /* [005] -46.5 dB: AKM[001] = -48.131 dB (diff=1.63080 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 0x01, /* [006] -47.0 dB: AKM[001] = -48.131 dB (diff=1.13080 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 0x01, /* [007] -46.0 dB: AKM[001] = -48.131 dB (diff=2.13080 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 0x01, /* [008] -45.5 dB: AKM[001] = -48.131 dB (diff=2.63080 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 0x02, /* [009] -45.0 dB: AKM[002] = -42.110 dB (diff=2.88980 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 0x02, /* [010] -44.5 dB: AKM[002] = -42.110 dB (diff=2.38980 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 0x02, /* [011] -44.0 dB: AKM[002] = -42.110 dB (diff=1.88980 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 0x02, /* [012] -43.5 dB: AKM[002] = -42.110 dB (diff=1.38980 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 0x02, /* [013] -43.0 dB: AKM[002] = -42.110 dB (diff=0.88980 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 0x02, /* [014] -42.5 dB: AKM[002] = -42.110 dB (diff=0.38980 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 0x02, /* [015] -42.0 dB: AKM[002] = -42.110 dB (diff=0.11020 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 0x02, /* [016] -41.5 dB: AKM[002] = -42.110 dB (diff=0.61020 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 0x02, /* [017] -41.0 dB: AKM[002] = -42.110 dB (diff=1.11020 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 0x02, /* [018] -40.5 dB: AKM[002] = -42.110 dB (diff=1.61020 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 0x03, /* [019] -40.0 dB: AKM[003] = -38.588 dB (diff=1.41162 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 0x03, /* [020] -39.5 dB: AKM[003] = -38.588 dB (diff=0.91162 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 0x03, /* [021] -39.0 dB: AKM[003] = -38.588 dB (diff=0.41162 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 0x03, /* [022] -38.5 dB: AKM[003] = -38.588 dB (diff=0.08838 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 0x03, /* [023] -38.0 dB: AKM[003] = -38.588 dB (diff=0.58838 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 0x03, /* [024] -37.5 dB: AKM[003] = -38.588 dB (diff=1.08838 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 0x04, /* [025] -37.0 dB: AKM[004] = -36.090 dB (diff=0.91040 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 0x04, /* [026] -36.5 dB: AKM[004] = -36.090 dB (diff=0.41040 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 0x04, /* [027] -36.0 dB: AKM[004] = -36.090 dB (diff=0.08960 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 0x04, /* [028] -35.5 dB: AKM[004] = -36.090 dB (diff=0.58960 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 0x05, /* [029] -35.0 dB: AKM[005] = -34.151 dB (diff=0.84860 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 0x05, /* [030] -34.5 dB: AKM[005] = -34.151 dB (diff=0.34860 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 0x05, /* [031] -34.0 dB: AKM[005] = -34.151 dB (diff=0.15140 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 0x05, /* [032] -33.5 dB: AKM[005] = -34.151 dB (diff=0.65140 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 0x06, /* [033] -33.0 dB: AKM[006] = -32.568 dB (diff=0.43222 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 0x06, /* [034] -32.5 dB: AKM[006] = -32.568 dB (diff=0.06778 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 0x06, /* [035] -32.0 dB: AKM[006] = -32.568 dB (diff=0.56778 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 0x07, /* [036] -31.5 dB: AKM[007] = -31.229 dB (diff=0.27116 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 0x07, /* [037] -31.0 dB: AKM[007] = -31.229 dB (diff=0.22884 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 0x08, /* [038] -30.5 dB: AKM[008] = -30.069 dB (diff=0.43100 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 0x08, /* [039] -30.0 dB: AKM[008] = -30.069 dB (diff=0.06900 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 0x09, /* [040] -29.5 dB: AKM[009] = -29.046 dB (diff=0.45405 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 0x09, /* [041] -29.0 dB: AKM[009] = -29.046 dB (diff=0.04595 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 0x0a, /* [042] -28.5 dB: AKM[010] = -28.131 dB (diff=0.36920 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 0x0a, /* [043] -28.0 dB: AKM[010] = -28.131 dB (diff=0.13080 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 0x0b, /* [044] -27.5 dB: AKM[011] = -27.303 dB (diff=0.19705 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 0x0b, /* [045] -27.0 dB: AKM[011] = -27.303 dB (diff=0.30295 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 0x0c, /* [046] -26.5 dB: AKM[012] = -26.547 dB (diff=0.04718 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 0x0d, /* [047] -26.0 dB: AKM[013] = -25.852 dB (diff=0.14806 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 0x0e, /* [048] -25.5 dB: AKM[014] = -25.208 dB (diff=0.29176 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 0x0e, /* [049] -25.0 dB: AKM[014] = -25.208 dB (diff=0.20824 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 0x0f, /* [050] -24.5 dB: AKM[015] = -24.609 dB (diff=0.10898 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 0x10, /* [051] -24.0 dB: AKM[016] = -24.048 dB (diff=0.04840 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 0x11, /* [052] -23.5 dB: AKM[017] = -23.522 dB (diff=0.02183 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 0x12, /* [053] -23.0 dB: AKM[018] = -23.025 dB (diff=0.02535 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 0x13, /* [054] -22.5 dB: AKM[019] = -22.556 dB (diff=0.05573 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 0x14, /* [055] -22.0 dB: AKM[020] = -22.110 dB (diff=0.11020 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 0x15, /* [056] -21.5 dB: AKM[021] = -21.686 dB (diff=0.18642 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 0x17, /* [057] -21.0 dB: AKM[023] = -20.896 dB (diff=0.10375 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 0x18, /* [058] -20.5 dB: AKM[024] = -20.527 dB (diff=0.02658 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 0x1a, /* [059] -20.0 dB: AKM[026] = -19.831 dB (diff=0.16866 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 0x1b, /* [060] -19.5 dB: AKM[027] = -19.504 dB (diff=0.00353 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 0x1d, /* [061] -19.0 dB: AKM[029] = -18.883 dB (diff=0.11716 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 0x1e, /* [062] -18.5 dB: AKM[030] = -18.588 dB (diff=0.08838 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 0x20, /* [063] -18.0 dB: AKM[032] = -18.028 dB (diff=0.02780 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 0x22, /* [064] -17.5 dB: AKM[034] = -17.501 dB (diff=0.00123 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 0x24, /* [065] -17.0 dB: AKM[036] = -17.005 dB (diff=0.00475 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 0x26, /* [066] -16.5 dB: AKM[038] = -16.535 dB (diff=0.03513 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 0x28, /* [067] -16.0 dB: AKM[040] = -16.090 dB (diff=0.08960 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 0x2b, /* [068] -15.5 dB: AKM[043] = -15.461 dB (diff=0.03857 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 0x2d, /* [069] -15.0 dB: AKM[045] = -15.067 dB (diff=0.06655 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 0x30, /* [070] -14.5 dB: AKM[048] = -14.506 dB (diff=0.00598 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 0x33, /* [071] -14.0 dB: AKM[051] = -13.979 dB (diff=0.02060 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 0x36, /* [072] -13.5 dB: AKM[054] = -13.483 dB (diff=0.01707 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 0x39, /* [073] -13.0 dB: AKM[057] = -13.013 dB (diff=0.01331 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 0x3c, /* [074] -12.5 dB: AKM[060] = -12.568 dB (diff=0.06778 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 0x40, /* [075] -12.0 dB: AKM[064] = -12.007 dB (diff=0.00720 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 0x44, /* [076] -11.5 dB: AKM[068] = -11.481 dB (diff=0.01937 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 0x48, /* [077] -11.0 dB: AKM[072] = -10.984 dB (diff=0.01585 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 0x4c, /* [078] -10.5 dB: AKM[076] = -10.515 dB (diff=0.01453 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 0x51, /* [079] -10.0 dB: AKM[081] = -9.961 dB (diff=0.03890 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 0x55, /* [080] -9.5 dB: AKM[085] = -9.542 dB (diff=0.04243 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 0x5a, /* [081] -9.0 dB: AKM[090] = -9.046 dB (diff=0.04595 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 0x60, /* [082] -8.5 dB: AKM[096] = -8.485 dB (diff=0.01462 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 0x66, /* [083] -8.0 dB: AKM[102] = -7.959 dB (diff=0.04120 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 0x6c, /* [084] -7.5 dB: AKM[108] = -7.462 dB (diff=0.03767 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 0x72, /* [085] -7.0 dB: AKM[114] = -6.993 dB (diff=0.00729 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 0x79, /* [086] -6.5 dB: AKM[121] = -6.475 dB (diff=0.02490 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 0x80, /* [087] -6.0 dB: AKM[128] = -5.987 dB (diff=0.01340 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 0x87, /* [088] -5.5 dB: AKM[135] = -5.524 dB (diff=0.02413 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 0x8f, /* [089] -5.0 dB: AKM[143] = -5.024 dB (diff=0.02408 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 0x98, /* [090] -4.5 dB: AKM[152] = -4.494 dB (diff=0.00607 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 0xa1, /* [091] -4.0 dB: AKM[161] = -3.994 dB (diff=0.00571 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 0xaa, /* [092] -3.5 dB: AKM[170] = -3.522 dB (diff=0.02183 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 0xb5, /* [093] -3.0 dB: AKM[181] = -2.977 dB (diff=0.02277 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 0xbf, /* [094] -2.5 dB: AKM[191] = -2.510 dB (diff=0.01014 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 0xcb, /* [095] -2.0 dB: AKM[203] = -1.981 dB (diff=0.01912 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 0xd7, /* [096] -1.5 dB: AKM[215] = -1.482 dB (diff=0.01797 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 0xe3, /* [097] -1.0 dB: AKM[227] = -1.010 dB (diff=0.01029 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 0xf1, /* [098] -0.5 dB: AKM[241] = -0.490 dB (diff=0.00954 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 0xff, /* [099] +0.0 dB: AKM[255] = +0.000 dB (diff=0.00000 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static void hr222_config_akm(struct pcxhr_mgr *mgr, unsigned short data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) unsigned short mask = 0x8000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /* activate access to codec registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) PCXHR_INPB(mgr, PCXHR_XLX_HIFREQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) while (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) PCXHR_OUTPB(mgr, PCXHR_XLX_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) data & mask ? PCXHR_DATA_CODEC : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) mask >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /* termiate access to codec registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) PCXHR_INPB(mgr, PCXHR_XLX_RUER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) static int hr222_set_hw_playback_level(struct pcxhr_mgr *mgr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) int idx, int level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) unsigned short cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (idx > 1 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) level < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) level >= ARRAY_SIZE(g_hr222_p_level))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (idx == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) cmd = AKM_LEFT_LEVEL_CMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) cmd = AKM_RIGHT_LEVEL_CMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /* conversion from PmBoardCodedLevel to AKM nonlinear programming */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) cmd += g_hr222_p_level[level];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) hr222_config_akm(mgr, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^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) static int hr222_set_hw_capture_level(struct pcxhr_mgr *mgr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) int level_l, int level_r, int level_mic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /* program all input levels at the same time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) unsigned int data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (!mgr->capture_chips)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return -EINVAL; /* no PCX22 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) data = ((level_mic & 0xff) << 24); /* micro is mono, but apply */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) data |= ((level_mic & 0xff) << 16); /* level on both channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) data |= ((level_r & 0xff) << 8); /* line input right channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) data |= (level_l & 0xff); /* line input left channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) PCXHR_INPB(mgr, PCXHR_XLX_DATA); /* activate input codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /* send 32 bits (4 x 8 bits) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) for (i = 0; i < 32; i++, data <<= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) PCXHR_OUTPB(mgr, PCXHR_XLX_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) (data & 0x80000000) ? PCXHR_DATA_CODEC : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) PCXHR_INPB(mgr, PCXHR_XLX_RUER); /* close input level codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static void hr222_micro_boost(struct pcxhr_mgr *mgr, int level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) int hr222_sub_init(struct pcxhr_mgr *mgr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) unsigned char reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) mgr->board_has_analog = 1; /* analog always available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) mgr->xlx_cfg = PCXHR_CFG_SYNCDSP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) reg = PCXHR_INPB(mgr, PCXHR_XLX_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (reg & PCXHR_STAT_MIC_CAPS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) mgr->board_has_mic = 1; /* microphone available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) dev_dbg(&mgr->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) "MIC input available = %d\n", mgr->board_has_mic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) /* reset codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) PCXHR_OUTPB(mgr, PCXHR_DSP_RESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) PCXHR_DSP_RESET_DSP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) msleep(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) mgr->dsp_reset = PCXHR_DSP_RESET_DSP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) PCXHR_DSP_RESET_MUTE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) PCXHR_DSP_RESET_CODEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, mgr->dsp_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) /* hr222_write_gpo(mgr, 0); does the same */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) msleep(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) /* config AKM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) hr222_config_akm(mgr, AKM_POWER_CONTROL_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) hr222_config_akm(mgr, AKM_CLOCK_INF_55K_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) hr222_config_akm(mgr, AKM_UNMUTE_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) hr222_config_akm(mgr, AKM_RESET_OFF_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /* init micro boost */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) hr222_micro_boost(mgr, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /* calc PLL register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) /* TODO : there is a very similar fct in pcxhr.c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static int hr222_pll_freq_register(unsigned int freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) unsigned int *pllreg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) unsigned int *realfreq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) unsigned int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (freq < 6900 || freq > 219000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) reg = (28224000 * 2) / freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) reg = (reg - 1) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (reg < 0x100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) *pllreg = reg + 0xC00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) else if (reg < 0x200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) *pllreg = reg + 0x800;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) else if (reg < 0x400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) *pllreg = reg & 0x1ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) else if (reg < 0x800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) *pllreg = ((reg >> 1) & 0x1ff) + 0x200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) reg &= ~1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) *pllreg = ((reg >> 2) & 0x1ff) + 0x400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) reg &= ~3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (realfreq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) *realfreq = (28224000 / (reg + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) int hr222_sub_set_clock(struct pcxhr_mgr *mgr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) unsigned int rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) int *changed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) unsigned int speed, pllreg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) unsigned realfreq = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) switch (mgr->use_clock_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) case HR22_CLOCK_TYPE_INTERNAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) err = hr222_pll_freq_register(rate, &pllreg, &realfreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) mgr->xlx_cfg &= ~(PCXHR_CFG_CLOCKIN_SEL_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) PCXHR_CFG_CLOCK_UER1_SEL_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) case HR22_CLOCK_TYPE_AES_SYNC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) mgr->xlx_cfg |= PCXHR_CFG_CLOCKIN_SEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) mgr->xlx_cfg &= ~PCXHR_CFG_CLOCK_UER1_SEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) case HR22_CLOCK_TYPE_AES_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (!mgr->board_has_aes1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) mgr->xlx_cfg |= (PCXHR_CFG_CLOCKIN_SEL_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) PCXHR_CFG_CLOCK_UER1_SEL_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) hr222_config_akm(mgr, AKM_MUTE_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (mgr->use_clock_type == HR22_CLOCK_TYPE_INTERNAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) PCXHR_OUTPB(mgr, PCXHR_XLX_HIFREQ, pllreg >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) PCXHR_OUTPB(mgr, PCXHR_XLX_LOFREQ, pllreg & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) /* set clock source */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) PCXHR_OUTPB(mgr, PCXHR_XLX_CFG, mgr->xlx_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /* codec speed modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) speed = rate < 55000 ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (mgr->codec_speed != speed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) mgr->codec_speed = speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (speed == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) hr222_config_akm(mgr, AKM_CLOCK_INF_55K_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) hr222_config_akm(mgr, AKM_CLOCK_SUP_55K_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) mgr->sample_rate_real = realfreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) mgr->cur_clock_type = mgr->use_clock_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (changed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) *changed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) hr222_config_akm(mgr, AKM_UNMUTE_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) dev_dbg(&mgr->pci->dev, "set_clock to %dHz (realfreq=%d pllreg=%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) rate, realfreq, pllreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) int hr222_get_external_clock(struct pcxhr_mgr *mgr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) enum pcxhr_clock_type clock_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) int *sample_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) int rate, calc_rate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) unsigned int ticks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) unsigned char mask, reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (clock_type == HR22_CLOCK_TYPE_AES_SYNC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) mask = (PCXHR_SUER_CLOCK_PRESENT_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) PCXHR_SUER_DATA_PRESENT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) reg = PCXHR_STAT_FREQ_SYNC_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) } else if (clock_type == HR22_CLOCK_TYPE_AES_1 && mgr->board_has_aes1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) mask = (PCXHR_SUER1_CLOCK_PRESENT_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) PCXHR_SUER1_DATA_PRESENT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) reg = PCXHR_STAT_FREQ_UER1_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) dev_dbg(&mgr->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) "get_external_clock : type %d not supported\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) clock_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) return -EINVAL; /* other clocks not supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if ((PCXHR_INPB(mgr, PCXHR_XLX_CSUER) & mask) != mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) dev_dbg(&mgr->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) "get_external_clock(%d) = 0 Hz\n", clock_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) *sample_rate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) return 0; /* no external clock locked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) PCXHR_OUTPB(mgr, PCXHR_XLX_STATUS, reg); /* calculate freq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) /* save the measured clock frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) reg |= PCXHR_STAT_FREQ_SAVE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (mgr->last_reg_stat != reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) udelay(500); /* wait min 2 cycles of lowest freq (8000) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) mgr->last_reg_stat = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) PCXHR_OUTPB(mgr, PCXHR_XLX_STATUS, reg); /* save */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) /* get the frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) ticks = (unsigned int)PCXHR_INPB(mgr, PCXHR_XLX_CFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) ticks = (ticks & 0x03) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) ticks |= (unsigned int)PCXHR_INPB(mgr, PCXHR_DSP_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (ticks != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) calc_rate = 28224000 / ticks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) /* rounding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (calc_rate > 184200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) rate = 192000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) else if (calc_rate > 152200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) rate = 176400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) else if (calc_rate > 112000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) rate = 128000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) else if (calc_rate > 92100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) rate = 96000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) else if (calc_rate > 76100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) rate = 88200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) else if (calc_rate > 56000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) rate = 64000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) else if (calc_rate > 46050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) rate = 48000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) else if (calc_rate > 38050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) rate = 44100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) else if (calc_rate > 28000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) rate = 32000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) else if (calc_rate > 23025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) rate = 24000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) else if (calc_rate > 19025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) rate = 22050;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) else if (calc_rate > 14000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) rate = 16000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) else if (calc_rate > 11512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) rate = 12000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) else if (calc_rate > 9512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) rate = 11025;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) else if (calc_rate > 7000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) rate = 8000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) rate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) dev_dbg(&mgr->pci->dev, "External clock is at %d Hz (measured %d Hz)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) rate, calc_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) *sample_rate = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) int hr222_read_gpio(struct pcxhr_mgr *mgr, int is_gpi, int *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (is_gpi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) unsigned char reg = PCXHR_INPB(mgr, PCXHR_XLX_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) *value = (int)(reg & PCXHR_STAT_GPI_MASK) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) PCXHR_STAT_GPI_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) *value = (int)(mgr->dsp_reset & PCXHR_DSP_RESET_GPO_MASK) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) PCXHR_DSP_RESET_GPO_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) return 0;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) int hr222_write_gpo(struct pcxhr_mgr *mgr, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) unsigned char reg = mgr->dsp_reset & ~PCXHR_DSP_RESET_GPO_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) reg |= (unsigned char)(value << PCXHR_DSP_RESET_GPO_OFFSET) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) PCXHR_DSP_RESET_GPO_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) mgr->dsp_reset = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) int hr222_manage_timecode(struct pcxhr_mgr *mgr, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) mgr->dsp_reset |= PCXHR_DSP_RESET_SMPTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) mgr->dsp_reset &= ~PCXHR_DSP_RESET_SMPTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, mgr->dsp_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) int hr222_update_analog_audio_level(struct snd_pcxhr *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) int is_capture, int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) dev_dbg(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) "hr222_update_analog_audio_level(%s chan=%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) is_capture ? "capture" : "playback", channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) if (is_capture) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) int level_l, level_r, level_mic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) /* we have to update all levels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (chip->analog_capture_active) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) level_l = chip->analog_capture_volume[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) level_r = chip->analog_capture_volume[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) level_l = HR222_LINE_CAPTURE_LEVEL_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) level_r = HR222_LINE_CAPTURE_LEVEL_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (chip->mic_active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) level_mic = chip->mic_volume;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) level_mic = HR222_MICRO_CAPTURE_LEVEL_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return hr222_set_hw_capture_level(chip->mgr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) level_l, level_r, level_mic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) int vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if (chip->analog_playback_active[channel])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) vol = chip->analog_playback_volume[channel];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) vol = HR222_LINE_PLAYBACK_LEVEL_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) return hr222_set_hw_playback_level(chip->mgr, channel, vol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) /*texts[5] = {"Line", "Digital", "Digi+SRC", "Mic", "Line+Mic"}*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) #define SOURCE_LINE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) #define SOURCE_DIGITAL 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) #define SOURCE_DIGISRC 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) #define SOURCE_MIC 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) #define SOURCE_LINEMIC 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) int hr222_set_audio_source(struct snd_pcxhr *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) int digital = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) /* default analog source */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) chip->mgr->xlx_cfg &= ~(PCXHR_CFG_SRC_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) PCXHR_CFG_DATAIN_SEL_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) PCXHR_CFG_DATA_UER1_SEL_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (chip->audio_capture_source == SOURCE_DIGISRC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) chip->mgr->xlx_cfg |= PCXHR_CFG_SRC_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) digital = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (chip->audio_capture_source == SOURCE_DIGITAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) digital = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (digital) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) chip->mgr->xlx_cfg |= PCXHR_CFG_DATAIN_SEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (chip->mgr->board_has_aes1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) /* get data from the AES1 plug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) chip->mgr->xlx_cfg |= PCXHR_CFG_DATA_UER1_SEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) /* chip->mic_active = 0; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) /* chip->analog_capture_active = 0; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) int update_lvl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) chip->analog_capture_active = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) chip->mic_active = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (chip->audio_capture_source == SOURCE_LINE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) chip->audio_capture_source == SOURCE_LINEMIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (chip->analog_capture_active == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) update_lvl = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) chip->analog_capture_active = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) if (chip->audio_capture_source == SOURCE_MIC ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) chip->audio_capture_source == SOURCE_LINEMIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) if (chip->mic_active == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) update_lvl = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) chip->mic_active = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (update_lvl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) /* capture: update all 3 mutes/unmutes with one call */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) hr222_update_analog_audio_level(chip, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) /* set the source infos (max 3 bits modified) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) PCXHR_OUTPB(chip->mgr, PCXHR_XLX_CFG, chip->mgr->xlx_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) int hr222_iec958_capture_byte(struct snd_pcxhr *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) int aes_idx, unsigned char *aes_bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) unsigned char idx = (unsigned char)(aes_idx * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) unsigned char temp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) unsigned char mask = chip->mgr->board_has_aes1 ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) PCXHR_SUER1_BIT_C_READ_MASK : PCXHR_SUER_BIT_C_READ_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) PCXHR_OUTPB(chip->mgr, PCXHR_XLX_RUER, idx++); /* idx < 192 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) temp <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (PCXHR_INPB(chip->mgr, PCXHR_XLX_CSUER) & mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) temp |= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) dev_dbg(chip->card->dev, "read iec958 AES %d byte %d = 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) chip->chip_idx, aes_idx, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) *aes_bits = temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) int hr222_iec958_update_byte(struct snd_pcxhr *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) int aes_idx, unsigned char aes_bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) unsigned char new_bits = aes_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) unsigned char old_bits = chip->aes_bits[aes_idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) unsigned char idx = (unsigned char)(aes_idx * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if ((old_bits & 0x01) != (new_bits & 0x01)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) /* idx < 192 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) PCXHR_OUTPB(chip->mgr, PCXHR_XLX_RUER, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) /* write C and U bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) PCXHR_OUTPB(chip->mgr, PCXHR_XLX_CSUER, new_bits&0x01 ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) PCXHR_SUER_BIT_C_WRITE_MASK : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) old_bits >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) new_bits >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) chip->aes_bits[aes_idx] = aes_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) static void hr222_micro_boost(struct pcxhr_mgr *mgr, int level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) unsigned char boost_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) boost_mask = (unsigned char) (level << PCXHR_SELMIC_PREAMPLI_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (boost_mask & (~PCXHR_SELMIC_PREAMPLI_MASK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) return; /* only values form 0 to 3 accepted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) mgr->xlx_selmic &= ~PCXHR_SELMIC_PREAMPLI_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) mgr->xlx_selmic |= boost_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) PCXHR_OUTPB(mgr, PCXHR_XLX_SELMIC, mgr->xlx_selmic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) dev_dbg(&mgr->pci->dev, "hr222_micro_boost : set %x\n", boost_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) static void hr222_phantom_power(struct pcxhr_mgr *mgr, int power)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (power)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) mgr->xlx_selmic |= PCXHR_SELMIC_PHANTOM_ALIM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) mgr->xlx_selmic &= ~PCXHR_SELMIC_PHANTOM_ALIM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) PCXHR_OUTPB(mgr, PCXHR_XLX_SELMIC, mgr->xlx_selmic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) dev_dbg(&mgr->pci->dev, "hr222_phantom_power : set %d\n", power);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) /* mic level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) static const DECLARE_TLV_DB_SCALE(db_scale_mic_hr222, -9850, 50, 650);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) static int hr222_mic_vol_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) uinfo->value.integer.min = HR222_MICRO_CAPTURE_LEVEL_MIN; /* -98 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) /* gains from 9 dB to 31.5 dB not recommended; use micboost instead */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) uinfo->value.integer.max = HR222_MICRO_CAPTURE_LEVEL_MAX; /* +7 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) static int hr222_mic_vol_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) mutex_lock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) ucontrol->value.integer.value[0] = chip->mic_volume;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) mutex_unlock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) static int hr222_mic_vol_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) int changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) mutex_lock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (chip->mic_volume != ucontrol->value.integer.value[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) changed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) chip->mic_volume = ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) hr222_update_analog_audio_level(chip, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) mutex_unlock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) static const struct snd_kcontrol_new hr222_control_mic_level = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) SNDRV_CTL_ELEM_ACCESS_TLV_READ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) .name = "Mic Capture Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) .info = hr222_mic_vol_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) .get = hr222_mic_vol_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) .put = hr222_mic_vol_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) .tlv = { .p = db_scale_mic_hr222 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) /* mic boost level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) static const DECLARE_TLV_DB_SCALE(db_scale_micboost_hr222, 0, 1800, 5400);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) static int hr222_mic_boost_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) uinfo->value.integer.min = 0; /* 0 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) uinfo->value.integer.max = 3; /* 54 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) return 0;
^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) static int hr222_mic_boost_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) mutex_lock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) ucontrol->value.integer.value[0] = chip->mic_boost;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) mutex_unlock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) return 0;
^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) static int hr222_mic_boost_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) int changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) mutex_lock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (chip->mic_boost != ucontrol->value.integer.value[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) changed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) chip->mic_boost = ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) hr222_micro_boost(chip->mgr, chip->mic_boost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) mutex_unlock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) return changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) static const struct snd_kcontrol_new hr222_control_mic_boost = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) SNDRV_CTL_ELEM_ACCESS_TLV_READ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) .name = "MicBoost Capture Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) .info = hr222_mic_boost_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) .get = hr222_mic_boost_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) .put = hr222_mic_boost_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) .tlv = { .p = db_scale_micboost_hr222 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) /******************* Phantom power switch *******************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) #define hr222_phantom_power_info snd_ctl_boolean_mono_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) static int hr222_phantom_power_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) mutex_lock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) ucontrol->value.integer.value[0] = chip->phantom_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) mutex_unlock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) static int hr222_phantom_power_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) int power, changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) mutex_lock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) power = !!ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (chip->phantom_power != power) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) hr222_phantom_power(chip->mgr, power);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) chip->phantom_power = power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) changed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) mutex_unlock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) return changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) static const struct snd_kcontrol_new hr222_phantom_power_switch = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) .name = "Phantom Power Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) .info = hr222_phantom_power_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) .get = hr222_phantom_power_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) .put = hr222_phantom_power_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) int hr222_add_mic_controls(struct snd_pcxhr *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) if (!chip->mgr->board_has_mic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) /* controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) err = snd_ctl_add(chip->card, snd_ctl_new1(&hr222_control_mic_level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) err = snd_ctl_add(chip->card, snd_ctl_new1(&hr222_control_mic_boost,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) err = snd_ctl_add(chip->card, snd_ctl_new1(&hr222_phantom_power_switch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) }