^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) * This driver supports the analog controls for the internal codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * found in Allwinner's A31s, A23, A33 and H3 SoCs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright 2016 Chen-Yu Tsai <wens@csie.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <sound/soc-dapm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <sound/tlv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "sun8i-adda-pr-regmap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /* Codec analog control register offsets and bit fields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define SUN8I_ADDA_HP_VOLC 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define SUN8I_ADDA_HP_VOLC_PA_CLK_GATE 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define SUN8I_ADDA_HP_VOLC_HP_VOL 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define SUN8I_ADDA_LOMIXSC 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define SUN8I_ADDA_LOMIXSC_MIC1 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define SUN8I_ADDA_LOMIXSC_MIC2 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define SUN8I_ADDA_LOMIXSC_PHONE 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define SUN8I_ADDA_LOMIXSC_PHONEN 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define SUN8I_ADDA_LOMIXSC_LINEINL 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define SUN8I_ADDA_LOMIXSC_DACL 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define SUN8I_ADDA_LOMIXSC_DACR 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define SUN8I_ADDA_ROMIXSC 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define SUN8I_ADDA_ROMIXSC_MIC1 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define SUN8I_ADDA_ROMIXSC_MIC2 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define SUN8I_ADDA_ROMIXSC_PHONE 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define SUN8I_ADDA_ROMIXSC_PHONEP 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define SUN8I_ADDA_ROMIXSC_LINEINR 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define SUN8I_ADDA_ROMIXSC_DACR 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define SUN8I_ADDA_ROMIXSC_DACL 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define SUN8I_ADDA_DAC_PA_SRC 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define SUN8I_ADDA_DAC_PA_SRC_DACAREN 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define SUN8I_ADDA_DAC_PA_SRC_DACALEN 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define SUN8I_ADDA_DAC_PA_SRC_RMIXEN 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define SUN8I_ADDA_DAC_PA_SRC_LMIXEN 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define SUN8I_ADDA_DAC_PA_SRC_RHPPAMUTE 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define SUN8I_ADDA_DAC_PA_SRC_LHPPAMUTE 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define SUN8I_ADDA_DAC_PA_SRC_RHPIS 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define SUN8I_ADDA_DAC_PA_SRC_LHPIS 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define SUN8I_ADDA_PHONEIN_GCTRL 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define SUN8I_ADDA_PHONEIN_GCTRL_PHONEPG 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define SUN8I_ADDA_PHONEIN_GCTRL_PHONENG 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define SUN8I_ADDA_LINEIN_GCTRL 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define SUN8I_ADDA_LINEIN_GCTRL_LINEING 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define SUN8I_ADDA_LINEIN_GCTRL_PHONEG 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define SUN8I_ADDA_MICIN_GCTRL 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define SUN8I_ADDA_MICIN_GCTRL_MIC1G 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define SUN8I_ADDA_MICIN_GCTRL_MIC2G 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define SUN8I_ADDA_PAEN_HP_CTRL 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define SUN8I_ADDA_PAEN_HP_CTRL_HPPAEN 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define SUN8I_ADDA_PAEN_HP_CTRL_LINEOUTEN 7 /* H3 specific */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define SUN8I_ADDA_PAEN_HP_CTRL_HPCOM_FC 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define SUN8I_ADDA_PAEN_HP_CTRL_COMPTEN 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define SUN8I_ADDA_PAEN_HP_CTRL_PA_ANTI_POP_CTRL 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define SUN8I_ADDA_PAEN_HP_CTRL_LTRNMUTE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define SUN8I_ADDA_PAEN_HP_CTRL_RTLNMUTE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define SUN8I_ADDA_PHONEOUT_CTRL 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define SUN8I_ADDA_PHONEOUT_CTRL_PHONEOUTG 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define SUN8I_ADDA_PHONEOUT_CTRL_PHONEOUTEN 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define SUN8I_ADDA_PHONEOUT_CTRL_PHONEOUT_MIC1 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define SUN8I_ADDA_PHONEOUT_CTRL_PHONEOUT_MIC2 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define SUN8I_ADDA_PHONEOUT_CTRL_PHONEOUT_RMIX 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define SUN8I_ADDA_PHONEOUT_CTRL_PHONEOUT_LMIX 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define SUN8I_ADDA_PHONE_GAIN_CTRL 0x09
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define SUN8I_ADDA_PHONE_GAIN_CTRL_LINEOUT_VOL 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define SUN8I_ADDA_PHONE_GAIN_CTRL_PHONEPREG 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define SUN8I_ADDA_MIC2G_CTRL 0x0a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define SUN8I_ADDA_MIC2G_CTRL_MIC2AMPEN 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define SUN8I_ADDA_MIC2G_CTRL_MIC2BOOST 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define SUN8I_ADDA_MIC2G_CTRL_LINEOUTLEN 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define SUN8I_ADDA_MIC2G_CTRL_LINEOUTREN 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define SUN8I_ADDA_MIC2G_CTRL_LINEOUTLSRC 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define SUN8I_ADDA_MIC2G_CTRL_LINEOUTRSRC 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define SUN8I_ADDA_MIC1G_MICBIAS_CTRL 0x0b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define SUN8I_ADDA_MIC1G_MICBIAS_CTRL_HMICBIASEN 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define SUN8I_ADDA_MIC1G_MICBIAS_CTRL_MMICBIASEN 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define SUN8I_ADDA_MIC1G_MICBIAS_CTRL_HMICBIAS_MODE 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define SUN8I_ADDA_MIC1G_MICBIAS_CTRL_MIC1AMPEN 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define SUN8I_ADDA_MIC1G_MICBIAS_CTRL_MIC1BOOST 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define SUN8I_ADDA_LADCMIXSC 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define SUN8I_ADDA_LADCMIXSC_MIC1 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define SUN8I_ADDA_LADCMIXSC_MIC2 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define SUN8I_ADDA_LADCMIXSC_PHONE 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define SUN8I_ADDA_LADCMIXSC_PHONEN 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define SUN8I_ADDA_LADCMIXSC_LINEINL 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define SUN8I_ADDA_LADCMIXSC_OMIXRL 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define SUN8I_ADDA_LADCMIXSC_OMIXRR 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define SUN8I_ADDA_RADCMIXSC 0x0d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define SUN8I_ADDA_RADCMIXSC_MIC1 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define SUN8I_ADDA_RADCMIXSC_MIC2 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define SUN8I_ADDA_RADCMIXSC_PHONE 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define SUN8I_ADDA_RADCMIXSC_PHONEP 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define SUN8I_ADDA_RADCMIXSC_LINEINR 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define SUN8I_ADDA_RADCMIXSC_OMIXR 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define SUN8I_ADDA_RADCMIXSC_OMIXL 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define SUN8I_ADDA_RES 0x0e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define SUN8I_ADDA_RES_MMICBIAS_SEL 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define SUN8I_ADDA_RES_PA_ANTI_POP_CTRL 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define SUN8I_ADDA_ADC_AP_EN 0x0f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define SUN8I_ADDA_ADC_AP_EN_ADCREN 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define SUN8I_ADDA_ADC_AP_EN_ADCLEN 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define SUN8I_ADDA_ADC_AP_EN_ADCG 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* mixer controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static const struct snd_kcontrol_new sun8i_codec_mixer_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) SOC_DAPM_DOUBLE_R("DAC Playback Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) SUN8I_ADDA_LOMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) SUN8I_ADDA_ROMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) SUN8I_ADDA_LOMIXSC_DACL, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) SOC_DAPM_DOUBLE_R("DAC Reversed Playback Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) SUN8I_ADDA_LOMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) SUN8I_ADDA_ROMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) SUN8I_ADDA_LOMIXSC_DACR, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) SOC_DAPM_DOUBLE_R("Line In Playback Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) SUN8I_ADDA_LOMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) SUN8I_ADDA_ROMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) SUN8I_ADDA_LOMIXSC_LINEINL, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) SOC_DAPM_DOUBLE_R("Mic1 Playback Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) SUN8I_ADDA_LOMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) SUN8I_ADDA_ROMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) SUN8I_ADDA_LOMIXSC_MIC1, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) SOC_DAPM_DOUBLE_R("Mic2 Playback Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) SUN8I_ADDA_LOMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) SUN8I_ADDA_ROMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) SUN8I_ADDA_LOMIXSC_MIC2, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* mixer controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static const struct snd_kcontrol_new sun8i_v3s_codec_mixer_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) SOC_DAPM_DOUBLE_R("DAC Playback Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) SUN8I_ADDA_LOMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) SUN8I_ADDA_ROMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) SUN8I_ADDA_LOMIXSC_DACL, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) SOC_DAPM_DOUBLE_R("DAC Reversed Playback Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) SUN8I_ADDA_LOMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) SUN8I_ADDA_ROMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) SUN8I_ADDA_LOMIXSC_DACR, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) SOC_DAPM_DOUBLE_R("Mic1 Playback Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) SUN8I_ADDA_LOMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) SUN8I_ADDA_ROMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) SUN8I_ADDA_LOMIXSC_MIC1, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /* ADC mixer controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static const struct snd_kcontrol_new sun8i_codec_adc_mixer_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) SOC_DAPM_DOUBLE_R("Mixer Capture Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) SUN8I_ADDA_LADCMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) SUN8I_ADDA_RADCMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) SUN8I_ADDA_LADCMIXSC_OMIXRL, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) SOC_DAPM_DOUBLE_R("Mixer Reversed Capture Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) SUN8I_ADDA_LADCMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) SUN8I_ADDA_RADCMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) SUN8I_ADDA_LADCMIXSC_OMIXRR, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) SOC_DAPM_DOUBLE_R("Line In Capture Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) SUN8I_ADDA_LADCMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) SUN8I_ADDA_RADCMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) SUN8I_ADDA_LADCMIXSC_LINEINL, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) SOC_DAPM_DOUBLE_R("Mic1 Capture Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) SUN8I_ADDA_LADCMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) SUN8I_ADDA_RADCMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) SUN8I_ADDA_LADCMIXSC_MIC1, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) SOC_DAPM_DOUBLE_R("Mic2 Capture Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) SUN8I_ADDA_LADCMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) SUN8I_ADDA_RADCMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) SUN8I_ADDA_LADCMIXSC_MIC2, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) /* ADC mixer controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static const struct snd_kcontrol_new sun8i_v3s_codec_adc_mixer_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) SOC_DAPM_DOUBLE_R("Mixer Capture Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) SUN8I_ADDA_LADCMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) SUN8I_ADDA_RADCMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) SUN8I_ADDA_LADCMIXSC_OMIXRL, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) SOC_DAPM_DOUBLE_R("Mixer Reversed Capture Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) SUN8I_ADDA_LADCMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) SUN8I_ADDA_RADCMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) SUN8I_ADDA_LADCMIXSC_OMIXRR, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) SOC_DAPM_DOUBLE_R("Mic1 Capture Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) SUN8I_ADDA_LADCMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) SUN8I_ADDA_RADCMIXSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) SUN8I_ADDA_LADCMIXSC_MIC1, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /* volume / mute controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static const DECLARE_TLV_DB_SCALE(sun8i_codec_out_mixer_pregain_scale,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) -450, 150, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static const DECLARE_TLV_DB_RANGE(sun8i_codec_mic_gain_scale,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 1, 7, TLV_DB_SCALE_ITEM(2400, 300, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static const struct snd_kcontrol_new sun8i_codec_common_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) /* Mixer pre-gain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) SOC_SINGLE_TLV("Mic1 Playback Volume", SUN8I_ADDA_MICIN_GCTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) SUN8I_ADDA_MICIN_GCTRL_MIC1G,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 0x7, 0, sun8i_codec_out_mixer_pregain_scale),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /* Microphone Amp boost gain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) SOC_SINGLE_TLV("Mic1 Boost Volume", SUN8I_ADDA_MIC1G_MICBIAS_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) SUN8I_ADDA_MIC1G_MICBIAS_CTRL_MIC1BOOST, 0x7, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) sun8i_codec_mic_gain_scale),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /* ADC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) SOC_SINGLE_TLV("ADC Gain Capture Volume", SUN8I_ADDA_ADC_AP_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) SUN8I_ADDA_ADC_AP_EN_ADCG, 0x7, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) sun8i_codec_out_mixer_pregain_scale),
^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) static const struct snd_soc_dapm_widget sun8i_codec_common_widgets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /* ADC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) SND_SOC_DAPM_ADC("Left ADC", NULL, SUN8I_ADDA_ADC_AP_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) SUN8I_ADDA_ADC_AP_EN_ADCLEN, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) SND_SOC_DAPM_ADC("Right ADC", NULL, SUN8I_ADDA_ADC_AP_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) SUN8I_ADDA_ADC_AP_EN_ADCREN, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /* DAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) SND_SOC_DAPM_DAC("Left DAC", NULL, SUN8I_ADDA_DAC_PA_SRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) SUN8I_ADDA_DAC_PA_SRC_DACALEN, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) SND_SOC_DAPM_DAC("Right DAC", NULL, SUN8I_ADDA_DAC_PA_SRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) SUN8I_ADDA_DAC_PA_SRC_DACAREN, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * Due to this component and the codec belonging to separate DAPM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * contexts, we need to manually link the above widgets to their
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * stream widgets at the card level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /* Microphone input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) SND_SOC_DAPM_INPUT("MIC1"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /* Mic input path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) SND_SOC_DAPM_PGA("Mic1 Amplifier", SUN8I_ADDA_MIC1G_MICBIAS_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) SUN8I_ADDA_MIC1G_MICBIAS_CTRL_MIC1AMPEN, 0, NULL, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static const struct snd_soc_dapm_widget sun8i_codec_mixer_widgets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) SND_SOC_DAPM_MIXER("Left Mixer", SUN8I_ADDA_DAC_PA_SRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) SUN8I_ADDA_DAC_PA_SRC_LMIXEN, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) sun8i_codec_mixer_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) ARRAY_SIZE(sun8i_codec_mixer_controls)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) SND_SOC_DAPM_MIXER("Right Mixer", SUN8I_ADDA_DAC_PA_SRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) SUN8I_ADDA_DAC_PA_SRC_RMIXEN, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) sun8i_codec_mixer_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) ARRAY_SIZE(sun8i_codec_mixer_controls)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) SND_SOC_DAPM_MIXER("Left ADC Mixer", SUN8I_ADDA_ADC_AP_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) SUN8I_ADDA_ADC_AP_EN_ADCLEN, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) sun8i_codec_adc_mixer_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) ARRAY_SIZE(sun8i_codec_adc_mixer_controls)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) SND_SOC_DAPM_MIXER("Right ADC Mixer", SUN8I_ADDA_ADC_AP_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) SUN8I_ADDA_ADC_AP_EN_ADCREN, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) sun8i_codec_adc_mixer_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) ARRAY_SIZE(sun8i_codec_adc_mixer_controls)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) static const struct snd_soc_dapm_widget sun8i_v3s_codec_mixer_widgets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) SND_SOC_DAPM_MIXER("Left Mixer", SUN8I_ADDA_DAC_PA_SRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) SUN8I_ADDA_DAC_PA_SRC_LMIXEN, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) sun8i_v3s_codec_mixer_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) ARRAY_SIZE(sun8i_v3s_codec_mixer_controls)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) SND_SOC_DAPM_MIXER("Right Mixer", SUN8I_ADDA_DAC_PA_SRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) SUN8I_ADDA_DAC_PA_SRC_RMIXEN, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) sun8i_v3s_codec_mixer_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) ARRAY_SIZE(sun8i_v3s_codec_mixer_controls)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) SND_SOC_DAPM_MIXER("Left ADC Mixer", SUN8I_ADDA_ADC_AP_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) SUN8I_ADDA_ADC_AP_EN_ADCLEN, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) sun8i_v3s_codec_adc_mixer_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) ARRAY_SIZE(sun8i_v3s_codec_adc_mixer_controls)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) SND_SOC_DAPM_MIXER("Right ADC Mixer", SUN8I_ADDA_ADC_AP_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) SUN8I_ADDA_ADC_AP_EN_ADCREN, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) sun8i_v3s_codec_adc_mixer_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) ARRAY_SIZE(sun8i_v3s_codec_adc_mixer_controls)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) static const struct snd_soc_dapm_route sun8i_codec_common_routes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) /* Microphone Routes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) { "Mic1 Amplifier", NULL, "MIC1"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) static const struct snd_soc_dapm_route sun8i_codec_mixer_routes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* Left Mixer Routes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) { "Left Mixer", "DAC Playback Switch", "Left DAC" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) { "Left Mixer", "DAC Reversed Playback Switch", "Right DAC" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) { "Left Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /* Right Mixer Routes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) { "Right Mixer", "DAC Playback Switch", "Right DAC" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) { "Right Mixer", "DAC Reversed Playback Switch", "Left DAC" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) { "Right Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /* Left ADC Mixer Routes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) { "Left ADC Mixer", "Mixer Capture Switch", "Left Mixer" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) { "Left ADC Mixer", "Mixer Reversed Capture Switch", "Right Mixer" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) { "Left ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) /* Right ADC Mixer Routes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) { "Right ADC Mixer", "Mixer Capture Switch", "Right Mixer" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) { "Right ADC Mixer", "Mixer Reversed Capture Switch", "Left Mixer" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) { "Right ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) /* ADC Routes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) { "Left ADC", NULL, "Left ADC Mixer" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) { "Right ADC", NULL, "Right ADC Mixer" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) /* headphone specific controls, widgets, and routes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) static const DECLARE_TLV_DB_SCALE(sun8i_codec_hp_vol_scale, -6300, 100, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) static const struct snd_kcontrol_new sun8i_codec_headphone_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) SOC_SINGLE_TLV("Headphone Playback Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) SUN8I_ADDA_HP_VOLC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) SUN8I_ADDA_HP_VOLC_HP_VOL, 0x3f, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) sun8i_codec_hp_vol_scale),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) SOC_DOUBLE("Headphone Playback Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) SUN8I_ADDA_DAC_PA_SRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) SUN8I_ADDA_DAC_PA_SRC_LHPPAMUTE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) SUN8I_ADDA_DAC_PA_SRC_RHPPAMUTE, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) static const char * const sun8i_codec_hp_src_enum_text[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) "DAC", "Mixer",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static SOC_ENUM_DOUBLE_DECL(sun8i_codec_hp_src_enum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) SUN8I_ADDA_DAC_PA_SRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) SUN8I_ADDA_DAC_PA_SRC_LHPIS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) SUN8I_ADDA_DAC_PA_SRC_RHPIS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) sun8i_codec_hp_src_enum_text);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static const struct snd_kcontrol_new sun8i_codec_hp_src[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) SOC_DAPM_ENUM("Headphone Source Playback Route",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) sun8i_codec_hp_src_enum),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) static int sun8i_headphone_amp_event(struct snd_soc_dapm_widget *w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) struct snd_kcontrol *k, int event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (SND_SOC_DAPM_EVENT_ON(event)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) snd_soc_component_update_bits(component, SUN8I_ADDA_PAEN_HP_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) BIT(SUN8I_ADDA_PAEN_HP_CTRL_HPPAEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) BIT(SUN8I_ADDA_PAEN_HP_CTRL_HPPAEN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * Need a delay to have the amplifier up. 700ms seems the best
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * compromise between the time to let the amplifier up and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * time not to feel this delay while playing a sound.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) msleep(700);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) } else if (SND_SOC_DAPM_EVENT_OFF(event)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) snd_soc_component_update_bits(component, SUN8I_ADDA_PAEN_HP_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) BIT(SUN8I_ADDA_PAEN_HP_CTRL_HPPAEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static const struct snd_soc_dapm_widget sun8i_codec_headphone_widgets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) SND_SOC_DAPM_MUX("Headphone Source Playback Route",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) SND_SOC_NOPM, 0, 0, sun8i_codec_hp_src),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) SND_SOC_DAPM_OUT_DRV_E("Headphone Amp", SUN8I_ADDA_PAEN_HP_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) SUN8I_ADDA_PAEN_HP_CTRL_HPPAEN, 0, NULL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) sun8i_headphone_amp_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) SND_SOC_DAPM_SUPPLY("HPCOM Protection", SUN8I_ADDA_PAEN_HP_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) SUN8I_ADDA_PAEN_HP_CTRL_COMPTEN, 0, NULL, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) SND_SOC_DAPM_REG(snd_soc_dapm_supply, "HPCOM", SUN8I_ADDA_PAEN_HP_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) SUN8I_ADDA_PAEN_HP_CTRL_HPCOM_FC, 0x3, 0x3, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) SND_SOC_DAPM_OUTPUT("HP"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static const struct snd_soc_dapm_route sun8i_codec_headphone_routes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) { "Headphone Source Playback Route", "DAC", "Left DAC" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) { "Headphone Source Playback Route", "DAC", "Right DAC" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) { "Headphone Source Playback Route", "Mixer", "Left Mixer" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) { "Headphone Source Playback Route", "Mixer", "Right Mixer" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) { "Headphone Amp", NULL, "Headphone Source Playback Route" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) { "HPCOM", NULL, "HPCOM Protection" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) { "HP", NULL, "Headphone Amp" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) static int sun8i_codec_add_headphone(struct snd_soc_component *cmpnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) struct device *dev = cmpnt->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) ret = snd_soc_add_component_controls(cmpnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) sun8i_codec_headphone_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) ARRAY_SIZE(sun8i_codec_headphone_controls));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) dev_err(dev, "Failed to add Headphone controls: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) ret = snd_soc_dapm_new_controls(dapm, sun8i_codec_headphone_widgets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) ARRAY_SIZE(sun8i_codec_headphone_widgets));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) dev_err(dev, "Failed to add Headphone DAPM widgets: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) ret = snd_soc_dapm_add_routes(dapm, sun8i_codec_headphone_routes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) ARRAY_SIZE(sun8i_codec_headphone_routes));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) dev_err(dev, "Failed to add Headphone DAPM routes: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) /* mbias specific widget */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) static const struct snd_soc_dapm_widget sun8i_codec_mbias_widgets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) SND_SOC_DAPM_SUPPLY("MBIAS", SUN8I_ADDA_MIC1G_MICBIAS_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) SUN8I_ADDA_MIC1G_MICBIAS_CTRL_MMICBIASEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 0, NULL, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) static int sun8i_codec_add_mbias(struct snd_soc_component *cmpnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) struct device *dev = cmpnt->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) ret = snd_soc_dapm_new_controls(dapm, sun8i_codec_mbias_widgets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) ARRAY_SIZE(sun8i_codec_mbias_widgets));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) dev_err(dev, "Failed to add MBIAS DAPM widgets: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) /* hmic specific widget */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) static const struct snd_soc_dapm_widget sun8i_codec_hmic_widgets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) SND_SOC_DAPM_SUPPLY("HBIAS", SUN8I_ADDA_MIC1G_MICBIAS_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) SUN8I_ADDA_MIC1G_MICBIAS_CTRL_HMICBIASEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 0, NULL, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) static int sun8i_codec_add_hmic(struct snd_soc_component *cmpnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) struct device *dev = cmpnt->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) ret = snd_soc_dapm_new_controls(dapm, sun8i_codec_hmic_widgets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) ARRAY_SIZE(sun8i_codec_hmic_widgets));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) dev_err(dev, "Failed to add Mic3 DAPM widgets: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) /* line in specific controls, widgets and rines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) static const struct snd_kcontrol_new sun8i_codec_linein_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) /* Mixer pre-gain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) SOC_SINGLE_TLV("Line In Playback Volume", SUN8I_ADDA_LINEIN_GCTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) SUN8I_ADDA_LINEIN_GCTRL_LINEING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 0x7, 0, sun8i_codec_out_mixer_pregain_scale),
^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 const struct snd_soc_dapm_widget sun8i_codec_linein_widgets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /* Line input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) SND_SOC_DAPM_INPUT("LINEIN"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) static const struct snd_soc_dapm_route sun8i_codec_linein_routes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) { "Left Mixer", "Line In Playback Switch", "LINEIN" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) { "Right Mixer", "Line In Playback Switch", "LINEIN" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) { "Left ADC Mixer", "Line In Capture Switch", "LINEIN" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) { "Right ADC Mixer", "Line In Capture Switch", "LINEIN" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) static int sun8i_codec_add_linein(struct snd_soc_component *cmpnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) struct device *dev = cmpnt->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) ret = snd_soc_add_component_controls(cmpnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) sun8i_codec_linein_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) ARRAY_SIZE(sun8i_codec_linein_controls));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) dev_err(dev, "Failed to add Line In controls: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) ret = snd_soc_dapm_new_controls(dapm, sun8i_codec_linein_widgets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) ARRAY_SIZE(sun8i_codec_linein_widgets));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) dev_err(dev, "Failed to add Line In DAPM widgets: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) return ret;
^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) ret = snd_soc_dapm_add_routes(dapm, sun8i_codec_linein_routes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) ARRAY_SIZE(sun8i_codec_linein_routes));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) dev_err(dev, "Failed to add Line In DAPM routes: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) /* line out specific controls, widgets and routes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) static const DECLARE_TLV_DB_RANGE(sun8i_codec_lineout_vol_scale,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 0, 1, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 2, 31, TLV_DB_SCALE_ITEM(-4350, 150, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static const struct snd_kcontrol_new sun8i_codec_lineout_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) SOC_SINGLE_TLV("Line Out Playback Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) SUN8I_ADDA_PHONE_GAIN_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) SUN8I_ADDA_PHONE_GAIN_CTRL_LINEOUT_VOL, 0x1f, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) sun8i_codec_lineout_vol_scale),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) SOC_DOUBLE("Line Out Playback Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) SUN8I_ADDA_MIC2G_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) SUN8I_ADDA_MIC2G_CTRL_LINEOUTLEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) SUN8I_ADDA_MIC2G_CTRL_LINEOUTREN, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) static const char * const sun8i_codec_lineout_src_enum_text[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) "Stereo", "Mono Differential",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) static SOC_ENUM_DOUBLE_DECL(sun8i_codec_lineout_src_enum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) SUN8I_ADDA_MIC2G_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) SUN8I_ADDA_MIC2G_CTRL_LINEOUTLSRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) SUN8I_ADDA_MIC2G_CTRL_LINEOUTRSRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) sun8i_codec_lineout_src_enum_text);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) static const struct snd_kcontrol_new sun8i_codec_lineout_src[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) SOC_DAPM_ENUM("Line Out Source Playback Route",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) sun8i_codec_lineout_src_enum),
^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) static const struct snd_soc_dapm_widget sun8i_codec_lineout_widgets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) SND_SOC_DAPM_MUX("Line Out Source Playback Route",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) SND_SOC_NOPM, 0, 0, sun8i_codec_lineout_src),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) /* It is unclear if this is a buffer or gate, model it as a supply */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) SND_SOC_DAPM_SUPPLY("Line Out Enable", SUN8I_ADDA_PAEN_HP_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) SUN8I_ADDA_PAEN_HP_CTRL_LINEOUTEN, 0, NULL, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) SND_SOC_DAPM_OUTPUT("LINEOUT"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) static const struct snd_soc_dapm_route sun8i_codec_lineout_routes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) { "Line Out Source Playback Route", "Stereo", "Left Mixer" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) { "Line Out Source Playback Route", "Stereo", "Right Mixer" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) { "Line Out Source Playback Route", "Mono Differential", "Left Mixer" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) { "Line Out Source Playback Route", "Mono Differential", "Right Mixer" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) { "LINEOUT", NULL, "Line Out Source Playback Route" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) { "LINEOUT", NULL, "Line Out Enable", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) static int sun8i_codec_add_lineout(struct snd_soc_component *cmpnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) struct device *dev = cmpnt->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) ret = snd_soc_add_component_controls(cmpnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) sun8i_codec_lineout_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) ARRAY_SIZE(sun8i_codec_lineout_controls));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) dev_err(dev, "Failed to add Line Out controls: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) ret = snd_soc_dapm_new_controls(dapm, sun8i_codec_lineout_widgets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) ARRAY_SIZE(sun8i_codec_lineout_widgets));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) dev_err(dev, "Failed to add Line Out DAPM widgets: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) ret = snd_soc_dapm_add_routes(dapm, sun8i_codec_lineout_routes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) ARRAY_SIZE(sun8i_codec_lineout_routes));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) dev_err(dev, "Failed to add Line Out DAPM routes: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) /* mic2 specific controls, widgets and routes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) static const struct snd_kcontrol_new sun8i_codec_mic2_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) /* Mixer pre-gain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) SOC_SINGLE_TLV("Mic2 Playback Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) SUN8I_ADDA_MICIN_GCTRL, SUN8I_ADDA_MICIN_GCTRL_MIC2G,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 0x7, 0, sun8i_codec_out_mixer_pregain_scale),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) /* Microphone Amp boost gain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) SOC_SINGLE_TLV("Mic2 Boost Volume", SUN8I_ADDA_MIC2G_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) SUN8I_ADDA_MIC2G_CTRL_MIC2BOOST, 0x7, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) sun8i_codec_mic_gain_scale),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) static const struct snd_soc_dapm_widget sun8i_codec_mic2_widgets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) /* Microphone input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) SND_SOC_DAPM_INPUT("MIC2"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) /* Mic input path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) SND_SOC_DAPM_PGA("Mic2 Amplifier", SUN8I_ADDA_MIC2G_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) SUN8I_ADDA_MIC2G_CTRL_MIC2AMPEN, 0, NULL, 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) static const struct snd_soc_dapm_route sun8i_codec_mic2_routes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) { "Mic2 Amplifier", NULL, "MIC2"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) { "Left Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) { "Right Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) { "Left ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) { "Right ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) static int sun8i_codec_add_mic2(struct snd_soc_component *cmpnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) struct device *dev = cmpnt->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) ret = snd_soc_add_component_controls(cmpnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) sun8i_codec_mic2_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) ARRAY_SIZE(sun8i_codec_mic2_controls));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) dev_err(dev, "Failed to add MIC2 controls: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) ret = snd_soc_dapm_new_controls(dapm, sun8i_codec_mic2_widgets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) ARRAY_SIZE(sun8i_codec_mic2_widgets));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) dev_err(dev, "Failed to add MIC2 DAPM widgets: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) ret = snd_soc_dapm_add_routes(dapm, sun8i_codec_mic2_routes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) ARRAY_SIZE(sun8i_codec_mic2_routes));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) dev_err(dev, "Failed to add MIC2 DAPM routes: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) struct sun8i_codec_analog_quirks {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) bool has_headphone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) bool has_hmic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) bool has_linein;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) bool has_lineout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) bool has_mbias;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) bool has_mic2;
^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) static const struct sun8i_codec_analog_quirks sun8i_a23_quirks = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) .has_headphone = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) .has_hmic = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) .has_linein = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) .has_mbias = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) .has_mic2 = true,
^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 const struct sun8i_codec_analog_quirks sun8i_h3_quirks = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) .has_linein = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) .has_lineout = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) .has_mbias = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) .has_mic2 = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) static int sun8i_codec_analog_add_mixer(struct snd_soc_component *cmpnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) const struct sun8i_codec_analog_quirks *quirks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) struct device *dev = cmpnt->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) if (!quirks->has_mic2 && !quirks->has_linein) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) * Apply the special widget set which has uses a control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) * without MIC2 and Line In, for SoCs without these.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) * TODO: not all special cases are supported now, this case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) * is present because it's the case of V3s.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) ret = snd_soc_dapm_new_controls(dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) sun8i_v3s_codec_mixer_widgets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) ARRAY_SIZE(sun8i_v3s_codec_mixer_widgets));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) dev_err(dev, "Failed to add V3s Mixer DAPM widgets: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) /* Apply the generic mixer widget set. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) ret = snd_soc_dapm_new_controls(dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) sun8i_codec_mixer_widgets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) ARRAY_SIZE(sun8i_codec_mixer_widgets));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) dev_err(dev, "Failed to add Mixer DAPM widgets: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) ret = snd_soc_dapm_add_routes(dapm, sun8i_codec_mixer_routes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) ARRAY_SIZE(sun8i_codec_mixer_routes));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) dev_err(dev, "Failed to add Mixer DAPM routes: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) static const struct sun8i_codec_analog_quirks sun8i_v3s_quirks = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) .has_headphone = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) .has_hmic = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) static int sun8i_codec_analog_cmpnt_probe(struct snd_soc_component *cmpnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) struct device *dev = cmpnt->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) const struct sun8i_codec_analog_quirks *quirks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) * This would never return NULL unless someone directly registers a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) * platform device matching this driver's name, without specifying a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) * device tree node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) quirks = of_device_get_match_data(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) /* Add controls, widgets, and routes for individual features */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) ret = sun8i_codec_analog_add_mixer(cmpnt, quirks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (quirks->has_headphone) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) ret = sun8i_codec_add_headphone(cmpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) if (quirks->has_hmic) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) ret = sun8i_codec_add_hmic(cmpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) if (quirks->has_linein) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) ret = sun8i_codec_add_linein(cmpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (quirks->has_lineout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) ret = sun8i_codec_add_lineout(cmpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) if (quirks->has_mbias) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) ret = sun8i_codec_add_mbias(cmpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) return ret;
^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) if (quirks->has_mic2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) ret = sun8i_codec_add_mic2(cmpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) static const struct snd_soc_component_driver sun8i_codec_analog_cmpnt_drv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) .controls = sun8i_codec_common_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) .num_controls = ARRAY_SIZE(sun8i_codec_common_controls),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) .dapm_widgets = sun8i_codec_common_widgets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) .num_dapm_widgets = ARRAY_SIZE(sun8i_codec_common_widgets),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) .dapm_routes = sun8i_codec_common_routes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) .num_dapm_routes = ARRAY_SIZE(sun8i_codec_common_routes),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) .probe = sun8i_codec_analog_cmpnt_probe,
^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) static const struct of_device_id sun8i_codec_analog_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) .compatible = "allwinner,sun8i-a23-codec-analog",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) .data = &sun8i_a23_quirks,
^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) .compatible = "allwinner,sun8i-h3-codec-analog",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) .data = &sun8i_h3_quirks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) .compatible = "allwinner,sun8i-v3s-codec-analog",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) .data = &sun8i_v3s_quirks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) MODULE_DEVICE_TABLE(of, sun8i_codec_analog_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) static int sun8i_codec_analog_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) base = devm_platform_ioremap_resource(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) if (IS_ERR(base)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) dev_err(&pdev->dev, "Failed to map the registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) return PTR_ERR(base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) regmap = sun8i_adda_pr_regmap_init(&pdev->dev, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if (IS_ERR(regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) dev_err(&pdev->dev, "Failed to create regmap\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) return PTR_ERR(regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) return devm_snd_soc_register_component(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) &sun8i_codec_analog_cmpnt_drv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) static struct platform_driver sun8i_codec_analog_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) .name = "sun8i-codec-analog",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) .of_match_table = sun8i_codec_analog_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) .probe = sun8i_codec_analog_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) module_platform_driver(sun8i_codec_analog_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) MODULE_DESCRIPTION("Allwinner internal codec analog controls driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) MODULE_ALIAS("platform:sun8i-codec-analog");