Pull sound update from Takashi Iwai: "This is a fairly quiet release in all sound area. Only a little bit of changes in the core side while most of changes are seen in the drivers. HD-audio: - A few new codec additions for Nvidia, Realtek and VIA - Intel Haswell audio support - Support for "phantom" jacks for consistent jack reporting - Major clean-ups in HDMI/DP driver codes - A workaround for inverted digital-mic pins with Realtek codecs - Removal of beep_mode=2 option ASoC: - Added the ability to add and remove DAPM paths dynamically, mostly for reparenting on clock changes - New machine drivers for Marvell Brownstone, ST-Ericsson Ux500 reference platform and ttc-dkp - New CPU drivers for Blackfin BF6xx SPORTs in I2S mode, Marvell MMP, Synopsis Designware I2S controllers, and SPEAr DMA and S/PDIF - New CODEC drivers for Dialog DA732x, ST STA529, ST-Ericsson AB8500, TI Isabelle and Wolfson Microelectronics WM5102 and WM5110 - DAPM fixes for the recent locking changes - Fix for _PRE and _POST widgets (which have been broken for a few releases now) - A couple of minor driver updates Misc - Conversion to new dev_pm_ops in platform and PCI drivers - LTC support and some fixes in PCXHR driver - A few fixes and PM support for ISA OPti9xx and WSS cards - Some TLV code cleanup - Move driver-specific headers from include/sound to local dirs" * tag 'sound-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (212 commits) ASoC: dapm: Fix _PRE and _POST events for DAPM performance improvements ALSA: hda - add dock support for Thinkpad X230 Tablet ALSA: hda - Turn on PIN_OUT from hdmi playback prepare. ASoC imx-audmux: add MX31_AUDMUX_PORT7_SSI_PINS_7 define ASoC: littlemill: Add userspace control of the WM1250 I/O ASoC: wm8994: Update micdet for irqdomain conversion ALSA: hda - make sure alc268 does not OOPS on codec parse ALSA: hda - Add support for Realtek ALC282 ALSA: hda - Fix index number conflicts of phantom jacks ALSA: opti9xx: Fix section mismatch by PM support ALSA: snd-opti9xx: Implement suspend/resume ALSA: hda - Add new GPU codec ID to snd-hda ALSA: hda - Fix driver type of Haswell controller to AZX_DRIVER_SCH ALSA: hda - add Haswell HDMI codec id ALSA: hda - Add DeviceID for Haswell HDA ALSA: wss_lib: Fix resume on Yamaha OPL3-SAx ALSA: wss_lib: fix suspend/resume ALSA: es1938: replace TLV_DB_RANGE_HEAD with DECLARE_TLV_DB_RANGE ALSA: tlv: add DECLARE_TLV_DB_RANGE() ALSA: tlv: add DECLARE_TLV_CONTAINER() ...
Unified · Split
| @@ -875,8 +875,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. · 874 unmodified lines | ||
| 875 | 875 | setup before initializing the codecs. This option is |
| 876 | 876 | available only when CONFIG_SND_HDA_PATCH_LOADER=y is set. |
| 877 | 877 | See HD-Audio.txt for details. |
| 878 | − beep_mode - Selects the beep registration mode (0=off, 1=on, 2= | |
| 879 | − dynamic registration via mute switch on/off); the default | |
| 878 | + beep_mode - Selects the beep registration mode (0=off, 1=on); default | |
| 880 | 879 | value is set via CONFIG_SND_HDA_INPUT_BEEP_MODE kconfig. |
| 881 | 880 | |
| 882 | 881 | [Single (global) options] |
| @@ -15,19 +15,24 @@ ALC260 · 14 unmodified lines | ||
| 15 | 15 | |
| 16 | 16 | ALC262 |
| 17 | 17 | ====== |
| 18 | − N/A | |
| 18 | + inv-dmic Inverted internal mic workaround | |
| 19 | 19 | |
| 20 | 20 | ALC267/268 |
| 21 | 21 | ========== |
| 22 | − N/A | |
| 22 | + inv-dmic Inverted internal mic workaround | |
| 23 | 23 | |
| 24 | −ALC269 | |
| 24 | +ALC269/270/275/276/280/282 | |
| 25 | 25 | ====== |
| 26 | 26 | laptop-amic Laptops with analog-mic input |
| 27 | 27 | laptop-dmic Laptops with digital-mic input |
| 28 | + alc269-dmic Enable ALC269(VA) digital mic workaround | |
| 29 | + alc271-dmic Enable ALC271X digital mic workaround | |
| 30 | + inv-dmic Inverted internal mic workaround | |
| 31 | + lenovo-dock Enables docking station I/O for some Lenovos | |
| 28 | 32 | |
| 29 | 33 | ALC662/663/272 |
| 30 | 34 | ============== |
| 35 | + mario Chromebook mario model fixup | |
| 31 | 36 | asus-mode1 ASUS |
| 32 | 37 | asus-mode2 ASUS |
| 33 | 38 | asus-mode3 ASUS |
| @@ -36,6 +41,7 @@ ALC662/663/272 · 2 unmodified lines | ||
| 36 | 41 | asus-mode6 ASUS |
| 37 | 42 | asus-mode7 ASUS |
| 38 | 43 | asus-mode8 ASUS |
| 44 | + inv-dmic Inverted internal mic workaround | |
| 39 | 45 | |
| 40 | 46 | ALC680 |
| 41 | 47 | ====== |
| @@ -46,6 +52,7 @@ ALC882/883/885/888/889 · 4 unmodified lines | ||
| 46 | 52 | acer-aspire-4930g Acer Aspire 4930G/5930G/6530G/6930G/7730G |
| 47 | 53 | acer-aspire-8930g Acer Aspire 8330G/6935G |
| 48 | 54 | acer-aspire Acer Aspire others |
| 55 | + inv-dmic Inverted internal mic workaround | |
| 49 | 56 | |
| 50 | 57 | ALC861/660 |
| 51 | 58 | ========== |
| @@ -6765,9 +6765,11 @@ F: include/linux/tifm.h · 6764 unmodified lines | ||
| 6765 | 6765 | |
| 6766 | 6766 | TI LM49xxx FAMILY ASoC CODEC DRIVERS |
| 6767 | 6767 | M: M R Swami Reddy <mr.swami.reddy@ti.com> |
| 6768 | +M: Vishwas A Deshpande <vishwas.a.deshpande@ti.com> | |
| 6768 | 6769 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) |
| 6769 | 6770 | S: Maintained |
| 6770 | 6771 | F: sound/soc/codecs/lm49453* |
| 6772 | +F: sound/soc/codecs/isabelle* | |
| 6771 | 6773 | |
| 6772 | 6774 | TI TWL4030 SERIES SOC CODEC DRIVER |
| 6773 | 6775 | M: Peter Ujfalusi <peter.ujfalusi@ti.com> |
| @@ -25,6 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | #include <linux/mfd/tc3589x.h> |
| 26 | 26 | #include <linux/mfd/tps6105x.h> |
| 27 | 27 | #include <linux/mfd/abx500/ab8500-gpio.h> |
| 28 | +#include <linux/mfd/abx500/ab8500-codec.h> | |
| 28 | 29 | #include <linux/leds-lp5521.h> |
| 29 | 30 | #include <linux/input.h> |
| 30 | 31 | #include <linux/smsc911x.h> |
| @@ -97,6 +98,18 @@ static struct ab8500_gpio_platform_data ab8500_gpio_pdata = { · 66 unmodified lines | ||
| 97 | 98 | 0x7A, 0x00, 0x00}, |
| 98 | 99 | }; |
| 99 | 100 | |
| 101 | +/* ab8500-codec */ | |
| 102 | +static struct ab8500_codec_platform_data ab8500_codec_pdata = { | |
| 103 | + .amics = { | |
| 104 | + .mic1_type = AMIC_TYPE_DIFFERENTIAL, | |
| 105 | + .mic2_type = AMIC_TYPE_DIFFERENTIAL, | |
| 106 | + .mic1a_micbias = AMIC_MICBIAS_VAMIC1, | |
| 107 | + .mic1b_micbias = AMIC_MICBIAS_VAMIC1, | |
| 108 | + .mic2_micbias = AMIC_MICBIAS_VAMIC2 | |
| 109 | + }, | |
| 110 | + .ear_cmv = EAR_CMV_0_95V | |
| 111 | +}; | |
| 112 | + | |
| 100 | 113 | static struct gpio_keys_button snowball_key_array[] = { |
| 101 | 114 | { |
| 102 | 115 | .gpio = 32, |
| @@ -195,6 +208,7 @@ static struct ab8500_platform_data ab8500_platdata = { · 92 unmodified lines | ||
| 195 | 208 | .regulator = ab8500_regulators, |
| 196 | 209 | .num_regulator = ARRAY_SIZE(ab8500_regulators), |
| 197 | 210 | .gpio = &ab8500_gpio_pdata, |
| 211 | + .codec = &ab8500_codec_pdata, | |
| 198 | 212 | }; |
| 199 | 213 | |
| 200 | 214 | static struct resource ab8500_resources[] = { |
| @@ -1,362 +0,0 @@ | ||
| 1 | −#ifndef _AC97_CODEC_H_ | |
| 2 | −#define _AC97_CODEC_H_ | |
| 3 | − | |
| 4 | −#include <linux/types.h> | |
| 5 | −#include <linux/soundcard.h> | |
| 6 | − | |
| 7 | −/* AC97 1.0 */ | |
| 8 | −#define AC97_RESET 0x0000 // | |
| 9 | −#define AC97_MASTER_VOL_STEREO 0x0002 // Line Out | |
| 10 | −#define AC97_HEADPHONE_VOL 0x0004 // | |
| 11 | −#define AC97_MASTER_VOL_MONO 0x0006 // TAD Output | |
| 12 | −#define AC97_MASTER_TONE 0x0008 // | |
| 13 | −#define AC97_PCBEEP_VOL 0x000a // none | |
| 14 | −#define AC97_PHONE_VOL 0x000c // TAD Input (mono) | |
| 15 | −#define AC97_MIC_VOL 0x000e // MIC Input (mono) | |
| 16 | −#define AC97_LINEIN_VOL 0x0010 // Line Input (stereo) | |
| 17 | −#define AC97_CD_VOL 0x0012 // CD Input (stereo) | |
| 18 | −#define AC97_VIDEO_VOL 0x0014 // none | |
| 19 | −#define AC97_AUX_VOL 0x0016 // Aux Input (stereo) | |
| 20 | −#define AC97_PCMOUT_VOL 0x0018 // Wave Output (stereo) | |
| 21 | −#define AC97_RECORD_SELECT 0x001a // | |
| 22 | −#define AC97_RECORD_GAIN 0x001c | |
| 23 | −#define AC97_RECORD_GAIN_MIC 0x001e | |
| 24 | −#define AC97_GENERAL_PURPOSE 0x0020 | |
| 25 | −#define AC97_3D_CONTROL 0x0022 | |
| 26 | −#define AC97_MODEM_RATE 0x0024 | |
| 27 | −#define AC97_POWER_CONTROL 0x0026 | |
| 28 | − | |
| 29 | −/* AC'97 2.0 */ | |
| 30 | −#define AC97_EXTENDED_ID 0x0028 /* Extended Audio ID */ | |
| 31 | −#define AC97_EXTENDED_STATUS 0x002A /* Extended Audio Status */ | |
| 32 | −#define AC97_PCM_FRONT_DAC_RATE 0x002C /* PCM Front DAC Rate */ | |
| 33 | −#define AC97_PCM_SURR_DAC_RATE 0x002E /* PCM Surround DAC Rate */ | |
| 34 | −#define AC97_PCM_LFE_DAC_RATE 0x0030 /* PCM LFE DAC Rate */ | |
| 35 | −#define AC97_PCM_LR_ADC_RATE 0x0032 /* PCM LR ADC Rate */ | |
| 36 | −#define AC97_PCM_MIC_ADC_RATE 0x0034 /* PCM MIC ADC Rate */ | |
| 37 | −#define AC97_CENTER_LFE_MASTER 0x0036 /* Center + LFE Master Volume */ | |
| 38 | −#define AC97_SURROUND_MASTER 0x0038 /* Surround (Rear) Master Volume */ | |
| 39 | −#define AC97_RESERVED_3A 0x003A /* Reserved in AC '97 < 2.2 */ | |
| 40 | − | |
| 41 | −/* AC'97 2.2 */ | |
| 42 | −#define AC97_SPDIF_CONTROL 0x003A /* S/PDIF Control */ | |
| 43 | − | |
| 44 | −/* range 0x3c-0x58 - MODEM */ | |
| 45 | −#define AC97_EXTENDED_MODEM_ID 0x003C | |
| 46 | −#define AC97_EXTEND_MODEM_STAT 0x003E | |
| 47 | −#define AC97_LINE1_RATE 0x0040 | |
| 48 | −#define AC97_LINE2_RATE 0x0042 | |
| 49 | −#define AC97_HANDSET_RATE 0x0044 | |
| 50 | −#define AC97_LINE1_LEVEL 0x0046 | |
| 51 | −#define AC97_LINE2_LEVEL 0x0048 | |
| 52 | −#define AC97_HANDSET_LEVEL 0x004A | |
| 53 | −#define AC97_GPIO_CONFIG 0x004C | |
| 54 | −#define AC97_GPIO_POLARITY 0x004E | |
| 55 | −#define AC97_GPIO_STICKY 0x0050 | |
| 56 | −#define AC97_GPIO_WAKE_UP 0x0052 | |
| 57 | −#define AC97_GPIO_STATUS 0x0054 | |
| 58 | −#define AC97_MISC_MODEM_STAT 0x0056 | |
| 59 | −#define AC97_RESERVED_58 0x0058 | |
| 60 | − | |
| 61 | −/* registers 0x005a - 0x007a are vendor reserved */ | |
| 62 | − | |
| 63 | −#define AC97_VENDOR_ID1 0x007c | |
| 64 | −#define AC97_VENDOR_ID2 0x007e | |
| 65 | − | |
| 66 | −/* volume control bit defines */ | |
| 67 | −#define AC97_MUTE 0x8000 | |
| 68 | −#define AC97_MICBOOST 0x0040 | |
| 69 | −#define AC97_LEFTVOL 0x3f00 | |
| 70 | −#define AC97_RIGHTVOL 0x003f | |
| 71 | − | |
| 72 | −/* record mux defines */ | |
| 73 | −#define AC97_RECMUX_MIC 0x0000 | |
| 74 | −#define AC97_RECMUX_CD 0x0101 | |
| 75 | −#define AC97_RECMUX_VIDEO 0x0202 | |
| 76 | −#define AC97_RECMUX_AUX 0x0303 | |
| 77 | −#define AC97_RECMUX_LINE 0x0404 | |
| 78 | −#define AC97_RECMUX_STEREO_MIX 0x0505 | |
| 79 | −#define AC97_RECMUX_MONO_MIX 0x0606 | |
| 80 | −#define AC97_RECMUX_PHONE 0x0707 | |
| 81 | − | |
| 82 | −/* general purpose register bit defines */ | |
| 83 | −#define AC97_GP_LPBK 0x0080 /* Loopback mode */ | |
| 84 | −#define AC97_GP_MS 0x0100 /* Mic Select 0=Mic1, 1=Mic2 */ | |
| 85 | −#define AC97_GP_MIX 0x0200 /* Mono output select 0=Mix, 1=Mic */ | |
| 86 | −#define AC97_GP_RLBK 0x0400 /* Remote Loopback - Modem line codec */ | |
| 87 | −#define AC97_GP_LLBK 0x0800 /* Local Loopback - Modem Line codec */ | |
| 88 | −#define AC97_GP_LD 0x1000 /* Loudness 1=on */ | |
| 89 | −#define AC97_GP_3D 0x2000 /* 3D Enhancement 1=on */ | |
| 90 | −#define AC97_GP_ST 0x4000 /* Stereo Enhancement 1=on */ | |
| 91 | −#define AC97_GP_POP 0x8000 /* Pcm Out Path, 0=pre 3D, 1=post 3D */ | |
| 92 | − | |
| 93 | −/* extended audio status and control bit defines */ | |
| 94 | −#define AC97_EA_VRA 0x0001 /* Variable bit rate enable bit */ | |
| 95 | −#define AC97_EA_DRA 0x0002 /* Double-rate audio enable bit */ | |
| 96 | −#define AC97_EA_SPDIF 0x0004 /* S/PDIF Enable bit */ | |
| 97 | −#define AC97_EA_VRM 0x0008 /* Variable bit rate for MIC enable bit */ | |
| 98 | −#define AC97_EA_CDAC 0x0040 /* PCM Center DAC is ready (Read only) */ | |
| 99 | −#define AC97_EA_SDAC 0x0040 /* PCM Surround DACs are ready (Read only) */ | |
| 100 | −#define AC97_EA_LDAC 0x0080 /* PCM LFE DAC is ready (Read only) */ | |
| 101 | −#define AC97_EA_MDAC 0x0100 /* MIC ADC is ready (Read only) */ | |
| 102 | −#define AC97_EA_SPCV 0x0400 /* S/PDIF configuration valid (Read only) */ | |
| 103 | −#define AC97_EA_PRI 0x0800 /* Turns the PCM Center DAC off */ | |
| 104 | −#define AC97_EA_PRJ 0x1000 /* Turns the PCM Surround DACs off */ | |
| 105 | −#define AC97_EA_PRK 0x2000 /* Turns the PCM LFE DAC off */ | |
| 106 | −#define AC97_EA_PRL 0x4000 /* Turns the MIC ADC off */ | |
| 107 | −#define AC97_EA_SLOT_MASK 0xffcf /* Mask for slot assignment bits */ | |
| 108 | −#define AC97_EA_SPSA_3_4 0x0000 /* Slot assigned to 3 & 4 */ | |
| 109 | −#define AC97_EA_SPSA_7_8 0x0010 /* Slot assigned to 7 & 8 */ | |
| 110 | −#define AC97_EA_SPSA_6_9 0x0020 /* Slot assigned to 6 & 9 */ | |
| 111 | −#define AC97_EA_SPSA_10_11 0x0030 /* Slot assigned to 10 & 11 */ | |
| 112 | − | |
| 113 | −/* S/PDIF control bit defines */ | |
| 114 | −#define AC97_SC_PRO 0x0001 /* Professional status */ | |
| 115 | −#define AC97_SC_NAUDIO 0x0002 /* Non audio stream */ | |
| 116 | −#define AC97_SC_COPY 0x0004 /* Copyright status */ | |
| 117 | −#define AC97_SC_PRE 0x0008 /* Preemphasis status */ | |
| 118 | −#define AC97_SC_CC_MASK 0x07f0 /* Category Code mask */ | |
| 119 | −#define AC97_SC_L 0x0800 /* Generation Level status */ | |
| 120 | −#define AC97_SC_SPSR_MASK 0xcfff /* S/PDIF Sample Rate bits */ | |
| 121 | −#define AC97_SC_SPSR_44K 0x0000 /* Use 44.1kHz Sample rate */ | |
| 122 | −#define AC97_SC_SPSR_48K 0x2000 /* Use 48kHz Sample rate */ | |
| 123 | −#define AC97_SC_SPSR_32K 0x3000 /* Use 32kHz Sample rate */ | |
| 124 | −#define AC97_SC_DRS 0x4000 /* Double Rate S/PDIF */ | |
| 125 | −#define AC97_SC_V 0x8000 /* Validity status */ | |
| 126 | − | |
| 127 | −/* powerdown control and status bit defines */ | |
| 128 | − | |
| 129 | −/* status */ | |
| 130 | −#define AC97_PWR_MDM 0x0010 /* Modem section ready */ | |
| 131 | −#define AC97_PWR_REF 0x0008 /* Vref nominal */ | |
| 132 | −#define AC97_PWR_ANL 0x0004 /* Analog section ready */ | |
| 133 | −#define AC97_PWR_DAC 0x0002 /* DAC section ready */ | |
| 134 | −#define AC97_PWR_ADC 0x0001 /* ADC section ready */ | |
| 135 | − | |
| 136 | −/* control */ | |
| 137 | −#define AC97_PWR_PR0 0x0100 /* ADC and Mux powerdown */ | |
| 138 | −#define AC97_PWR_PR1 0x0200 /* DAC powerdown */ | |
| 139 | −#define AC97_PWR_PR2 0x0400 /* Output mixer powerdown (Vref on) */ | |
| 140 | −#define AC97_PWR_PR3 0x0800 /* Output mixer powerdown (Vref off) */ | |
| 141 | −#define AC97_PWR_PR4 0x1000 /* AC-link powerdown */ | |
| 142 | −#define AC97_PWR_PR5 0x2000 /* Internal Clk disable */ | |
| 143 | −#define AC97_PWR_PR6 0x4000 /* HP amp powerdown */ | |
| 144 | −#define AC97_PWR_PR7 0x8000 /* Modem off - if supported */ | |
| 145 | − | |
| 146 | −/* extended audio ID register bit defines */ | |
| 147 | −#define AC97_EXTID_VRA 0x0001 | |
| 148 | −#define AC97_EXTID_DRA 0x0002 | |
| 149 | −#define AC97_EXTID_SPDIF 0x0004 | |
| 150 | −#define AC97_EXTID_VRM 0x0008 | |
| 151 | −#define AC97_EXTID_DSA0 0x0010 | |
| 152 | −#define AC97_EXTID_DSA1 0x0020 | |
| 153 | −#define AC97_EXTID_CDAC 0x0040 | |
| 154 | −#define AC97_EXTID_SDAC 0x0080 | |
| 155 | −#define AC97_EXTID_LDAC 0x0100 | |
| 156 | −#define AC97_EXTID_AMAP 0x0200 | |
| 157 | −#define AC97_EXTID_REV0 0x0400 | |
| 158 | −#define AC97_EXTID_REV1 0x0800 | |
| 159 | −#define AC97_EXTID_ID0 0x4000 | |
| 160 | −#define AC97_EXTID_ID1 0x8000 | |
| 161 | − | |
| 162 | −/* extended status register bit defines */ | |
| 163 | −#define AC97_EXTSTAT_VRA 0x0001 | |
| 164 | −#define AC97_EXTSTAT_DRA 0x0002 | |
| 165 | −#define AC97_EXTSTAT_SPDIF 0x0004 | |
| 166 | −#define AC97_EXTSTAT_VRM 0x0008 | |
| 167 | −#define AC97_EXTSTAT_SPSA0 0x0010 | |
| 168 | −#define AC97_EXTSTAT_SPSA1 0x0020 | |
| 169 | −#define AC97_EXTSTAT_CDAC 0x0040 | |
| 170 | −#define AC97_EXTSTAT_SDAC 0x0080 | |
| 171 | −#define AC97_EXTSTAT_LDAC 0x0100 | |
| 172 | −#define AC97_EXTSTAT_MADC 0x0200 | |
| 173 | −#define AC97_EXTSTAT_SPCV 0x0400 | |
| 174 | −#define AC97_EXTSTAT_PRI 0x0800 | |
| 175 | −#define AC97_EXTSTAT_PRJ 0x1000 | |
| 176 | −#define AC97_EXTSTAT_PRK 0x2000 | |
| 177 | −#define AC97_EXTSTAT_PRL 0x4000 | |
| 178 | − | |
| 179 | −/* extended audio ID register bit defines */ | |
| 180 | −#define AC97_EXTID_VRA 0x0001 | |
| 181 | −#define AC97_EXTID_DRA 0x0002 | |
| 182 | −#define AC97_EXTID_SPDIF 0x0004 | |
| 183 | −#define AC97_EXTID_VRM 0x0008 | |
| 184 | −#define AC97_EXTID_DSA0 0x0010 | |
| 185 | −#define AC97_EXTID_DSA1 0x0020 | |
| 186 | −#define AC97_EXTID_CDAC 0x0040 | |
| 187 | −#define AC97_EXTID_SDAC 0x0080 | |
| 188 | −#define AC97_EXTID_LDAC 0x0100 | |
| 189 | −#define AC97_EXTID_AMAP 0x0200 | |
| 190 | −#define AC97_EXTID_REV0 0x0400 | |
| 191 | −#define AC97_EXTID_REV1 0x0800 | |
| 192 | −#define AC97_EXTID_ID0 0x4000 | |
| 193 | −#define AC97_EXTID_ID1 0x8000 | |
| 194 | − | |
| 195 | −/* extended status register bit defines */ | |
| 196 | −#define AC97_EXTSTAT_VRA 0x0001 | |
| 197 | −#define AC97_EXTSTAT_DRA 0x0002 | |
| 198 | −#define AC97_EXTSTAT_SPDIF 0x0004 | |
| 199 | −#define AC97_EXTSTAT_VRM 0x0008 | |
| 200 | −#define AC97_EXTSTAT_SPSA0 0x0010 | |
| 201 | −#define AC97_EXTSTAT_SPSA1 0x0020 | |
| 202 | −#define AC97_EXTSTAT_CDAC 0x0040 | |
| 203 | −#define AC97_EXTSTAT_SDAC 0x0080 | |
| 204 | −#define AC97_EXTSTAT_LDAC 0x0100 | |
| 205 | −#define AC97_EXTSTAT_MADC 0x0200 | |
| 206 | −#define AC97_EXTSTAT_SPCV 0x0400 | |
| 207 | −#define AC97_EXTSTAT_PRI 0x0800 | |
| 208 | −#define AC97_EXTSTAT_PRJ 0x1000 | |
| 209 | −#define AC97_EXTSTAT_PRK 0x2000 | |
| 210 | −#define AC97_EXTSTAT_PRL 0x4000 | |
| 211 | − | |
| 212 | −/* useful power states */ | |
| 213 | −#define AC97_PWR_D0 0x0000 /* everything on */ | |
| 214 | −#define AC97_PWR_D1 AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR4 | |
| 215 | −#define AC97_PWR_D2 AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR2|AC97_PWR_PR3|AC97_PWR_PR4 | |
| 216 | −#define AC97_PWR_D3 AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR2|AC97_PWR_PR3|AC97_PWR_PR4 | |
| 217 | −#define AC97_PWR_ANLOFF AC97_PWR_PR2|AC97_PWR_PR3 /* analog section off */ | |
| 218 | − | |
| 219 | −/* Total number of defined registers. */ | |
| 220 | −#define AC97_REG_CNT 64 | |
| 221 | − | |
| 222 | − | |
| 223 | −/* OSS interface to the ac97s.. */ | |
| 224 | −#define AC97_STEREO_MASK (SOUND_MASK_VOLUME|SOUND_MASK_PCM|\ | |
| 225 | − SOUND_MASK_LINE|SOUND_MASK_CD|\ | |
| 226 | − SOUND_MASK_ALTPCM|SOUND_MASK_IGAIN|\ | |
| 227 | − SOUND_MASK_LINE1|SOUND_MASK_VIDEO) | |
| 228 | − | |
| 229 | −#define AC97_SUPPORTED_MASK (AC97_STEREO_MASK | \ | |
| 230 | − SOUND_MASK_BASS|SOUND_MASK_TREBLE|\ | |
| 231 | − SOUND_MASK_SPEAKER|SOUND_MASK_MIC|\ | |
| 232 | − SOUND_MASK_PHONEIN|SOUND_MASK_PHONEOUT) | |
| 233 | − | |
| 234 | −#define AC97_RECORD_MASK (SOUND_MASK_MIC|\ | |
| 235 | − SOUND_MASK_CD|SOUND_MASK_IGAIN|SOUND_MASK_VIDEO|\ | |
| 236 | − SOUND_MASK_LINE1| SOUND_MASK_LINE|\ | |
| 237 | − SOUND_MASK_PHONEIN) | |
| 238 | − | |
| 239 | −/* original check is not good enough in case FOO is greater than | |
| 240 | − * SOUND_MIXER_NRDEVICES because the supported_mixers has exactly | |
| 241 | − * SOUND_MIXER_NRDEVICES elements. | |
| 242 | − * before matching the given mixer against the bitmask in supported_mixers we | |
| 243 | − * check if mixer number exceeds maximum allowed size which is as mentioned | |
| 244 | − * above SOUND_MIXER_NRDEVICES */ | |
| 245 | −#define supported_mixer(CODEC,FOO) ((FOO >= 0) && \ | |
| 246 | − (FOO < SOUND_MIXER_NRDEVICES) && \ | |
| 247 | − (CODEC)->supported_mixers & (1<<FOO) ) | |
| 248 | − | |
| 249 | −struct ac97_codec { | |
| 250 | − /* Linked list of codecs */ | |
| 251 | − struct list_head list; | |
| 252 | − | |
| 253 | − /* AC97 controller connected with */ | |
| 254 | − void *private_data; | |
| 255 | − | |
| 256 | − char *name; | |
| 257 | − int id; | |
| 258 | − int dev_mixer; | |
| 259 | − int type; | |
| 260 | − u32 model; | |
| 261 | − | |
| 262 | − unsigned int modem:1; | |
| 263 | − | |
| 264 | − struct ac97_ops *codec_ops; | |
| 265 | − | |
| 266 | − /* controller specific lower leverl ac97 accessing routines. | |
| 267 | − must be re-entrant safe */ | |
| 268 | − u16 (*codec_read) (struct ac97_codec *codec, u8 reg); | |
| 269 | − void (*codec_write) (struct ac97_codec *codec, u8 reg, u16 val); | |
| 270 | − | |
| 271 | − /* Wait for codec-ready. Ok to sleep here. */ | |
| 272 | − void (*codec_wait) (struct ac97_codec *codec); | |
| 273 | − | |
| 274 | − /* callback used by helper drivers for interesting ac97 setups */ | |
| 275 | − void (*codec_unregister) (struct ac97_codec *codec); | |
| 276 | − | |
| 277 | − struct ac97_driver *driver; | |
| 278 | − void *driver_private; /* Private data for the driver */ | |
| 279 | − | |
| 280 | − spinlock_t lock; | |
| 281 | − | |
| 282 | − /* OSS mixer masks */ | |
| 283 | − int modcnt; | |
| 284 | − int supported_mixers; | |
| 285 | − int stereo_mixers; | |
| 286 | − int record_sources; | |
| 287 | − | |
| 288 | − /* Property flags */ | |
| 289 | − int flags; | |
| 290 | − | |
| 291 | − int bit_resolution; | |
| 292 | − | |
| 293 | − /* OSS mixer interface */ | |
| 294 | − int (*read_mixer) (struct ac97_codec *codec, int oss_channel); | |
| 295 | − void (*write_mixer)(struct ac97_codec *codec, int oss_channel, | |
| 296 | − unsigned int left, unsigned int right); | |
| 297 | − int (*recmask_io) (struct ac97_codec *codec, int rw, int mask); | |
| 298 | − int (*mixer_ioctl)(struct ac97_codec *codec, unsigned int cmd, unsigned long arg); | |
| 299 | − | |
| 300 | − /* saved OSS mixer states */ | |
| 301 | − unsigned int mixer_state[SOUND_MIXER_NRDEVICES]; | |
| 302 | − | |
| 303 | − /* Software Modem interface */ | |
| 304 | − int (*modem_ioctl)(struct ac97_codec *codec, unsigned int cmd, unsigned long arg); | |
| 305 | −}; | |
| 306 | − | |
| 307 | −/* | |
| 308 | − * Operation structures for each known AC97 chip | |
| 309 | − */ | |
| 310 | − | |
| 311 | −struct ac97_ops | |
| 312 | −{ | |
| 313 | − /* Initialise */ | |
| 314 | − int (*init)(struct ac97_codec *c); | |
| 315 | − /* Amplifier control */ | |
| 316 | − int (*amplifier)(struct ac97_codec *codec, int on); | |
| 317 | − /* Digital mode control */ | |
| 318 | − int (*digital)(struct ac97_codec *codec, int slots, int rate, int mode); | |
| 319 | −#define AUDIO_DIGITAL 0x8000 | |
| 320 | −#define AUDIO_PRO 0x4000 | |
| 321 | −#define AUDIO_DRS 0x2000 | |
| 322 | −#define AUDIO_CCMASK 0x003F | |
| 323 | − | |
| 324 | −#define AC97_DELUDED_MODEM 1 /* Audio codec reports its a modem */ | |
| 325 | −#define AC97_NO_PCM_VOLUME 2 /* Volume control is missing */ | |
| 326 | −#define AC97_DEFAULT_POWER_OFF 4 /* Needs warm reset to power up */ | |
| 327 | −}; | |
| 328 | − | |
| 329 | −extern int ac97_probe_codec(struct ac97_codec *); | |
| 330 | − | |
| 331 | −extern struct ac97_codec *ac97_alloc_codec(void); | |
| 332 | −extern void ac97_release_codec(struct ac97_codec *codec); | |
| 333 | − | |
| 334 | −struct ac97_driver { | |
| 335 | − struct list_head list; | |
| 336 | − char *name; | |
| 337 | − u32 codec_id; | |
| 338 | − u32 codec_mask; | |
| 339 | − int (*probe) (struct ac97_codec *codec, struct ac97_driver *driver); | |
| 340 | − void (*remove) (struct ac97_codec *codec, struct ac97_driver *driver); | |
| 341 | −}; | |
| 342 | − | |
| 343 | −/* quirk types */ | |
| 344 | −enum { | |
| 345 | − AC97_TUNE_DEFAULT = -1, /* use default from quirk list (not valid in list) */ | |
| 346 | − AC97_TUNE_NONE = 0, /* nothing extra to do */ | |
| 347 | − AC97_TUNE_HP_ONLY, /* headphone (true line-out) control as master only */ | |
| 348 | − AC97_TUNE_SWAP_HP, /* swap headphone and master controls */ | |
| 349 | − AC97_TUNE_SWAP_SURROUND, /* swap master and surround controls */ | |
| 350 | − AC97_TUNE_AD_SHARING, /* for AD1985, turn on OMS bit and use headphone */ | |
| 351 | − AC97_TUNE_ALC_JACK, /* for Realtek, enable JACK detection */ | |
| 352 | −}; | |
| 353 | − | |
| 354 | −struct ac97_quirk { | |
| 355 | − unsigned short vendor; /* PCI vendor id */ | |
| 356 | − unsigned short device; /* PCI device id */ | |
| 357 | − unsigned short mask; /* device id bit mask, 0 = accept all */ | |
| 358 | − const char *name; /* name shown as info */ | |
| 359 | − int type; /* quirk type above */ | |
| 360 | −}; | |
| 361 | − | |
| 362 | −#endif /* _AC97_CODEC_H_ */ | |
| @@ -670,6 +670,12 @@ static inline int dmaengine_resume(struct dma_chan *chan) · 669 unmodified lines | ||
| 670 | 670 | return dmaengine_device_control(chan, DMA_RESUME, 0); |
| 671 | 671 | } |
| 672 | 672 | |
| 673 | +static inline enum dma_status dmaengine_tx_status(struct dma_chan *chan, | |
| 674 | + dma_cookie_t cookie, struct dma_tx_state *state) | |
| 675 | +{ | |
| 676 | + return chan->device->device_tx_status(chan, cookie, state); | |
| 677 | +} | |
| 678 | + | |
| 673 | 679 | static inline dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc) |
| 674 | 680 | { |
| 675 | 681 | return desc->tx_submit(desc); |
| @@ -0,0 +1,52 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C) ST-Ericsson SA 2012 | |
| 3 | + * | |
| 4 | + * Author: Ola Lilja <ola.o.lilja@stericsson.com> | |
| 5 | + * for ST-Ericsson. | |
| 6 | + * | |
| 7 | + * License terms: | |
| 8 | + * | |
| 9 | + * This program is free software; you can redistribute it and/or modify it | |
| 10 | + * under the terms of the GNU General Public License version 2 as published | |
| 11 | + * by the Free Software Foundation. | |
| 12 | + */ | |
| 13 | + | |
| 14 | +#ifndef AB8500_CORE_CODEC_H | |
| 15 | +#define AB8500_CORE_CODEC_H | |
| 16 | + | |
| 17 | +/* Mic-types */ | |
| 18 | +enum amic_type { | |
| 19 | + AMIC_TYPE_SINGLE_ENDED, | |
| 20 | + AMIC_TYPE_DIFFERENTIAL | |
| 21 | +}; | |
| 22 | + | |
| 23 | +/* Mic-biases */ | |
| 24 | +enum amic_micbias { | |
| 25 | + AMIC_MICBIAS_VAMIC1, | |
| 26 | + AMIC_MICBIAS_VAMIC2 | |
| 27 | +}; | |
| 28 | + | |
| 29 | +/* Bias-voltage */ | |
| 30 | +enum ear_cm_voltage { | |
| 31 | + EAR_CMV_0_95V, | |
| 32 | + EAR_CMV_1_10V, | |
| 33 | + EAR_CMV_1_27V, | |
| 34 | + EAR_CMV_1_58V | |
| 35 | +}; | |
| 36 | + | |
| 37 | +/* Analog microphone settings */ | |
| 38 | +struct amic_settings { | |
| 39 | + enum amic_type mic1_type; | |
| 40 | + enum amic_type mic2_type; | |
| 41 | + enum amic_micbias mic1a_micbias; | |
| 42 | + enum amic_micbias mic1b_micbias; | |
| 43 | + enum amic_micbias mic2_micbias; | |
| 44 | +}; | |
| 45 | + | |
| 46 | +/* Platform data structure for the audio-parts of the AB8500 */ | |
| 47 | +struct ab8500_codec_platform_data { | |
| 48 | + struct amic_settings amics; | |
| 49 | + enum ear_cm_voltage ear_cmv; | |
| 50 | +}; | |
| 51 | + | |
| 52 | +#endif | |
| @@ -266,6 +266,7 @@ struct ab8500 { · 265 unmodified lines | ||
| 266 | 266 | struct regulator_reg_init; |
| 267 | 267 | struct regulator_init_data; |
| 268 | 268 | struct ab8500_gpio_platform_data; |
| 269 | +struct ab8500_codec_platform_data; | |
| 269 | 270 | |
| 270 | 271 | /** |
| 271 | 272 | * struct ab8500_platform_data - AB8500 platform data |
| @@ -284,6 +285,7 @@ struct ab8500_platform_data { · 12 unmodified lines | ||
| 284 | 285 | int num_regulator; |
| 285 | 286 | struct regulator_init_data *regulator; |
| 286 | 287 | struct ab8500_gpio_platform_data *gpio; |
| 288 | + struct ab8500_codec_platform_data *codec; | |
| 287 | 289 | }; |
| 288 | 290 | |
| 289 | 291 | extern int __devinit ab8500_init(struct ab8500 *ab8500, |
| @@ -0,0 +1,22 @@ | ||
| 1 | +/* | |
| 2 | + * MMP Platform AUDIO Management | |
| 3 | + * | |
| 4 | + * Copyright (c) 2011 Marvell Semiconductors Inc. | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License version 2 as | |
| 8 | + * published by the Free Software Foundation. | |
| 9 | + * | |
| 10 | + */ | |
| 11 | + | |
| 12 | +#ifndef MMP_AUDIO_H | |
| 13 | +#define MMP_AUDIO_H | |
| 14 | + | |
| 15 | +struct mmp_audio_platdata { | |
| 16 | + u32 period_max_capture; | |
| 17 | + u32 buffer_max_capture; | |
| 18 | + u32 period_max_playback; | |
| 19 | + u32 buffer_max_playback; | |
| 20 | +}; | |
| 21 | + | |
| 22 | +#endif /* MMP_AUDIO_H */ | |
| @@ -0,0 +1,69 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (ST) 2012 Rajeev Kumar (rajeev-dlh.kumar@st.com) | |
| 3 | + * | |
| 4 | + * This program is free software; you can redistribute it and/or modify | |
| 5 | + * it under the terms of the GNU General Public License as published by | |
| 6 | + * the Free Software Foundation; either version 2 of the License, or | |
| 7 | + * (at your option) any later version. | |
| 8 | + * | |
| 9 | + * This program is distributed in the hope that it will be useful, | |
| 10 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 | + * GNU General Public License for more details. | |
| 13 | + * | |
| 14 | + * You should have received a copy of the GNU General Public License | |
| 15 | + * along with this program; if not, write to the Free Software | |
| 16 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 17 | + * | |
| 18 | + */ | |
| 19 | + | |
| 20 | +#ifndef __SOUND_DESIGNWARE_I2S_H | |
| 21 | +#define __SOUND_DESIGNWARE_I2S_H | |
| 22 | + | |
| 23 | +#include <linux/dmaengine.h> | |
| 24 | +#include <linux/types.h> | |
| 25 | + | |
| 26 | +/* | |
| 27 | + * struct i2s_clk_config_data - represent i2s clk configuration data | |
| 28 | + * @chan_nr: number of channel | |
| 29 | + * @data_width: number of bits per sample (8/16/24/32 bit) | |
| 30 | + * @sample_rate: sampling frequency (8Khz, 16Khz, 32Khz, 44Khz, 48Khz) | |
| 31 | + */ | |
| 32 | +struct i2s_clk_config_data { | |
| 33 | + int chan_nr; | |
| 34 | + u32 data_width; | |
| 35 | + u32 sample_rate; | |
| 36 | +}; | |
| 37 | + | |
| 38 | +struct i2s_platform_data { | |
| 39 | + #define DWC_I2S_PLAY (1 << 0) | |
| 40 | + #define DWC_I2S_RECORD (1 << 1) | |
| 41 | + unsigned int cap; | |
| 42 | + int channel; | |
| 43 | + u32 snd_fmts; | |
| 44 | + u32 snd_rates; | |
| 45 | + | |
| 46 | + void *play_dma_data; | |
| 47 | + void *capture_dma_data; | |
| 48 | + bool (*filter)(struct dma_chan *chan, void *slave); | |
| 49 | + int (*i2s_clk_cfg)(struct i2s_clk_config_data *config); | |
| 50 | +}; | |
| 51 | + | |
| 52 | +struct i2s_dma_data { | |
| 53 | + void *data; | |
| 54 | + dma_addr_t addr; | |
| 55 | + u32 max_burst; | |
| 56 | + enum dma_slave_buswidth addr_width; | |
| 57 | + bool (*filter)(struct dma_chan *chan, void *slave); | |
| 58 | +}; | |
| 59 | + | |
| 60 | +/* I2S DMA registers */ | |
| 61 | +#define I2S_RXDMA 0x01C0 | |
| 62 | +#define I2S_TXDMA 0x01C8 | |
| 63 | + | |
| 64 | +#define TWO_CHANNEL_SUPPORT 2 /* up to 2.0 */ | |
| 65 | +#define FOUR_CHANNEL_SUPPORT 4 /* up to 3.1 */ | |
| 66 | +#define SIX_CHANNEL_SUPPORT 6 /* up to 5.1 */ | |
| 67 | +#define EIGHT_CHANNEL_SUPPORT 8 /* up to 7.1 */ | |
| 68 | + | |
| 69 | +#endif /* __SOUND_DESIGNWARE_I2S_H */ | |
| @@ -39,6 +39,7 @@ int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, · 38 unmodified lines | ||
| 39 | 39 | const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config); |
| 40 | 40 | int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd); |
| 41 | 41 | snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream); |
| 42 | +snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream); | |
| 42 | 43 | |
| 43 | 44 | int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, |
| 44 | 45 | dma_filter_fn filter_fn, void *filter_data); |
| @@ -810,7 +810,7 @@ int snd_pcm_hw_constraint_integer(struct snd_pcm_runtime *runtime, snd_pcm_hw_pa · 809 unmodified lines | ||
| 810 | 810 | int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime, |
| 811 | 811 | unsigned int cond, |
| 812 | 812 | snd_pcm_hw_param_t var, |
| 813 | − struct snd_pcm_hw_constraint_list *l); | |
| 813 | + const struct snd_pcm_hw_constraint_list *l); | |
| 814 | 814 | int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime, |
| 815 | 815 | unsigned int cond, |
| 816 | 816 | snd_pcm_hw_param_t var, |
| @@ -893,6 +893,7 @@ extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates; · 76 unmodified lines | ||
| 893 | 893 | |
| 894 | 894 | int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime); |
| 895 | 895 | unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate); |
| 896 | +unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit); | |
| 896 | 897 | |
| 897 | 898 | static inline void snd_pcm_set_runtime_buffer(struct snd_pcm_substream *substream, |
| 898 | 899 | struct snd_dma_buffer *bufp) |
| @@ -1073,4 +1074,15 @@ static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max) · 174 unmodified lines | ||
| 1073 | 1074 | |
| 1074 | 1075 | const char *snd_pcm_format_name(snd_pcm_format_t format); |
| 1075 | 1076 | |
| 1077 | +/** | |
| 1078 | + * Get a string naming the direction of a stream | |
| 1079 | + */ | |
| 1080 | +static inline const char *snd_pcm_stream_str(struct snd_pcm_substream *substream) | |
| 1081 | +{ | |
| 1082 | + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | |
| 1083 | + return "Playback"; | |
| 1084 | + else | |
| 1085 | + return "Capture"; | |
| 1086 | +} | |
| 1087 | + | |
| 1076 | 1088 | #endif /* __SOUND_PCM_H */ |
| @@ -22,6 +22,8 @@ · 21 unmodified lines | ||
| 22 | 22 | * |
| 23 | 23 | */ |
| 24 | 24 | |
| 25 | +#include <sound/pcm.h> | |
| 26 | + | |
| 25 | 27 | int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm, |
| 26 | 28 | struct snd_pcm_hw_params *params, |
| 27 | 29 | snd_pcm_hw_param_t var, int *dir); |
| @@ -229,6 +229,10 @@ struct device; · 228 unmodified lines | ||
| 229 | 229 | { .id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \ |
| 230 | 230 | .shift = wshift, .invert = winvert, \ |
| 231 | 231 | .event = wevent, .event_flags = wflags} |
| 232 | +#define SND_SOC_DAPM_CLOCK_SUPPLY(wname) \ | |
| 233 | +{ .id = snd_soc_dapm_clock_supply, .name = wname, \ | |
| 234 | + .reg = SND_SOC_NOPM, .event = dapm_clock_event, \ | |
| 235 | + .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD } | |
| 232 | 236 | |
| 233 | 237 | /* generic widgets */ |
| 234 | 238 | #define SND_SOC_DAPM_REG(wid, wname, wreg, wshift, wmask, won_val, woff_val) \ |
| @@ -245,6 +249,7 @@ struct device; · 10 unmodified lines | ||
| 245 | 249 | .reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \ |
| 246 | 250 | .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD } |
| 247 | 251 | |
| 252 | + | |
| 248 | 253 | /* dapm kcontrol types */ |
| 249 | 254 | #define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \ |
| 250 | 255 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
| @@ -327,6 +332,8 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w, · 76 unmodified lines | ||
| 327 | 332 | struct snd_kcontrol *kcontrol, int event); |
| 328 | 333 | int dapm_regulator_event(struct snd_soc_dapm_widget *w, |
| 329 | 334 | struct snd_kcontrol *kcontrol, int event); |
| 335 | +int dapm_clock_event(struct snd_soc_dapm_widget *w, | |
| 336 | + struct snd_kcontrol *kcontrol, int event); | |
| 330 | 337 | |
| 331 | 338 | /* dapm controls */ |
| 332 | 339 | int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, |
| @@ -367,6 +374,8 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm); · 34 unmodified lines | ||
| 367 | 374 | void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm); |
| 368 | 375 | int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, |
| 369 | 376 | const struct snd_soc_dapm_route *route, int num); |
| 377 | +int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm, | |
| 378 | + const struct snd_soc_dapm_route *route, int num); | |
| 370 | 379 | int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm, |
| 371 | 380 | const struct snd_soc_dapm_route *route, int num); |
| 372 | 381 | |
| @@ -432,6 +441,7 @@ enum snd_soc_dapm_type { · 59 unmodified lines | ||
| 432 | 441 | snd_soc_dapm_post, /* machine specific post widget - exec last */ |
| 433 | 442 | snd_soc_dapm_supply, /* power/clock supply */ |
| 434 | 443 | snd_soc_dapm_regulator_supply, /* external regulator */ |
| 444 | + snd_soc_dapm_clock_supply, /* external clock */ | |
| 435 | 445 | snd_soc_dapm_aif_in, /* audio interface input */ |
| 436 | 446 | snd_soc_dapm_aif_out, /* audio interface output */ |
| 437 | 447 | snd_soc_dapm_siggen, /* signal generator */ |
| @@ -537,6 +547,8 @@ struct snd_soc_dapm_widget { · 99 unmodified lines | ||
| 537 | 547 | struct list_head dirty; |
| 538 | 548 | int inputs; |
| 539 | 549 | int outputs; |
| 550 | + | |
| 551 | + struct clk *clk; | |
| 540 | 552 | }; |
| 541 | 553 | |
| 542 | 554 | struct snd_soc_dapm_update { |
| @@ -42,11 +42,22 @@ · 41 unmodified lines | ||
| 42 | 42 | ((unsigned long)&(struct soc_mixer_control) \ |
| 43 | 43 | {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ |
| 44 | 44 | .max = xmax, .platform_max = xmax, .invert = xinvert}) |
| 45 | +#define SOC_DOUBLE_R_RANGE_VALUE(xlreg, xrreg, xshift, xmin, xmax, xinvert) \ | |
| 46 | + ((unsigned long)&(struct soc_mixer_control) \ | |
| 47 | + {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ | |
| 48 | + .min = xmin, .max = xmax, .platform_max = xmax, .invert = xinvert}) | |
| 45 | 49 | #define SOC_SINGLE(xname, reg, shift, max, invert) \ |
| 46 | 50 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
| 47 | 51 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ |
| 48 | 52 | .put = snd_soc_put_volsw, \ |
| 49 | 53 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } |
| 54 | +#define SOC_SINGLE_RANGE(xname, xreg, xshift, xmin, xmax, xinvert) \ | |
| 55 | +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ | |
| 56 | + .info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \ | |
| 57 | + .put = snd_soc_put_volsw_range, \ | |
| 58 | + .private_value = (unsigned long)&(struct soc_mixer_control) \ | |
| 59 | + {.reg = xreg, .shift = xshift, .min = xmin,\ | |
| 60 | + .max = xmax, .platform_max = xmax, .invert = xinvert} } | |
| 50 | 61 | #define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ |
| 51 | 62 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
| 52 | 63 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ |
| @@ -67,6 +78,16 @@ · 14 unmodified lines | ||
| 67 | 78 | {.reg = xreg, .rreg = xreg, \ |
| 68 | 79 | .shift = xshift, .rshift = xshift, \ |
| 69 | 80 | .max = xmax, .min = xmin} } |
| 81 | +#define SOC_SINGLE_RANGE_TLV(xname, xreg, xshift, xmin, xmax, xinvert, tlv_array) \ | |
| 82 | +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ | |
| 83 | + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | |
| 84 | + SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | |
| 85 | + .tlv.p = (tlv_array), \ | |
| 86 | + .info = snd_soc_info_volsw_range, \ | |
| 87 | + .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \ | |
| 88 | + .private_value = (unsigned long)&(struct soc_mixer_control) \ | |
| 89 | + {.reg = xreg, .shift = xshift, .min = xmin,\ | |
| 90 | + .max = xmax, .platform_max = xmax, .invert = xinvert} } | |
| 70 | 91 | #define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \ |
| 71 | 92 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ |
| 72 | 93 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ |
| @@ -79,6 +100,13 @@ · 6 unmodified lines | ||
| 79 | 100 | .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ |
| 80 | 101 | .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ |
| 81 | 102 | xmax, xinvert) } |
| 103 | +#define SOC_DOUBLE_R_RANGE(xname, reg_left, reg_right, xshift, xmin, \ | |
| 104 | + xmax, xinvert) \ | |
| 105 | +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ | |
| 106 | + .info = snd_soc_info_volsw_range, \ | |
| 107 | + .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \ | |
| 108 | + .private_value = SOC_DOUBLE_R_RANGE_VALUE(reg_left, reg_right, \ | |
| 109 | + xshift, xmin, xmax, xinvert) } | |
| 82 | 110 | #define SOC_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, tlv_array) \ |
| 83 | 111 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ |
| 84 | 112 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ |
| @@ -97,6 +125,16 @@ · 12 unmodified lines | ||
| 97 | 125 | .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ |
| 98 | 126 | .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ |
| 99 | 127 | xmax, xinvert) } |
| 128 | +#define SOC_DOUBLE_R_RANGE_TLV(xname, reg_left, reg_right, xshift, xmin, \ | |
| 129 | + xmax, xinvert, tlv_array) \ | |
| 130 | +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ | |
| 131 | + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | |
| 132 | + SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | |
| 133 | + .tlv.p = (tlv_array), \ | |
| 134 | + .info = snd_soc_info_volsw_range, \ | |
| 135 | + .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \ | |
| 136 | + .private_value = SOC_DOUBLE_R_RANGE_VALUE(reg_left, reg_right, \ | |
| 137 | + xshift, xmin, xmax, xinvert) } | |
| 100 | 138 | #define SOC_DOUBLE_R_SX_TLV(xname, xreg, xrreg, xshift, xmin, xmax, tlv_array) \ |
| 101 | 139 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ |
| 102 | 140 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ |
| @@ -460,6 +498,12 @@ int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol, · 357 unmodified lines | ||
| 460 | 498 | struct snd_ctl_elem_value *ucontrol); |
| 461 | 499 | int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, |
| 462 | 500 | struct snd_ctl_elem_value *ucontrol); |
| 501 | +int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, | |
| 502 | + struct snd_ctl_elem_info *uinfo); | |
| 503 | +int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, | |
| 504 | + struct snd_ctl_elem_value *ucontrol); | |
| 505 | +int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, | |
| 506 | + struct snd_ctl_elem_value *ucontrol); | |
| 463 | 507 | int snd_soc_limit_volume(struct snd_soc_codec *codec, |
| 464 | 508 | const char *name, int max); |
| 465 | 509 | int snd_soc_bytes_info(struct snd_kcontrol *kcontrol, |
| @@ -785,13 +829,36 @@ struct snd_soc_dai_link { · 319 unmodified lines | ||
| 785 | 829 | /* config - must be set by machine driver */ |
| 786 | 830 | const char *name; /* Codec name */ |
| 787 | 831 | const char *stream_name; /* Stream name */ |
| 788 | − const char *codec_name; /* for multi-codec */ | |
| 789 | − const struct device_node *codec_of_node; | |
| 790 | − const char *platform_name; /* for multi-platform */ | |
| 791 | − const struct device_node *platform_of_node; | |
| 832 | + /* | |
| 833 | + * You MAY specify the link's CPU-side device, either by device name, | |
| 834 | + * or by DT/OF node, but not both. If this information is omitted, | |
| 835 | + * the CPU-side DAI is matched using .cpu_dai_name only, which hence | |
| 836 | + * must be globally unique. These fields are currently typically used | |
| 837 | + * only for codec to codec links, or systems using device tree. | |
| 838 | + */ | |
| 839 | + const char *cpu_name; | |
| 840 | + const struct device_node *cpu_of_node; | |
| 841 | + /* | |
| 842 | + * You MAY specify the DAI name of the CPU DAI. If this information is | |
| 843 | + * omitted, the CPU-side DAI is matched using .cpu_name/.cpu_of_node | |
| 844 | + * only, which only works well when that device exposes a single DAI. | |
| 845 | + */ | |
| 792 | 846 | const char *cpu_dai_name; |
| 793 | − const struct device_node *cpu_dai_of_node; | |
| 847 | + /* | |
| 848 | + * You MUST specify the link's codec, either by device name, or by | |
| 849 | + * DT/OF node, but not both. | |
| 850 | + */ | |
| 851 | + const char *codec_name; | |
| 852 | + const struct device_node *codec_of_node; | |
| 853 | + /* You MUST specify the DAI name within the codec */ | |
| 794 | 854 | const char *codec_dai_name; |
| 855 | + /* | |
| 856 | + * You MAY specify the link's platform/PCM/DMA driver, either by | |
| 857 | + * device name, or by DT/OF node, but not both. Some forms of link | |
| 858 | + * do not need a platform. | |
| 859 | + */ | |
| 860 | + const char *platform_name; | |
| 861 | + const struct device_node *platform_of_node; | |
| 795 | 862 | int be_id; /* optional ID for machine driver BE identification */ |
| 796 | 863 | |
| 797 | 864 | const struct snd_soc_pcm_stream *params; |
| @@ -0,0 +1,35 @@ | ||
| 1 | +/* | |
| 2 | +* linux/spear_dma.h | |
| 3 | +* | |
| 4 | +* Copyright (ST) 2012 Rajeev Kumar (rajeev-dlh.kumar@st.com) | |
| 5 | +* | |
| 6 | +* This program is free software; you can redistribute it and/or modify | |
| 7 | +* it under the terms of the GNU General Public License as published by | |
| 8 | +* the Free Software Foundation; either version 2 of the License, or | |
| 9 | +* (at your option) any later version. | |
| 10 | +* | |
| 11 | +* This program is distributed in the hope that it will be useful, | |
| 12 | +* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | +* GNU General Public License for more details. | |
| 15 | +* | |
| 16 | +* You should have received a copy of the GNU General Public License | |
| 17 | +* along with this program; if not, write to the Free Software | |
| 18 | +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 19 | +* | |
| 20 | +*/ | |
| 21 | + | |
| 22 | +#ifndef SPEAR_DMA_H | |
| 23 | +#define SPEAR_DMA_H | |
| 24 | + | |
| 25 | +#include <linux/dmaengine.h> | |
| 26 | + | |
| 27 | +struct spear_dma_data { | |
| 28 | + void *data; | |
| 29 | + dma_addr_t addr; | |
| 30 | + u32 max_burst; | |
| 31 | + enum dma_slave_buswidth addr_width; | |
| 32 | + bool (*filter)(struct dma_chan *chan, void *slave); | |
| 33 | +}; | |
| 34 | + | |
| 35 | +#endif /* SPEAR_DMA_H */ | |
| @@ -0,0 +1,29 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (ST) 2012 Vipin Kumar (vipin.kumar@st.com) | |
| 3 | + * | |
| 4 | + * This program is free software; you can redistribute it and/or modify | |
| 5 | + * it under the terms of the GNU General Public License as published by | |
| 6 | + * the Free Software Foundation; either version 2 of the License, or | |
| 7 | + * (at your option) any later version. | |
| 8 | + * | |
| 9 | + * This program is distributed in the hope that it will be useful, | |
| 10 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 | + * GNU General Public License for more details. | |
| 13 | + * | |
| 14 | + * You should have received a copy of the GNU General Public License | |
| 15 | + * along with this program; if not, write to the Free Software | |
| 16 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 17 | + */ | |
| 18 | + | |
| 19 | +#ifndef __SOUND_SPDIF_H | |
| 20 | +#define __SOUND_SPDIF_H | |
| 21 | + | |
| 22 | +struct spear_spdif_platform_data { | |
| 23 | + /* DMA params */ | |
| 24 | + void *dma_params; | |
| 25 | + bool (*filter)(struct dma_chan *chan, void *slave); | |
| 26 | + void (*reset_perip)(void); | |
| 27 | +}; | |
| 28 | + | |
| 29 | +#endif /* SOUND_SPDIF_H */ | |
| @@ -38,21 +38,31 @@ · 37 unmodified lines | ||
| 38 | 38 | #define SNDRV_CTL_TLVT_DB_MINMAX 4 /* dB scale with min/max */ |
| 39 | 39 | #define SNDRV_CTL_TLVT_DB_MINMAX_MUTE 5 /* dB scale with min/max with mute */ |
| 40 | 40 | |
| 41 | +#define TLV_ITEM(type, ...) \ | |
| 42 | + (type), TLV_LENGTH(__VA_ARGS__), __VA_ARGS__ | |
| 43 | +#define TLV_LENGTH(...) \ | |
| 44 | + ((unsigned int)sizeof((const unsigned int[]) { __VA_ARGS__ })) | |
| 45 | + | |
| 46 | +#define TLV_CONTAINER_ITEM(...) \ | |
| 47 | + TLV_ITEM(SNDRV_CTL_TLVT_CONTAINER, __VA_ARGS__) | |
| 48 | +#define DECLARE_TLV_CONTAINER(name, ...) \ | |
| 49 | + unsigned int name[] = { TLV_CONTAINER_ITEM(__VA_ARGS__) } | |
| 50 | + | |
| 41 | 51 | #define TLV_DB_SCALE_MASK 0xffff |
| 42 | 52 | #define TLV_DB_SCALE_MUTE 0x10000 |
| 43 | 53 | #define TLV_DB_SCALE_ITEM(min, step, mute) \ |
| 44 | − SNDRV_CTL_TLVT_DB_SCALE, 2 * sizeof(unsigned int), \ | |
| 45 | − (min), ((step) & TLV_DB_SCALE_MASK) | ((mute) ? TLV_DB_SCALE_MUTE : 0) | |
| 54 | + TLV_ITEM(SNDRV_CTL_TLVT_DB_SCALE, \ | |
| 55 | + (min), \ | |
| 56 | + ((step) & TLV_DB_SCALE_MASK) | \ | |
| 57 | + ((mute) ? TLV_DB_SCALE_MUTE : 0)) | |
| 46 | 58 | #define DECLARE_TLV_DB_SCALE(name, min, step, mute) \ |
| 47 | 59 | unsigned int name[] = { TLV_DB_SCALE_ITEM(min, step, mute) } |
| 48 | 60 | |
| 49 | 61 | /* dB scale specified with min/max values instead of step */ |
| 50 | 62 | #define TLV_DB_MINMAX_ITEM(min_dB, max_dB) \ |
| 51 | − SNDRV_CTL_TLVT_DB_MINMAX, 2 * sizeof(unsigned int), \ | |
| 52 | − (min_dB), (max_dB) | |
| 63 | + TLV_ITEM(SNDRV_CTL_TLVT_DB_MINMAX, (min_dB), (max_dB)) | |
| 53 | 64 | #define TLV_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) \ |
| 54 | − SNDRV_CTL_TLVT_DB_MINMAX_MUTE, 2 * sizeof(unsigned int), \ | |
| 55 | − (min_dB), (max_dB) | |
| 65 | + TLV_ITEM(SNDRV_CTL_TLVT_DB_MINMAX_MUTE, (min_dB), (max_dB)) | |
| 56 | 66 | #define DECLARE_TLV_DB_MINMAX(name, min_dB, max_dB) \ |
| 57 | 67 | unsigned int name[] = { TLV_DB_MINMAX_ITEM(min_dB, max_dB) } |
| 58 | 68 | #define DECLARE_TLV_DB_MINMAX_MUTE(name, min_dB, max_dB) \ |
| @@ -60,13 +70,16 @@ · 1 unmodified line | ||
| 60 | 70 | |
| 61 | 71 | /* linear volume between min_dB and max_dB (.01dB unit) */ |
| 62 | 72 | #define TLV_DB_LINEAR_ITEM(min_dB, max_dB) \ |
| 63 | − SNDRV_CTL_TLVT_DB_LINEAR, 2 * sizeof(unsigned int), \ | |
| 64 | − (min_dB), (max_dB) | |
| 73 | + TLV_ITEM(SNDRV_CTL_TLVT_DB_LINEAR, (min_dB), (max_dB)) | |
| 65 | 74 | #define DECLARE_TLV_DB_LINEAR(name, min_dB, max_dB) \ |
| 66 | 75 | unsigned int name[] = { TLV_DB_LINEAR_ITEM(min_dB, max_dB) } |
| 67 | 76 | |
| 68 | 77 | /* dB range container */ |
| 69 | 78 | /* Each item is: <min> <max> <TLV> */ |
| 79 | +#define TLV_DB_RANGE_ITEM(...) \ | |
| 80 | + TLV_ITEM(SNDRV_CTL_TLVT_DB_RANGE, __VA_ARGS__) | |
| 81 | +#define DECLARE_TLV_DB_RANGE(name, ...) \ | |
| 82 | + unsigned int name[] = { TLV_DB_RANGE_ITEM(__VA_ARGS__) } | |
| 70 | 83 | /* The below assumes that each item TLV is 4 words like DB_SCALE or LINEAR */ |
| 71 | 84 | #define TLV_DB_RANGE_HEAD(num) \ |
| 72 | 85 | SNDRV_CTL_TLVT_DB_RANGE, 6 * (num) * sizeof(unsigned int) |
| @@ -341,7 +341,7 @@ int vx_change_frequency(struct vx_core *chip); · 340 unmodified lines | ||
| 341 | 341 | /* |
| 342 | 342 | * PM |
| 343 | 343 | */ |
| 344 | −int snd_vx_suspend(struct vx_core *card, pm_message_t state); | |
| 344 | +int snd_vx_suspend(struct vx_core *card); | |
| 345 | 345 | int snd_vx_resume(struct vx_core *card); |
| 346 | 346 | |
| 347 | 347 | /* |
| @@ -108,7 +108,7 @@ static struct pxa2xx_pcm_client pxa2xx_ac97_pcm_client = { · 107 unmodified lines | ||
| 108 | 108 | |
| 109 | 109 | #ifdef CONFIG_PM |
| 110 | 110 | |
| 111 | −static int pxa2xx_ac97_do_suspend(struct snd_card *card, pm_message_t state) | |
| 111 | +static int pxa2xx_ac97_do_suspend(struct snd_card *card) | |
| 112 | 112 | { |
| 113 | 113 | pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data; |
| 114 | 114 | |
| @@ -144,7 +144,7 @@ static int pxa2xx_ac97_suspend(struct device *dev) · 29 unmodified lines | ||
| 144 | 144 | int ret = 0; |
| 145 | 145 | |
| 146 | 146 | if (card) |
| 147 | − ret = pxa2xx_ac97_do_suspend(card, PMSG_SUSPEND); | |
| 147 | + ret = pxa2xx_ac97_do_suspend(card); | |
| 148 | 148 | |
| 149 | 149 | return ret; |
| 150 | 150 | } |
| @@ -160,10 +160,7 @@ static int pxa2xx_ac97_resume(struct device *dev) · 9 unmodified lines | ||
| 160 | 160 | return ret; |
| 161 | 161 | } |
| 162 | 162 | |
| 163 | −static const struct dev_pm_ops pxa2xx_ac97_pm_ops = { | |
| 164 | − .suspend = pxa2xx_ac97_suspend, | |
| 165 | − .resume = pxa2xx_ac97_resume, | |
| 166 | −}; | |
| 163 | +static SIMPLE_DEV_PM_OPS(pxa2xx_ac97_pm_ops, pxa2xx_ac97_suspend, pxa2xx_ac97_resume); | |
| 167 | 164 | #endif |
| 168 | 165 | |
| 169 | 166 | static int __devinit pxa2xx_ac97_probe(struct platform_device *dev) |
| @@ -535,9 +535,9 @@ out_put_pclk: · 534 unmodified lines | ||
| 535 | 535 | } |
| 536 | 536 | |
| 537 | 537 | #ifdef CONFIG_PM |
| 538 | −static int atmel_abdac_suspend(struct platform_device *pdev, pm_message_t msg) | |
| 538 | +static int atmel_abdac_suspend(struct device *pdev) | |
| 539 | 539 | { |
| 540 | − struct snd_card *card = platform_get_drvdata(pdev); | |
| 540 | + struct snd_card *card = dev_get_drvdata(pdev); | |
| 541 | 541 | struct atmel_abdac *dac = card->private_data; |
| 542 | 542 | |
| 543 | 543 | dw_dma_cyclic_stop(dac->dma.chan); |
| @@ -547,9 +547,9 @@ static int atmel_abdac_suspend(struct platform_device *pdev, pm_message_t msg) · 3 unmodified lines | ||
| 547 | 547 | return 0; |
| 548 | 548 | } |
| 549 | 549 | |
| 550 | −static int atmel_abdac_resume(struct platform_device *pdev) | |
| 550 | +static int atmel_abdac_resume(struct device *pdev) | |
| 551 | 551 | { |
| 552 | − struct snd_card *card = platform_get_drvdata(pdev); | |
| 552 | + struct snd_card *card = dev_get_drvdata(pdev); | |
| 553 | 553 | struct atmel_abdac *dac = card->private_data; |
| 554 | 554 | |
| 555 | 555 | clk_enable(dac->pclk); |
| @@ -559,9 +559,11 @@ static int atmel_abdac_resume(struct platform_device *pdev) · 3 unmodified lines | ||
| 559 | 559 | |
| 560 | 560 | return 0; |
| 561 | 561 | } |
| 562 | + | |
| 563 | +static SIMPLE_DEV_PM_OPS(atmel_abdac_pm, atmel_abdac_suspend, atmel_abdac_resume); | |
| 564 | +#define ATMEL_ABDAC_PM_OPS &atmel_abdac_pm | |
| 562 | 565 | #else |
| 563 | −#define atmel_abdac_suspend NULL | |
| 564 | −#define atmel_abdac_resume NULL | |
| 566 | +#define ATMEL_ABDAC_PM_OPS NULL | |
| 565 | 567 | #endif |
| 566 | 568 | |
| 567 | 569 | static int __devexit atmel_abdac_remove(struct platform_device *pdev) |
| @@ -589,9 +591,9 @@ static struct platform_driver atmel_abdac_driver = { · 21 unmodified lines | ||
| 589 | 591 | .remove = __devexit_p(atmel_abdac_remove), |
| 590 | 592 | .driver = { |
| 591 | 593 | .name = "atmel_abdac", |
| 594 | + .owner = THIS_MODULE, | |
| 595 | + .pm = ATMEL_ABDAC_PM_OPS, | |
| 592 | 596 | }, |
| 593 | − .suspend = atmel_abdac_suspend, | |
| 594 | − .resume = atmel_abdac_resume, | |
| 595 | 597 | }; |
| 596 | 598 | |
| 597 | 599 | static int __init atmel_abdac_init(void) |
| @@ -1135,9 +1135,9 @@ err_snd_card_new: · 1134 unmodified lines | ||
| 1135 | 1135 | } |
| 1136 | 1136 | |
| 1137 | 1137 | #ifdef CONFIG_PM |
| 1138 | −static int atmel_ac97c_suspend(struct platform_device *pdev, pm_message_t msg) | |
| 1138 | +static int atmel_ac97c_suspend(struct device *pdev) | |
| 1139 | 1139 | { |
| 1140 | − struct snd_card *card = platform_get_drvdata(pdev); | |
| 1140 | + struct snd_card *card = dev_get_drvdata(pdev); | |
| 1141 | 1141 | struct atmel_ac97c *chip = card->private_data; |
| 1142 | 1142 | |
| 1143 | 1143 | if (cpu_is_at32ap7000()) { |
| @@ -1151,9 +1151,9 @@ static int atmel_ac97c_suspend(struct platform_device *pdev, pm_message_t msg) · 7 unmodified lines | ||
| 1151 | 1151 | return 0; |
| 1152 | 1152 | } |
| 1153 | 1153 | |
| 1154 | −static int atmel_ac97c_resume(struct platform_device *pdev) | |
| 1154 | +static int atmel_ac97c_resume(struct device *pdev) | |
| 1155 | 1155 | { |
| 1156 | − struct snd_card *card = platform_get_drvdata(pdev); | |
| 1156 | + struct snd_card *card = dev_get_drvdata(pdev); | |
| 1157 | 1157 | struct atmel_ac97c *chip = card->private_data; |
| 1158 | 1158 | |
| 1159 | 1159 | clk_enable(chip->pclk); |
| @@ -1165,9 +1165,11 @@ static int atmel_ac97c_resume(struct platform_device *pdev) · 5 unmodified lines | ||
| 1165 | 1165 | } |
| 1166 | 1166 | return 0; |
| 1167 | 1167 | } |
| 1168 | + | |
| 1169 | +static SIMPLE_DEV_PM_OPS(atmel_ac97c_pm, atmel_ac97c_suspend, atmel_ac97c_resume); | |
| 1170 | +#define ATMEL_AC97C_PM_OPS &atmel_ac97c_pm | |
| 1168 | 1171 | #else |
| 1169 | −#define atmel_ac97c_suspend NULL | |
| 1170 | −#define atmel_ac97c_resume NULL | |
| 1172 | +#define ATMEL_AC97C_PM_OPS NULL | |
| 1171 | 1173 | #endif |
| 1172 | 1174 | |
| 1173 | 1175 | static int __devexit atmel_ac97c_remove(struct platform_device *pdev) |
| @@ -1210,9 +1212,9 @@ static struct platform_driver atmel_ac97c_driver = { · 36 unmodified lines | ||
| 1210 | 1212 | .remove = __devexit_p(atmel_ac97c_remove), |
| 1211 | 1213 | .driver = { |
| 1212 | 1214 | .name = "atmel_ac97c", |
| 1215 | + .owner = THIS_MODULE, | |
| 1216 | + .pm = ATMEL_AC97C_PM_OPS, | |
| 1213 | 1217 | }, |
| 1214 | − .suspend = atmel_ac97c_suspend, | |
| 1215 | − .resume = atmel_ac97c_resume, | |
| 1216 | 1218 | }; |
| 1217 | 1219 | |
| 1218 | 1220 | static int __init atmel_ac97c_init(void) |
| @@ -1250,10 +1250,10 @@ static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params, · 1249 unmodified lines | ||
| 1250 | 1250 | int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime, |
| 1251 | 1251 | unsigned int cond, |
| 1252 | 1252 | snd_pcm_hw_param_t var, |
| 1253 | − struct snd_pcm_hw_constraint_list *l) | |
| 1253 | + const struct snd_pcm_hw_constraint_list *l) | |
| 1254 | 1254 | { |
| 1255 | 1255 | return snd_pcm_hw_rule_add(runtime, cond, var, |
| 1256 | − snd_pcm_hw_rule_list, l, | |
| 1256 | + snd_pcm_hw_rule_list, (void *)l, | |
| 1257 | 1257 | var, -1); |
| 1258 | 1258 | } |
| 1259 | 1259 | |
| @@ -488,3 +488,21 @@ unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate) · 487 unmodified lines | ||
| 488 | 488 | return SNDRV_PCM_RATE_KNOT; |
| 489 | 489 | } |
| 490 | 490 | EXPORT_SYMBOL(snd_pcm_rate_to_rate_bit); |
| 491 | + | |
| 492 | +/** | |
| 493 | + * snd_pcm_rate_bit_to_rate - converts SNDRV_PCM_RATE_xxx bit to sample rate | |
| 494 | + * @rate_bit: the rate bit to convert | |
| 495 | + * | |
| 496 | + * Returns the sample rate that corresponds to the given SNDRV_PCM_RATE_xxx flag | |
| 497 | + * or 0 for an unknown rate bit | |
| 498 | + */ | |
| 499 | +unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit) | |
| 500 | +{ | |
| 501 | + unsigned int i; | |
| 502 | + | |
| 503 | + for (i = 0; i < snd_pcm_known_rates.count; i++) | |
| 504 | + if ((1u << i) == rate_bit) | |
| 505 | + return snd_pcm_known_rates.list[i]; | |
| 506 | + return 0; | |
| 507 | +} | |
| 508 | +EXPORT_SYMBOL(snd_pcm_rate_bit_to_rate); | |
| @@ -1177,10 +1177,9 @@ static int __devexit loopback_remove(struct platform_device *devptr) · 1176 unmodified lines | ||
| 1177 | 1177 | } |
| 1178 | 1178 | |
| 1179 | 1179 | #ifdef CONFIG_PM |
| 1180 | −static int loopback_suspend(struct platform_device *pdev, | |
| 1181 | − pm_message_t state) | |
| 1180 | +static int loopback_suspend(struct device *pdev) | |
| 1182 | 1181 | { |
| 1183 | − struct snd_card *card = platform_get_drvdata(pdev); | |
| 1182 | + struct snd_card *card = dev_get_drvdata(pdev); | |
| 1184 | 1183 | struct loopback *loopback = card->private_data; |
| 1185 | 1184 | |
| 1186 | 1185 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
| @@ -1190,13 +1189,18 @@ static int loopback_suspend(struct platform_device *pdev, · 3 unmodified lines | ||
| 1190 | 1189 | return 0; |
| 1191 | 1190 | } |
| 1192 | 1191 | |
| 1193 | −static int loopback_resume(struct platform_device *pdev) | |
| 1192 | +static int loopback_resume(struct device *pdev) | |
| 1194 | 1193 | { |
| 1195 | − struct snd_card *card = platform_get_drvdata(pdev); | |
| 1194 | + struct snd_card *card = dev_get_drvdata(pdev); | |
| 1196 | 1195 | |
| 1197 | 1196 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 1198 | 1197 | return 0; |
| 1199 | 1198 | } |
| 1199 | + | |
| 1200 | +static SIMPLE_DEV_PM_OPS(loopback_pm, loopback_suspend, loopback_resume); | |
| 1201 | +#define LOOPBACK_PM_OPS &loopback_pm | |
| 1202 | +#else | |
| 1203 | +#define LOOPBACK_PM_OPS NULL | |
| 1200 | 1204 | #endif |
| 1201 | 1205 | |
| 1202 | 1206 | #define SND_LOOPBACK_DRIVER "snd_aloop" |
| @@ -1204,12 +1208,10 @@ static int loopback_resume(struct platform_device *pdev) · 1 unmodified line | ||
| 1204 | 1208 | static struct platform_driver loopback_driver = { |
| 1205 | 1209 | .probe = loopback_probe, |
| 1206 | 1210 | .remove = __devexit_p(loopback_remove), |
| 1207 | −#ifdef CONFIG_PM | |
| 1208 | − .suspend = loopback_suspend, | |
| 1209 | − .resume = loopback_resume, | |
| 1210 | −#endif | |
| 1211 | 1211 | .driver = { |
| 1212 | − .name = SND_LOOPBACK_DRIVER | |
| 1212 | + .name = SND_LOOPBACK_DRIVER, | |
| 1213 | + .owner = THIS_MODULE, | |
| 1214 | + .pm = LOOPBACK_PM_OPS, | |
| 1213 | 1215 | }, |
| 1214 | 1216 | }; |
| 1215 | 1217 | |
| @@ -1065,9 +1065,9 @@ static int __devexit snd_dummy_remove(struct platform_device *devptr) · 1064 unmodified lines | ||
| 1065 | 1065 | } |
| 1066 | 1066 | |
| 1067 | 1067 | #ifdef CONFIG_PM |
| 1068 | −static int snd_dummy_suspend(struct platform_device *pdev, pm_message_t state) | |
| 1068 | +static int snd_dummy_suspend(struct device *pdev) | |
| 1069 | 1069 | { |
| 1070 | − struct snd_card *card = platform_get_drvdata(pdev); | |
| 1070 | + struct snd_card *card = dev_get_drvdata(pdev); | |
| 1071 | 1071 | struct snd_dummy *dummy = card->private_data; |
| 1072 | 1072 | |
| 1073 | 1073 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
| @@ -1075,13 +1075,18 @@ static int snd_dummy_suspend(struct platform_device *pdev, pm_message_t state) · 1 unmodified line | ||
| 1075 | 1075 | return 0; |
| 1076 | 1076 | } |
| 1077 | 1077 | |
| 1078 | −static int snd_dummy_resume(struct platform_device *pdev) | |
| 1078 | +static int snd_dummy_resume(struct device *pdev) | |
| 1079 | 1079 | { |
| 1080 | − struct snd_card *card = platform_get_drvdata(pdev); | |
| 1080 | + struct snd_card *card = dev_get_drvdata(pdev); | |
| 1081 | 1081 | |
| 1082 | 1082 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 1083 | 1083 | return 0; |
| 1084 | 1084 | } |
| 1085 | + | |
| 1086 | +static SIMPLE_DEV_PM_OPS(snd_dummy_pm, snd_dummy_suspend, snd_dummy_resume); | |
| 1087 | +#define SND_DUMMY_PM_OPS &snd_dummy_pm | |
| 1088 | +#else | |
| 1089 | +#define SND_DUMMY_PM_OPS NULL | |
| 1085 | 1090 | #endif |
| 1086 | 1091 | |
| 1087 | 1092 | #define SND_DUMMY_DRIVER "snd_dummy" |
| @@ -1089,12 +1094,10 @@ static int snd_dummy_resume(struct platform_device *pdev) · 1 unmodified line | ||
| 1089 | 1094 | static struct platform_driver snd_dummy_driver = { |
| 1090 | 1095 | .probe = snd_dummy_probe, |
| 1091 | 1096 | .remove = __devexit_p(snd_dummy_remove), |
| 1092 | −#ifdef CONFIG_PM | |
| 1093 | − .suspend = snd_dummy_suspend, | |
| 1094 | − .resume = snd_dummy_resume, | |
| 1095 | −#endif | |
| 1096 | 1097 | .driver = { |
| 1097 | − .name = SND_DUMMY_DRIVER | |
| 1098 | + .name = SND_DUMMY_DRIVER, | |
| 1099 | + .owner = THIS_MODULE, | |
| 1100 | + .pm = SND_DUMMY_PM_OPS, | |
| 1098 | 1101 | }, |
| 1099 | 1102 | }; |
| 1100 | 1103 | |
| @@ -139,7 +139,8 @@ static struct platform_driver snd_mpu401_driver = { · 138 unmodified lines | ||
| 139 | 139 | .probe = snd_mpu401_probe, |
| 140 | 140 | .remove = __devexit_p(snd_mpu401_remove), |
| 141 | 141 | .driver = { |
| 142 | − .name = SND_MPU401_DRIVER | |
| 142 | + .name = SND_MPU401_DRIVER, | |
| 143 | + .owner = THIS_MODULE, | |
| 143 | 144 | }, |
| 144 | 145 | }; |
| 145 | 146 | |
| @@ -759,7 +759,8 @@ static struct platform_driver snd_mtpav_driver = { · 758 unmodified lines | ||
| 759 | 759 | .probe = snd_mtpav_probe, |
| 760 | 760 | .remove = __devexit_p(snd_mtpav_remove), |
| 761 | 761 | .driver = { |
| 762 | − .name = SND_MTPAV_DRIVER | |
| 762 | + .name = SND_MTPAV_DRIVER, | |
| 763 | + .owner = THIS_MODULE, | |
| 763 | 764 | }, |
| 764 | 765 | }; |
| 765 | 766 | |
| @@ -1040,7 +1040,8 @@ static struct platform_driver snd_mts64_driver = { · 1039 unmodified lines | ||
| 1040 | 1040 | .probe = snd_mts64_probe, |
| 1041 | 1041 | .remove = __devexit_p(snd_mts64_remove), |
| 1042 | 1042 | .driver = { |
| 1043 | − .name = PLATFORM_DRIVER | |
| 1043 | + .name = PLATFORM_DRIVER, | |
| 1044 | + .owner = THIS_MODULE, | |
| 1044 | 1045 | } |
| 1045 | 1046 | }; |
| 1046 | 1047 | |
| @@ -200,15 +200,18 @@ static void pcsp_stop_beep(struct snd_pcsp *chip) · 199 unmodified lines | ||
| 200 | 200 | } |
| 201 | 201 | |
| 202 | 202 | #ifdef CONFIG_PM |
| 203 | −static int pcsp_suspend(struct platform_device *dev, pm_message_t state) | |
| 203 | +static int pcsp_suspend(struct device *dev) | |
| 204 | 204 | { |
| 205 | − struct snd_pcsp *chip = platform_get_drvdata(dev); | |
| 205 | + struct snd_pcsp *chip = dev_get_drvdata(dev); | |
| 206 | 206 | pcsp_stop_beep(chip); |
| 207 | 207 | snd_pcm_suspend_all(chip->pcm); |
| 208 | 208 | return 0; |
| 209 | 209 | } |
| 210 | + | |
| 211 | +static SIMPLE_DEV_PM_OPS(pcsp_pm, pcsp_suspend, NULL); | |
| 212 | +#define PCSP_PM_OPS &pcsp_pm | |
| 210 | 213 | #else |
| 211 | −#define pcsp_suspend NULL | |
| 214 | +#define PCSP_PM_OPS NULL | |
| 212 | 215 | #endif /* CONFIG_PM */ |
| 213 | 216 | |
| 214 | 217 | static void pcsp_shutdown(struct platform_device *dev) |
| @@ -221,10 +224,10 @@ static struct platform_driver pcsp_platform_driver = { · 6 unmodified lines | ||
| 221 | 224 | .driver = { |
| 222 | 225 | .name = "pcspkr", |
| 223 | 226 | .owner = THIS_MODULE, |
| 227 | + .pm = PCSP_PM_OPS, | |
| 224 | 228 | }, |
| 225 | 229 | .probe = pcsp_probe, |
| 226 | 230 | .remove = __devexit_p(pcsp_remove), |
| 227 | − .suspend = pcsp_suspend, | |
| 228 | 231 | .shutdown = pcsp_shutdown, |
| 229 | 232 | }; |
| 230 | 233 | |
| @@ -829,7 +829,8 @@ static struct platform_driver snd_portman_driver = { · 828 unmodified lines | ||
| 829 | 829 | .probe = snd_portman_probe, |
| 830 | 830 | .remove = __devexit_p(snd_portman_remove), |
| 831 | 831 | .driver = { |
| 832 | − .name = PLATFORM_DRIVER | |
| 832 | + .name = PLATFORM_DRIVER, | |
| 833 | + .owner = THIS_MODULE, | |
| 833 | 834 | } |
| 834 | 835 | }; |
| 835 | 836 | |
| @@ -995,7 +995,8 @@ static struct platform_driver snd_serial_driver = { · 994 unmodified lines | ||
| 995 | 995 | .probe = snd_serial_probe, |
| 996 | 996 | .remove = __devexit_p( snd_serial_remove), |
| 997 | 997 | .driver = { |
| 998 | − .name = SND_SERIAL_DRIVER | |
| 998 | + .name = SND_SERIAL_DRIVER, | |
| 999 | + .owner = THIS_MODULE, | |
| 999 | 1000 | }, |
| 1000 | 1001 | }; |
| 1001 | 1002 | |
| @@ -142,7 +142,8 @@ static struct platform_driver snd_virmidi_driver = { · 141 unmodified lines | ||
| 142 | 142 | .probe = snd_virmidi_probe, |
| 143 | 143 | .remove = __devexit_p(snd_virmidi_remove), |
| 144 | 144 | .driver = { |
| 145 | − .name = SND_VIRMIDI_DRIVER | |
| 145 | + .name = SND_VIRMIDI_DRIVER, | |
| 146 | + .owner = THIS_MODULE, | |
| 146 | 147 | }, |
| 147 | 148 | }; |
| 148 | 149 | |
| @@ -725,7 +725,7 @@ EXPORT_SYMBOL(snd_vx_dsp_load); · 724 unmodified lines | ||
| 725 | 725 | /* |
| 726 | 726 | * suspend |
| 727 | 727 | */ |
| 728 | −int snd_vx_suspend(struct vx_core *chip, pm_message_t state) | |
| 728 | +int snd_vx_suspend(struct vx_core *chip) | |
| 729 | 729 | { |
| 730 | 730 | unsigned int i; |
| 731 | 731 | |
| @@ -135,10 +135,9 @@ struct snd_opti9xx { · 134 unmodified lines | ||
| 135 | 135 | unsigned long mc_base_size; |
| 136 | 136 | #ifdef OPTi93X |
| 137 | 137 | unsigned long mc_indir_index; |
| 138 | − unsigned long mc_indir_size; | |
| 139 | 138 | struct resource *res_mc_indir; |
| 140 | − struct snd_wss *codec; | |
| 141 | 139 | #endif /* OPTi93X */ |
| 140 | + struct snd_wss *codec; | |
| 142 | 141 | unsigned long pwd_reg; |
| 143 | 142 | |
| 144 | 143 | spinlock_t lock; |
| @@ -245,10 +244,8 @@ static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip, · 100 unmodified lines | ||
| 245 | 244 | case OPTi9XX_HW_82C931: |
| 246 | 245 | case OPTi9XX_HW_82C933: |
| 247 | 246 | chip->mc_base = (hardware == OPTi9XX_HW_82C930) ? 0xf8f : 0xf8d; |
| 248 | − if (!chip->mc_indir_index) { | |
| 247 | + if (!chip->mc_indir_index) | |
| 249 | 248 | chip->mc_indir_index = 0xe0e; |
| 250 | − chip->mc_indir_size = 2; | |
| 251 | − } | |
| 252 | 249 | chip->password = 0xe4; |
| 253 | 250 | chip->pwd_reg = 0; |
| 254 | 251 | break; |
| @@ -351,7 +348,7 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, · 96 unmodified lines | ||
| 351 | 348 | (snd_opti9xx_read(chip, reg) & ~(mask)) | ((value) & (mask))) |
| 352 | 349 | |
| 353 | 350 | |
| 354 | −static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, | |
| 351 | +static int snd_opti9xx_configure(struct snd_opti9xx *chip, | |
| 355 | 352 | long port, |
| 356 | 353 | int irq, int dma1, int dma2, |
| 357 | 354 | long mpu_port, int mpu_irq) |
| @@ -403,7 +400,9 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, · 45 unmodified lines | ||
| 403 | 400 | |
| 404 | 401 | #else /* OPTi93X */ |
| 405 | 402 | case OPTi9XX_HW_82C931: |
| 406 | − case OPTi9XX_HW_82C933: | |
| 403 | + /* disable 3D sound (set GPIO1 as output, low) */ | |
| 404 | + snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(20), 0x04, 0x0c); | |
| 405 | + case OPTi9XX_HW_82C933: /* FALL THROUGH */ | |
| 407 | 406 | /* |
| 408 | 407 | * The BTC 1817DW has QS1000 wavetable which is connected |
| 409 | 408 | * to the serial digital input of the OPTI931. |
| @@ -696,8 +695,7 @@ static int __devinit snd_opti9xx_read_check(struct snd_opti9xx *chip) · 286 unmodified lines | ||
| 696 | 695 | if (value == snd_opti9xx_read(chip, OPTi9XX_MC_REG(1))) |
| 697 | 696 | return 0; |
| 698 | 697 | #else /* OPTi93X */ |
| 699 | − chip->res_mc_indir = request_region(chip->mc_indir_index, | |
| 700 | − chip->mc_indir_size, | |
| 698 | + chip->res_mc_indir = request_region(chip->mc_indir_index, 2, | |
| 701 | 699 | "OPTi93x MC"); |
| 702 | 700 | if (chip->res_mc_indir == NULL) |
| 703 | 701 | return -EBUSY; |
| @@ -770,8 +768,9 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, · 66 unmodified lines | ||
| 770 | 768 | #ifdef OPTi93X |
| 771 | 769 | port = pnp_port_start(pdev, 0) - 4; |
| 772 | 770 | fm_port = pnp_port_start(pdev, 1) + 8; |
| 773 | − chip->mc_indir_index = pnp_port_start(pdev, 3) + 2; | |
| 774 | − chip->mc_indir_size = pnp_port_len(pdev, 3) - 2; | |
| 771 | + /* adjust mc_indir_index - some cards report it at 0xe?d, | |
| 772 | + other at 0xe?c but it really is always at 0xe?e */ | |
| 773 | + chip->mc_indir_index = (pnp_port_start(pdev, 3) & ~0xf) | 0xe; | |
| 775 | 774 | #else |
| 776 | 775 | devmc = pnp_request_card_device(card, pid->devs[2].id, NULL); |
| 777 | 776 | if (devmc == NULL) |
| @@ -871,9 +870,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) · 93 unmodified lines | ||
| 871 | 870 | &codec); |
| 872 | 871 | if (error < 0) |
| 873 | 872 | return error; |
| 874 | −#ifdef OPTi93X | |
| 875 | 873 | chip->codec = codec; |
| 876 | −#endif | |
| 877 | 874 | error = snd_wss_pcm(codec, 0, &pcm); |
| 878 | 875 | if (error < 0) |
| 879 | 876 | return error; |
| @@ -1054,11 +1051,55 @@ static int __devexit snd_opti9xx_isa_remove(struct device *devptr, · 174 unmodified lines | ||
| 1054 | 1051 | return 0; |
| 1055 | 1052 | } |
| 1056 | 1053 | |
| 1054 | +#ifdef CONFIG_PM | |
| 1055 | +static int snd_opti9xx_suspend(struct snd_card *card) | |
| 1056 | +{ | |
| 1057 | + struct snd_opti9xx *chip = card->private_data; | |
| 1058 | + | |
| 1059 | + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | |
| 1060 | + chip->codec->suspend(chip->codec); | |
| 1061 | + return 0; | |
| 1062 | +} | |
| 1063 | + | |
| 1064 | +static int snd_opti9xx_resume(struct snd_card *card) | |
| 1065 | +{ | |
| 1066 | + struct snd_opti9xx *chip = card->private_data; | |
| 1067 | + int error, xdma2; | |
| 1068 | +#if defined(CS4231) || defined(OPTi93X) | |
| 1069 | + xdma2 = dma2; | |
| 1070 | +#else | |
| 1071 | + xdma2 = -1; | |
| 1072 | +#endif | |
| 1073 | + | |
| 1074 | + error = snd_opti9xx_configure(chip, port, irq, dma1, xdma2, | |
| 1075 | + mpu_port, mpu_irq); | |
| 1076 | + if (error) | |
| 1077 | + return error; | |
| 1078 | + chip->codec->resume(chip->codec); | |
| 1079 | + snd_power_change_state(card, SNDRV_CTL_POWER_D0); | |
| 1080 | + return 0; | |
| 1081 | +} | |
| 1082 | + | |
| 1083 | +static int snd_opti9xx_isa_suspend(struct device *dev, unsigned int n, | |
| 1084 | + pm_message_t state) | |
| 1085 | +{ | |
| 1086 | + return snd_opti9xx_suspend(dev_get_drvdata(dev)); | |
| 1087 | +} | |
| 1088 | + | |
| 1089 | +static int snd_opti9xx_isa_resume(struct device *dev, unsigned int n) | |
| 1090 | +{ | |
| 1091 | + return snd_opti9xx_resume(dev_get_drvdata(dev)); | |
| 1092 | +} | |
| 1093 | +#endif | |
| 1094 | + | |
| 1057 | 1095 | static struct isa_driver snd_opti9xx_driver = { |
| 1058 | 1096 | .match = snd_opti9xx_isa_match, |
| 1059 | 1097 | .probe = snd_opti9xx_isa_probe, |
| 1060 | 1098 | .remove = __devexit_p(snd_opti9xx_isa_remove), |
| 1061 | − /* FIXME: suspend/resume */ | |
| 1099 | +#ifdef CONFIG_PM | |
| 1100 | + .suspend = snd_opti9xx_isa_suspend, | |
| 1101 | + .resume = snd_opti9xx_isa_resume, | |
| 1102 | +#endif | |
| 1062 | 1103 | .driver = { |
| 1063 | 1104 | .name = DEV_NAME |
| 1064 | 1105 | }, |
| @@ -1124,12 +1165,29 @@ static void __devexit snd_opti9xx_pnp_remove(struct pnp_card_link * pcard) · 59 unmodified lines | ||
| 1124 | 1165 | snd_opti9xx_pnp_is_probed = 0; |
| 1125 | 1166 | } |
| 1126 | 1167 | |
| 1168 | +#ifdef CONFIG_PM | |
| 1169 | +static int snd_opti9xx_pnp_suspend(struct pnp_card_link *pcard, | |
| 1170 | + pm_message_t state) | |
| 1171 | +{ | |
| 1172 | + return snd_opti9xx_suspend(pnp_get_card_drvdata(pcard)); | |
| 1173 | +} | |
| 1174 | + | |
| 1175 | +static int snd_opti9xx_pnp_resume(struct pnp_card_link *pcard) | |
| 1176 | +{ | |
| 1177 | + return snd_opti9xx_resume(pnp_get_card_drvdata(pcard)); | |
| 1178 | +} | |
| 1179 | +#endif | |
| 1180 | + | |
| 1127 | 1181 | static struct pnp_card_driver opti9xx_pnpc_driver = { |
| 1128 | 1182 | .flags = PNP_DRIVER_RES_DISABLE, |
| 1129 | 1183 | .name = "opti9xx", |
| 1130 | 1184 | .id_table = snd_opti9xx_pnpids, |
| 1131 | 1185 | .probe = snd_opti9xx_pnp_probe, |
| 1132 | 1186 | .remove = __devexit_p(snd_opti9xx_pnp_remove), |
| 1187 | +#ifdef CONFIG_PM | |
| 1188 | + .suspend = snd_opti9xx_pnp_suspend, | |
| 1189 | + .resume = snd_opti9xx_pnp_resume, | |
| 1190 | +#endif | |
| 1133 | 1191 | }; |
| 1134 | 1192 | #endif |
| 1135 | 1193 | |
| @@ -1456,7 +1456,6 @@ static struct snd_pcm_hardware snd_wss_playback = · 1455 unmodified lines | ||
| 1456 | 1456 | { |
| 1457 | 1457 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | |
| 1458 | 1458 | SNDRV_PCM_INFO_MMAP_VALID | |
| 1459 | − SNDRV_PCM_INFO_RESUME | | |
| 1460 | 1459 | SNDRV_PCM_INFO_SYNC_START), |
| 1461 | 1460 | .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM | |
| 1462 | 1461 | SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE), |
| @@ -1657,6 +1656,10 @@ static void snd_wss_resume(struct snd_wss *chip) · 194 unmodified lines | ||
| 1657 | 1656 | break; |
| 1658 | 1657 | } |
| 1659 | 1658 | } |
| 1659 | + /* Yamaha needs this to resume properly */ | |
| 1660 | + if (chip->hardware == WSS_HW_OPL3SA2) | |
| 1661 | + snd_wss_out(chip, CS4231_PLAYBK_FORMAT, | |
| 1662 | + chip->image[CS4231_PLAYBK_FORMAT]); | |
| 1660 | 1663 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
| 1661 | 1664 | #if 1 |
| 1662 | 1665 | snd_wss_mce_down(chip); |
| @@ -69,7 +69,6 @@ · 68 unmodified lines | ||
| 69 | 69 | #include <linux/sound.h> |
| 70 | 70 | #include <linux/slab.h> |
| 71 | 71 | #include <linux/soundcard.h> |
| 72 | −#include <linux/ac97_codec.h> | |
| 73 | 72 | #include <linux/pci.h> |
| 74 | 73 | #include <linux/bitops.h> |
| 75 | 74 | #include <linux/interrupt.h> |
| @@ -199,6 +198,22 @@ static const char invalid_magic[] = · 123 unmodified lines | ||
| 199 | 198 | } \ |
| 200 | 199 | }) |
| 201 | 200 | |
| 201 | +/* AC97 registers */ | |
| 202 | +#define AC97_MASTER_VOL_STEREO 0x0002 /* Line Out */ | |
| 203 | +#define AC97_PCBEEP_VOL 0x000a /* none */ | |
| 204 | +#define AC97_PHONE_VOL 0x000c /* TAD Input (mono) */ | |
| 205 | +#define AC97_MIC_VOL 0x000e /* MIC Input (mono) */ | |
| 206 | +#define AC97_LINEIN_VOL 0x0010 /* Line Input (stereo) */ | |
| 207 | +#define AC97_CD_VOL 0x0012 /* CD Input (stereo) */ | |
| 208 | +#define AC97_AUX_VOL 0x0016 /* Aux Input (stereo) */ | |
| 209 | +#define AC97_PCMOUT_VOL 0x0018 /* Wave Output (stereo) */ | |
| 210 | +#define AC97_RECORD_SELECT 0x001a /* */ | |
| 211 | +#define AC97_RECORD_GAIN 0x001c | |
| 212 | +#define AC97_GENERAL_PURPOSE 0x0020 | |
| 213 | +#define AC97_3D_CONTROL 0x0022 | |
| 214 | +#define AC97_POWER_CONTROL 0x0026 | |
| 215 | +#define AC97_VENDOR_ID1 0x007c | |
| 216 | + | |
| 202 | 217 | struct list_head cs4297a_devs = { &cs4297a_devs, &cs4297a_devs }; |
| 203 | 218 | |
| 204 | 219 | typedef struct serdma_descr_s { |
| @@ -1884,9 +1884,10 @@ static int __devinit snd_ali_mixer(struct snd_ali * codec) · 1883 unmodified lines | ||
| 1884 | 1884 | } |
| 1885 | 1885 | |
| 1886 | 1886 | #ifdef CONFIG_PM |
| 1887 | −static int ali_suspend(struct pci_dev *pci, pm_message_t state) | |
| 1887 | +static int ali_suspend(struct device *dev) | |
| 1888 | 1888 | { |
| 1889 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 1889 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 1890 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 1890 | 1891 | struct snd_ali *chip = card->private_data; |
| 1891 | 1892 | struct snd_ali_image *im; |
| 1892 | 1893 | int i, j; |
| @@ -1929,13 +1930,14 @@ static int ali_suspend(struct pci_dev *pci, pm_message_t state) · 36 unmodified lines | ||
| 1929 | 1930 | |
| 1930 | 1931 | pci_disable_device(pci); |
| 1931 | 1932 | pci_save_state(pci); |
| 1932 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 1933 | + pci_set_power_state(pci, PCI_D3hot); | |
| 1933 | 1934 | return 0; |
| 1934 | 1935 | } |
| 1935 | 1936 | |
| 1936 | −static int ali_resume(struct pci_dev *pci) | |
| 1937 | +static int ali_resume(struct device *dev) | |
| 1937 | 1938 | { |
| 1938 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 1939 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 1940 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 1939 | 1941 | struct snd_ali *chip = card->private_data; |
| 1940 | 1942 | struct snd_ali_image *im; |
| 1941 | 1943 | int i, j; |
| @@ -1982,6 +1984,11 @@ static int ali_resume(struct pci_dev *pci) · 40 unmodified lines | ||
| 1982 | 1984 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 1983 | 1985 | return 0; |
| 1984 | 1986 | } |
| 1987 | + | |
| 1988 | +static SIMPLE_DEV_PM_OPS(ali_pm, ali_suspend, ali_resume); | |
| 1989 | +#define ALI_PM_OPS &ali_pm | |
| 1990 | +#else | |
| 1991 | +#define ALI_PM_OPS NULL | |
| 1985 | 1992 | #endif /* CONFIG_PM */ |
| 1986 | 1993 | |
| 1987 | 1994 | static int snd_ali_free(struct snd_ali * codec) |
| @@ -2299,10 +2306,9 @@ static struct pci_driver ali5451_driver = { · 311 unmodified lines | ||
| 2299 | 2306 | .id_table = snd_ali_ids, |
| 2300 | 2307 | .probe = snd_ali_probe, |
| 2301 | 2308 | .remove = __devexit_p(snd_ali_remove), |
| 2302 | −#ifdef CONFIG_PM | |
| 2303 | − .suspend = ali_suspend, | |
| 2304 | − .resume = ali_resume, | |
| 2305 | −#endif | |
| 2309 | + .driver = { | |
| 2310 | + .pm = ALI_PM_OPS, | |
| 2311 | + }, | |
| 2306 | 2312 | }; |
| 2307 | 2313 | |
| 2308 | 2314 | module_pci_driver(ali5451_driver); |
| @@ -766,9 +766,10 @@ static int __devinit snd_als300_create(struct snd_card *card, · 765 unmodified lines | ||
| 766 | 766 | } |
| 767 | 767 | |
| 768 | 768 | #ifdef CONFIG_PM |
| 769 | −static int snd_als300_suspend(struct pci_dev *pci, pm_message_t state) | |
| 769 | +static int snd_als300_suspend(struct device *dev) | |
| 770 | 770 | { |
| 771 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 771 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 772 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 772 | 773 | struct snd_als300 *chip = card->private_data; |
| 773 | 774 | |
| 774 | 775 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
| @@ -777,13 +778,14 @@ static int snd_als300_suspend(struct pci_dev *pci, pm_message_t state) · 2 unmodified lines | ||
| 777 | 778 | |
| 778 | 779 | pci_disable_device(pci); |
| 779 | 780 | pci_save_state(pci); |
| 780 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 781 | + pci_set_power_state(pci, PCI_D3hot); | |
| 781 | 782 | return 0; |
| 782 | 783 | } |
| 783 | 784 | |
| 784 | −static int snd_als300_resume(struct pci_dev *pci) | |
| 785 | +static int snd_als300_resume(struct device *dev) | |
| 785 | 786 | { |
| 786 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 787 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 788 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 787 | 789 | struct snd_als300 *chip = card->private_data; |
| 788 | 790 | |
| 789 | 791 | pci_set_power_state(pci, PCI_D0); |
| @@ -802,6 +804,11 @@ static int snd_als300_resume(struct pci_dev *pci) · 12 unmodified lines | ||
| 802 | 804 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 803 | 805 | return 0; |
| 804 | 806 | } |
| 807 | + | |
| 808 | +static SIMPLE_DEV_PM_OPS(snd_als300_pm, snd_als300_suspend, snd_als300_resume); | |
| 809 | +#define SND_ALS300_PM_OPS &snd_als300_pm | |
| 810 | +#else | |
| 811 | +#define SND_ALS300_PM_OPS NULL | |
| 805 | 812 | #endif |
| 806 | 813 | |
| 807 | 814 | static int __devinit snd_als300_probe(struct pci_dev *pci, |
| @@ -857,10 +864,9 @@ static struct pci_driver als300_driver = { · 49 unmodified lines | ||
| 857 | 864 | .id_table = snd_als300_ids, |
| 858 | 865 | .probe = snd_als300_probe, |
| 859 | 866 | .remove = __devexit_p(snd_als300_remove), |
| 860 | −#ifdef CONFIG_PM | |
| 861 | − .suspend = snd_als300_suspend, | |
| 862 | − .resume = snd_als300_resume, | |
| 863 | −#endif | |
| 867 | + .driver = { | |
| 868 | + .pm = SND_ALS300_PM_OPS, | |
| 869 | + }, | |
| 864 | 870 | }; |
| 865 | 871 | |
| 866 | 872 | module_pci_driver(als300_driver); |
| @@ -988,9 +988,10 @@ static void __devexit snd_card_als4000_remove(struct pci_dev *pci) · 987 unmodified lines | ||
| 988 | 988 | } |
| 989 | 989 | |
| 990 | 990 | #ifdef CONFIG_PM |
| 991 | −static int snd_als4000_suspend(struct pci_dev *pci, pm_message_t state) | |
| 991 | +static int snd_als4000_suspend(struct device *dev) | |
| 992 | 992 | { |
| 993 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 993 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 994 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 994 | 995 | struct snd_card_als4000 *acard = card->private_data; |
| 995 | 996 | struct snd_sb *chip = acard->chip; |
| 996 | 997 | |
| @@ -1001,13 +1002,14 @@ static int snd_als4000_suspend(struct pci_dev *pci, pm_message_t state) · 4 unmodified lines | ||
| 1001 | 1002 | |
| 1002 | 1003 | pci_disable_device(pci); |
| 1003 | 1004 | pci_save_state(pci); |
| 1004 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 1005 | + pci_set_power_state(pci, PCI_D3hot); | |
| 1005 | 1006 | return 0; |
| 1006 | 1007 | } |
| 1007 | 1008 | |
| 1008 | −static int snd_als4000_resume(struct pci_dev *pci) | |
| 1009 | +static int snd_als4000_resume(struct device *dev) | |
| 1009 | 1010 | { |
| 1010 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 1011 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 1012 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 1011 | 1013 | struct snd_card_als4000 *acard = card->private_data; |
| 1012 | 1014 | struct snd_sb *chip = acard->chip; |
| 1013 | 1015 | |
| @@ -1033,18 +1035,21 @@ static int snd_als4000_resume(struct pci_dev *pci) · 19 unmodified lines | ||
| 1033 | 1035 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 1034 | 1036 | return 0; |
| 1035 | 1037 | } |
| 1036 | −#endif /* CONFIG_PM */ | |
| 1037 | 1038 | |
| 1039 | +static SIMPLE_DEV_PM_OPS(snd_als4000_pm, snd_als4000_suspend, snd_als4000_resume); | |
| 1040 | +#define SND_ALS4000_PM_OPS &snd_als4000_pm | |
| 1041 | +#else | |
| 1042 | +#define SND_ALS4000_PM_OPS NULL | |
| 1043 | +#endif /* CONFIG_PM */ | |
| 1038 | 1044 | |
| 1039 | 1045 | static struct pci_driver als4000_driver = { |
| 1040 | 1046 | .name = KBUILD_MODNAME, |
| 1041 | 1047 | .id_table = snd_als4000_ids, |
| 1042 | 1048 | .probe = snd_card_als4000_probe, |
| 1043 | 1049 | .remove = __devexit_p(snd_card_als4000_remove), |
| 1044 | −#ifdef CONFIG_PM | |
| 1045 | − .suspend = snd_als4000_suspend, | |
| 1046 | − .resume = snd_als4000_resume, | |
| 1047 | −#endif | |
| 1050 | + .driver = { | |
| 1051 | + .pm = SND_ALS4000_PM_OPS, | |
| 1052 | + }, | |
| 1048 | 1053 | }; |
| 1049 | 1054 | |
| 1050 | 1055 | module_pci_driver(als4000_driver); |
| @@ -1462,9 +1462,10 @@ static int __devinit snd_atiixp_mixer_new(struct atiixp *chip, int clock, · 1461 unmodified lines | ||
| 1462 | 1462 | /* |
| 1463 | 1463 | * power management |
| 1464 | 1464 | */ |
| 1465 | −static int snd_atiixp_suspend(struct pci_dev *pci, pm_message_t state) | |
| 1465 | +static int snd_atiixp_suspend(struct device *dev) | |
| 1466 | 1466 | { |
| 1467 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 1467 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 1468 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 1468 | 1469 | struct atiixp *chip = card->private_data; |
| 1469 | 1470 | int i; |
| 1470 | 1471 | |
| @@ -1484,13 +1485,14 @@ static int snd_atiixp_suspend(struct pci_dev *pci, pm_message_t state) · 13 unmodified lines | ||
| 1484 | 1485 | |
| 1485 | 1486 | pci_disable_device(pci); |
| 1486 | 1487 | pci_save_state(pci); |
| 1487 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 1488 | + pci_set_power_state(pci, PCI_D3hot); | |
| 1488 | 1489 | return 0; |
| 1489 | 1490 | } |
| 1490 | 1491 | |
| 1491 | −static int snd_atiixp_resume(struct pci_dev *pci) | |
| 1492 | +static int snd_atiixp_resume(struct device *dev) | |
| 1492 | 1493 | { |
| 1493 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 1494 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 1495 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 1494 | 1496 | struct atiixp *chip = card->private_data; |
| 1495 | 1497 | int i; |
| 1496 | 1498 | |
| @@ -1526,6 +1528,11 @@ static int snd_atiixp_resume(struct pci_dev *pci) · 29 unmodified lines | ||
| 1526 | 1528 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 1527 | 1529 | return 0; |
| 1528 | 1530 | } |
| 1531 | + | |
| 1532 | +static SIMPLE_DEV_PM_OPS(snd_atiixp_pm, snd_atiixp_suspend, snd_atiixp_resume); | |
| 1533 | +#define SND_ATIIXP_PM_OPS &snd_atiixp_pm | |
| 1534 | +#else | |
| 1535 | +#define SND_ATIIXP_PM_OPS NULL | |
| 1529 | 1536 | #endif /* CONFIG_PM */ |
| 1530 | 1537 | |
| 1531 | 1538 | |
| @@ -1705,10 +1712,9 @@ static struct pci_driver atiixp_driver = { · 173 unmodified lines | ||
| 1705 | 1712 | .id_table = snd_atiixp_ids, |
| 1706 | 1713 | .probe = snd_atiixp_probe, |
| 1707 | 1714 | .remove = __devexit_p(snd_atiixp_remove), |
| 1708 | −#ifdef CONFIG_PM | |
| 1709 | − .suspend = snd_atiixp_suspend, | |
| 1710 | − .resume = snd_atiixp_resume, | |
| 1711 | −#endif | |
| 1715 | + .driver = { | |
| 1716 | + .pm = SND_ATIIXP_PM_OPS, | |
| 1717 | + }, | |
| 1712 | 1718 | }; |
| 1713 | 1719 | |
| 1714 | 1720 | module_pci_driver(atiixp_driver); |
| @@ -1117,9 +1117,10 @@ static int __devinit snd_atiixp_mixer_new(struct atiixp_modem *chip, int clock) · 1116 unmodified lines | ||
| 1117 | 1117 | /* |
| 1118 | 1118 | * power management |
| 1119 | 1119 | */ |
| 1120 | −static int snd_atiixp_suspend(struct pci_dev *pci, pm_message_t state) | |
| 1120 | +static int snd_atiixp_suspend(struct device *dev) | |
| 1121 | 1121 | { |
| 1122 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 1122 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 1123 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 1123 | 1124 | struct atiixp_modem *chip = card->private_data; |
| 1124 | 1125 | int i; |
| 1125 | 1126 | |
| @@ -1133,13 +1134,14 @@ static int snd_atiixp_suspend(struct pci_dev *pci, pm_message_t state) · 7 unmodified lines | ||
| 1133 | 1134 | |
| 1134 | 1135 | pci_disable_device(pci); |
| 1135 | 1136 | pci_save_state(pci); |
| 1136 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 1137 | + pci_set_power_state(pci, PCI_D3hot); | |
| 1137 | 1138 | return 0; |
| 1138 | 1139 | } |
| 1139 | 1140 | |
| 1140 | −static int snd_atiixp_resume(struct pci_dev *pci) | |
| 1141 | +static int snd_atiixp_resume(struct device *dev) | |
| 1141 | 1142 | { |
| 1142 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 1143 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 1144 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 1143 | 1145 | struct atiixp_modem *chip = card->private_data; |
| 1144 | 1146 | int i; |
| 1145 | 1147 | |
| @@ -1162,8 +1164,12 @@ static int snd_atiixp_resume(struct pci_dev *pci) · 16 unmodified lines | ||
| 1162 | 1164 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 1163 | 1165 | return 0; |
| 1164 | 1166 | } |
| 1165 | −#endif /* CONFIG_PM */ | |
| 1166 | 1167 | |
| 1168 | +static SIMPLE_DEV_PM_OPS(snd_atiixp_pm, snd_atiixp_suspend, snd_atiixp_resume); | |
| 1169 | +#define SND_ATIIXP_PM_OPS &snd_atiixp_pm | |
| 1170 | +#else | |
| 1171 | +#define SND_ATIIXP_PM_OPS NULL | |
| 1172 | +#endif /* CONFIG_PM */ | |
| 1167 | 1173 | |
| 1168 | 1174 | #ifdef CONFIG_PROC_FS |
| 1169 | 1175 | /* |
| @@ -1336,10 +1342,9 @@ static struct pci_driver atiixp_modem_driver = { · 166 unmodified lines | ||
| 1336 | 1342 | .id_table = snd_atiixp_ids, |
| 1337 | 1343 | .probe = snd_atiixp_probe, |
| 1338 | 1344 | .remove = __devexit_p(snd_atiixp_remove), |
| 1339 | −#ifdef CONFIG_PM | |
| 1340 | − .suspend = snd_atiixp_suspend, | |
| 1341 | − .resume = snd_atiixp_resume, | |
| 1342 | −#endif | |
| 1345 | + .driver = { | |
| 1346 | + .pm = SND_ATIIXP_PM_OPS, | |
| 1347 | + }, | |
| 1343 | 1348 | }; |
| 1344 | 1349 | |
| 1345 | 1350 | module_pci_driver(atiixp_modem_driver); |
| @@ -10,6 +10,15 @@ · 9 unmodified lines | ||
| 10 | 10 | #include <sound/core.h> |
| 11 | 11 | #include "au88x0.h" |
| 12 | 12 | |
| 13 | +static int remove_ctl(struct snd_card *card, const char *name) | |
| 14 | +{ | |
| 15 | + struct snd_ctl_elem_id id; | |
| 16 | + memset(&id, 0, sizeof(id)); | |
| 17 | + strcpy(id.name, name); | |
| 18 | + id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | |
| 19 | + return snd_ctl_remove_id(card, &id); | |
| 20 | +} | |
| 21 | + | |
| 13 | 22 | static int __devinit snd_vortex_mixer(vortex_t * vortex) |
| 14 | 23 | { |
| 15 | 24 | struct snd_ac97_bus *pbus; |
| @@ -28,5 +37,7 @@ static int __devinit snd_vortex_mixer(vortex_t * vortex) · 12 unmodified lines | ||
| 28 | 37 | ac97.scaps = AC97_SCAP_NO_SPDIF; |
| 29 | 38 | err = snd_ac97_mixer(pbus, &ac97, &vortex->codec); |
| 30 | 39 | vortex->isquad = ((vortex->codec == NULL) ? 0 : (vortex->codec->ext_id&0x80)); |
| 40 | + remove_ctl(vortex->card, "Master Mono Playback Volume"); | |
| 41 | + remove_ctl(vortex->card, "Master Mono Playback Switch"); | |
| 31 | 42 | return err; |
| 32 | 43 | } |
| @@ -2794,9 +2794,10 @@ snd_azf3328_resume_ac97(const struct snd_azf3328 *chip) · 2793 unmodified lines | ||
| 2794 | 2794 | } |
| 2795 | 2795 | |
| 2796 | 2796 | static int |
| 2797 | −snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state) | |
| 2797 | +snd_azf3328_suspend(struct device *dev) | |
| 2798 | 2798 | { |
| 2799 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 2799 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 2800 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 2800 | 2801 | struct snd_azf3328 *chip = card->private_data; |
| 2801 | 2802 | u16 *saved_regs_ctrl_u16; |
| 2802 | 2803 | |
| @@ -2824,14 +2825,15 @@ snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state) · 21 unmodified lines | ||
| 2824 | 2825 | |
| 2825 | 2826 | pci_disable_device(pci); |
| 2826 | 2827 | pci_save_state(pci); |
| 2827 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 2828 | + pci_set_power_state(pci, PCI_D3hot); | |
| 2828 | 2829 | return 0; |
| 2829 | 2830 | } |
| 2830 | 2831 | |
| 2831 | 2832 | static int |
| 2832 | −snd_azf3328_resume(struct pci_dev *pci) | |
| 2833 | +snd_azf3328_resume(struct device *dev) | |
| 2833 | 2834 | { |
| 2834 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 2835 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 2836 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 2835 | 2837 | const struct snd_azf3328 *chip = card->private_data; |
| 2836 | 2838 | |
| 2837 | 2839 | pci_set_power_state(pci, PCI_D0); |
| @@ -2859,18 +2861,21 @@ snd_azf3328_resume(struct pci_dev *pci) · 21 unmodified lines | ||
| 2859 | 2861 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 2860 | 2862 | return 0; |
| 2861 | 2863 | } |
| 2862 | −#endif /* CONFIG_PM */ | |
| 2863 | 2864 | |
| 2865 | +static SIMPLE_DEV_PM_OPS(snd_azf3328_pm, snd_azf3328_suspend, snd_azf3328_resume); | |
| 2866 | +#define SND_AZF3328_PM_OPS &snd_azf3328_pm | |
| 2867 | +#else | |
| 2868 | +#define SND_AZF3328_PM_OPS NULL | |
| 2869 | +#endif /* CONFIG_PM */ | |
| 2864 | 2870 | |
| 2865 | 2871 | static struct pci_driver azf3328_driver = { |
| 2866 | 2872 | .name = KBUILD_MODNAME, |
| 2867 | 2873 | .id_table = snd_azf3328_ids, |
| 2868 | 2874 | .probe = snd_azf3328_probe, |
| 2869 | 2875 | .remove = __devexit_p(snd_azf3328_remove), |
| 2870 | −#ifdef CONFIG_PM | |
| 2871 | − .suspend = snd_azf3328_suspend, | |
| 2872 | − .resume = snd_azf3328_resume, | |
| 2873 | −#endif | |
| 2876 | + .driver = { | |
| 2877 | + .pm = SND_AZF3328_PM_OPS, | |
| 2878 | + }, | |
| 2874 | 2879 | }; |
| 2875 | 2880 | |
| 2876 | 2881 | module_pci_driver(azf3328_driver); |
| @@ -1872,9 +1872,10 @@ static void __devexit snd_ca0106_remove(struct pci_dev *pci) · 1871 unmodified lines | ||
| 1872 | 1872 | } |
| 1873 | 1873 | |
| 1874 | 1874 | #ifdef CONFIG_PM |
| 1875 | −static int snd_ca0106_suspend(struct pci_dev *pci, pm_message_t state) | |
| 1875 | +static int snd_ca0106_suspend(struct device *dev) | |
| 1876 | 1876 | { |
| 1877 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 1877 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 1878 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 1878 | 1879 | struct snd_ca0106 *chip = card->private_data; |
| 1879 | 1880 | int i; |
| 1880 | 1881 | |
| @@ -1889,13 +1890,14 @@ static int snd_ca0106_suspend(struct pci_dev *pci, pm_message_t state) · 8 unmodified lines | ||
| 1889 | 1890 | |
| 1890 | 1891 | pci_disable_device(pci); |
| 1891 | 1892 | pci_save_state(pci); |
| 1892 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 1893 | + pci_set_power_state(pci, PCI_D3hot); | |
| 1893 | 1894 | return 0; |
| 1894 | 1895 | } |
| 1895 | 1896 | |
| 1896 | −static int snd_ca0106_resume(struct pci_dev *pci) | |
| 1897 | +static int snd_ca0106_resume(struct device *dev) | |
| 1897 | 1898 | { |
| 1898 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 1899 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 1900 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 1899 | 1901 | struct snd_ca0106 *chip = card->private_data; |
| 1900 | 1902 | int i; |
| 1901 | 1903 | |
| @@ -1922,6 +1924,11 @@ static int snd_ca0106_resume(struct pci_dev *pci) · 20 unmodified lines | ||
| 1922 | 1924 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 1923 | 1925 | return 0; |
| 1924 | 1926 | } |
| 1927 | + | |
| 1928 | +static SIMPLE_DEV_PM_OPS(snd_ca0106_pm, snd_ca0106_suspend, snd_ca0106_resume); | |
| 1929 | +#define SND_CA0106_PM_OPS &snd_ca0106_pm | |
| 1930 | +#else | |
| 1931 | +#define SND_CA0106_PM_OPS NULL | |
| 1925 | 1932 | #endif |
| 1926 | 1933 | |
| 1927 | 1934 | // PCI IDs |
| @@ -1937,10 +1944,9 @@ static struct pci_driver ca0106_driver = { · 9 unmodified lines | ||
| 1937 | 1944 | .id_table = snd_ca0106_ids, |
| 1938 | 1945 | .probe = snd_ca0106_probe, |
| 1939 | 1946 | .remove = __devexit_p(snd_ca0106_remove), |
| 1940 | −#ifdef CONFIG_PM | |
| 1941 | − .suspend = snd_ca0106_suspend, | |
| 1942 | − .resume = snd_ca0106_resume, | |
| 1943 | −#endif | |
| 1947 | + .driver = { | |
| 1948 | + .pm = SND_CA0106_PM_OPS, | |
| 1949 | + }, | |
| 1944 | 1950 | }; |
| 1945 | 1951 | |
| 1946 | 1952 | module_pci_driver(ca0106_driver); |
| @@ -3338,9 +3338,10 @@ static unsigned char saved_mixers[] = { · 3337 unmodified lines | ||
| 3338 | 3338 | SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, |
| 3339 | 3339 | }; |
| 3340 | 3340 | |
| 3341 | −static int snd_cmipci_suspend(struct pci_dev *pci, pm_message_t state) | |
| 3341 | +static int snd_cmipci_suspend(struct device *dev) | |
| 3342 | 3342 | { |
| 3343 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 3343 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 3344 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 3344 | 3345 | struct cmipci *cm = card->private_data; |
| 3345 | 3346 | int i; |
| 3346 | 3347 | |
| @@ -3361,13 +3362,14 @@ static int snd_cmipci_suspend(struct pci_dev *pci, pm_message_t state) · 14 unmodified lines | ||
| 3361 | 3362 | |
| 3362 | 3363 | pci_disable_device(pci); |
| 3363 | 3364 | pci_save_state(pci); |
| 3364 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 3365 | + pci_set_power_state(pci, PCI_D3hot); | |
| 3365 | 3366 | return 0; |
| 3366 | 3367 | } |
| 3367 | 3368 | |
| 3368 | −static int snd_cmipci_resume(struct pci_dev *pci) | |
| 3369 | +static int snd_cmipci_resume(struct device *dev) | |
| 3369 | 3370 | { |
| 3370 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 3371 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 3372 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 3371 | 3373 | struct cmipci *cm = card->private_data; |
| 3372 | 3374 | int i; |
| 3373 | 3375 | |
| @@ -3396,6 +3398,11 @@ static int snd_cmipci_resume(struct pci_dev *pci) · 22 unmodified lines | ||
| 3396 | 3398 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 3397 | 3399 | return 0; |
| 3398 | 3400 | } |
| 3401 | + | |
| 3402 | +static SIMPLE_DEV_PM_OPS(snd_cmipci_pm, snd_cmipci_suspend, snd_cmipci_resume); | |
| 3403 | +#define SND_CMIPCI_PM_OPS &snd_cmipci_pm | |
| 3404 | +#else | |
| 3405 | +#define SND_CMIPCI_PM_OPS NULL | |
| 3399 | 3406 | #endif /* CONFIG_PM */ |
| 3400 | 3407 | |
| 3401 | 3408 | static struct pci_driver cmipci_driver = { |
| @@ -3403,10 +3410,9 @@ static struct pci_driver cmipci_driver = { · 1 unmodified line | ||
| 3403 | 3410 | .id_table = snd_cmipci_ids, |
| 3404 | 3411 | .probe = snd_cmipci_probe, |
| 3405 | 3412 | .remove = __devexit_p(snd_cmipci_remove), |
| 3406 | −#ifdef CONFIG_PM | |
| 3407 | − .suspend = snd_cmipci_suspend, | |
| 3408 | − .resume = snd_cmipci_resume, | |
| 3409 | −#endif | |
| 3413 | + .driver = { | |
| 3414 | + .pm = SND_CMIPCI_PM_OPS, | |
| 3415 | + }, | |
| 3410 | 3416 | }; |
| 3411 | 3417 | |
| 3412 | 3418 | module_pci_driver(cmipci_driver); |
| @@ -1997,9 +1997,10 @@ static int saved_regs[SUSPEND_REGISTERS] = { · 1996 unmodified lines | ||
| 1997 | 1997 | |
| 1998 | 1998 | #define CLKCR1_CKRA 0x00010000L |
| 1999 | 1999 | |
| 2000 | −static int cs4281_suspend(struct pci_dev *pci, pm_message_t state) | |
| 2000 | +static int cs4281_suspend(struct device *dev) | |
| 2001 | 2001 | { |
| 2002 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 2002 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 2003 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 2003 | 2004 | struct cs4281 *chip = card->private_data; |
| 2004 | 2005 | u32 ulCLK; |
| 2005 | 2006 | unsigned int i; |
| @@ -2040,13 +2041,14 @@ static int cs4281_suspend(struct pci_dev *pci, pm_message_t state) · 34 unmodified lines | ||
| 2040 | 2041 | |
| 2041 | 2042 | pci_disable_device(pci); |
| 2042 | 2043 | pci_save_state(pci); |
| 2043 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 2044 | + pci_set_power_state(pci, PCI_D3hot); | |
| 2044 | 2045 | return 0; |
| 2045 | 2046 | } |
| 2046 | 2047 | |
| 2047 | −static int cs4281_resume(struct pci_dev *pci) | |
| 2048 | +static int cs4281_resume(struct device *dev) | |
| 2048 | 2049 | { |
| 2049 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 2050 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 2051 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 2050 | 2052 | struct cs4281 *chip = card->private_data; |
| 2051 | 2053 | unsigned int i; |
| 2052 | 2054 | u32 ulCLK; |
| @@ -2082,6 +2084,11 @@ static int cs4281_resume(struct pci_dev *pci) · 29 unmodified lines | ||
| 2082 | 2084 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 2083 | 2085 | return 0; |
| 2084 | 2086 | } |
| 2087 | + | |
| 2088 | +static SIMPLE_DEV_PM_OPS(cs4281_pm, cs4281_suspend, cs4281_resume); | |
| 2089 | +#define CS4281_PM_OPS &cs4281_pm | |
| 2090 | +#else | |
| 2091 | +#define CS4281_PM_OPS NULL | |
| 2085 | 2092 | #endif /* CONFIG_PM */ |
| 2086 | 2093 | |
| 2087 | 2094 | static struct pci_driver cs4281_driver = { |
| @@ -2089,10 +2096,9 @@ static struct pci_driver cs4281_driver = { · 1 unmodified line | ||
| 2089 | 2096 | .id_table = snd_cs4281_ids, |
| 2090 | 2097 | .probe = snd_cs4281_probe, |
| 2091 | 2098 | .remove = __devexit_p(snd_cs4281_remove), |
| 2092 | −#ifdef CONFIG_PM | |
| 2093 | − .suspend = cs4281_suspend, | |
| 2094 | − .resume = cs4281_resume, | |
| 2095 | −#endif | |
| 2099 | + .driver = { | |
| 2100 | + .pm = CS4281_PM_OPS, | |
| 2101 | + }, | |
| 2096 | 2102 | }; |
| 2097 | 2103 | |
| 2098 | 2104 | module_pci_driver(cs4281_driver); |
| @@ -30,7 +30,7 @@ · 29 unmodified lines | ||
| 30 | 30 | #include <linux/init.h> |
| 31 | 31 | #include <linux/module.h> |
| 32 | 32 | #include <sound/core.h> |
| 33 | −#include <sound/cs46xx.h> | |
| 33 | +#include "cs46xx.h" | |
| 34 | 34 | #include <sound/initval.h> |
| 35 | 35 | |
| 36 | 36 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
| @@ -167,8 +167,9 @@ static struct pci_driver cs46xx_driver = { · 130 unmodified lines | ||
| 167 | 167 | .probe = snd_card_cs46xx_probe, |
| 168 | 168 | .remove = __devexit_p(snd_card_cs46xx_remove), |
| 169 | 169 | #ifdef CONFIG_PM |
| 170 | − .suspend = snd_cs46xx_suspend, | |
| 171 | − .resume = snd_cs46xx_resume, | |
| 170 | + .driver = { | |
| 171 | + .pm = &snd_cs46xx_pm, | |
| 172 | + }, | |
| 172 | 173 | #endif |
| 173 | 174 | }; |
| 174 | 175 | |
| @@ -23,10 +23,10 @@ · 22 unmodified lines | ||
| 23 | 23 | * |
| 24 | 24 | */ |
| 25 | 25 | |
| 26 | −#include "pcm.h" | |
| 27 | −#include "pcm-indirect.h" | |
| 28 | −#include "rawmidi.h" | |
| 29 | −#include "ac97_codec.h" | |
| 26 | +#include <sound/pcm.h> | |
| 27 | +#include <sound/pcm-indirect.h> | |
| 28 | +#include <sound/rawmidi.h> | |
| 29 | +#include <sound/ac97_codec.h> | |
| 30 | 30 | #include "cs46xx_dsp_spos.h" |
| 31 | 31 | |
| 32 | 32 | /* |
| @@ -1730,8 +1730,7 @@ int snd_cs46xx_create(struct snd_card *card, · 1697 unmodified lines | ||
| 1730 | 1730 | struct pci_dev *pci, |
| 1731 | 1731 | int external_amp, int thinkpad, |
| 1732 | 1732 | struct snd_cs46xx **rcodec); |
| 1733 | −int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state); | |
| 1734 | −int snd_cs46xx_resume(struct pci_dev *pci); | |
| 1733 | +extern const struct dev_pm_ops snd_cs46xx_pm; | |
| 1735 | 1734 | |
| 1736 | 1735 | int snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm); |
| 1737 | 1736 | int snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm); |
File renamed without changes.
File renamed without changes.
File renamed without changes.
| @@ -61,7 +61,7 @@ · 60 unmodified lines | ||
| 61 | 61 | #include <sound/info.h> |
| 62 | 62 | #include <sound/pcm.h> |
| 63 | 63 | #include <sound/pcm_params.h> |
| 64 | −#include <sound/cs46xx.h> | |
| 64 | +#include "cs46xx.h" | |
| 65 | 65 | |
| 66 | 66 | #include <asm/io.h> |
| 67 | 67 | |
| @@ -3599,9 +3599,10 @@ static unsigned int saved_regs[] = { · 3531 unmodified lines | ||
| 3599 | 3599 | BA1_CVOL, |
| 3600 | 3600 | }; |
| 3601 | 3601 | |
| 3602 | −int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state) | |
| 3602 | +static int snd_cs46xx_suspend(struct device *dev) | |
| 3603 | 3603 | { |
| 3604 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 3604 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 3605 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 3605 | 3606 | struct snd_cs46xx *chip = card->private_data; |
| 3606 | 3607 | int i, amp_saved; |
| 3607 | 3608 | |
| @@ -3628,13 +3629,14 @@ int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state) · 20 unmodified lines | ||
| 3628 | 3629 | |
| 3629 | 3630 | pci_disable_device(pci); |
| 3630 | 3631 | pci_save_state(pci); |
| 3631 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 3632 | + pci_set_power_state(pci, PCI_D3hot); | |
| 3632 | 3633 | return 0; |
| 3633 | 3634 | } |
| 3634 | 3635 | |
| 3635 | −int snd_cs46xx_resume(struct pci_dev *pci) | |
| 3636 | +static int snd_cs46xx_resume(struct device *dev) | |
| 3636 | 3637 | { |
| 3637 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 3638 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 3639 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 3638 | 3640 | struct snd_cs46xx *chip = card->private_data; |
| 3639 | 3641 | int amp_saved; |
| 3640 | 3642 | #ifdef CONFIG_SND_CS46XX_NEW_DSP |
| @@ -3707,6 +3709,8 @@ int snd_cs46xx_resume(struct pci_dev *pci) · 66 unmodified lines | ||
| 3707 | 3709 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 3708 | 3710 | return 0; |
| 3709 | 3711 | } |
| 3712 | + | |
| 3713 | +SIMPLE_DEV_PM_OPS(snd_cs46xx_pm, snd_cs46xx_suspend, snd_cs46xx_resume); | |
| 3710 | 3714 | #endif /* CONFIG_PM */ |
| 3711 | 3715 | |
| 3712 | 3716 | |
| @@ -32,7 +32,7 @@ · 31 unmodified lines | ||
| 32 | 32 | #include <sound/control.h> |
| 33 | 33 | #include <sound/info.h> |
| 34 | 34 | #include <sound/asoundef.h> |
| 35 | −#include <sound/cs46xx.h> | |
| 35 | +#include "cs46xx.h" | |
| 36 | 36 | |
| 37 | 37 | #include "cs46xx_lib.h" |
| 38 | 38 | #include "dsp_spos.h" |
| @@ -31,7 +31,7 @@ · 30 unmodified lines | ||
| 31 | 31 | #include <sound/core.h> |
| 32 | 32 | #include <sound/control.h> |
| 33 | 33 | #include <sound/info.h> |
| 34 | −#include <sound/cs46xx.h> | |
| 34 | +#include "cs46xx.h" | |
| 35 | 35 | |
| 36 | 36 | #include "cs46xx_lib.h" |
| 37 | 37 | #include "dsp_spos.h" |
| @@ -400,8 +400,9 @@ static struct pci_driver cs5535audio_driver = { · 399 unmodified lines | ||
| 400 | 400 | .probe = snd_cs5535audio_probe, |
| 401 | 401 | .remove = __devexit_p(snd_cs5535audio_remove), |
| 402 | 402 | #ifdef CONFIG_PM |
| 403 | − .suspend = snd_cs5535audio_suspend, | |
| 404 | − .resume = snd_cs5535audio_resume, | |
| 403 | + .driver = { | |
| 404 | + .pm = &snd_cs5535audio_pm, | |
| 405 | + }, | |
| 405 | 406 | #endif |
| 406 | 407 | }; |
| 407 | 408 | |
| @@ -94,10 +94,7 @@ struct cs5535audio { · 93 unmodified lines | ||
| 94 | 94 | struct cs5535audio_dma dmas[NUM_CS5535AUDIO_DMAS]; |
| 95 | 95 | }; |
| 96 | 96 | |
| 97 | −#ifdef CONFIG_PM | |
| 98 | −int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state); | |
| 99 | −int snd_cs5535audio_resume(struct pci_dev *pci); | |
| 100 | −#endif | |
| 97 | +extern const struct dev_pm_ops snd_cs5535audio_pm; | |
| 101 | 98 | |
| 102 | 99 | #ifdef CONFIG_OLPC |
| 103 | 100 | void __devinit olpc_prequirks(struct snd_card *card, |
| @@ -55,9 +55,10 @@ static void snd_cs5535audio_stop_hardware(struct cs5535audio *cs5535au) · 54 unmodified lines | ||
| 55 | 55 | |
| 56 | 56 | } |
| 57 | 57 | |
| 58 | −int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state) | |
| 58 | +static int snd_cs5535audio_suspend(struct device *dev) | |
| 59 | 59 | { |
| 60 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 60 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 61 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 61 | 62 | struct cs5535audio *cs5535au = card->private_data; |
| 62 | 63 | int i; |
| 63 | 64 | |
| @@ -77,13 +78,14 @@ int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state) · 13 unmodified lines | ||
| 77 | 78 | return -EIO; |
| 78 | 79 | } |
| 79 | 80 | pci_disable_device(pci); |
| 80 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 81 | + pci_set_power_state(pci, PCI_D3hot); | |
| 81 | 82 | return 0; |
| 82 | 83 | } |
| 83 | 84 | |
| 84 | −int snd_cs5535audio_resume(struct pci_dev *pci) | |
| 85 | +static int snd_cs5535audio_resume(struct device *dev) | |
| 85 | 86 | { |
| 86 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 87 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 88 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 87 | 89 | struct cs5535audio *cs5535au = card->private_data; |
| 88 | 90 | u32 tmp; |
| 89 | 91 | int timeout; |
| @@ -129,3 +131,4 @@ int snd_cs5535audio_resume(struct pci_dev *pci) · 39 unmodified lines | ||
| 129 | 131 | return 0; |
| 130 | 132 | } |
| 131 | 133 | |
| 134 | +SIMPLE_DEV_PM_OPS(snd_cs5535audio_pm, snd_cs5535audio_suspend, snd_cs5535audio_resume); | |
| @@ -1537,7 +1537,7 @@ static void atc_connect_resources(struct ct_atc *atc) · 1536 unmodified lines | ||
| 1537 | 1537 | } |
| 1538 | 1538 | |
| 1539 | 1539 | #ifdef CONFIG_PM |
| 1540 | −static int atc_suspend(struct ct_atc *atc, pm_message_t state) | |
| 1540 | +static int atc_suspend(struct ct_atc *atc) | |
| 1541 | 1541 | { |
| 1542 | 1542 | int i; |
| 1543 | 1543 | struct hw *hw = atc->hw; |
| @@ -1553,7 +1553,7 @@ static int atc_suspend(struct ct_atc *atc, pm_message_t state) · 9 unmodified lines | ||
| 1553 | 1553 | |
| 1554 | 1554 | atc_release_resources(atc); |
| 1555 | 1555 | |
| 1556 | − hw->suspend(hw, state); | |
| 1556 | + hw->suspend(hw); | |
| 1557 | 1557 | |
| 1558 | 1558 | return 0; |
| 1559 | 1559 | } |
| @@ -144,7 +144,7 @@ struct ct_atc { · 143 unmodified lines | ||
| 144 | 144 | struct ct_timer *timer; |
| 145 | 145 | |
| 146 | 146 | #ifdef CONFIG_PM |
| 147 | − int (*suspend)(struct ct_atc *atc, pm_message_t state); | |
| 147 | + int (*suspend)(struct ct_atc *atc); | |
| 148 | 148 | int (*resume)(struct ct_atc *atc); |
| 149 | 149 | #define NUM_PCMS (NUM_CTALSADEVS - 1) |
| 150 | 150 | struct snd_pcm *pcms[NUM_PCMS]; |
| @@ -73,7 +73,7 @@ struct hw { · 72 unmodified lines | ||
| 73 | 73 | int (*card_stop)(struct hw *hw); |
| 74 | 74 | int (*pll_init)(struct hw *hw, unsigned int rsr); |
| 75 | 75 | #ifdef CONFIG_PM |
| 76 | − int (*suspend)(struct hw *hw, pm_message_t state); | |
| 76 | + int (*suspend)(struct hw *hw); | |
| 77 | 77 | int (*resume)(struct hw *hw, struct card_conf *info); |
| 78 | 78 | #endif |
| 79 | 79 | int (*is_adc_source_selected)(struct hw *hw, enum ADCSRC source); |
| @@ -2086,7 +2086,7 @@ static int hw_card_init(struct hw *hw, struct card_conf *info) · 2085 unmodified lines | ||
| 2086 | 2086 | } |
| 2087 | 2087 | |
| 2088 | 2088 | #ifdef CONFIG_PM |
| 2089 | −static int hw_suspend(struct hw *hw, pm_message_t state) | |
| 2089 | +static int hw_suspend(struct hw *hw) | |
| 2090 | 2090 | { |
| 2091 | 2091 | struct pci_dev *pci = hw->pci; |
| 2092 | 2092 | |
| @@ -2099,7 +2099,7 @@ static int hw_suspend(struct hw *hw, pm_message_t state) · 6 unmodified lines | ||
| 2099 | 2099 | |
| 2100 | 2100 | pci_disable_device(pci); |
| 2101 | 2101 | pci_save_state(pci); |
| 2102 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 2102 | + pci_set_power_state(pci, PCI_D3hot); | |
| 2103 | 2103 | |
| 2104 | 2104 | return 0; |
| 2105 | 2105 | } |
| @@ -2202,7 +2202,7 @@ static int hw_card_init(struct hw *hw, struct card_conf *info) · 2201 unmodified lines | ||
| 2202 | 2202 | } |
| 2203 | 2203 | |
| 2204 | 2204 | #ifdef CONFIG_PM |
| 2205 | −static int hw_suspend(struct hw *hw, pm_message_t state) | |
| 2205 | +static int hw_suspend(struct hw *hw) | |
| 2206 | 2206 | { |
| 2207 | 2207 | struct pci_dev *pci = hw->pci; |
| 2208 | 2208 | |
| @@ -2210,7 +2210,7 @@ static int hw_suspend(struct hw *hw, pm_message_t state) · 1 unmodified line | ||
| 2210 | 2210 | |
| 2211 | 2211 | pci_disable_device(pci); |
| 2212 | 2212 | pci_save_state(pci); |
| 2213 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 2213 | + pci_set_power_state(pci, PCI_D3hot); | |
| 2214 | 2214 | |
| 2215 | 2215 | return 0; |
| 2216 | 2216 | } |
| @@ -126,21 +126,26 @@ static void __devexit ct_card_remove(struct pci_dev *pci) · 125 unmodified lines | ||
| 126 | 126 | } |
| 127 | 127 | |
| 128 | 128 | #ifdef CONFIG_PM |
| 129 | −static int ct_card_suspend(struct pci_dev *pci, pm_message_t state) | |
| 129 | +static int ct_card_suspend(struct device *dev) | |
| 130 | 130 | { |
| 131 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 131 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 132 | 132 | struct ct_atc *atc = card->private_data; |
| 133 | 133 | |
| 134 | − return atc->suspend(atc, state); | |
| 134 | + return atc->suspend(atc); | |
| 135 | 135 | } |
| 136 | 136 | |
| 137 | −static int ct_card_resume(struct pci_dev *pci) | |
| 137 | +static int ct_card_resume(struct device *dev) | |
| 138 | 138 | { |
| 139 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 139 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 140 | 140 | struct ct_atc *atc = card->private_data; |
| 141 | 141 | |
| 142 | 142 | return atc->resume(atc); |
| 143 | 143 | } |
| 144 | + | |
| 145 | +static SIMPLE_DEV_PM_OPS(ct_card_pm, ct_card_suspend, ct_card_resume); | |
| 146 | +#define CT_CARD_PM_OPS &ct_card_pm | |
| 147 | +#else | |
| 148 | +#define CT_CARD_PM_OPS NULL | |
| 144 | 149 | #endif |
| 145 | 150 | |
| 146 | 151 | static struct pci_driver ct_driver = { |
| @@ -148,10 +153,9 @@ static struct pci_driver ct_driver = { · 1 unmodified line | ||
| 148 | 153 | .id_table = ct_pci_dev_ids, |
| 149 | 154 | .probe = ct_card_probe, |
| 150 | 155 | .remove = __devexit_p(ct_card_remove), |
| 151 | −#ifdef CONFIG_PM | |
| 152 | − .suspend = ct_card_suspend, | |
| 153 | − .resume = ct_card_resume, | |
| 154 | −#endif | |
| 156 | + .driver = { | |
| 157 | + .pm = CT_CARD_PM_OPS, | |
| 158 | + }, | |
| 155 | 159 | }; |
| 156 | 160 | |
| 157 | 161 | module_pci_driver(ct_driver); |
| @@ -2205,9 +2205,10 @@ ctl_error: · 2204 unmodified lines | ||
| 2205 | 2205 | |
| 2206 | 2206 | #if defined(CONFIG_PM) |
| 2207 | 2207 | |
| 2208 | −static int snd_echo_suspend(struct pci_dev *pci, pm_message_t state) | |
| 2208 | +static int snd_echo_suspend(struct device *dev) | |
| 2209 | 2209 | { |
| 2210 | − struct echoaudio *chip = pci_get_drvdata(pci); | |
| 2210 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 2211 | + struct echoaudio *chip = dev_get_drvdata(dev); | |
| 2211 | 2212 | |
| 2212 | 2213 | DE_INIT(("suspend start\n")); |
| 2213 | 2214 | snd_pcm_suspend_all(chip->analog_pcm); |
| @@ -2242,9 +2243,10 @@ static int snd_echo_suspend(struct pci_dev *pci, pm_message_t state) · 28 unmodified lines | ||
| 2242 | 2243 | |
| 2243 | 2244 | |
| 2244 | 2245 | |
| 2245 | −static int snd_echo_resume(struct pci_dev *pci) | |
| 2246 | +static int snd_echo_resume(struct device *dev) | |
| 2246 | 2247 | { |
| 2247 | − struct echoaudio *chip = pci_get_drvdata(pci); | |
| 2248 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 2249 | + struct echoaudio *chip = dev_get_drvdata(dev); | |
| 2248 | 2250 | struct comm_page *commpage, *commpage_bak; |
| 2249 | 2251 | u32 pipe_alloc_mask; |
| 2250 | 2252 | int err; |
| @@ -2307,10 +2309,13 @@ static int snd_echo_resume(struct pci_dev *pci) · 56 unmodified lines | ||
| 2307 | 2309 | return 0; |
| 2308 | 2310 | } |
| 2309 | 2311 | |
| 2312 | +static SIMPLE_DEV_PM_OPS(snd_echo_pm, snd_echo_suspend, snd_echo_resume); | |
| 2313 | +#define SND_ECHO_PM_OPS &snd_echo_pm | |
| 2314 | +#else | |
| 2315 | +#define SND_ECHO_PM_OPS NULL | |
| 2310 | 2316 | #endif /* CONFIG_PM */ |
| 2311 | 2317 | |
| 2312 | 2318 | |
| 2313 | − | |
| 2314 | 2319 | static void __devexit snd_echo_remove(struct pci_dev *pci) |
| 2315 | 2320 | { |
| 2316 | 2321 | struct echoaudio *chip; |
| @@ -2333,10 +2338,9 @@ static struct pci_driver echo_driver = { · 16 unmodified lines | ||
| 2333 | 2338 | .id_table = snd_echo_ids, |
| 2334 | 2339 | .probe = snd_echo_probe, |
| 2335 | 2340 | .remove = __devexit_p(snd_echo_remove), |
| 2336 | −#ifdef CONFIG_PM | |
| 2337 | − .suspend = snd_echo_suspend, | |
| 2338 | − .resume = snd_echo_resume, | |
| 2339 | −#endif /* CONFIG_PM */ | |
| 2341 | + .driver = { | |
| 2342 | + .pm = SND_ECHO_PM_OPS, | |
| 2343 | + }, | |
| 2340 | 2344 | }; |
| 2341 | 2345 | |
| 2342 | 2346 | module_pci_driver(echo_driver); |
| @@ -207,9 +207,10 @@ static void __devexit snd_card_emu10k1_remove(struct pci_dev *pci) · 206 unmodified lines | ||
| 207 | 207 | |
| 208 | 208 | |
| 209 | 209 | #ifdef CONFIG_PM |
| 210 | −static int snd_emu10k1_suspend(struct pci_dev *pci, pm_message_t state) | |
| 210 | +static int snd_emu10k1_suspend(struct device *dev) | |
| 211 | 211 | { |
| 212 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 212 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 213 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 213 | 214 | struct snd_emu10k1 *emu = card->private_data; |
| 214 | 215 | |
| 215 | 216 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
| @@ -231,13 +232,14 @@ static int snd_emu10k1_suspend(struct pci_dev *pci, pm_message_t state) · 15 unmodified lines | ||
| 231 | 232 | |
| 232 | 233 | pci_disable_device(pci); |
| 233 | 234 | pci_save_state(pci); |
| 234 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 235 | + pci_set_power_state(pci, PCI_D3hot); | |
| 235 | 236 | return 0; |
| 236 | 237 | } |
| 237 | 238 | |
| 238 | −static int snd_emu10k1_resume(struct pci_dev *pci) | |
| 239 | +static int snd_emu10k1_resume(struct device *dev) | |
| 239 | 240 | { |
| 240 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 241 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 242 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 241 | 243 | struct snd_emu10k1 *emu = card->private_data; |
| 242 | 244 | |
| 243 | 245 | pci_set_power_state(pci, PCI_D0); |
| @@ -261,17 +263,21 @@ static int snd_emu10k1_resume(struct pci_dev *pci) · 17 unmodified lines | ||
| 261 | 263 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 262 | 264 | return 0; |
| 263 | 265 | } |
| 264 | −#endif | |
| 266 | + | |
| 267 | +static SIMPLE_DEV_PM_OPS(snd_emu10k1_pm, snd_emu10k1_suspend, snd_emu10k1_resume); | |
| 268 | +#define SND_EMU10K1_PM_OPS &snd_emu10k1_pm | |
| 269 | +#else | |
| 270 | +#define SND_EMU10K1_PM_OPS NULL | |
| 271 | +#endif /* CONFIG_PM */ | |
| 265 | 272 | |
| 266 | 273 | static struct pci_driver emu10k1_driver = { |
| 267 | 274 | .name = KBUILD_MODNAME, |
| 268 | 275 | .id_table = snd_emu10k1_ids, |
| 269 | 276 | .probe = snd_card_emu10k1_probe, |
| 270 | 277 | .remove = __devexit_p(snd_card_emu10k1_remove), |
| 271 | −#ifdef CONFIG_PM | |
| 272 | − .suspend = snd_emu10k1_suspend, | |
| 273 | − .resume = snd_emu10k1_resume, | |
| 274 | −#endif | |
| 278 | + .driver = { | |
| 279 | + .pm = SND_EMU10K1_PM_OPS, | |
| 280 | + }, | |
| 275 | 281 | }; |
| 276 | 282 | |
| 277 | 283 | module_pci_driver(emu10k1_driver); |
| @@ -2033,9 +2033,10 @@ static void snd_ensoniq_chip_init(struct ensoniq *ensoniq) · 2032 unmodified lines | ||
| 2033 | 2033 | } |
| 2034 | 2034 | |
| 2035 | 2035 | #ifdef CONFIG_PM |
| 2036 | −static int snd_ensoniq_suspend(struct pci_dev *pci, pm_message_t state) | |
| 2036 | +static int snd_ensoniq_suspend(struct device *dev) | |
| 2037 | 2037 | { |
| 2038 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 2038 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 2039 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 2039 | 2040 | struct ensoniq *ensoniq = card->private_data; |
| 2040 | 2041 | |
| 2041 | 2042 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
| @@ -2058,13 +2059,14 @@ static int snd_ensoniq_suspend(struct pci_dev *pci, pm_message_t state) · 16 unmodified lines | ||
| 2058 | 2059 | |
| 2059 | 2060 | pci_disable_device(pci); |
| 2060 | 2061 | pci_save_state(pci); |
| 2061 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 2062 | + pci_set_power_state(pci, PCI_D3hot); | |
| 2062 | 2063 | return 0; |
| 2063 | 2064 | } |
| 2064 | 2065 | |
| 2065 | −static int snd_ensoniq_resume(struct pci_dev *pci) | |
| 2066 | +static int snd_ensoniq_resume(struct device *dev) | |
| 2066 | 2067 | { |
| 2067 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 2068 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 2069 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 2068 | 2070 | struct ensoniq *ensoniq = card->private_data; |
| 2069 | 2071 | |
| 2070 | 2072 | pci_set_power_state(pci, PCI_D0); |
| @@ -2087,8 +2089,12 @@ static int snd_ensoniq_resume(struct pci_dev *pci) · 16 unmodified lines | ||
| 2087 | 2089 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 2088 | 2090 | return 0; |
| 2089 | 2091 | } |
| 2090 | −#endif /* CONFIG_PM */ | |
| 2091 | 2092 | |
| 2093 | +static SIMPLE_DEV_PM_OPS(snd_ensoniq_pm, snd_ensoniq_suspend, snd_ensoniq_resume); | |
| 2094 | +#define SND_ENSONIQ_PM_OPS &snd_ensoniq_pm | |
| 2095 | +#else | |
| 2096 | +#define SND_ENSONIQ_PM_OPS NULL | |
| 2097 | +#endif /* CONFIG_PM */ | |
| 2092 | 2098 | |
| 2093 | 2099 | static int __devinit snd_ensoniq_create(struct snd_card *card, |
| 2094 | 2100 | struct pci_dev *pci, |
| @@ -2493,10 +2499,9 @@ static struct pci_driver ens137x_driver = { · 398 unmodified lines | ||
| 2493 | 2499 | .id_table = snd_audiopci_ids, |
| 2494 | 2500 | .probe = snd_audiopci_probe, |
| 2495 | 2501 | .remove = __devexit_p(snd_audiopci_remove), |
| 2496 | −#ifdef CONFIG_PM | |
| 2497 | − .suspend = snd_ensoniq_suspend, | |
| 2498 | − .resume = snd_ensoniq_resume, | |
| 2499 | −#endif | |
| 2502 | + .driver = { | |
| 2503 | + .pm = SND_ENSONIQ_PM_OPS, | |
| 2504 | + }, | |
| 2500 | 2505 | }; |
| 2501 | 2506 | |
| 2502 | 2507 | module_pci_driver(ens137x_driver); |
| @@ -1321,35 +1321,30 @@ static int snd_es1938_put_double(struct snd_kcontrol *kcontrol, · 1320 unmodified lines | ||
| 1321 | 1321 | return change; |
| 1322 | 1322 | } |
| 1323 | 1323 | |
| 1324 | −static unsigned int db_scale_master[] = { | |
| 1325 | − TLV_DB_RANGE_HEAD(2), | |
| 1324 | +static const DECLARE_TLV_DB_RANGE(db_scale_master, | |
| 1326 | 1325 | 0, 54, TLV_DB_SCALE_ITEM(-3600, 50, 1), |
| 1327 | 1326 | 54, 63, TLV_DB_SCALE_ITEM(-900, 100, 0), |
| 1328 | −}; | |
| 1327 | +); | |
| 1329 | 1328 | |
| 1330 | −static unsigned int db_scale_audio1[] = { | |
| 1331 | − TLV_DB_RANGE_HEAD(2), | |
| 1329 | +static const DECLARE_TLV_DB_RANGE(db_scale_audio1, | |
| 1332 | 1330 | 0, 8, TLV_DB_SCALE_ITEM(-3300, 300, 1), |
| 1333 | 1331 | 8, 15, TLV_DB_SCALE_ITEM(-900, 150, 0), |
| 1334 | −}; | |
| 1332 | +); | |
| 1335 | 1333 | |
| 1336 | −static unsigned int db_scale_audio2[] = { | |
| 1337 | − TLV_DB_RANGE_HEAD(2), | |
| 1334 | +static const DECLARE_TLV_DB_RANGE(db_scale_audio2, | |
| 1338 | 1335 | 0, 8, TLV_DB_SCALE_ITEM(-3450, 300, 1), |
| 1339 | 1336 | 8, 15, TLV_DB_SCALE_ITEM(-1050, 150, 0), |
| 1340 | −}; | |
| 1337 | +); | |
| 1341 | 1338 | |
| 1342 | −static unsigned int db_scale_mic[] = { | |
| 1343 | − TLV_DB_RANGE_HEAD(2), | |
| 1339 | +static const DECLARE_TLV_DB_RANGE(db_scale_mic, | |
| 1344 | 1340 | 0, 8, TLV_DB_SCALE_ITEM(-2400, 300, 1), |
| 1345 | 1341 | 8, 15, TLV_DB_SCALE_ITEM(0, 150, 0), |
| 1346 | −}; | |
| 1342 | +); | |
| 1347 | 1343 | |
| 1348 | −static unsigned int db_scale_line[] = { | |
| 1349 | − TLV_DB_RANGE_HEAD(2), | |
| 1344 | +static const DECLARE_TLV_DB_RANGE(db_scale_line, | |
| 1350 | 1345 | 0, 8, TLV_DB_SCALE_ITEM(-3150, 300, 1), |
| 1351 | 1346 | 8, 15, TLV_DB_SCALE_ITEM(-750, 150, 0), |
| 1352 | −}; | |
| 1347 | +); | |
| 1353 | 1348 | |
| 1354 | 1349 | static const DECLARE_TLV_DB_SCALE(db_scale_capture, 0, 150, 0); |
| 1355 | 1350 | |
| @@ -1474,9 +1469,10 @@ static unsigned char saved_regs[SAVED_REG_SIZE+1] = { · 118 unmodified lines | ||
| 1474 | 1469 | }; |
| 1475 | 1470 | |
| 1476 | 1471 | |
| 1477 | −static int es1938_suspend(struct pci_dev *pci, pm_message_t state) | |
| 1472 | +static int es1938_suspend(struct device *dev) | |
| 1478 | 1473 | { |
| 1479 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 1474 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 1475 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 1480 | 1476 | struct es1938 *chip = card->private_data; |
| 1481 | 1477 | unsigned char *s, *d; |
| 1482 | 1478 | |
| @@ -1494,13 +1490,14 @@ static int es1938_suspend(struct pci_dev *pci, pm_message_t state) · 11 unmodified lines | ||
| 1494 | 1490 | } |
| 1495 | 1491 | pci_disable_device(pci); |
| 1496 | 1492 | pci_save_state(pci); |
| 1497 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 1493 | + pci_set_power_state(pci, PCI_D3hot); | |
| 1498 | 1494 | return 0; |
| 1499 | 1495 | } |
| 1500 | 1496 | |
| 1501 | −static int es1938_resume(struct pci_dev *pci) | |
| 1497 | +static int es1938_resume(struct device *dev) | |
| 1502 | 1498 | { |
| 1503 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 1499 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 1500 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 1504 | 1501 | struct es1938 *chip = card->private_data; |
| 1505 | 1502 | unsigned char *s, *d; |
| 1506 | 1503 | |
| @@ -1534,6 +1531,11 @@ static int es1938_resume(struct pci_dev *pci) · 27 unmodified lines | ||
| 1534 | 1531 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 1535 | 1532 | return 0; |
| 1536 | 1533 | } |
| 1534 | + | |
| 1535 | +static SIMPLE_DEV_PM_OPS(es1938_pm, es1938_suspend, es1938_resume); | |
| 1536 | +#define ES1938_PM_OPS &es1938_pm | |
| 1537 | +#else | |
| 1538 | +#define ES1938_PM_OPS NULL | |
| 1537 | 1539 | #endif /* CONFIG_PM */ |
| 1538 | 1540 | |
| 1539 | 1541 | #ifdef SUPPORT_JOYSTICK |
| @@ -1887,10 +1889,9 @@ static struct pci_driver es1938_driver = { · 347 unmodified lines | ||
| 1887 | 1889 | .id_table = snd_es1938_ids, |
| 1888 | 1890 | .probe = snd_es1938_probe, |
| 1889 | 1891 | .remove = __devexit_p(snd_es1938_remove), |
| 1890 | −#ifdef CONFIG_PM | |
| 1891 | − .suspend = es1938_suspend, | |
| 1892 | − .resume = es1938_resume, | |
| 1893 | −#endif | |
| 1892 | + .driver = { | |
| 1893 | + .pm = ES1938_PM_OPS, | |
| 1894 | + }, | |
| 1894 | 1895 | }; |
| 1895 | 1896 | |
| 1896 | 1897 | module_pci_driver(es1938_driver); |
| @@ -2381,9 +2381,10 @@ static void snd_es1968_start_irq(struct es1968 *chip) · 2380 unmodified lines | ||
| 2381 | 2381 | /* |
| 2382 | 2382 | * PM support |
| 2383 | 2383 | */ |
| 2384 | −static int es1968_suspend(struct pci_dev *pci, pm_message_t state) | |
| 2384 | +static int es1968_suspend(struct device *dev) | |
| 2385 | 2385 | { |
| 2386 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 2386 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 2387 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 2387 | 2388 | struct es1968 *chip = card->private_data; |
| 2388 | 2389 | |
| 2389 | 2390 | if (! chip->do_pm) |
| @@ -2398,13 +2399,14 @@ static int es1968_suspend(struct pci_dev *pci, pm_message_t state) · 8 unmodified lines | ||
| 2398 | 2399 | |
| 2399 | 2400 | pci_disable_device(pci); |
| 2400 | 2401 | pci_save_state(pci); |
| 2401 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 2402 | + pci_set_power_state(pci, PCI_D3hot); | |
| 2402 | 2403 | return 0; |
| 2403 | 2404 | } |
| 2404 | 2405 | |
| 2405 | −static int es1968_resume(struct pci_dev *pci) | |
| 2406 | +static int es1968_resume(struct device *dev) | |
| 2406 | 2407 | { |
| 2407 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 2408 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 2409 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 2408 | 2410 | struct es1968 *chip = card->private_data; |
| 2409 | 2411 | struct esschan *es; |
| 2410 | 2412 | |
| @@ -2454,6 +2456,11 @@ static int es1968_resume(struct pci_dev *pci) · 43 unmodified lines | ||
| 2454 | 2456 | chip->in_suspend = 0; |
| 2455 | 2457 | return 0; |
| 2456 | 2458 | } |
| 2459 | + | |
| 2460 | +static SIMPLE_DEV_PM_OPS(es1968_pm, es1968_suspend, es1968_resume); | |
| 2461 | +#define ES1968_PM_OPS &es1968_pm | |
| 2462 | +#else | |
| 2463 | +#define ES1968_PM_OPS NULL | |
| 2457 | 2464 | #endif /* CONFIG_PM */ |
| 2458 | 2465 | |
| 2459 | 2466 | #ifdef SUPPORT_JOYSTICK |
| @@ -2903,10 +2910,9 @@ static struct pci_driver es1968_driver = { · 443 unmodified lines | ||
| 2903 | 2910 | .id_table = snd_es1968_ids, |
| 2904 | 2911 | .probe = snd_es1968_probe, |
| 2905 | 2912 | .remove = __devexit_p(snd_es1968_remove), |
| 2906 | −#ifdef CONFIG_PM | |
| 2907 | − .suspend = es1968_suspend, | |
| 2908 | − .resume = es1968_resume, | |
| 2909 | −#endif | |
| 2913 | + .driver = { | |
| 2914 | + .pm = ES1968_PM_OPS, | |
| 2915 | + }, | |
| 2910 | 2916 | }; |
| 2911 | 2917 | |
| 2912 | 2918 | module_pci_driver(es1968_driver); |
| @@ -1369,9 +1369,10 @@ static unsigned char saved_regs[] = { · 1368 unmodified lines | ||
| 1369 | 1369 | FM801_CODEC_CTRL, FM801_I2S_MODE, FM801_VOLUME, FM801_GEN_CTRL, |
| 1370 | 1370 | }; |
| 1371 | 1371 | |
| 1372 | −static int snd_fm801_suspend(struct pci_dev *pci, pm_message_t state) | |
| 1372 | +static int snd_fm801_suspend(struct device *dev) | |
| 1373 | 1373 | { |
| 1374 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 1374 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 1375 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 1375 | 1376 | struct fm801 *chip = card->private_data; |
| 1376 | 1377 | int i; |
| 1377 | 1378 | |
| @@ -1385,13 +1386,14 @@ static int snd_fm801_suspend(struct pci_dev *pci, pm_message_t state) · 7 unmodified lines | ||
| 1385 | 1386 | |
| 1386 | 1387 | pci_disable_device(pci); |
| 1387 | 1388 | pci_save_state(pci); |
| 1388 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 1389 | + pci_set_power_state(pci, PCI_D3hot); | |
| 1389 | 1390 | return 0; |
| 1390 | 1391 | } |
| 1391 | 1392 | |
| 1392 | −static int snd_fm801_resume(struct pci_dev *pci) | |
| 1393 | +static int snd_fm801_resume(struct device *dev) | |
| 1393 | 1394 | { |
| 1394 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 1395 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 1396 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 1395 | 1397 | struct fm801 *chip = card->private_data; |
| 1396 | 1398 | int i; |
| 1397 | 1399 | |
| @@ -1414,17 +1416,21 @@ static int snd_fm801_resume(struct pci_dev *pci) · 16 unmodified lines | ||
| 1414 | 1416 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 1415 | 1417 | return 0; |
| 1416 | 1418 | } |
| 1417 | −#endif | |
| 1419 | + | |
| 1420 | +static SIMPLE_DEV_PM_OPS(snd_fm801_pm, snd_fm801_suspend, snd_fm801_resume); | |
| 1421 | +#define SND_FM801_PM_OPS &snd_fm801_pm | |
| 1422 | +#else | |
| 1423 | +#define SND_FM801_PM_OPS NULL | |
| 1424 | +#endif /* CONFIG_PM */ | |
| 1418 | 1425 | |
| 1419 | 1426 | static struct pci_driver fm801_driver = { |
| 1420 | 1427 | .name = KBUILD_MODNAME, |
| 1421 | 1428 | .id_table = snd_fm801_ids, |
| 1422 | 1429 | .probe = snd_card_fm801_probe, |
| 1423 | 1430 | .remove = __devexit_p(snd_card_fm801_remove), |
| 1424 | −#ifdef CONFIG_PM | |
| 1425 | − .suspend = snd_fm801_suspend, | |
| 1426 | − .resume = snd_fm801_resume, | |
| 1427 | −#endif | |
| 1431 | + .driver = { | |
| 1432 | + .pm = SND_FM801_PM_OPS, | |
| 1433 | + }, | |
| 1428 | 1434 | }; |
| 1429 | 1435 | |
| 1430 | 1436 | module_pci_driver(fm801_driver); |
| @@ -53,15 +53,14 @@ config SND_HDA_INPUT_BEEP · 52 unmodified lines | ||
| 53 | 53 | driver. This interface is used to generate digital beeps. |
| 54 | 54 | |
| 55 | 55 | config SND_HDA_INPUT_BEEP_MODE |
| 56 | − int "Digital beep registration mode (0=off, 1=on, 2=mute sw on/off)" | |
| 56 | + int "Digital beep registration mode (0=off, 1=on)" | |
| 57 | 57 | depends on SND_HDA_INPUT_BEEP=y |
| 58 | 58 | default "1" |
| 59 | − range 0 2 | |
| 59 | + range 0 1 | |
| 60 | 60 | help |
| 61 | 61 | Set 0 to disable the digital beep interface for HD-audio by default. |
| 62 | 62 | Set 1 to always enable the digital beep interface for HD-audio by |
| 63 | − default. Set 2 to control the beep device registration to input | |
| 64 | − layer using a "Beep Switch" in mixer applications. | |
| 63 | + default. | |
| 65 | 64 | |
| 66 | 65 | config SND_HDA_INPUT_JACK |
| 67 | 66 | bool "Support jack plugging notification via input layer" |
| @@ -727,7 +727,7 @@ void snd_hda_pick_fixup(struct hda_codec *codec, · 726 unmodified lines | ||
| 727 | 727 | models++; |
| 728 | 728 | } |
| 729 | 729 | } |
| 730 | − if (id < 0) { | |
| 730 | + if (id < 0 && quirk) { | |
| 731 | 731 | q = snd_pci_quirk_lookup(codec->bus->pci, quirk); |
| 732 | 732 | if (q) { |
| 733 | 733 | id = q->value; |
| @@ -736,7 +736,7 @@ void snd_hda_pick_fixup(struct hda_codec *codec, · 2 unmodified lines | ||
| 736 | 736 | #endif |
| 737 | 737 | } |
| 738 | 738 | } |
| 739 | − if (id < 0) { | |
| 739 | + if (id < 0 && quirk) { | |
| 740 | 740 | for (q = quirk; q->subvendor; q++) { |
| 741 | 741 | unsigned int vendorid = |
| 742 | 742 | q->subdevice | (q->subvendor << 16); |
| @@ -162,50 +162,20 @@ static int snd_hda_do_attach(struct hda_beep *beep) · 161 unmodified lines | ||
| 162 | 162 | return 0; |
| 163 | 163 | } |
| 164 | 164 | |
| 165 | −static void snd_hda_do_register(struct work_struct *work) | |
| 166 | −{ | |
| 167 | − struct hda_beep *beep = | |
| 168 | − container_of(work, struct hda_beep, register_work); | |
| 169 | − | |
| 170 | − mutex_lock(&beep->mutex); | |
| 171 | − if (beep->enabled && !beep->dev) | |
| 172 | − snd_hda_do_attach(beep); | |
| 173 | − mutex_unlock(&beep->mutex); | |
| 174 | −} | |
| 175 | − | |
| 176 | −static void snd_hda_do_unregister(struct work_struct *work) | |
| 177 | −{ | |
| 178 | − struct hda_beep *beep = | |
| 179 | − container_of(work, struct hda_beep, unregister_work.work); | |
| 180 | − | |
| 181 | − mutex_lock(&beep->mutex); | |
| 182 | − if (!beep->enabled && beep->dev) | |
| 183 | − snd_hda_do_detach(beep); | |
| 184 | − mutex_unlock(&beep->mutex); | |
| 185 | −} | |
| 186 | − | |
| 187 | 165 | int snd_hda_enable_beep_device(struct hda_codec *codec, int enable) |
| 188 | 166 | { |
| 189 | 167 | struct hda_beep *beep = codec->beep; |
| 190 | − enable = !!enable; | |
| 191 | − if (beep == NULL) | |
| 168 | + if (!beep) | |
| 192 | 169 | return 0; |
| 170 | + enable = !!enable; | |
| 193 | 171 | if (beep->enabled != enable) { |
| 194 | 172 | beep->enabled = enable; |
| 195 | 173 | if (!enable) { |
| 174 | + cancel_work_sync(&beep->beep_work); | |
| 196 | 175 | /* turn off beep */ |
| 197 | 176 | snd_hda_codec_write(beep->codec, beep->nid, 0, |
| 198 | 177 | AC_VERB_SET_BEEP_CONTROL, 0); |
| 199 | 178 | } |
| 200 | − if (beep->mode == HDA_BEEP_MODE_SWREG) { | |
| 201 | − if (enable) { | |
| 202 | − cancel_delayed_work(&beep->unregister_work); | |
| 203 | − schedule_work(&beep->register_work); | |
| 204 | − } else { | |
| 205 | − schedule_delayed_work(&beep->unregister_work, | |
| 206 | − HZ); | |
| 207 | − } | |
| 208 | − } | |
| 209 | 179 | return 1; |
| 210 | 180 | } |
| 211 | 181 | return 0; |
| @@ -215,6 +185,7 @@ EXPORT_SYMBOL_HDA(snd_hda_enable_beep_device); · 3 unmodified lines | ||
| 215 | 185 | int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) |
| 216 | 186 | { |
| 217 | 187 | struct hda_beep *beep; |
| 188 | + int err; | |
| 218 | 189 | |
| 219 | 190 | if (!snd_hda_get_bool_hint(codec, "beep")) |
| 220 | 191 | return 0; /* disabled explicitly by hints */ |
| @@ -232,21 +203,16 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) · 11 unmodified lines | ||
| 232 | 203 | |
| 233 | 204 | beep->nid = nid; |
| 234 | 205 | beep->codec = codec; |
| 235 | − beep->mode = codec->beep_mode; | |
| 236 | 206 | codec->beep = beep; |
| 237 | 207 | |
| 238 | − INIT_WORK(&beep->register_work, &snd_hda_do_register); | |
| 239 | − INIT_DELAYED_WORK(&beep->unregister_work, &snd_hda_do_unregister); | |
| 240 | 208 | INIT_WORK(&beep->beep_work, &snd_hda_generate_beep); |
| 241 | 209 | mutex_init(&beep->mutex); |
| 242 | 210 | |
| 243 | − if (beep->mode == HDA_BEEP_MODE_ON) { | |
| 244 | − int err = snd_hda_do_attach(beep); | |
| 245 | − if (err < 0) { | |
| 246 | − kfree(beep); | |
| 247 | − codec->beep = NULL; | |
| 248 | − return err; | |
| 249 | − } | |
| 211 | + err = snd_hda_do_attach(beep); | |
| 212 | + if (err < 0) { | |
| 213 | + kfree(beep); | |
| 214 | + codec->beep = NULL; | |
| 215 | + return err; | |
| 250 | 216 | } |
| 251 | 217 | |
| 252 | 218 | return 0; |
| @@ -257,8 +223,6 @@ void snd_hda_detach_beep_device(struct hda_codec *codec) · 4 unmodified lines | ||
| 257 | 223 | { |
| 258 | 224 | struct hda_beep *beep = codec->beep; |
| 259 | 225 | if (beep) { |
| 260 | − cancel_work_sync(&beep->register_work); | |
| 261 | − cancel_delayed_work(&beep->unregister_work); | |
| 262 | 226 | if (beep->dev) |
| 263 | 227 | snd_hda_do_detach(beep); |
| 264 | 228 | codec->beep = NULL; |
| @@ -266,3 +230,31 @@ void snd_hda_detach_beep_device(struct hda_codec *codec) · 1 unmodified line | ||
| 266 | 230 | } |
| 267 | 231 | } |
| 268 | 232 | EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device); |
| 233 | + | |
| 234 | +/* get/put callbacks for beep mute mixer switches */ | |
| 235 | +int snd_hda_mixer_amp_switch_get_beep(struct snd_kcontrol *kcontrol, | |
| 236 | + struct snd_ctl_elem_value *ucontrol) | |
| 237 | +{ | |
| 238 | + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | |
| 239 | + struct hda_beep *beep = codec->beep; | |
| 240 | + if (beep) { | |
| 241 | + ucontrol->value.integer.value[0] = | |
| 242 | + ucontrol->value.integer.value[1] = | |
| 243 | + beep->enabled; | |
| 244 | + return 0; | |
| 245 | + } | |
| 246 | + return snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); | |
| 247 | +} | |
| 248 | +EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get_beep); | |
| 249 | + | |
| 250 | +int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol, | |
| 251 | + struct snd_ctl_elem_value *ucontrol) | |
| 252 | +{ | |
| 253 | + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | |
| 254 | + struct hda_beep *beep = codec->beep; | |
| 255 | + if (beep) | |
| 256 | + snd_hda_enable_beep_device(codec, | |
| 257 | + *ucontrol->value.integer.value); | |
| 258 | + return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); | |
| 259 | +} | |
| 260 | +EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put_beep); | |
| @@ -26,21 +26,16 @@ · 25 unmodified lines | ||
| 26 | 26 | |
| 27 | 27 | #define HDA_BEEP_MODE_OFF 0 |
| 28 | 28 | #define HDA_BEEP_MODE_ON 1 |
| 29 | −#define HDA_BEEP_MODE_SWREG 2 | |
| 30 | 29 | |
| 31 | 30 | /* beep information */ |
| 32 | 31 | struct hda_beep { |
| 33 | 32 | struct input_dev *dev; |
| 34 | 33 | struct hda_codec *codec; |
| 35 | − unsigned int mode; | |
| 36 | 34 | char phys[32]; |
| 37 | 35 | int tone; |
| 38 | 36 | hda_nid_t nid; |
| 39 | 37 | unsigned int enabled:1; |
| 40 | − unsigned int request_enable:1; | |
| 41 | 38 | unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */ |
| 42 | − struct work_struct register_work; /* registration work */ | |
| 43 | − struct delayed_work unregister_work; /* unregistration work */ | |
| 44 | 39 | struct work_struct beep_work; /* scheduled task for beep event */ |
| 45 | 40 | struct mutex mutex; |
| 46 | 41 | }; |
| @@ -2676,25 +2676,6 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, · 2675 unmodified lines | ||
| 2676 | 2676 | } |
| 2677 | 2677 | EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put); |
| 2678 | 2678 | |
| 2679 | −#ifdef CONFIG_SND_HDA_INPUT_BEEP | |
| 2680 | −/** | |
| 2681 | − * snd_hda_mixer_amp_switch_put_beep - Put callback for a beep AMP switch | |
| 2682 | − * | |
| 2683 | − * This function calls snd_hda_enable_beep_device(), which behaves differently | |
| 2684 | − * depending on beep_mode option. | |
| 2685 | − */ | |
| 2686 | −int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol, | |
| 2687 | − struct snd_ctl_elem_value *ucontrol) | |
| 2688 | −{ | |
| 2689 | − struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | |
| 2690 | − long *valp = ucontrol->value.integer.value; | |
| 2691 | − | |
| 2692 | − snd_hda_enable_beep_device(codec, *valp); | |
| 2693 | − return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); | |
| 2694 | −} | |
| 2695 | −EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put_beep); | |
| 2696 | −#endif /* CONFIG_SND_HDA_INPUT_BEEP */ | |
| 2697 | − | |
| 2698 | 2679 | /* |
| 2699 | 2680 | * bound volume controls |
| 2700 | 2681 | * |
| @@ -3508,23 +3489,53 @@ void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg, · 807 unmodified lines | ||
| 3508 | 3489 | } |
| 3509 | 3490 | EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all); |
| 3510 | 3491 | |
| 3492 | +/* | |
| 3493 | + * supported power states check | |
| 3494 | + */ | |
| 3495 | +static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, hda_nid_t fg, | |
| 3496 | + unsigned int power_state) | |
| 3497 | +{ | |
| 3498 | + int sup = snd_hda_param_read(codec, fg, AC_PAR_POWER_STATE); | |
| 3499 | + | |
| 3500 | + if (sup < 0) | |
| 3501 | + return false; | |
| 3502 | + if (sup & power_state) | |
| 3503 | + return true; | |
| 3504 | + else | |
| 3505 | + return false; | |
| 3506 | +} | |
| 3507 | + | |
| 3511 | 3508 | /* |
| 3512 | 3509 | * set power state of the codec |
| 3513 | 3510 | */ |
| 3514 | 3511 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, |
| 3515 | 3512 | unsigned int power_state) |
| 3516 | 3513 | { |
| 3514 | + int count; | |
| 3515 | + unsigned int state; | |
| 3516 | + | |
| 3517 | 3517 | if (codec->patch_ops.set_power_state) { |
| 3518 | 3518 | codec->patch_ops.set_power_state(codec, fg, power_state); |
| 3519 | 3519 | return; |
| 3520 | 3520 | } |
| 3521 | 3521 | |
| 3522 | 3522 | /* this delay seems necessary to avoid click noise at power-down */ |
| 3523 | − if (power_state == AC_PWRST_D3) | |
| 3524 | − msleep(100); | |
| 3525 | − snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, | |
| 3526 | − power_state); | |
| 3527 | − snd_hda_codec_set_power_to_all(codec, fg, power_state, true); | |
| 3523 | + if (power_state == AC_PWRST_D3) { | |
| 3524 | + /* transition time less than 10ms for power down */ | |
| 3525 | + bool epss = snd_hda_codec_get_supported_ps(codec, fg, AC_PWRST_EPSS); | |
| 3526 | + msleep(epss ? 10 : 100); | |
| 3527 | + } | |
| 3528 | + | |
| 3529 | + /* repeat power states setting at most 10 times*/ | |
| 3530 | + for (count = 0; count < 10; count++) { | |
| 3531 | + snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, | |
| 3532 | + power_state); | |
| 3533 | + snd_hda_codec_set_power_to_all(codec, fg, power_state, true); | |
| 3534 | + state = snd_hda_codec_read(codec, fg, 0, | |
| 3535 | + AC_VERB_GET_POWER_STATE, 0); | |
| 3536 | + if (!(state & AC_PWRST_ERROR)) | |
| 3537 | + break; | |
| 3538 | + } | |
| 3528 | 3539 | } |
| 3529 | 3540 | |
| 3530 | 3541 | #ifdef CONFIG_SND_HDA_HWDEP |
| @@ -3545,7 +3556,7 @@ static inline void hda_exec_init_verbs(struct hda_codec *codec) {} · 14 unmodified lines | ||
| 3545 | 3556 | static void hda_call_codec_suspend(struct hda_codec *codec) |
| 3546 | 3557 | { |
| 3547 | 3558 | if (codec->patch_ops.suspend) |
| 3548 | − codec->patch_ops.suspend(codec, PMSG_SUSPEND); | |
| 3559 | + codec->patch_ops.suspend(codec); | |
| 3549 | 3560 | hda_cleanup_all_streams(codec); |
| 3550 | 3561 | hda_set_power_state(codec, |
| 3551 | 3562 | codec->afg ? codec->afg : codec->mfg, |
| @@ -4418,6 +4429,13 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down) · 866 unmodified lines | ||
| 4418 | 4429 | cancel_delayed_work_sync(&codec->power_work); |
| 4419 | 4430 | |
| 4420 | 4431 | spin_lock(&codec->power_lock); |
| 4432 | + /* If the power down delayed work was cancelled above before starting, | |
| 4433 | + * then there is no need to go through power up here. | |
| 4434 | + */ | |
| 4435 | + if (codec->power_on) { | |
| 4436 | + spin_unlock(&codec->power_lock); | |
| 4437 | + return; | |
| 4438 | + } | |
| 4421 | 4439 | trace_hda_power_up(codec); |
| 4422 | 4440 | snd_hda_update_power_acct(codec); |
| 4423 | 4441 | codec->power_on = 1; |
| @@ -323,6 +323,9 @@ enum { · 322 unmodified lines | ||
| 323 | 323 | #define AC_PWRST_D1 0x01 |
| 324 | 324 | #define AC_PWRST_D2 0x02 |
| 325 | 325 | #define AC_PWRST_D3 0x03 |
| 326 | +#define AC_PWRST_ERROR (1<<8) | |
| 327 | +#define AC_PWRST_CLK_STOP_OK (1<<9) | |
| 328 | +#define AC_PWRST_SETTING_RESET (1<<10) | |
| 326 | 329 | |
| 327 | 330 | /* Processing capabilies */ |
| 328 | 331 | #define AC_PCAP_BENIGN (1<<0) |
| @@ -703,7 +706,7 @@ struct hda_codec_ops { · 374 unmodified lines | ||
| 703 | 706 | void (*set_power_state)(struct hda_codec *codec, hda_nid_t fg, |
| 704 | 707 | unsigned int power_state); |
| 705 | 708 | #ifdef CONFIG_PM |
| 706 | − int (*suspend)(struct hda_codec *codec, pm_message_t state); | |
| 709 | + int (*suspend)(struct hda_codec *codec); | |
| 707 | 710 | int (*resume)(struct hda_codec *codec); |
| 708 | 711 | #endif |
| 709 | 712 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
| @@ -72,7 +72,7 @@ static int enable_msi = -1; · 71 unmodified lines | ||
| 72 | 72 | static char *patch[SNDRV_CARDS]; |
| 73 | 73 | #endif |
| 74 | 74 | #ifdef CONFIG_SND_HDA_INPUT_BEEP |
| 75 | −static int beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = | |
| 75 | +static bool beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = | |
| 76 | 76 | CONFIG_SND_HDA_INPUT_BEEP_MODE}; |
| 77 | 77 | #endif |
| 78 | 78 | |
| @@ -103,9 +103,9 @@ module_param_array(patch, charp, NULL, 0444); · 24 unmodified lines | ||
| 103 | 103 | MODULE_PARM_DESC(patch, "Patch file for Intel HD audio interface."); |
| 104 | 104 | #endif |
| 105 | 105 | #ifdef CONFIG_SND_HDA_INPUT_BEEP |
| 106 | −module_param_array(beep_mode, int, NULL, 0444); | |
| 106 | +module_param_array(beep_mode, bool, NULL, 0444); | |
| 107 | 107 | MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode " |
| 108 | − "(0=off, 1=on, 2=mute switch on/off) (default=1)."); | |
| 108 | + "(0=off, 1=on) (default=1)."); | |
| 109 | 109 | #endif |
| 110 | 110 | |
| 111 | 111 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
| @@ -151,6 +151,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," · 39 unmodified lines | ||
| 151 | 151 | "{Intel, CPT}," |
| 152 | 152 | "{Intel, PPT}," |
| 153 | 153 | "{Intel, LPT}," |
| 154 | + "{Intel, HPT}," | |
| 154 | 155 | "{Intel, PBG}," |
| 155 | 156 | "{Intel, SCH}," |
| 156 | 157 | "{ATI, SB450}," |
| @@ -535,6 +536,7 @@ enum { · 378 unmodified lines | ||
| 535 | 536 | #define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */ |
| 536 | 537 | #define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */ |
| 537 | 538 | #define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */ |
| 539 | +#define AZX_DCAPS_POSFIX_COMBO (1 << 24) /* Use COMBO as default */ | |
| 538 | 540 | |
| 539 | 541 | /* quirks for ATI SB / AMD Hudson */ |
| 540 | 542 | #define AZX_DCAPS_PRESET_ATI_SB \ |
| @@ -2403,9 +2405,10 @@ static void azx_power_notify(struct hda_bus *bus) · 1862 unmodified lines | ||
| 2403 | 2405 | * power management |
| 2404 | 2406 | */ |
| 2405 | 2407 | |
| 2406 | −static int azx_suspend(struct pci_dev *pci, pm_message_t state) | |
| 2408 | +static int azx_suspend(struct device *dev) | |
| 2407 | 2409 | { |
| 2408 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 2410 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 2411 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 2409 | 2412 | struct azx *chip = card->private_data; |
| 2410 | 2413 | struct azx_pcm *p; |
| 2411 | 2414 | |
| @@ -2424,13 +2427,14 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) · 12 unmodified lines | ||
| 2424 | 2427 | pci_disable_msi(chip->pci); |
| 2425 | 2428 | pci_disable_device(pci); |
| 2426 | 2429 | pci_save_state(pci); |
| 2427 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 2430 | + pci_set_power_state(pci, PCI_D3hot); | |
| 2428 | 2431 | return 0; |
| 2429 | 2432 | } |
| 2430 | 2433 | |
| 2431 | −static int azx_resume(struct pci_dev *pci) | |
| 2434 | +static int azx_resume(struct device *dev) | |
| 2432 | 2435 | { |
| 2433 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 2436 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 2437 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 2434 | 2438 | struct azx *chip = card->private_data; |
| 2435 | 2439 | |
| 2436 | 2440 | pci_set_power_state(pci, PCI_D0); |
| @@ -2455,6 +2459,12 @@ static int azx_resume(struct pci_dev *pci) · 18 unmodified lines | ||
| 2455 | 2459 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 2456 | 2460 | return 0; |
| 2457 | 2461 | } |
| 2462 | +static SIMPLE_DEV_PM_OPS(azx_pm, azx_suspend, azx_resume); | |
| 2463 | +#define AZX_PM_OPS &azx_pm | |
| 2464 | +#else | |
| 2465 | +#define azx_suspend(dev) | |
| 2466 | +#define azx_resume(dev) | |
| 2467 | +#define AZX_PM_OPS NULL | |
| 2458 | 2468 | #endif /* CONFIG_PM */ |
| 2459 | 2469 | |
| 2460 | 2470 | |
| @@ -2521,13 +2531,13 @@ static void azx_vs_set_state(struct pci_dev *pci, · 60 unmodified lines | ||
| 2521 | 2531 | disabled ? "Disabling" : "Enabling", |
| 2522 | 2532 | pci_name(chip->pci)); |
| 2523 | 2533 | if (disabled) { |
| 2524 | − azx_suspend(pci, PMSG_FREEZE); | |
| 2534 | + azx_suspend(&pci->dev); | |
| 2525 | 2535 | chip->disabled = true; |
| 2526 | 2536 | snd_hda_lock_devices(chip->bus); |
| 2527 | 2537 | } else { |
| 2528 | 2538 | snd_hda_unlock_devices(chip->bus); |
| 2529 | 2539 | chip->disabled = false; |
| 2530 | − azx_resume(pci); | |
| 2540 | + azx_resume(&pci->dev); | |
| 2531 | 2541 | } |
| 2532 | 2542 | } |
| 2533 | 2543 | } |
| @@ -2731,6 +2741,10 @@ static int __devinit check_position_fix(struct azx *chip, int fix) · 197 unmodified lines | ||
| 2731 | 2741 | snd_printd(SFX "Using LPIB position fix\n"); |
| 2732 | 2742 | return POS_FIX_LPIB; |
| 2733 | 2743 | } |
| 2744 | + if (chip->driver_caps & AZX_DCAPS_POSFIX_COMBO) { | |
| 2745 | + snd_printd(SFX "Using COMBO position fix\n"); | |
| 2746 | + return POS_FIX_COMBO; | |
| 2747 | + } | |
| 2734 | 2748 | return POS_FIX_AUTO; |
| 2735 | 2749 | } |
| 2736 | 2750 | |
| @@ -3243,7 +3257,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { · 506 unmodified lines | ||
| 3243 | 3257 | /* CPT */ |
| 3244 | 3258 | { PCI_DEVICE(0x8086, 0x1c20), |
| 3245 | 3259 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | |
| 3246 | − AZX_DCAPS_BUFSIZE }, | |
| 3260 | + AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, | |
| 3247 | 3261 | /* PBG */ |
| 3248 | 3262 | { PCI_DEVICE(0x8086, 0x1d20), |
| 3249 | 3263 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | |
| @@ -3251,11 +3265,15 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { · 1 unmodified line | ||
| 3251 | 3265 | /* Panther Point */ |
| 3252 | 3266 | { PCI_DEVICE(0x8086, 0x1e20), |
| 3253 | 3267 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | |
| 3254 | − AZX_DCAPS_BUFSIZE}, | |
| 3268 | + AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, | |
| 3255 | 3269 | /* Lynx Point */ |
| 3256 | 3270 | { PCI_DEVICE(0x8086, 0x8c20), |
| 3257 | 3271 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | |
| 3258 | − AZX_DCAPS_BUFSIZE}, | |
| 3272 | + AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, | |
| 3273 | + /* Haswell */ | |
| 3274 | + { PCI_DEVICE(0x8086, 0x0c0c), | |
| 3275 | + .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | | |
| 3276 | + AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, | |
| 3259 | 3277 | /* SCH */ |
| 3260 | 3278 | { PCI_DEVICE(0x8086, 0x811b), |
| 3261 | 3279 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | |
| @@ -3341,6 +3359,10 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { · 79 unmodified lines | ||
| 3341 | 3359 | /* VIA VT8251/VT8237A */ |
| 3342 | 3360 | { PCI_DEVICE(0x1106, 0x3288), |
| 3343 | 3361 | .driver_data = AZX_DRIVER_VIA | AZX_DCAPS_POSFIX_VIA }, |
| 3362 | + /* VIA GFX VT7122/VX900 */ | |
| 3363 | + { PCI_DEVICE(0x1106, 0x9170), .driver_data = AZX_DRIVER_GENERIC }, | |
| 3364 | + /* VIA GFX VT6122/VX11 */ | |
| 3365 | + { PCI_DEVICE(0x1106, 0x9140), .driver_data = AZX_DRIVER_GENERIC }, | |
| 3344 | 3366 | /* SIS966 */ |
| 3345 | 3367 | { PCI_DEVICE(0x1039, 0x7502), .driver_data = AZX_DRIVER_SIS }, |
| 3346 | 3368 | /* ULI M5461 */ |
| @@ -3398,10 +3420,9 @@ static struct pci_driver azx_driver = { · 51 unmodified lines | ||
| 3398 | 3420 | .id_table = azx_ids, |
| 3399 | 3421 | .probe = azx_probe, |
| 3400 | 3422 | .remove = __devexit_p(azx_remove), |
| 3401 | −#ifdef CONFIG_PM | |
| 3402 | − .suspend = azx_suspend, | |
| 3403 | − .resume = azx_resume, | |
| 3404 | −#endif | |
| 3423 | + .driver = { | |
| 3424 | + .pm = AZX_PM_OPS, | |
| 3425 | + }, | |
| 3405 | 3426 | }; |
| 3406 | 3427 | |
| 3407 | 3428 | module_pci_driver(azx_driver); |
| @@ -127,10 +127,15 @@ void snd_hda_jack_tbl_clear(struct hda_codec *codec) · 126 unmodified lines | ||
| 127 | 127 | static void jack_detect_update(struct hda_codec *codec, |
| 128 | 128 | struct hda_jack_tbl *jack) |
| 129 | 129 | { |
| 130 | − if (jack->jack_dirty || !jack->jack_detect) { | |
| 130 | + if (!jack->jack_dirty) | |
| 131 | + return; | |
| 132 | + | |
| 133 | + if (jack->phantom_jack) | |
| 134 | + jack->pin_sense = AC_PINSENSE_PRESENCE; | |
| 135 | + else | |
| 131 | 136 | jack->pin_sense = read_pin_sense(codec, jack->nid); |
| 132 | − jack->jack_dirty = 0; | |
| 133 | − } | |
| 137 | + | |
| 138 | + jack->jack_dirty = 0; | |
| 134 | 139 | } |
| 135 | 140 | |
| 136 | 141 | /** |
| @@ -264,8 +269,8 @@ static void hda_free_jack_priv(struct snd_jack *jack) · 127 unmodified lines | ||
| 264 | 269 | * This assigns a jack-detection kctl to the given pin. The kcontrol |
| 265 | 270 | * will have the given name and index. |
| 266 | 271 | */ |
| 267 | −int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | |
| 268 | − const char *name, int idx) | |
| 272 | +static int __snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | |
| 273 | + const char *name, int idx, bool phantom_jack) | |
| 269 | 274 | { |
| 270 | 275 | struct hda_jack_tbl *jack; |
| 271 | 276 | struct snd_kcontrol *kctl; |
| @@ -283,47 +288,81 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, · 11 unmodified lines | ||
| 283 | 288 | if (err < 0) |
| 284 | 289 | return err; |
| 285 | 290 | jack->kctl = kctl; |
| 291 | + jack->phantom_jack = !!phantom_jack; | |
| 292 | + | |
| 286 | 293 | state = snd_hda_jack_detect(codec, nid); |
| 287 | 294 | snd_kctl_jack_report(codec->bus->card, kctl, state); |
| 288 | 295 | #ifdef CONFIG_SND_HDA_INPUT_JACK |
| 289 | − jack->type = get_input_jack_type(codec, nid); | |
| 290 | − err = snd_jack_new(codec->bus->card, name, jack->type, &jack->jack); | |
| 291 | − if (err < 0) | |
| 292 | − return err; | |
| 293 | − jack->jack->private_data = jack; | |
| 294 | − jack->jack->private_free = hda_free_jack_priv; | |
| 295 | − snd_jack_report(jack->jack, state ? jack->type : 0); | |
| 296 | + if (!phantom_jack) { | |
| 297 | + jack->type = get_input_jack_type(codec, nid); | |
| 298 | + err = snd_jack_new(codec->bus->card, name, jack->type, | |
| 299 | + &jack->jack); | |
| 300 | + if (err < 0) | |
| 301 | + return err; | |
| 302 | + jack->jack->private_data = jack; | |
| 303 | + jack->jack->private_free = hda_free_jack_priv; | |
| 304 | + snd_jack_report(jack->jack, state ? jack->type : 0); | |
| 305 | + } | |
| 296 | 306 | #endif |
| 297 | 307 | return 0; |
| 298 | 308 | } |
| 309 | + | |
| 310 | +int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | |
| 311 | + const char *name, int idx) | |
| 312 | +{ | |
| 313 | + return __snd_hda_jack_add_kctl(codec, nid, name, idx, false); | |
| 314 | +} | |
| 299 | 315 | EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl); |
| 300 | 316 | |
| 317 | +/* get the unique index number for the given kctl name */ | |
| 318 | +static int get_unique_index(struct hda_codec *codec, const char *name, int idx) | |
| 319 | +{ | |
| 320 | + struct hda_jack_tbl *jack; | |
| 321 | + int i, len = strlen(name); | |
| 322 | + again: | |
| 323 | + jack = codec->jacktbl.list; | |
| 324 | + for (i = 0; i < codec->jacktbl.used; i++, jack++) { | |
| 325 | + /* jack->kctl.id contains "XXX Jack" name string with index */ | |
| 326 | + if (jack->kctl && | |
| 327 | + !strncmp(name, jack->kctl->id.name, len) && | |
| 328 | + !strcmp(" Jack", jack->kctl->id.name + len) && | |
| 329 | + jack->kctl->id.index == idx) { | |
| 330 | + idx++; | |
| 331 | + goto again; | |
| 332 | + } | |
| 333 | + } | |
| 334 | + return idx; | |
| 335 | +} | |
| 336 | + | |
| 301 | 337 | static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, |
| 302 | − const struct auto_pin_cfg *cfg, | |
| 303 | − char *lastname, int *lastidx) | |
| 338 | + const struct auto_pin_cfg *cfg) | |
| 304 | 339 | { |
| 305 | 340 | unsigned int def_conf, conn; |
| 306 | 341 | char name[44]; |
| 307 | 342 | int idx, err; |
| 343 | + bool phantom_jack; | |
| 308 | 344 | |
| 309 | 345 | if (!nid) |
| 310 | 346 | return 0; |
| 311 | − if (!is_jack_detectable(codec, nid)) | |
| 312 | − return 0; | |
| 313 | 347 | def_conf = snd_hda_codec_get_pincfg(codec, nid); |
| 314 | 348 | conn = get_defcfg_connect(def_conf); |
| 315 | − if (conn != AC_JACK_PORT_COMPLEX) | |
| 349 | + if (conn == AC_JACK_PORT_NONE) | |
| 316 | 350 | return 0; |
| 351 | + phantom_jack = (conn != AC_JACK_PORT_COMPLEX) || | |
| 352 | + !is_jack_detectable(codec, nid); | |
| 317 | 353 | |
| 318 | 354 | snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx); |
| 319 | − if (!strcmp(name, lastname) && idx == *lastidx) | |
| 320 | − idx++; | |
| 321 | − strncpy(lastname, name, 44); | |
| 322 | − *lastidx = idx; | |
| 323 | − err = snd_hda_jack_add_kctl(codec, nid, name, idx); | |
| 355 | + if (phantom_jack) | |
| 356 | + /* Example final name: "Internal Mic Phantom Jack" */ | |
| 357 | + strncat(name, " Phantom", sizeof(name) - strlen(name) - 1); | |
| 358 | + idx = get_unique_index(codec, name, idx); | |
| 359 | + err = __snd_hda_jack_add_kctl(codec, nid, name, idx, phantom_jack); | |
| 324 | 360 | if (err < 0) |
| 325 | 361 | return err; |
| 326 | − return snd_hda_jack_detect_enable(codec, nid, 0); | |
| 362 | + | |
| 363 | + if (!phantom_jack) | |
| 364 | + return snd_hda_jack_detect_enable(codec, nid, 0); | |
| 365 | + return 0; | |
| 327 | 366 | } |
| 328 | 367 | |
| 329 | 368 | /** |
| @@ -333,42 +372,41 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec, · 3 unmodified lines | ||
| 333 | 372 | const struct auto_pin_cfg *cfg) |
| 334 | 373 | { |
| 335 | 374 | const hda_nid_t *p; |
| 336 | − int i, err, lastidx = 0; | |
| 337 | − char lastname[44] = ""; | |
| 375 | + int i, err; | |
| 338 | 376 | |
| 339 | 377 | for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) { |
| 340 | − err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); | |
| 378 | + err = add_jack_kctl(codec, *p, cfg); | |
| 341 | 379 | if (err < 0) |
| 342 | 380 | return err; |
| 343 | 381 | } |
| 344 | 382 | for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) { |
| 345 | 383 | if (*p == *cfg->line_out_pins) /* might be duplicated */ |
| 346 | 384 | break; |
| 347 | − err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); | |
| 385 | + err = add_jack_kctl(codec, *p, cfg); | |
| 348 | 386 | if (err < 0) |
| 349 | 387 | return err; |
| 350 | 388 | } |
| 351 | 389 | for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) { |
| 352 | 390 | if (*p == *cfg->line_out_pins) /* might be duplicated */ |
| 353 | 391 | break; |
| 354 | − err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); | |
| 392 | + err = add_jack_kctl(codec, *p, cfg); | |
| 355 | 393 | if (err < 0) |
| 356 | 394 | return err; |
| 357 | 395 | } |
| 358 | 396 | for (i = 0; i < cfg->num_inputs; i++) { |
| 359 | − err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg, lastname, &lastidx); | |
| 397 | + err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg); | |
| 360 | 398 | if (err < 0) |
| 361 | 399 | return err; |
| 362 | 400 | } |
| 363 | 401 | for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) { |
| 364 | − err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); | |
| 402 | + err = add_jack_kctl(codec, *p, cfg); | |
| 365 | 403 | if (err < 0) |
| 366 | 404 | return err; |
| 367 | 405 | } |
| 368 | − err = add_jack_kctl(codec, cfg->dig_in_pin, cfg, lastname, &lastidx); | |
| 406 | + err = add_jack_kctl(codec, cfg->dig_in_pin, cfg); | |
| 369 | 407 | if (err < 0) |
| 370 | 408 | return err; |
| 371 | − err = add_jack_kctl(codec, cfg->mono_out_pin, cfg, lastname, &lastidx); | |
| 409 | + err = add_jack_kctl(codec, cfg->mono_out_pin, cfg); | |
| 372 | 410 | if (err < 0) |
| 373 | 411 | return err; |
| 374 | 412 | return 0; |
| @@ -23,6 +23,7 @@ struct hda_jack_tbl { · 22 unmodified lines | ||
| 23 | 23 | unsigned int pin_sense; /* cached pin-sense value */ |
| 24 | 24 | unsigned int jack_detect:1; /* capable of jack-detection? */ |
| 25 | 25 | unsigned int jack_dirty:1; /* needs to update? */ |
| 26 | + unsigned int phantom_jack:1; /* a fixed, always present port? */ | |
| 26 | 27 | struct snd_kcontrol *kctl; /* assigned kctl for jack-detection */ |
| 27 | 28 | #ifdef CONFIG_SND_HDA_INPUT_JACK |
| 28 | 29 | int type; |
| @@ -89,7 +89,7 @@ · 88 unmodified lines | ||
| 89 | 89 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ |
| 90 | 90 | .subdevice = HDA_SUBDEV_AMP_FLAG, \ |
| 91 | 91 | .info = snd_hda_mixer_amp_switch_info, \ |
| 92 | − .get = snd_hda_mixer_amp_switch_get, \ | |
| 92 | + .get = snd_hda_mixer_amp_switch_get_beep, \ | |
| 93 | 93 | .put = snd_hda_mixer_amp_switch_put_beep, \ |
| 94 | 94 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } |
| 95 | 95 | #else |
| @@ -121,6 +121,8 @@ int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, · 25 unmodified lines | ||
| 121 | 121 | int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, |
| 122 | 122 | struct snd_ctl_elem_value *ucontrol); |
| 123 | 123 | #ifdef CONFIG_SND_HDA_INPUT_BEEP |
| 124 | +int snd_hda_mixer_amp_switch_get_beep(struct snd_kcontrol *kcontrol, | |
| 125 | + struct snd_ctl_elem_value *ucontrol); | |
| 124 | 126 | int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol, |
| 125 | 127 | struct snd_ctl_elem_value *ucontrol); |
| 126 | 128 | #endif |
| @@ -426,10 +426,10 @@ static void print_digital_conv(struct snd_info_buffer *buffer, · 425 unmodified lines | ||
| 426 | 426 | |
| 427 | 427 | static const char *get_pwr_state(u32 state) |
| 428 | 428 | { |
| 429 | − static const char * const buf[4] = { | |
| 430 | − "D0", "D1", "D2", "D3" | |
| 429 | + static const char * const buf[] = { | |
| 430 | + "D0", "D1", "D2", "D3", "D3cold" | |
| 431 | 431 | }; |
| 432 | − if (state < 4) | |
| 432 | + if (state < ARRAY_SIZE(buf)) | |
| 433 | 433 | return buf[state]; |
| 434 | 434 | return "UNKNOWN"; |
| 435 | 435 | } |
| @@ -451,14 +451,21 @@ static void print_power_state(struct snd_info_buffer *buffer, · 15 unmodified lines | ||
| 451 | 451 | int sup = snd_hda_param_read(codec, nid, AC_PAR_POWER_STATE); |
| 452 | 452 | int pwr = snd_hda_codec_read(codec, nid, 0, |
| 453 | 453 | AC_VERB_GET_POWER_STATE, 0); |
| 454 | − if (sup) | |
| 454 | + if (sup != -1) | |
| 455 | 455 | snd_iprintf(buffer, " Power states: %s\n", |
| 456 | 456 | bits_names(sup, names, ARRAY_SIZE(names))); |
| 457 | 457 | |
| 458 | − snd_iprintf(buffer, " Power: setting=%s, actual=%s\n", | |
| 458 | + snd_iprintf(buffer, " Power: setting=%s, actual=%s", | |
| 459 | 459 | get_pwr_state(pwr & AC_PWRST_SETTING), |
| 460 | 460 | get_pwr_state((pwr & AC_PWRST_ACTUAL) >> |
| 461 | 461 | AC_PWRST_ACTUAL_SHIFT)); |
| 462 | + if (pwr & AC_PWRST_ERROR) | |
| 463 | + snd_iprintf(buffer, ", Error"); | |
| 464 | + if (pwr & AC_PWRST_CLK_STOP_OK) | |
| 465 | + snd_iprintf(buffer, ", Clock-stop-OK"); | |
| 466 | + if (pwr & AC_PWRST_SETTING_RESET) | |
| 467 | + snd_iprintf(buffer, ", Setting-reset"); | |
| 468 | + snd_iprintf(buffer, "\n"); | |
| 462 | 469 | } |
| 463 | 470 | |
| 464 | 471 | static void print_unsol_cap(struct snd_info_buffer *buffer, |
| @@ -642,7 +642,7 @@ static void ad198x_free(struct hda_codec *codec) · 641 unmodified lines | ||
| 642 | 642 | } |
| 643 | 643 | |
| 644 | 644 | #ifdef CONFIG_PM |
| 645 | −static int ad198x_suspend(struct hda_codec *codec, pm_message_t state) | |
| 645 | +static int ad198x_suspend(struct hda_codec *codec) | |
| 646 | 646 | { |
| 647 | 647 | ad198x_shutup(codec); |
| 648 | 648 | return 0; |
| @@ -1892,7 +1892,7 @@ static int cs421x_parse_auto_config(struct hda_codec *codec) · 1891 unmodified lines | ||
| 1892 | 1892 | Manage PDREF, when transitioning to D3hot |
| 1893 | 1893 | (DAC,ADC) -> D3, PDREF=1, AFG->D3 |
| 1894 | 1894 | */ |
| 1895 | −static int cs421x_suspend(struct hda_codec *codec, pm_message_t state) | |
| 1895 | +static int cs421x_suspend(struct hda_codec *codec) | |
| 1896 | 1896 | { |
| 1897 | 1897 | struct cs_spec *spec = codec->spec; |
| 1898 | 1898 | unsigned int coef; |
| @@ -554,7 +554,7 @@ static int conexant_build_controls(struct hda_codec *codec) · 553 unmodified lines | ||
| 554 | 554 | } |
| 555 | 555 | |
| 556 | 556 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
| 557 | −static int conexant_suspend(struct hda_codec *codec, pm_message_t state) | |
| 557 | +static int conexant_suspend(struct hda_codec *codec) | |
| 558 | 558 | { |
| 559 | 559 | snd_hda_shutup_pins(codec); |
| 560 | 560 | return 0; |
| @@ -85,7 +85,7 @@ struct hdmi_spec { · 84 unmodified lines | ||
| 85 | 85 | * Non-generic ATI/NVIDIA specific |
| 86 | 86 | */ |
| 87 | 87 | struct hda_multi_out multiout; |
| 88 | − const struct hda_pcm_stream *pcm_playback; | |
| 88 | + struct hda_pcm_stream pcm_playback; | |
| 89 | 89 | }; |
| 90 | 90 | |
| 91 | 91 | |
| @@ -787,7 +787,7 @@ static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) · 695 unmodified lines | ||
| 787 | 787 | int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); |
| 788 | 788 | |
| 789 | 789 | printk(KERN_INFO |
| 790 | − "HDMI CP event: CODEC=%d PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", | |
| 790 | + "HDMI CP event: CODEC=%d TAG=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", | |
| 791 | 791 | codec->addr, |
| 792 | 792 | tag, |
| 793 | 793 | subtag, |
| @@ -876,7 +876,6 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, · 82 unmodified lines | ||
| 876 | 876 | struct hdmi_spec_per_pin *per_pin; |
| 877 | 877 | struct hdmi_eld *eld; |
| 878 | 878 | struct hdmi_spec_per_cvt *per_cvt = NULL; |
| 879 | − int pinctl; | |
| 880 | 879 | |
| 881 | 880 | /* Validate hinfo */ |
| 882 | 881 | pin_idx = hinfo_to_pin_index(spec, hinfo); |
| @@ -912,11 +911,6 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, · 29 unmodified lines | ||
| 912 | 911 | snd_hda_codec_write(codec, per_pin->pin_nid, 0, |
| 913 | 912 | AC_VERB_SET_CONNECT_SEL, |
| 914 | 913 | mux_idx); |
| 915 | − pinctl = snd_hda_codec_read(codec, per_pin->pin_nid, 0, | |
| 916 | − AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | |
| 917 | − snd_hda_codec_write(codec, per_pin->pin_nid, 0, | |
| 918 | − AC_VERB_SET_PIN_WIDGET_CONTROL, | |
| 919 | − pinctl | PIN_OUT); | |
| 920 | 914 | snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid); |
| 921 | 915 | |
| 922 | 916 | /* Initially set the converter's capabilities */ |
| @@ -1153,11 +1147,17 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, · 230 unmodified lines | ||
| 1153 | 1147 | struct hdmi_spec *spec = codec->spec; |
| 1154 | 1148 | int pin_idx = hinfo_to_pin_index(spec, hinfo); |
| 1155 | 1149 | hda_nid_t pin_nid = spec->pins[pin_idx].pin_nid; |
| 1150 | + int pinctl; | |
| 1156 | 1151 | |
| 1157 | 1152 | hdmi_set_channel_count(codec, cvt_nid, substream->runtime->channels); |
| 1158 | 1153 | |
| 1159 | 1154 | hdmi_setup_audio_infoframe(codec, pin_idx, substream); |
| 1160 | 1155 | |
| 1156 | + pinctl = snd_hda_codec_read(codec, pin_nid, 0, | |
| 1157 | + AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | |
| 1158 | + snd_hda_codec_write(codec, pin_nid, 0, | |
| 1159 | + AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl | PIN_OUT); | |
| 1160 | + | |
| 1161 | 1161 | return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); |
| 1162 | 1162 | } |
| 1163 | 1163 | |
| @@ -1277,23 +1277,34 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) · 113 unmodified lines | ||
| 1277 | 1277 | return 0; |
| 1278 | 1278 | } |
| 1279 | 1279 | |
| 1280 | −static int generic_hdmi_init(struct hda_codec *codec) | |
| 1280 | +static int generic_hdmi_init_per_pins(struct hda_codec *codec) | |
| 1281 | 1281 | { |
| 1282 | 1282 | struct hdmi_spec *spec = codec->spec; |
| 1283 | 1283 | int pin_idx; |
| 1284 | 1284 | |
| 1285 | 1285 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
| 1286 | 1286 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; |
| 1287 | − hda_nid_t pin_nid = per_pin->pin_nid; | |
| 1288 | 1287 | struct hdmi_eld *eld = &per_pin->sink_eld; |
| 1289 | 1288 | |
| 1290 | − hdmi_init_pin(codec, pin_nid); | |
| 1291 | − snd_hda_jack_detect_enable(codec, pin_nid, pin_nid); | |
| 1292 | − | |
| 1293 | 1289 | per_pin->codec = codec; |
| 1294 | 1290 | INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld); |
| 1295 | 1291 | snd_hda_eld_proc_new(codec, eld, pin_idx); |
| 1296 | 1292 | } |
| 1293 | + return 0; | |
| 1294 | +} | |
| 1295 | + | |
| 1296 | +static int generic_hdmi_init(struct hda_codec *codec) | |
| 1297 | +{ | |
| 1298 | + struct hdmi_spec *spec = codec->spec; | |
| 1299 | + int pin_idx; | |
| 1300 | + | |
| 1301 | + for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | |
| 1302 | + struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | |
| 1303 | + hda_nid_t pin_nid = per_pin->pin_nid; | |
| 1304 | + | |
| 1305 | + hdmi_init_pin(codec, pin_nid); | |
| 1306 | + snd_hda_jack_detect_enable(codec, pin_nid, pin_nid); | |
| 1307 | + } | |
| 1297 | 1308 | snd_hda_jack_report_sync(codec); |
| 1298 | 1309 | return 0; |
| 1299 | 1310 | } |
| @@ -1338,6 +1349,7 @@ static int patch_generic_hdmi(struct hda_codec *codec) · 38 unmodified lines | ||
| 1338 | 1349 | return -EINVAL; |
| 1339 | 1350 | } |
| 1340 | 1351 | codec->patch_ops = generic_hdmi_patch_ops; |
| 1352 | + generic_hdmi_init_per_pins(codec); | |
| 1341 | 1353 | |
| 1342 | 1354 | init_channel_allocations(); |
| 1343 | 1355 | |
| @@ -1352,45 +1364,65 @@ static int simple_playback_build_pcms(struct hda_codec *codec) · 8 unmodified lines | ||
| 1352 | 1364 | { |
| 1353 | 1365 | struct hdmi_spec *spec = codec->spec; |
| 1354 | 1366 | struct hda_pcm *info = spec->pcm_rec; |
| 1355 | − int i; | |
| 1367 | + unsigned int chans; | |
| 1368 | + struct hda_pcm_stream *pstr; | |
| 1356 | 1369 | |
| 1357 | − codec->num_pcms = spec->num_cvts; | |
| 1370 | + codec->num_pcms = 1; | |
| 1358 | 1371 | codec->pcm_info = info; |
| 1359 | 1372 | |
| 1360 | − for (i = 0; i < codec->num_pcms; i++, info++) { | |
| 1361 | − unsigned int chans; | |
| 1362 | − struct hda_pcm_stream *pstr; | |
| 1363 | − | |
| 1364 | − chans = get_wcaps(codec, spec->cvts[i].cvt_nid); | |
| 1365 | − chans = get_wcaps_channels(chans); | |
| 1373 | + chans = get_wcaps(codec, spec->cvts[0].cvt_nid); | |
| 1374 | + chans = get_wcaps_channels(chans); | |
| 1366 | 1375 | |
| 1367 | − info->name = get_hdmi_pcm_name(i); | |
| 1368 | − info->pcm_type = HDA_PCM_TYPE_HDMI; | |
| 1369 | − pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; | |
| 1370 | − snd_BUG_ON(!spec->pcm_playback); | |
| 1371 | − *pstr = *spec->pcm_playback; | |
| 1372 | − pstr->nid = spec->cvts[i].cvt_nid; | |
| 1373 | − if (pstr->channels_max <= 2 && chans && chans <= 16) | |
| 1374 | − pstr->channels_max = chans; | |
| 1375 | − } | |
| 1376 | + info->name = get_hdmi_pcm_name(0); | |
| 1377 | + info->pcm_type = HDA_PCM_TYPE_HDMI; | |
| 1378 | + pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; | |
| 1379 | + *pstr = spec->pcm_playback; | |
| 1380 | + pstr->nid = spec->cvts[0].cvt_nid; | |
| 1381 | + if (pstr->channels_max <= 2 && chans && chans <= 16) | |
| 1382 | + pstr->channels_max = chans; | |
| 1376 | 1383 | |
| 1377 | 1384 | return 0; |
| 1378 | 1385 | } |
| 1379 | 1386 | |
| 1387 | +/* unsolicited event for jack sensing */ | |
| 1388 | +static void simple_hdmi_unsol_event(struct hda_codec *codec, | |
| 1389 | + unsigned int res) | |
| 1390 | +{ | |
| 1391 | + snd_hda_jack_set_dirty_all(codec); | |
| 1392 | + snd_hda_jack_report_sync(codec); | |
| 1393 | +} | |
| 1394 | + | |
| 1395 | +/* generic_hdmi_build_jack can be used for simple_hdmi, too, | |
| 1396 | + * as long as spec->pins[] is set correctly | |
| 1397 | + */ | |
| 1398 | +#define simple_hdmi_build_jack generic_hdmi_build_jack | |
| 1399 | + | |
| 1380 | 1400 | static int simple_playback_build_controls(struct hda_codec *codec) |
| 1381 | 1401 | { |
| 1382 | 1402 | struct hdmi_spec *spec = codec->spec; |
| 1383 | 1403 | int err; |
| 1384 | − int i; | |
| 1385 | 1404 | |
| 1386 | − for (i = 0; i < codec->num_pcms; i++) { | |
| 1387 | − err = snd_hda_create_spdif_out_ctls(codec, | |
| 1388 | − spec->cvts[i].cvt_nid, | |
| 1389 | − spec->cvts[i].cvt_nid); | |
| 1390 | − if (err < 0) | |
| 1391 | − return err; | |
| 1392 | − } | |
| 1405 | + err = snd_hda_create_spdif_out_ctls(codec, | |
| 1406 | + spec->cvts[0].cvt_nid, | |
| 1407 | + spec->cvts[0].cvt_nid); | |
| 1408 | + if (err < 0) | |
| 1409 | + return err; | |
| 1410 | + return simple_hdmi_build_jack(codec, 0); | |
| 1411 | +} | |
| 1393 | 1412 | |
| 1413 | +static int simple_playback_init(struct hda_codec *codec) | |
| 1414 | +{ | |
| 1415 | + struct hdmi_spec *spec = codec->spec; | |
| 1416 | + hda_nid_t pin = spec->pins[0].pin_nid; | |
| 1417 | + | |
| 1418 | + snd_hda_codec_write(codec, pin, 0, | |
| 1419 | + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | |
| 1420 | + /* some codecs require to unmute the pin */ | |
| 1421 | + if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) | |
| 1422 | + snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_AMP_GAIN_MUTE, | |
| 1423 | + AMP_OUT_UNMUTE); | |
| 1424 | + snd_hda_jack_detect_enable(codec, pin, pin); | |
| 1425 | + snd_hda_jack_report_sync(codec); | |
| 1394 | 1426 | return 0; |
| 1395 | 1427 | } |
| 1396 | 1428 | |
| @@ -1418,7 +1450,15 @@ static const hda_nid_t nvhdmi_con_nids_7x[4] = { · 21 unmodified lines | ||
| 1418 | 1450 | 0x6, 0x8, 0xa, 0xc, |
| 1419 | 1451 | }; |
| 1420 | 1452 | |
| 1421 | −static const struct hda_verb nvhdmi_basic_init_7x[] = { | |
| 1453 | +static const struct hda_verb nvhdmi_basic_init_7x_2ch[] = { | |
| 1454 | + /* set audio protect on */ | |
| 1455 | + { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, | |
| 1456 | + /* enable digital output on pin widget */ | |
| 1457 | + { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | |
| 1458 | + {} /* terminator */ | |
| 1459 | +}; | |
| 1460 | + | |
| 1461 | +static const struct hda_verb nvhdmi_basic_init_7x_8ch[] = { | |
| 1422 | 1462 | /* set audio protect on */ |
| 1423 | 1463 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, |
| 1424 | 1464 | /* enable digital output on pin widget */ |
| @@ -1446,9 +1486,15 @@ static const struct hda_verb nvhdmi_basic_init_7x[] = { · 21 unmodified lines | ||
| 1446 | 1486 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) |
| 1447 | 1487 | #endif |
| 1448 | 1488 | |
| 1449 | −static int nvhdmi_7x_init(struct hda_codec *codec) | |
| 1489 | +static int nvhdmi_7x_init_2ch(struct hda_codec *codec) | |
| 1450 | 1490 | { |
| 1451 | − snd_hda_sequence_write(codec, nvhdmi_basic_init_7x); | |
| 1491 | + snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_2ch); | |
| 1492 | + return 0; | |
| 1493 | +} | |
| 1494 | + | |
| 1495 | +static int nvhdmi_7x_init_8ch(struct hda_codec *codec) | |
| 1496 | +{ | |
| 1497 | + snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_8ch); | |
| 1452 | 1498 | return 0; |
| 1453 | 1499 | } |
| 1454 | 1500 | |
| @@ -1524,6 +1570,50 @@ static int simple_playback_pcm_prepare(struct hda_pcm_stream *hinfo, · 69 unmodified lines | ||
| 1524 | 1570 | stream_tag, format, substream); |
| 1525 | 1571 | } |
| 1526 | 1572 | |
| 1573 | +static const struct hda_pcm_stream simple_pcm_playback = { | |
| 1574 | + .substreams = 1, | |
| 1575 | + .channels_min = 2, | |
| 1576 | + .channels_max = 2, | |
| 1577 | + .ops = { | |
| 1578 | + .open = simple_playback_pcm_open, | |
| 1579 | + .close = simple_playback_pcm_close, | |
| 1580 | + .prepare = simple_playback_pcm_prepare | |
| 1581 | + }, | |
| 1582 | +}; | |
| 1583 | + | |
| 1584 | +static const struct hda_codec_ops simple_hdmi_patch_ops = { | |
| 1585 | + .build_controls = simple_playback_build_controls, | |
| 1586 | + .build_pcms = simple_playback_build_pcms, | |
| 1587 | + .init = simple_playback_init, | |
| 1588 | + .free = simple_playback_free, | |
| 1589 | + .unsol_event = simple_hdmi_unsol_event, | |
| 1590 | +}; | |
| 1591 | + | |
| 1592 | +static int patch_simple_hdmi(struct hda_codec *codec, | |
| 1593 | + hda_nid_t cvt_nid, hda_nid_t pin_nid) | |
| 1594 | +{ | |
| 1595 | + struct hdmi_spec *spec; | |
| 1596 | + | |
| 1597 | + spec = kzalloc(sizeof(*spec), GFP_KERNEL); | |
| 1598 | + if (!spec) | |
| 1599 | + return -ENOMEM; | |
| 1600 | + | |
| 1601 | + codec->spec = spec; | |
| 1602 | + | |
| 1603 | + spec->multiout.num_dacs = 0; /* no analog */ | |
| 1604 | + spec->multiout.max_channels = 2; | |
| 1605 | + spec->multiout.dig_out_nid = cvt_nid; | |
| 1606 | + spec->num_cvts = 1; | |
| 1607 | + spec->num_pins = 1; | |
| 1608 | + spec->cvts[0].cvt_nid = cvt_nid; | |
| 1609 | + spec->pins[0].pin_nid = pin_nid; | |
| 1610 | + spec->pcm_playback = simple_pcm_playback; | |
| 1611 | + | |
| 1612 | + codec->patch_ops = simple_hdmi_patch_ops; | |
| 1613 | + | |
| 1614 | + return 0; | |
| 1615 | +} | |
| 1616 | + | |
| 1527 | 1617 | static void nvhdmi_8ch_7x_set_info_frame_parameters(struct hda_codec *codec, |
| 1528 | 1618 | int channels) |
| 1529 | 1619 | { |
| @@ -1696,54 +1786,20 @@ static const struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = { · 166 unmodified lines | ||
| 1696 | 1786 | }, |
| 1697 | 1787 | }; |
| 1698 | 1788 | |
| 1699 | −static const struct hda_pcm_stream nvhdmi_pcm_playback_2ch = { | |
| 1700 | − .substreams = 1, | |
| 1701 | − .channels_min = 2, | |
| 1702 | − .channels_max = 2, | |
| 1703 | − .nid = nvhdmi_master_con_nid_7x, | |
| 1704 | − .rates = SUPPORTED_RATES, | |
| 1705 | − .maxbps = SUPPORTED_MAXBPS, | |
| 1706 | − .formats = SUPPORTED_FORMATS, | |
| 1707 | − .ops = { | |
| 1708 | − .open = simple_playback_pcm_open, | |
| 1709 | − .close = simple_playback_pcm_close, | |
| 1710 | − .prepare = simple_playback_pcm_prepare | |
| 1711 | − }, | |
| 1712 | −}; | |
| 1713 | − | |
| 1714 | −static const struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = { | |
| 1715 | − .build_controls = simple_playback_build_controls, | |
| 1716 | − .build_pcms = simple_playback_build_pcms, | |
| 1717 | − .init = nvhdmi_7x_init, | |
| 1718 | − .free = simple_playback_free, | |
| 1719 | −}; | |
| 1720 | − | |
| 1721 | −static const struct hda_codec_ops nvhdmi_patch_ops_2ch = { | |
| 1722 | − .build_controls = simple_playback_build_controls, | |
| 1723 | − .build_pcms = simple_playback_build_pcms, | |
| 1724 | − .init = nvhdmi_7x_init, | |
| 1725 | − .free = simple_playback_free, | |
| 1726 | −}; | |
| 1727 | − | |
| 1728 | 1789 | static int patch_nvhdmi_2ch(struct hda_codec *codec) |
| 1729 | 1790 | { |
| 1730 | 1791 | struct hdmi_spec *spec; |
| 1792 | + int err = patch_simple_hdmi(codec, nvhdmi_master_con_nid_7x, | |
| 1793 | + nvhdmi_master_pin_nid_7x); | |
| 1794 | + if (err < 0) | |
| 1795 | + return err; | |
| 1731 | 1796 | |
| 1732 | − spec = kzalloc(sizeof(*spec), GFP_KERNEL); | |
| 1733 | − if (spec == NULL) | |
| 1734 | − return -ENOMEM; | |
| 1735 | − | |
| 1736 | − codec->spec = spec; | |
| 1737 | − | |
| 1738 | − spec->multiout.num_dacs = 0; /* no analog */ | |
| 1739 | − spec->multiout.max_channels = 2; | |
| 1740 | − spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; | |
| 1741 | − spec->num_cvts = 1; | |
| 1742 | − spec->cvts[0].cvt_nid = nvhdmi_master_con_nid_7x; | |
| 1743 | − spec->pcm_playback = &nvhdmi_pcm_playback_2ch; | |
| 1744 | − | |
| 1745 | − codec->patch_ops = nvhdmi_patch_ops_2ch; | |
| 1746 | − | |
| 1797 | + codec->patch_ops.init = nvhdmi_7x_init_2ch; | |
| 1798 | + /* override the PCM rates, etc, as the codec doesn't give full list */ | |
| 1799 | + spec = codec->spec; | |
| 1800 | + spec->pcm_playback.rates = SUPPORTED_RATES; | |
| 1801 | + spec->pcm_playback.maxbps = SUPPORTED_MAXBPS; | |
| 1802 | + spec->pcm_playback.formats = SUPPORTED_FORMATS; | |
| 1747 | 1803 | return 0; |
| 1748 | 1804 | } |
| 1749 | 1805 | |
| @@ -1751,13 +1807,12 @@ static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) · 1 unmodified line | ||
| 1751 | 1807 | { |
| 1752 | 1808 | struct hdmi_spec *spec; |
| 1753 | 1809 | int err = patch_nvhdmi_2ch(codec); |
| 1754 | − | |
| 1755 | 1810 | if (err < 0) |
| 1756 | 1811 | return err; |
| 1757 | 1812 | spec = codec->spec; |
| 1758 | 1813 | spec->multiout.max_channels = 8; |
| 1759 | − spec->pcm_playback = &nvhdmi_pcm_playback_8ch_7x; | |
| 1760 | − codec->patch_ops = nvhdmi_patch_ops_8ch_7x; | |
| 1814 | + spec->pcm_playback = nvhdmi_pcm_playback_8ch_7x; | |
| 1815 | + codec->patch_ops.init = nvhdmi_7x_init_8ch; | |
| 1761 | 1816 | |
| 1762 | 1817 | /* Initialize the audio infoframe channel mask and checksum to something |
| 1763 | 1818 | * valid */ |
| @@ -1801,69 +1856,26 @@ static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, · 37 unmodified lines | ||
| 1801 | 1856 | return 0; |
| 1802 | 1857 | } |
| 1803 | 1858 | |
| 1804 | −static const struct hda_pcm_stream atihdmi_pcm_digital_playback = { | |
| 1805 | − .substreams = 1, | |
| 1806 | − .channels_min = 2, | |
| 1807 | − .channels_max = 2, | |
| 1808 | − .nid = ATIHDMI_CVT_NID, | |
| 1809 | − .ops = { | |
| 1810 | − .open = simple_playback_pcm_open, | |
| 1811 | − .close = simple_playback_pcm_close, | |
| 1812 | − .prepare = atihdmi_playback_pcm_prepare | |
| 1813 | − }, | |
| 1814 | −}; | |
| 1815 | − | |
| 1816 | −static const struct hda_verb atihdmi_basic_init[] = { | |
| 1817 | − /* enable digital output on pin widget */ | |
| 1818 | − { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | |
| 1819 | − {} /* terminator */ | |
| 1820 | −}; | |
| 1821 | − | |
| 1822 | −static int atihdmi_init(struct hda_codec *codec) | |
| 1859 | +static int patch_atihdmi(struct hda_codec *codec) | |
| 1823 | 1860 | { |
| 1824 | − struct hdmi_spec *spec = codec->spec; | |
| 1825 | − | |
| 1826 | − snd_hda_sequence_write(codec, atihdmi_basic_init); | |
| 1827 | − /* SI codec requires to unmute the pin */ | |
| 1828 | − if (get_wcaps(codec, spec->pins[0].pin_nid) & AC_WCAP_OUT_AMP) | |
| 1829 | − snd_hda_codec_write(codec, spec->pins[0].pin_nid, 0, | |
| 1830 | − AC_VERB_SET_AMP_GAIN_MUTE, | |
| 1831 | − AMP_OUT_UNMUTE); | |
| 1861 | + struct hdmi_spec *spec; | |
| 1862 | + int err = patch_simple_hdmi(codec, ATIHDMI_CVT_NID, ATIHDMI_PIN_NID); | |
| 1863 | + if (err < 0) | |
| 1864 | + return err; | |
| 1865 | + spec = codec->spec; | |
| 1866 | + spec->pcm_playback.ops.prepare = atihdmi_playback_pcm_prepare; | |
| 1832 | 1867 | return 0; |
| 1833 | 1868 | } |
| 1834 | 1869 | |
| 1835 | −static const struct hda_codec_ops atihdmi_patch_ops = { | |
| 1836 | − .build_controls = simple_playback_build_controls, | |
| 1837 | − .build_pcms = simple_playback_build_pcms, | |
| 1838 | − .init = atihdmi_init, | |
| 1839 | − .free = simple_playback_free, | |
| 1840 | −}; | |
| 1870 | +/* VIA HDMI Implementation */ | |
| 1871 | +#define VIAHDMI_CVT_NID 0x02 /* audio converter1 */ | |
| 1872 | +#define VIAHDMI_PIN_NID 0x03 /* HDMI output pin1 */ | |
| 1841 | 1873 | |
| 1842 | − | |
| 1843 | −static int patch_atihdmi(struct hda_codec *codec) | |
| 1874 | +static int patch_via_hdmi(struct hda_codec *codec) | |
| 1844 | 1875 | { |
| 1845 | − struct hdmi_spec *spec; | |
| 1846 | − | |
| 1847 | − spec = kzalloc(sizeof(*spec), GFP_KERNEL); | |
| 1848 | − if (spec == NULL) | |
| 1849 | − return -ENOMEM; | |
| 1850 | − | |
| 1851 | − codec->spec = spec; | |
| 1852 | − | |
| 1853 | − spec->multiout.num_dacs = 0; /* no analog */ | |
| 1854 | − spec->multiout.max_channels = 2; | |
| 1855 | − spec->multiout.dig_out_nid = ATIHDMI_CVT_NID; | |
| 1856 | − spec->num_cvts = 1; | |
| 1857 | − spec->cvts[0].cvt_nid = ATIHDMI_CVT_NID; | |
| 1858 | − spec->pins[0].pin_nid = ATIHDMI_PIN_NID; | |
| 1859 | − spec->pcm_playback = &atihdmi_pcm_digital_playback; | |
| 1860 | − | |
| 1861 | − codec->patch_ops = atihdmi_patch_ops; | |
| 1862 | − | |
| 1863 | − return 0; | |
| 1876 | + return patch_simple_hdmi(codec, VIAHDMI_CVT_NID, VIAHDMI_PIN_NID); | |
| 1864 | 1877 | } |
| 1865 | 1878 | |
| 1866 | − | |
| 1867 | 1879 | /* |
| 1868 | 1880 | * patch entries |
| 1869 | 1881 | */ |
| @@ -1902,8 +1914,13 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { · 32 unmodified lines | ||
| 1902 | 1914 | { .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_generic_hdmi }, |
| 1903 | 1915 | { .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_generic_hdmi }, |
| 1904 | 1916 | { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_generic_hdmi }, |
| 1917 | +{ .id = 0x10de0051, .name = "GPU 51 HDMI/DP", .patch = patch_generic_hdmi }, | |
| 1905 | 1918 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, |
| 1906 | 1919 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, |
| 1920 | +{ .id = 0x11069f80, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, | |
| 1921 | +{ .id = 0x11069f81, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, | |
| 1922 | +{ .id = 0x11069f84, .name = "VX11 HDMI/DP", .patch = patch_generic_hdmi }, | |
| 1923 | +{ .id = 0x11069f85, .name = "VX11 HDMI/DP", .patch = patch_generic_hdmi }, | |
| 1907 | 1924 | { .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, |
| 1908 | 1925 | { .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_generic_hdmi }, |
| 1909 | 1926 | { .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_generic_hdmi }, |
| @@ -1911,6 +1928,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { · 1 unmodified line | ||
| 1911 | 1928 | { .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, |
| 1912 | 1929 | { .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi }, |
| 1913 | 1930 | { .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi }, |
| 1931 | +{ .id = 0x80862807, .name = "Haswell HDMI", .patch = patch_generic_hdmi }, | |
| 1914 | 1932 | { .id = 0x80862880, .name = "CedarTrail HDMI", .patch = patch_generic_hdmi }, |
| 1915 | 1933 | { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi }, |
| 1916 | 1934 | {} /* terminator */ |
| @@ -1948,8 +1966,13 @@ MODULE_ALIAS("snd-hda-codec-id:10de0041"); · 31 unmodified lines | ||
| 1948 | 1966 | MODULE_ALIAS("snd-hda-codec-id:10de0042"); |
| 1949 | 1967 | MODULE_ALIAS("snd-hda-codec-id:10de0043"); |
| 1950 | 1968 | MODULE_ALIAS("snd-hda-codec-id:10de0044"); |
| 1969 | +MODULE_ALIAS("snd-hda-codec-id:10de0051"); | |
| 1951 | 1970 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); |
| 1952 | 1971 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); |
| 1972 | +MODULE_ALIAS("snd-hda-codec-id:11069f80"); | |
| 1973 | +MODULE_ALIAS("snd-hda-codec-id:11069f81"); | |
| 1974 | +MODULE_ALIAS("snd-hda-codec-id:11069f84"); | |
| 1975 | +MODULE_ALIAS("snd-hda-codec-id:11069f85"); | |
| 1953 | 1976 | MODULE_ALIAS("snd-hda-codec-id:17e80047"); |
| 1954 | 1977 | MODULE_ALIAS("snd-hda-codec-id:80860054"); |
| 1955 | 1978 | MODULE_ALIAS("snd-hda-codec-id:80862801"); |
| @@ -1958,6 +1981,7 @@ MODULE_ALIAS("snd-hda-codec-id:80862803"); · 2 unmodified lines | ||
| 1958 | 1981 | MODULE_ALIAS("snd-hda-codec-id:80862804"); |
| 1959 | 1982 | MODULE_ALIAS("snd-hda-codec-id:80862805"); |
| 1960 | 1983 | MODULE_ALIAS("snd-hda-codec-id:80862806"); |
| 1984 | +MODULE_ALIAS("snd-hda-codec-id:80862807"); | |
| 1961 | 1985 | MODULE_ALIAS("snd-hda-codec-id:80862880"); |
| 1962 | 1986 | MODULE_ALIAS("snd-hda-codec-id:808629fb"); |
| 1963 | 1987 | |
| @@ -170,10 +170,10 @@ struct alc_spec { · 169 unmodified lines | ||
| 170 | 170 | hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS]; |
| 171 | 171 | unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS]; |
| 172 | 172 | int int_mic_idx, ext_mic_idx, dock_mic_idx; /* for auto-mic */ |
| 173 | + hda_nid_t inv_dmic_pin; | |
| 173 | 174 | |
| 174 | 175 | /* hooks */ |
| 175 | 176 | void (*init_hook)(struct hda_codec *codec); |
| 176 | − void (*unsol_event)(struct hda_codec *codec, unsigned int res); | |
| 177 | 177 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
| 178 | 178 | void (*power_hook)(struct hda_codec *codec); |
| 179 | 179 | #endif |
| @@ -201,6 +201,8 @@ struct alc_spec { · 21 unmodified lines | ||
| 201 | 201 | unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */ |
| 202 | 202 | unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */ |
| 203 | 203 | unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */ |
| 204 | + unsigned int inv_dmic_fixup:1; /* has inverted digital-mic workaround */ | |
| 205 | + unsigned int inv_dmic_muted:1; /* R-ch of inv d-mic is muted? */ | |
| 204 | 206 | |
| 205 | 207 | /* auto-mute control */ |
| 206 | 208 | int automute_mode; |
| @@ -298,6 +300,39 @@ static inline hda_nid_t get_capsrc(struct alc_spec *spec, int idx) · 91 unmodified lines | ||
| 298 | 300 | } |
| 299 | 301 | |
| 300 | 302 | static void call_update_outputs(struct hda_codec *codec); |
| 303 | +static void alc_inv_dmic_sync(struct hda_codec *codec, bool force); | |
| 304 | + | |
| 305 | +/* for shared I/O, change the pin-control accordingly */ | |
| 306 | +static void update_shared_mic_hp(struct hda_codec *codec, bool set_as_mic) | |
| 307 | +{ | |
| 308 | + struct alc_spec *spec = codec->spec; | |
| 309 | + unsigned int val; | |
| 310 | + hda_nid_t pin = spec->autocfg.inputs[1].pin; | |
| 311 | + /* NOTE: this assumes that there are only two inputs, the | |
| 312 | + * first is the real internal mic and the second is HP/mic jack. | |
| 313 | + */ | |
| 314 | + | |
| 315 | + val = snd_hda_get_default_vref(codec, pin); | |
| 316 | + | |
| 317 | + /* This pin does not have vref caps - let's enable vref on pin 0x18 | |
| 318 | + instead, as suggested by Realtek */ | |
| 319 | + if (val == AC_PINCTL_VREF_HIZ) { | |
| 320 | + const hda_nid_t vref_pin = 0x18; | |
| 321 | + /* Sanity check pin 0x18 */ | |
| 322 | + if (get_wcaps_type(get_wcaps(codec, vref_pin)) == AC_WID_PIN && | |
| 323 | + get_defcfg_connect(snd_hda_codec_get_pincfg(codec, vref_pin)) == AC_JACK_PORT_NONE) { | |
| 324 | + unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin); | |
| 325 | + if (vref_val != AC_PINCTL_VREF_HIZ) | |
| 326 | + snd_hda_set_pin_ctl(codec, vref_pin, PIN_IN | (set_as_mic ? vref_val : 0)); | |
| 327 | + } | |
| 328 | + } | |
| 329 | + | |
| 330 | + val = set_as_mic ? val | PIN_IN : PIN_HP; | |
| 331 | + snd_hda_set_pin_ctl(codec, pin, val); | |
| 332 | + | |
| 333 | + spec->automute_speaker = !set_as_mic; | |
| 334 | + call_update_outputs(codec); | |
| 335 | +} | |
| 301 | 336 | |
| 302 | 337 | /* select the given imux item; either unmute exclusively or select the route */ |
| 303 | 338 | static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, |
| @@ -325,21 +360,8 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, · 21 unmodified lines | ||
| 325 | 360 | return 0; |
| 326 | 361 | spec->cur_mux[adc_idx] = idx; |
| 327 | 362 | |
| 328 | − /* for shared I/O, change the pin-control accordingly */ | |
| 329 | − if (spec->shared_mic_hp) { | |
| 330 | − unsigned int val; | |
| 331 | − hda_nid_t pin = spec->autocfg.inputs[1].pin; | |
| 332 | − /* NOTE: this assumes that there are only two inputs, the | |
| 333 | − * first is the real internal mic and the second is HP jack. | |
| 334 | − */ | |
| 335 | − if (spec->cur_mux[adc_idx]) | |
| 336 | − val = snd_hda_get_default_vref(codec, pin) | PIN_IN; | |
| 337 | − else | |
| 338 | − val = PIN_HP; | |
| 339 | − snd_hda_set_pin_ctl(codec, pin, val); | |
| 340 | − spec->automute_speaker = !spec->cur_mux[adc_idx]; | |
| 341 | − call_update_outputs(codec); | |
| 342 | − } | |
| 363 | + if (spec->shared_mic_hp) | |
| 364 | + update_shared_mic_hp(codec, spec->cur_mux[adc_idx]); | |
| 343 | 365 | |
| 344 | 366 | if (spec->dyn_adc_switch) { |
| 345 | 367 | alc_dyn_adc_pcm_resetup(codec, idx); |
| @@ -368,6 +390,7 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, · 22 unmodified lines | ||
| 368 | 390 | AC_VERB_SET_CONNECT_SEL, |
| 369 | 391 | imux->items[idx].index); |
| 370 | 392 | } |
| 393 | + alc_inv_dmic_sync(codec, true); | |
| 371 | 394 | return 1; |
| 372 | 395 | } |
| 373 | 396 | |
| @@ -664,7 +687,7 @@ static void alc_update_knob_master(struct hda_codec *codec, hda_nid_t nid) · 290 unmodified lines | ||
| 664 | 687 | } |
| 665 | 688 | |
| 666 | 689 | /* unsolicited event for HP jack sensing */ |
| 667 | −static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) | |
| 690 | +static void alc_unsol_event(struct hda_codec *codec, unsigned int res) | |
| 668 | 691 | { |
| 669 | 692 | int action; |
| 670 | 693 | |
| @@ -1000,11 +1023,9 @@ static void alc_init_automute(struct hda_codec *codec) · 329 unmodified lines | ||
| 1000 | 1023 | spec->automute_lo = spec->automute_lo_possible; |
| 1001 | 1024 | spec->automute_speaker = spec->automute_speaker_possible; |
| 1002 | 1025 | |
| 1003 | − if (spec->automute_speaker_possible || spec->automute_lo_possible) { | |
| 1026 | + if (spec->automute_speaker_possible || spec->automute_lo_possible) | |
| 1004 | 1027 | /* create a control for automute mode */ |
| 1005 | 1028 | alc_add_automute_mode_enum(codec); |
| 1006 | − spec->unsol_event = alc_sku_unsol_event; | |
| 1007 | − } | |
| 1008 | 1029 | } |
| 1009 | 1030 | |
| 1010 | 1031 | /* return the position of NID in the list, or -1 if not found */ |
| @@ -1167,7 +1188,6 @@ static void alc_init_auto_mic(struct hda_codec *codec) · 156 unmodified lines | ||
| 1167 | 1188 | |
| 1168 | 1189 | snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n", |
| 1169 | 1190 | ext, fixed, dock); |
| 1170 | − spec->unsol_event = alc_sku_unsol_event; | |
| 1171 | 1191 | } |
| 1172 | 1192 | |
| 1173 | 1193 | /* check the availabilities of auto-mute and auto-mic switches */ |
| @@ -1556,14 +1576,14 @@ typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol, · 382 unmodified lines | ||
| 1556 | 1576 | |
| 1557 | 1577 | static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol, |
| 1558 | 1578 | struct snd_ctl_elem_value *ucontrol, |
| 1559 | − getput_call_t func, bool check_adc_switch) | |
| 1579 | + getput_call_t func, bool is_put) | |
| 1560 | 1580 | { |
| 1561 | 1581 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
| 1562 | 1582 | struct alc_spec *spec = codec->spec; |
| 1563 | 1583 | int i, err = 0; |
| 1564 | 1584 | |
| 1565 | 1585 | mutex_lock(&codec->control_mutex); |
| 1566 | − if (check_adc_switch && spec->dyn_adc_switch) { | |
| 1586 | + if (is_put && spec->dyn_adc_switch) { | |
| 1567 | 1587 | for (i = 0; i < spec->num_adc_nids; i++) { |
| 1568 | 1588 | kcontrol->private_value = |
| 1569 | 1589 | HDA_COMPOSE_AMP_VAL(spec->adc_nids[i], |
| @@ -1584,6 +1604,8 @@ static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol, · 14 unmodified lines | ||
| 1584 | 1604 | 3, 0, HDA_INPUT); |
| 1585 | 1605 | err = func(kcontrol, ucontrol); |
| 1586 | 1606 | } |
| 1607 | + if (err >= 0 && is_put) | |
| 1608 | + alc_inv_dmic_sync(codec, false); | |
| 1587 | 1609 | error: |
| 1588 | 1610 | mutex_unlock(&codec->control_mutex); |
| 1589 | 1611 | return err; |
| @@ -1675,6 +1697,116 @@ DEFINE_CAPMIX_NOSRC(1); · 85 unmodified lines | ||
| 1675 | 1697 | DEFINE_CAPMIX_NOSRC(2); |
| 1676 | 1698 | DEFINE_CAPMIX_NOSRC(3); |
| 1677 | 1699 | |
| 1700 | +/* | |
| 1701 | + * Inverted digital-mic handling | |
| 1702 | + * | |
| 1703 | + * First off, it's a bit tricky. The "Inverted Internal Mic Capture Switch" | |
| 1704 | + * gives the additional mute only to the right channel of the digital mic | |
| 1705 | + * capture stream. This is a workaround for avoiding the almost silence | |
| 1706 | + * by summing the stereo stream from some (known to be ForteMedia) | |
| 1707 | + * digital mic unit. | |
| 1708 | + * | |
| 1709 | + * The logic is to call alc_inv_dmic_sync() after each action (possibly) | |
| 1710 | + * modifying ADC amp. When the mute flag is set, it mutes the R-channel | |
| 1711 | + * without caching so that the cache can still keep the original value. | |
| 1712 | + * The cached value is then restored when the flag is set off or any other | |
| 1713 | + * than d-mic is used as the current input source. | |
| 1714 | + */ | |
| 1715 | +static void alc_inv_dmic_sync(struct hda_codec *codec, bool force) | |
| 1716 | +{ | |
| 1717 | + struct alc_spec *spec = codec->spec; | |
| 1718 | + int i; | |
| 1719 | + | |
| 1720 | + if (!spec->inv_dmic_fixup) | |
| 1721 | + return; | |
| 1722 | + if (!spec->inv_dmic_muted && !force) | |
| 1723 | + return; | |
| 1724 | + for (i = 0; i < spec->num_adc_nids; i++) { | |
| 1725 | + int src = spec->dyn_adc_switch ? 0 : i; | |
| 1726 | + bool dmic_fixup = false; | |
| 1727 | + hda_nid_t nid; | |
| 1728 | + int parm, dir, v; | |
| 1729 | + | |
| 1730 | + if (spec->inv_dmic_muted && | |
| 1731 | + spec->imux_pins[spec->cur_mux[src]] == spec->inv_dmic_pin) | |
| 1732 | + dmic_fixup = true; | |
| 1733 | + if (!dmic_fixup && !force) | |
| 1734 | + continue; | |
| 1735 | + if (spec->vol_in_capsrc) { | |
| 1736 | + nid = spec->capsrc_nids[i]; | |
| 1737 | + parm = AC_AMP_SET_RIGHT | AC_AMP_SET_OUTPUT; | |
| 1738 | + dir = HDA_OUTPUT; | |
| 1739 | + } else { | |
| 1740 | + nid = spec->adc_nids[i]; | |
| 1741 | + parm = AC_AMP_SET_RIGHT | AC_AMP_SET_INPUT; | |
| 1742 | + dir = HDA_INPUT; | |
| 1743 | + } | |
| 1744 | + /* we care only right channel */ | |
| 1745 | + v = snd_hda_codec_amp_read(codec, nid, 1, dir, 0); | |
| 1746 | + if (v & 0x80) /* if already muted, we don't need to touch */ | |
| 1747 | + continue; | |
| 1748 | + if (dmic_fixup) /* add mute for d-mic */ | |
| 1749 | + v |= 0x80; | |
| 1750 | + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | |
| 1751 | + parm | v); | |
| 1752 | + } | |
| 1753 | +} | |
| 1754 | + | |
| 1755 | +static int alc_inv_dmic_sw_get(struct snd_kcontrol *kcontrol, | |
| 1756 | + struct snd_ctl_elem_value *ucontrol) | |
| 1757 | +{ | |
| 1758 | + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | |
| 1759 | + struct alc_spec *spec = codec->spec; | |
| 1760 | + | |
| 1761 | + ucontrol->value.integer.value[0] = !spec->inv_dmic_muted; | |
| 1762 | + return 0; | |
| 1763 | +} | |
| 1764 | + | |
| 1765 | +static int alc_inv_dmic_sw_put(struct snd_kcontrol *kcontrol, | |
| 1766 | + struct snd_ctl_elem_value *ucontrol) | |
| 1767 | +{ | |
| 1768 | + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | |
| 1769 | + struct alc_spec *spec = codec->spec; | |
| 1770 | + unsigned int val = !ucontrol->value.integer.value[0]; | |
| 1771 | + | |
| 1772 | + if (val == spec->inv_dmic_muted) | |
| 1773 | + return 0; | |
| 1774 | + spec->inv_dmic_muted = val; | |
| 1775 | + alc_inv_dmic_sync(codec, true); | |
| 1776 | + return 0; | |
| 1777 | +} | |
| 1778 | + | |
| 1779 | +static const struct snd_kcontrol_new alc_inv_dmic_sw = { | |
| 1780 | + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | |
| 1781 | + .info = snd_ctl_boolean_mono_info, | |
| 1782 | + .get = alc_inv_dmic_sw_get, | |
| 1783 | + .put = alc_inv_dmic_sw_put, | |
| 1784 | +}; | |
| 1785 | + | |
| 1786 | +static int alc_add_inv_dmic_mixer(struct hda_codec *codec, hda_nid_t nid) | |
| 1787 | +{ | |
| 1788 | + struct alc_spec *spec = codec->spec; | |
| 1789 | + struct snd_kcontrol_new *knew = alc_kcontrol_new(spec); | |
| 1790 | + if (!knew) | |
| 1791 | + return -ENOMEM; | |
| 1792 | + *knew = alc_inv_dmic_sw; | |
| 1793 | + knew->name = kstrdup("Inverted Internal Mic Capture Switch", GFP_KERNEL); | |
| 1794 | + if (!knew->name) | |
| 1795 | + return -ENOMEM; | |
| 1796 | + spec->inv_dmic_fixup = 1; | |
| 1797 | + spec->inv_dmic_muted = 0; | |
| 1798 | + spec->inv_dmic_pin = nid; | |
| 1799 | + return 0; | |
| 1800 | +} | |
| 1801 | + | |
| 1802 | +/* typically the digital mic is put at node 0x12 */ | |
| 1803 | +static void alc_fixup_inv_dmic_0x12(struct hda_codec *codec, | |
| 1804 | + const struct alc_fixup *fix, int action) | |
| 1805 | +{ | |
| 1806 | + if (action == ALC_FIXUP_ACT_PROBE) | |
| 1807 | + alc_add_inv_dmic_mixer(codec, 0x12); | |
| 1808 | +} | |
| 1809 | + | |
| 1678 | 1810 | /* |
| 1679 | 1811 | * virtual master controls |
| 1680 | 1812 | */ |
| @@ -1865,13 +1997,31 @@ static int __alc_build_controls(struct hda_codec *codec) · 184 unmodified lines | ||
| 1865 | 1997 | return 0; |
| 1866 | 1998 | } |
| 1867 | 1999 | |
| 1868 | −static int alc_build_controls(struct hda_codec *codec) | |
| 2000 | +static int alc_build_jacks(struct hda_codec *codec) | |
| 1869 | 2001 | { |
| 1870 | 2002 | struct alc_spec *spec = codec->spec; |
| 2003 | + | |
| 2004 | + if (spec->shared_mic_hp) { | |
| 2005 | + int err; | |
| 2006 | + int nid = spec->autocfg.inputs[1].pin; | |
| 2007 | + err = snd_hda_jack_add_kctl(codec, nid, "Headphone Mic", 0); | |
| 2008 | + if (err < 0) | |
| 2009 | + return err; | |
| 2010 | + err = snd_hda_jack_detect_enable(codec, nid, 0); | |
| 2011 | + if (err < 0) | |
| 2012 | + return err; | |
| 2013 | + } | |
| 2014 | + | |
| 2015 | + return snd_hda_jack_add_kctls(codec, &spec->autocfg); | |
| 2016 | +} | |
| 2017 | + | |
| 2018 | +static int alc_build_controls(struct hda_codec *codec) | |
| 2019 | +{ | |
| 1871 | 2020 | int err = __alc_build_controls(codec); |
| 1872 | 2021 | if (err < 0) |
| 1873 | 2022 | return err; |
| 1874 | − err = snd_hda_jack_add_kctls(codec, &spec->autocfg); | |
| 2023 | + | |
| 2024 | + err = alc_build_jacks(codec); | |
| 1875 | 2025 | if (err < 0) |
| 1876 | 2026 | return err; |
| 1877 | 2027 | alc_apply_fixup(codec, ALC_FIXUP_ACT_BUILD); |
| @@ -1908,14 +2058,6 @@ static int alc_init(struct hda_codec *codec) · 30 unmodified lines | ||
| 1908 | 2058 | return 0; |
| 1909 | 2059 | } |
| 1910 | 2060 | |
| 1911 | −static void alc_unsol_event(struct hda_codec *codec, unsigned int res) | |
| 1912 | −{ | |
| 1913 | − struct alc_spec *spec = codec->spec; | |
| 1914 | − | |
| 1915 | − if (spec->unsol_event) | |
| 1916 | − spec->unsol_event(codec, res); | |
| 1917 | −} | |
| 1918 | − | |
| 1919 | 2061 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
| 1920 | 2062 | static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid) |
| 1921 | 2063 | { |
| @@ -2300,7 +2442,7 @@ static void alc_power_eapd(struct hda_codec *codec) · 378 unmodified lines | ||
| 2300 | 2442 | alc_auto_setup_eapd(codec, false); |
| 2301 | 2443 | } |
| 2302 | 2444 | |
| 2303 | −static int alc_suspend(struct hda_codec *codec, pm_message_t state) | |
| 2445 | +static int alc_suspend(struct hda_codec *codec) | |
| 2304 | 2446 | { |
| 2305 | 2447 | struct alc_spec *spec = codec->spec; |
| 2306 | 2448 | alc_shutup(codec); |
| @@ -2317,6 +2459,7 @@ static int alc_resume(struct hda_codec *codec) · 10 unmodified lines | ||
| 2317 | 2459 | codec->patch_ops.init(codec); |
| 2318 | 2460 | snd_hda_codec_resume_amp(codec); |
| 2319 | 2461 | snd_hda_codec_resume_cache(codec); |
| 2462 | + alc_inv_dmic_sync(codec, true); | |
| 2320 | 2463 | hda_call_check_power_status(codec, 0x01); |
| 2321 | 2464 | return 0; |
| 2322 | 2465 | } |
| @@ -4116,14 +4259,12 @@ static void set_capture_mixer(struct hda_codec *codec) · 1793 unmodified lines | ||
| 4116 | 4259 | */ |
| 4117 | 4260 | static void alc_auto_init_std(struct hda_codec *codec) |
| 4118 | 4261 | { |
| 4119 | − struct alc_spec *spec = codec->spec; | |
| 4120 | 4262 | alc_auto_init_multi_out(codec); |
| 4121 | 4263 | alc_auto_init_extra_out(codec); |
| 4122 | 4264 | alc_auto_init_analog_input(codec); |
| 4123 | 4265 | alc_auto_init_input_src(codec); |
| 4124 | 4266 | alc_auto_init_digital(codec); |
| 4125 | − if (spec->unsol_event) | |
| 4126 | − alc_inithook(codec); | |
| 4267 | + alc_inithook(codec); | |
| 4127 | 4268 | } |
| 4128 | 4269 | |
| 4129 | 4270 | /* |
| @@ -4724,7 +4865,6 @@ static void alc260_fixup_gpio1_toggle(struct hda_codec *codec, · 594 unmodified lines | ||
| 4724 | 4865 | spec->automute_speaker = 1; |
| 4725 | 4866 | spec->autocfg.hp_pins[0] = 0x0f; /* copy it for automute */ |
| 4726 | 4867 | snd_hda_jack_detect_enable(codec, 0x0f, ALC_HP_EVENT); |
| 4727 | − spec->unsol_event = alc_sku_unsol_event; | |
| 4728 | 4868 | snd_hda_gen_add_verbs(&spec->gen, alc_gpio1_init_verbs); |
| 4729 | 4869 | } |
| 4730 | 4870 | } |
| @@ -4909,6 +5049,7 @@ enum { · 178 unmodified lines | ||
| 4909 | 5049 | ALC889_FIXUP_DAC_ROUTE, |
| 4910 | 5050 | ALC889_FIXUP_MBP_VREF, |
| 4911 | 5051 | ALC889_FIXUP_IMAC91_VREF, |
| 5052 | + ALC882_FIXUP_INV_DMIC, | |
| 4912 | 5053 | }; |
| 4913 | 5054 | |
| 4914 | 5055 | static void alc889_fixup_coef(struct hda_codec *codec, |
| @@ -5212,6 +5353,10 @@ static const struct alc_fixup alc882_fixups[] = { · 297 unmodified lines | ||
| 5212 | 5353 | .chained = true, |
| 5213 | 5354 | .chain_id = ALC882_FIXUP_GPIO1, |
| 5214 | 5355 | }, |
| 5356 | + [ALC882_FIXUP_INV_DMIC] = { | |
| 5357 | + .type = ALC_FIXUP_FUNC, | |
| 5358 | + .v.func = alc_fixup_inv_dmic_0x12, | |
| 5359 | + }, | |
| 5215 | 5360 | }; |
| 5216 | 5361 | |
| 5217 | 5362 | static const struct snd_pci_quirk alc882_fixup_tbl[] = { |
| @@ -5286,6 +5431,7 @@ static const struct alc_model_fixup alc882_fixup_models[] = { · 68 unmodified lines | ||
| 5286 | 5431 | {.id = ALC882_FIXUP_ACER_ASPIRE_4930G, .name = "acer-aspire-4930g"}, |
| 5287 | 5432 | {.id = ALC882_FIXUP_ACER_ASPIRE_8930G, .name = "acer-aspire-8930g"}, |
| 5288 | 5433 | {.id = ALC883_FIXUP_ACER_EAPD, .name = "acer-aspire"}, |
| 5434 | + {.id = ALC882_FIXUP_INV_DMIC, .name = "inv-dmic"}, | |
| 5289 | 5435 | {} |
| 5290 | 5436 | }; |
| 5291 | 5437 | |
| @@ -5373,6 +5519,7 @@ enum { · 81 unmodified lines | ||
| 5373 | 5519 | ALC262_FIXUP_LENOVO_3000, |
| 5374 | 5520 | ALC262_FIXUP_BENQ, |
| 5375 | 5521 | ALC262_FIXUP_BENQ_T31, |
| 5522 | + ALC262_FIXUP_INV_DMIC, | |
| 5376 | 5523 | }; |
| 5377 | 5524 | |
| 5378 | 5525 | static const struct alc_fixup alc262_fixups[] = { |
| @@ -5424,6 +5571,10 @@ static const struct alc_fixup alc262_fixups[] = { · 45 unmodified lines | ||
| 5424 | 5571 | {} |
| 5425 | 5572 | } |
| 5426 | 5573 | }, |
| 5574 | + [ALC262_FIXUP_INV_DMIC] = { | |
| 5575 | + .type = ALC_FIXUP_FUNC, | |
| 5576 | + .v.func = alc_fixup_inv_dmic_0x12, | |
| 5577 | + }, | |
| 5427 | 5578 | }; |
| 5428 | 5579 | |
| 5429 | 5580 | static const struct snd_pci_quirk alc262_fixup_tbl[] = { |
| @@ -5438,6 +5589,10 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = { · 8 unmodified lines | ||
| 5438 | 5589 | {} |
| 5439 | 5590 | }; |
| 5440 | 5591 | |
| 5592 | +static const struct alc_model_fixup alc262_fixup_models[] = { | |
| 5593 | + {.id = ALC262_FIXUP_INV_DMIC, .name = "inv-dmic"}, | |
| 5594 | + {} | |
| 5595 | +}; | |
| 5441 | 5596 | |
| 5442 | 5597 | /* |
| 5443 | 5598 | */ |
| @@ -5466,7 +5621,8 @@ static int patch_alc262(struct hda_codec *codec) · 22 unmodified lines | ||
| 5466 | 5621 | #endif |
| 5467 | 5622 | alc_fix_pll_init(codec, 0x20, 0x0a, 10); |
| 5468 | 5623 | |
| 5469 | − alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups); | |
| 5624 | + alc_pick_fixup(codec, alc262_fixup_models, alc262_fixup_tbl, | |
| 5625 | + alc262_fixups); | |
| 5470 | 5626 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); |
| 5471 | 5627 | |
| 5472 | 5628 | alc_auto_parse_customize_define(codec); |
| @@ -5522,6 +5678,22 @@ static const struct hda_verb alc268_beep_init_verbs[] = { · 49 unmodified lines | ||
| 5522 | 5678 | { } |
| 5523 | 5679 | }; |
| 5524 | 5680 | |
| 5681 | +enum { | |
| 5682 | + ALC268_FIXUP_INV_DMIC, | |
| 5683 | +}; | |
| 5684 | + | |
| 5685 | +static const struct alc_fixup alc268_fixups[] = { | |
| 5686 | + [ALC268_FIXUP_INV_DMIC] = { | |
| 5687 | + .type = ALC_FIXUP_FUNC, | |
| 5688 | + .v.func = alc_fixup_inv_dmic_0x12, | |
| 5689 | + }, | |
| 5690 | +}; | |
| 5691 | + | |
| 5692 | +static const struct alc_model_fixup alc268_fixup_models[] = { | |
| 5693 | + {.id = ALC268_FIXUP_INV_DMIC, .name = "inv-dmic"}, | |
| 5694 | + {} | |
| 5695 | +}; | |
| 5696 | + | |
| 5525 | 5697 | /* |
| 5526 | 5698 | * BIOS auto configuration |
| 5527 | 5699 | */ |
| @@ -5553,6 +5725,9 @@ static int patch_alc268(struct hda_codec *codec) · 25 unmodified lines | ||
| 5553 | 5725 | |
| 5554 | 5726 | spec = codec->spec; |
| 5555 | 5727 | |
| 5728 | + alc_pick_fixup(codec, alc268_fixup_models, NULL, alc268_fixups); | |
| 5729 | + alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); | |
| 5730 | + | |
| 5556 | 5731 | /* automatic parse from the BIOS config */ |
| 5557 | 5732 | err = alc268_parse_auto_config(codec); |
| 5558 | 5733 | if (err < 0) |
| @@ -5582,6 +5757,8 @@ static int patch_alc268(struct hda_codec *codec) · 23 unmodified lines | ||
| 5582 | 5757 | codec->patch_ops = alc_patch_ops; |
| 5583 | 5758 | spec->shutup = alc_eapd_shutup; |
| 5584 | 5759 | |
| 5760 | + alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); | |
| 5761 | + | |
| 5585 | 5762 | return 0; |
| 5586 | 5763 | |
| 5587 | 5764 | error: |
| @@ -5704,6 +5881,15 @@ static int alc269_resume(struct hda_codec *codec) · 116 unmodified lines | ||
| 5704 | 5881 | } |
| 5705 | 5882 | #endif /* CONFIG_PM */ |
| 5706 | 5883 | |
| 5884 | +static void alc269_fixup_pincfg_no_hp_to_lineout(struct hda_codec *codec, | |
| 5885 | + const struct alc_fixup *fix, int action) | |
| 5886 | +{ | |
| 5887 | + struct alc_spec *spec = codec->spec; | |
| 5888 | + | |
| 5889 | + if (action == ALC_FIXUP_ACT_PRE_PROBE) | |
| 5890 | + spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP; | |
| 5891 | +} | |
| 5892 | + | |
| 5707 | 5893 | static void alc269_fixup_hweq(struct hda_codec *codec, |
| 5708 | 5894 | const struct alc_fixup *fix, int action) |
| 5709 | 5895 | { |
| @@ -5810,6 +5996,7 @@ static void alc269_fixup_mic2_mute(struct hda_codec *codec, · 100 unmodified lines | ||
| 5810 | 5996 | } |
| 5811 | 5997 | } |
| 5812 | 5998 | |
| 5999 | + | |
| 5813 | 6000 | enum { |
| 5814 | 6001 | ALC269_FIXUP_SONY_VAIO, |
| 5815 | 6002 | ALC275_FIXUP_SONY_VAIO_GPIO2, |
| @@ -5828,6 +6015,9 @@ enum { · 12 unmodified lines | ||
| 5828 | 6015 | ALC269VB_FIXUP_AMIC, |
| 5829 | 6016 | ALC269VB_FIXUP_DMIC, |
| 5830 | 6017 | ALC269_FIXUP_MIC2_MUTE_LED, |
| 6018 | + ALC269_FIXUP_INV_DMIC, | |
| 6019 | + ALC269_FIXUP_LENOVO_DOCK, | |
| 6020 | + ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT, | |
| 5831 | 6021 | }; |
| 5832 | 6022 | |
| 5833 | 6023 | static const struct alc_fixup alc269_fixups[] = { |
| @@ -5952,12 +6142,33 @@ static const struct alc_fixup alc269_fixups[] = { · 118 unmodified lines | ||
| 5952 | 6142 | .type = ALC_FIXUP_FUNC, |
| 5953 | 6143 | .v.func = alc269_fixup_mic2_mute, |
| 5954 | 6144 | }, |
| 6145 | + [ALC269_FIXUP_INV_DMIC] = { | |
| 6146 | + .type = ALC_FIXUP_FUNC, | |
| 6147 | + .v.func = alc_fixup_inv_dmic_0x12, | |
| 6148 | + }, | |
| 6149 | + [ALC269_FIXUP_LENOVO_DOCK] = { | |
| 6150 | + .type = ALC_FIXUP_PINS, | |
| 6151 | + .v.pins = (const struct alc_pincfg[]) { | |
| 6152 | + { 0x19, 0x23a11040 }, /* dock mic */ | |
| 6153 | + { 0x1b, 0x2121103f }, /* dock headphone */ | |
| 6154 | + { } | |
| 6155 | + }, | |
| 6156 | + .chained = true, | |
| 6157 | + .chain_id = ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT | |
| 6158 | + }, | |
| 6159 | + [ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT] = { | |
| 6160 | + .type = ALC_FIXUP_FUNC, | |
| 6161 | + .v.func = alc269_fixup_pincfg_no_hp_to_lineout, | |
| 6162 | + }, | |
| 5955 | 6163 | }; |
| 5956 | 6164 | |
| 5957 | 6165 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
| 6166 | + SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC), | |
| 6167 | + SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC), | |
| 5958 | 6168 | SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED), |
| 5959 | 6169 | SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC), |
| 5960 | 6170 | SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), |
| 6171 | + SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC), | |
| 5961 | 6172 | SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), |
| 5962 | 6173 | SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), |
| 5963 | 6174 | SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC), |
| @@ -5975,6 +6186,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 11 unmodified lines | ||
| 5975 | 6186 | SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), |
| 5976 | 6187 | SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE), |
| 5977 | 6188 | SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE), |
| 6189 | + SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK), | |
| 5978 | 6190 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_QUANTA_MUTE), |
| 5979 | 6191 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K), |
| 5980 | 6192 | SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), |
| @@ -6033,6 +6245,10 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 52 unmodified lines | ||
| 6033 | 6245 | static const struct alc_model_fixup alc269_fixup_models[] = { |
| 6034 | 6246 | {.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"}, |
| 6035 | 6247 | {.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"}, |
| 6248 | + {.id = ALC269_FIXUP_STEREO_DMIC, .name = "alc269-dmic"}, | |
| 6249 | + {.id = ALC271_FIXUP_DMIC, .name = "alc271-dmic"}, | |
| 6250 | + {.id = ALC269_FIXUP_INV_DMIC, .name = "inv-dmic"}, | |
| 6251 | + {.id = ALC269_FIXUP_LENOVO_DOCK, .name = "lenovo-dock"}, | |
| 6036 | 6252 | {} |
| 6037 | 6253 | }; |
| 6038 | 6254 | |
| @@ -6329,12 +6545,6 @@ static const struct snd_pci_quirk alc861vd_fixup_tbl[] = { · 290 unmodified lines | ||
| 6329 | 6545 | {} |
| 6330 | 6546 | }; |
| 6331 | 6547 | |
| 6332 | −static const struct hda_verb alc660vd_eapd_verbs[] = { | |
| 6333 | − {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, | |
| 6334 | − {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2}, | |
| 6335 | − { } | |
| 6336 | −}; | |
| 6337 | − | |
| 6338 | 6548 | /* |
| 6339 | 6549 | */ |
| 6340 | 6550 | static int patch_alc861vd(struct hda_codec *codec) |
| @@ -6356,11 +6566,6 @@ static int patch_alc861vd(struct hda_codec *codec) · 15 unmodified lines | ||
| 6356 | 6566 | if (err < 0) |
| 6357 | 6567 | goto error; |
| 6358 | 6568 | |
| 6359 | − if (codec->vendor_id == 0x10ec0660) { | |
| 6360 | − /* always turn on EAPD */ | |
| 6361 | − snd_hda_gen_add_verbs(&spec->gen, alc660vd_eapd_verbs); | |
| 6362 | − } | |
| 6363 | − | |
| 6364 | 6569 | if (!spec->no_analog) { |
| 6365 | 6570 | err = snd_hda_attach_beep_device(codec, 0x23); |
| 6366 | 6571 | if (err < 0) |
| @@ -6443,6 +6648,7 @@ enum { · 76 unmodified lines | ||
| 6443 | 6648 | ALC662_FIXUP_ASUS_MODE8, |
| 6444 | 6649 | ALC662_FIXUP_NO_JACK_DETECT, |
| 6445 | 6650 | ALC662_FIXUP_ZOTAC_Z68, |
| 6651 | + ALC662_FIXUP_INV_DMIC, | |
| 6446 | 6652 | }; |
| 6447 | 6653 | |
| 6448 | 6654 | static const struct alc_fixup alc662_fixups[] = { |
| @@ -6599,12 +6805,17 @@ static const struct alc_fixup alc662_fixups[] = { · 150 unmodified lines | ||
| 6599 | 6805 | { } |
| 6600 | 6806 | } |
| 6601 | 6807 | }, |
| 6808 | + [ALC662_FIXUP_INV_DMIC] = { | |
| 6809 | + .type = ALC_FIXUP_FUNC, | |
| 6810 | + .v.func = alc_fixup_inv_dmic_0x12, | |
| 6811 | + }, | |
| 6602 | 6812 | }; |
| 6603 | 6813 | |
| 6604 | 6814 | static const struct snd_pci_quirk alc662_fixup_tbl[] = { |
| 6605 | 6815 | SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2), |
| 6606 | 6816 | SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE), |
| 6607 | 6817 | SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE), |
| 6818 | + SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC), | |
| 6608 | 6819 | SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), |
| 6609 | 6820 | SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), |
| 6610 | 6821 | SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT), |
| @@ -6685,6 +6896,7 @@ static const struct alc_model_fixup alc662_fixup_models[] = { · 74 unmodified lines | ||
| 6685 | 6896 | {.id = ALC662_FIXUP_ASUS_MODE6, .name = "asus-mode6"}, |
| 6686 | 6897 | {.id = ALC662_FIXUP_ASUS_MODE7, .name = "asus-mode7"}, |
| 6687 | 6898 | {.id = ALC662_FIXUP_ASUS_MODE8, .name = "asus-mode8"}, |
| 6899 | + {.id = ALC662_FIXUP_INV_DMIC, .name = "inv-dmic"}, | |
| 6688 | 6900 | {} |
| 6689 | 6901 | }; |
| 6690 | 6902 | |
| @@ -6831,6 +7043,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { · 140 unmodified lines | ||
| 6831 | 7043 | { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 }, |
| 6832 | 7044 | { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 }, |
| 6833 | 7045 | { .id = 0x10ec0280, .name = "ALC280", .patch = patch_alc269 }, |
| 7046 | + { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 }, | |
| 6834 | 7047 | { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", |
| 6835 | 7048 | .patch = patch_alc861 }, |
| 6836 | 7049 | { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, |
| @@ -4997,7 +4997,7 @@ static int stac92xx_resume(struct hda_codec *codec) · 4996 unmodified lines | ||
| 4997 | 4997 | return 0; |
| 4998 | 4998 | } |
| 4999 | 4999 | |
| 5000 | −static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) | |
| 5000 | +static int stac92xx_suspend(struct hda_codec *codec) | |
| 5001 | 5001 | { |
| 5002 | 5002 | stac92xx_shutup(codec); |
| 5003 | 5003 | return 0; |
| @@ -1748,7 +1748,7 @@ static void via_unsol_event(struct hda_codec *codec, · 1747 unmodified lines | ||
| 1748 | 1748 | } |
| 1749 | 1749 | |
| 1750 | 1750 | #ifdef CONFIG_PM |
| 1751 | −static int via_suspend(struct hda_codec *codec, pm_message_t state) | |
| 1751 | +static int via_suspend(struct hda_codec *codec) | |
| 1752 | 1752 | { |
| 1753 | 1753 | struct via_spec *spec = codec->spec; |
| 1754 | 1754 | vt1708_stop_hp_work(spec); |
| @@ -2793,9 +2793,10 @@ static void __devexit snd_vt1724_remove(struct pci_dev *pci) · 2792 unmodified lines | ||
| 2793 | 2793 | } |
| 2794 | 2794 | |
| 2795 | 2795 | #ifdef CONFIG_PM |
| 2796 | −static int snd_vt1724_suspend(struct pci_dev *pci, pm_message_t state) | |
| 2796 | +static int snd_vt1724_suspend(struct device *dev) | |
| 2797 | 2797 | { |
| 2798 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 2798 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 2799 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 2799 | 2800 | struct snd_ice1712 *ice = card->private_data; |
| 2800 | 2801 | |
| 2801 | 2802 | if (!ice->pm_suspend_enabled) |
| @@ -2820,13 +2821,14 @@ static int snd_vt1724_suspend(struct pci_dev *pci, pm_message_t state) · 18 unmodified lines | ||
| 2820 | 2821 | |
| 2821 | 2822 | pci_disable_device(pci); |
| 2822 | 2823 | pci_save_state(pci); |
| 2823 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 2824 | + pci_set_power_state(pci, PCI_D3hot); | |
| 2824 | 2825 | return 0; |
| 2825 | 2826 | } |
| 2826 | 2827 | |
| 2827 | −static int snd_vt1724_resume(struct pci_dev *pci) | |
| 2828 | +static int snd_vt1724_resume(struct device *dev) | |
| 2828 | 2829 | { |
| 2829 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 2830 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 2831 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 2830 | 2832 | struct snd_ice1712 *ice = card->private_data; |
| 2831 | 2833 | |
| 2832 | 2834 | if (!ice->pm_suspend_enabled) |
| @@ -2871,17 +2873,21 @@ static int snd_vt1724_resume(struct pci_dev *pci) · 38 unmodified lines | ||
| 2871 | 2873 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 2872 | 2874 | return 0; |
| 2873 | 2875 | } |
| 2874 | −#endif | |
| 2876 | + | |
| 2877 | +static SIMPLE_DEV_PM_OPS(snd_vt1724_pm, snd_vt1724_suspend, snd_vt1724_resume); | |
| 2878 | +#define SND_VT1724_PM_OPS &snd_vt1724_pm | |
| 2879 | +#else | |
| 2880 | +#define SND_VT1724_PM_OPS NULL | |
| 2881 | +#endif /* CONFIG_PM */ | |
| 2875 | 2882 | |
| 2876 | 2883 | static struct pci_driver vt1724_driver = { |
| 2877 | 2884 | .name = KBUILD_MODNAME, |
| 2878 | 2885 | .id_table = snd_vt1724_ids, |
| 2879 | 2886 | .probe = snd_vt1724_probe, |
| 2880 | 2887 | .remove = __devexit_p(snd_vt1724_remove), |
| 2881 | −#ifdef CONFIG_PM | |
| 2882 | − .suspend = snd_vt1724_suspend, | |
| 2883 | − .resume = snd_vt1724_resume, | |
| 2884 | −#endif | |
| 2888 | + .driver = { | |
| 2889 | + .pm = SND_VT1724_PM_OPS, | |
| 2890 | + }, | |
| 2885 | 2891 | }; |
| 2886 | 2892 | |
| 2887 | 2893 | module_pci_driver(vt1724_driver); |
| @@ -2624,9 +2624,10 @@ static int snd_intel8x0_free(struct intel8x0 *chip) · 2623 unmodified lines | ||
| 2624 | 2624 | /* |
| 2625 | 2625 | * power management |
| 2626 | 2626 | */ |
| 2627 | −static int intel8x0_suspend(struct pci_dev *pci, pm_message_t state) | |
| 2627 | +static int intel8x0_suspend(struct device *dev) | |
| 2628 | 2628 | { |
| 2629 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 2629 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 2630 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 2630 | 2631 | struct intel8x0 *chip = card->private_data; |
| 2631 | 2632 | int i; |
| 2632 | 2633 | |
| @@ -2658,13 +2659,14 @@ static int intel8x0_suspend(struct pci_dev *pci, pm_message_t state) · 25 unmodified lines | ||
| 2658 | 2659 | /* The call below may disable built-in speaker on some laptops |
| 2659 | 2660 | * after S2RAM. So, don't touch it. |
| 2660 | 2661 | */ |
| 2661 | − /* pci_set_power_state(pci, pci_choose_state(pci, state)); */ | |
| 2662 | + /* pci_set_power_state(pci, PCI_D3hot); */ | |
| 2662 | 2663 | return 0; |
| 2663 | 2664 | } |
| 2664 | 2665 | |
| 2665 | −static int intel8x0_resume(struct pci_dev *pci) | |
| 2666 | +static int intel8x0_resume(struct device *dev) | |
| 2666 | 2667 | { |
| 2667 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 2668 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 2669 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 2668 | 2670 | struct intel8x0 *chip = card->private_data; |
| 2669 | 2671 | int i; |
| 2670 | 2672 | |
| @@ -2734,6 +2736,11 @@ static int intel8x0_resume(struct pci_dev *pci) · 63 unmodified lines | ||
| 2734 | 2736 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 2735 | 2737 | return 0; |
| 2736 | 2738 | } |
| 2739 | + | |
| 2740 | +static SIMPLE_DEV_PM_OPS(intel8x0_pm, intel8x0_suspend, intel8x0_resume); | |
| 2741 | +#define INTEL8X0_PM_OPS &intel8x0_pm | |
| 2742 | +#else | |
| 2743 | +#define INTEL8X0_PM_OPS NULL | |
| 2737 | 2744 | #endif /* CONFIG_PM */ |
| 2738 | 2745 | |
| 2739 | 2746 | #define INTEL8X0_TESTBUF_SIZE 32768 /* enough large for one shot */ |
| @@ -3343,10 +3350,9 @@ static struct pci_driver intel8x0_driver = { · 603 unmodified lines | ||
| 3343 | 3350 | .id_table = snd_intel8x0_ids, |
| 3344 | 3351 | .probe = snd_intel8x0_probe, |
| 3345 | 3352 | .remove = __devexit_p(snd_intel8x0_remove), |
| 3346 | −#ifdef CONFIG_PM | |
| 3347 | − .suspend = intel8x0_suspend, | |
| 3348 | − .resume = intel8x0_resume, | |
| 3349 | −#endif | |
| 3353 | + .driver = { | |
| 3354 | + .pm = INTEL8X0_PM_OPS, | |
| 3355 | + }, | |
| 3350 | 3356 | }; |
| 3351 | 3357 | |
| 3352 | 3358 | module_pci_driver(intel8x0_driver); |
| @@ -1012,9 +1012,10 @@ static int snd_intel8x0m_free(struct intel8x0m *chip) · 1011 unmodified lines | ||
| 1012 | 1012 | /* |
| 1013 | 1013 | * power management |
| 1014 | 1014 | */ |
| 1015 | −static int intel8x0m_suspend(struct pci_dev *pci, pm_message_t state) | |
| 1015 | +static int intel8x0m_suspend(struct device *dev) | |
| 1016 | 1016 | { |
| 1017 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 1017 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 1018 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 1018 | 1019 | struct intel8x0m *chip = card->private_data; |
| 1019 | 1020 | int i; |
| 1020 | 1021 | |
| @@ -1028,13 +1029,14 @@ static int intel8x0m_suspend(struct pci_dev *pci, pm_message_t state) · 7 unmodified lines | ||
| 1028 | 1029 | } |
| 1029 | 1030 | pci_disable_device(pci); |
| 1030 | 1031 | pci_save_state(pci); |
| 1031 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 1032 | + pci_set_power_state(pci, PCI_D3hot); | |
| 1032 | 1033 | return 0; |
| 1033 | 1034 | } |
| 1034 | 1035 | |
| 1035 | −static int intel8x0m_resume(struct pci_dev *pci) | |
| 1036 | +static int intel8x0m_resume(struct device *dev) | |
| 1036 | 1037 | { |
| 1037 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 1038 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 1039 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 1038 | 1040 | struct intel8x0m *chip = card->private_data; |
| 1039 | 1041 | |
| 1040 | 1042 | pci_set_power_state(pci, PCI_D0); |
| @@ -1060,6 +1062,11 @@ static int intel8x0m_resume(struct pci_dev *pci) · 19 unmodified lines | ||
| 1060 | 1062 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 1061 | 1063 | return 0; |
| 1062 | 1064 | } |
| 1065 | + | |
| 1066 | +static SIMPLE_DEV_PM_OPS(intel8x0m_pm, intel8x0m_suspend, intel8x0m_resume); | |
| 1067 | +#define INTEL8X0M_PM_OPS &intel8x0m_pm | |
| 1068 | +#else | |
| 1069 | +#define INTEL8X0M_PM_OPS NULL | |
| 1063 | 1070 | #endif /* CONFIG_PM */ |
| 1064 | 1071 | |
| 1065 | 1072 | #ifdef CONFIG_PROC_FS |
| @@ -1329,10 +1336,9 @@ static struct pci_driver intel8x0m_driver = { · 263 unmodified lines | ||
| 1329 | 1336 | .id_table = snd_intel8x0m_ids, |
| 1330 | 1337 | .probe = snd_intel8x0m_probe, |
| 1331 | 1338 | .remove = __devexit_p(snd_intel8x0m_remove), |
| 1332 | −#ifdef CONFIG_PM | |
| 1333 | − .suspend = intel8x0m_suspend, | |
| 1334 | − .resume = intel8x0m_resume, | |
| 1335 | −#endif | |
| 1339 | + .driver = { | |
| 1340 | + .pm = INTEL8X0M_PM_OPS, | |
| 1341 | + }, | |
| 1336 | 1342 | }; |
| 1337 | 1343 | |
| 1338 | 1344 | module_pci_driver(intel8x0m_driver); |
| @@ -361,74 +361,6 @@ MODULE_PARM_DESC(amp_gpio, "GPIO pin number for external amp. (default = -1)"); · 360 unmodified lines | ||
| 361 | 361 | #define DSP2HOST_REQ_I2SRATE 0x02 |
| 362 | 362 | #define DSP2HOST_REQ_TIMER 0x04 |
| 363 | 363 | |
| 364 | −/* AC97 registers */ | |
| 365 | −/* XXX fix this crap up */ | |
| 366 | −/*#define AC97_RESET 0x00*/ | |
| 367 | − | |
| 368 | −#define AC97_VOL_MUTE_B 0x8000 | |
| 369 | −#define AC97_VOL_M 0x1F | |
| 370 | −#define AC97_LEFT_VOL_S 8 | |
| 371 | − | |
| 372 | −#define AC97_MASTER_VOL 0x02 | |
| 373 | −#define AC97_LINE_LEVEL_VOL 0x04 | |
| 374 | −#define AC97_MASTER_MONO_VOL 0x06 | |
| 375 | −#define AC97_PC_BEEP_VOL 0x0A | |
| 376 | −#define AC97_PC_BEEP_VOL_M 0x0F | |
| 377 | −#define AC97_SROUND_MASTER_VOL 0x38 | |
| 378 | −#define AC97_PC_BEEP_VOL_S 1 | |
| 379 | − | |
| 380 | −/*#define AC97_PHONE_VOL 0x0C | |
| 381 | −#define AC97_MIC_VOL 0x0E*/ | |
| 382 | −#define AC97_MIC_20DB_ENABLE 0x40 | |
| 383 | − | |
| 384 | −/*#define AC97_LINEIN_VOL 0x10 | |
| 385 | −#define AC97_CD_VOL 0x12 | |
| 386 | −#define AC97_VIDEO_VOL 0x14 | |
| 387 | −#define AC97_AUX_VOL 0x16*/ | |
| 388 | −#define AC97_PCM_OUT_VOL 0x18 | |
| 389 | −/*#define AC97_RECORD_SELECT 0x1A*/ | |
| 390 | −#define AC97_RECORD_MIC 0x00 | |
| 391 | −#define AC97_RECORD_CD 0x01 | |
| 392 | −#define AC97_RECORD_VIDEO 0x02 | |
| 393 | −#define AC97_RECORD_AUX 0x03 | |
| 394 | −#define AC97_RECORD_MONO_MUX 0x02 | |
| 395 | −#define AC97_RECORD_DIGITAL 0x03 | |
| 396 | −#define AC97_RECORD_LINE 0x04 | |
| 397 | −#define AC97_RECORD_STEREO 0x05 | |
| 398 | −#define AC97_RECORD_MONO 0x06 | |
| 399 | −#define AC97_RECORD_PHONE 0x07 | |
| 400 | − | |
| 401 | −/*#define AC97_RECORD_GAIN 0x1C*/ | |
| 402 | −#define AC97_RECORD_VOL_M 0x0F | |
| 403 | − | |
| 404 | −/*#define AC97_GENERAL_PURPOSE 0x20*/ | |
| 405 | −#define AC97_POWER_DOWN_CTRL 0x26 | |
| 406 | −#define AC97_ADC_READY 0x0001 | |
| 407 | −#define AC97_DAC_READY 0x0002 | |
| 408 | −#define AC97_ANALOG_READY 0x0004 | |
| 409 | −#define AC97_VREF_ON 0x0008 | |
| 410 | −#define AC97_PR0 0x0100 | |
| 411 | −#define AC97_PR1 0x0200 | |
| 412 | −#define AC97_PR2 0x0400 | |
| 413 | −#define AC97_PR3 0x0800 | |
| 414 | −#define AC97_PR4 0x1000 | |
| 415 | − | |
| 416 | −#define AC97_RESERVED1 0x28 | |
| 417 | − | |
| 418 | −#define AC97_VENDOR_TEST 0x5A | |
| 419 | − | |
| 420 | −#define AC97_CLOCK_DELAY 0x5C | |
| 421 | −#define AC97_LINEOUT_MUX_SEL 0x0001 | |
| 422 | −#define AC97_MONO_MUX_SEL 0x0002 | |
| 423 | −#define AC97_CLOCK_DELAY_SEL 0x1F | |
| 424 | −#define AC97_DAC_CDS_SHIFT 6 | |
| 425 | −#define AC97_ADC_CDS_SHIFT 11 | |
| 426 | − | |
| 427 | −#define AC97_MULTI_CHANNEL_SEL 0x74 | |
| 428 | − | |
| 429 | −/*#define AC97_VENDOR_ID1 0x7C | |
| 430 | −#define AC97_VENDOR_ID2 0x7E*/ | |
| 431 | − | |
| 432 | 364 | /* |
| 433 | 365 | * ASSP control regs |
| 434 | 366 | */ |
| @@ -2459,9 +2391,10 @@ static int snd_m3_free(struct snd_m3 *chip) · 2024 unmodified lines | ||
| 2459 | 2391 | * APM support |
| 2460 | 2392 | */ |
| 2461 | 2393 | #ifdef CONFIG_PM |
| 2462 | −static int m3_suspend(struct pci_dev *pci, pm_message_t state) | |
| 2394 | +static int m3_suspend(struct device *dev) | |
| 2463 | 2395 | { |
| 2464 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 2396 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 2397 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 2465 | 2398 | struct snd_m3 *chip = card->private_data; |
| 2466 | 2399 | int i, dsp_index; |
| 2467 | 2400 | |
| @@ -2489,13 +2422,14 @@ static int m3_suspend(struct pci_dev *pci, pm_message_t state) · 21 unmodified lines | ||
| 2489 | 2422 | |
| 2490 | 2423 | pci_disable_device(pci); |
| 2491 | 2424 | pci_save_state(pci); |
| 2492 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 2425 | + pci_set_power_state(pci, PCI_D3hot); | |
| 2493 | 2426 | return 0; |
| 2494 | 2427 | } |
| 2495 | 2428 | |
| 2496 | −static int m3_resume(struct pci_dev *pci) | |
| 2429 | +static int m3_resume(struct device *dev) | |
| 2497 | 2430 | { |
| 2498 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 2431 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 2432 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 2499 | 2433 | struct snd_m3 *chip = card->private_data; |
| 2500 | 2434 | int i, dsp_index; |
| 2501 | 2435 | |
| @@ -2546,6 +2480,11 @@ static int m3_resume(struct pci_dev *pci) · 44 unmodified lines | ||
| 2546 | 2480 | chip->in_suspend = 0; |
| 2547 | 2481 | return 0; |
| 2548 | 2482 | } |
| 2483 | + | |
| 2484 | +static SIMPLE_DEV_PM_OPS(m3_pm, m3_suspend, m3_resume); | |
| 2485 | +#define M3_PM_OPS &m3_pm | |
| 2486 | +#else | |
| 2487 | +#define M3_PM_OPS NULL | |
| 2549 | 2488 | #endif /* CONFIG_PM */ |
| 2550 | 2489 | |
| 2551 | 2490 | #ifdef CONFIG_SND_MAESTRO3_INPUT |
| @@ -2842,10 +2781,9 @@ static struct pci_driver m3_driver = { · 290 unmodified lines | ||
| 2842 | 2781 | .id_table = snd_m3_ids, |
| 2843 | 2782 | .probe = snd_m3_probe, |
| 2844 | 2783 | .remove = __devexit_p(snd_m3_remove), |
| 2845 | −#ifdef CONFIG_PM | |
| 2846 | − .suspend = m3_suspend, | |
| 2847 | − .resume = m3_resume, | |
| 2848 | −#endif | |
| 2784 | + .driver = { | |
| 2785 | + .pm = M3_PM_OPS, | |
| 2786 | + }, | |
| 2849 | 2787 | }; |
| 2850 | 2788 | |
| 2851 | 2789 | module_pci_driver(m3_driver); |
| @@ -1382,9 +1382,10 @@ snd_nm256_peek_for_sig(struct nm256 *chip) · 1381 unmodified lines | ||
| 1382 | 1382 | * APM event handler, so the card is properly reinitialized after a power |
| 1383 | 1383 | * event. |
| 1384 | 1384 | */ |
| 1385 | −static int nm256_suspend(struct pci_dev *pci, pm_message_t state) | |
| 1385 | +static int nm256_suspend(struct device *dev) | |
| 1386 | 1386 | { |
| 1387 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 1387 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 1388 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 1388 | 1389 | struct nm256 *chip = card->private_data; |
| 1389 | 1390 | |
| 1390 | 1391 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
| @@ -1393,13 +1394,14 @@ static int nm256_suspend(struct pci_dev *pci, pm_message_t state) · 2 unmodified lines | ||
| 1393 | 1394 | chip->coeffs_current = 0; |
| 1394 | 1395 | pci_disable_device(pci); |
| 1395 | 1396 | pci_save_state(pci); |
| 1396 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 1397 | + pci_set_power_state(pci, PCI_D3hot); | |
| 1397 | 1398 | return 0; |
| 1398 | 1399 | } |
| 1399 | 1400 | |
| 1400 | −static int nm256_resume(struct pci_dev *pci) | |
| 1401 | +static int nm256_resume(struct device *dev) | |
| 1401 | 1402 | { |
| 1402 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 1403 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 1404 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 1403 | 1405 | struct nm256 *chip = card->private_data; |
| 1404 | 1406 | int i; |
| 1405 | 1407 | |
| @@ -1434,6 +1436,11 @@ static int nm256_resume(struct pci_dev *pci) · 28 unmodified lines | ||
| 1434 | 1436 | chip->in_resume = 0; |
| 1435 | 1437 | return 0; |
| 1436 | 1438 | } |
| 1439 | + | |
| 1440 | +static SIMPLE_DEV_PM_OPS(nm256_pm, nm256_suspend, nm256_resume); | |
| 1441 | +#define NM256_PM_OPS &nm256_pm | |
| 1442 | +#else | |
| 1443 | +#define NM256_PM_OPS NULL | |
| 1437 | 1444 | #endif /* CONFIG_PM */ |
| 1438 | 1445 | |
| 1439 | 1446 | static int snd_nm256_free(struct nm256 *chip) |
| @@ -1747,10 +1754,9 @@ static struct pci_driver nm256_driver = { · 307 unmodified lines | ||
| 1747 | 1754 | .id_table = snd_nm256_ids, |
| 1748 | 1755 | .probe = snd_nm256_probe, |
| 1749 | 1756 | .remove = __devexit_p(snd_nm256_remove), |
| 1750 | −#ifdef CONFIG_PM | |
| 1751 | − .suspend = nm256_suspend, | |
| 1752 | − .resume = nm256_resume, | |
| 1753 | −#endif | |
| 1757 | + .driver = { | |
| 1758 | + .pm = NM256_PM_OPS, | |
| 1759 | + }, | |
| 1754 | 1760 | }; |
| 1755 | 1761 | |
| 1756 | 1762 | module_pci_driver(nm256_driver); |
| @@ -873,8 +873,9 @@ static struct pci_driver oxygen_driver = { · 872 unmodified lines | ||
| 873 | 873 | .probe = generic_oxygen_probe, |
| 874 | 874 | .remove = __devexit_p(oxygen_pci_remove), |
| 875 | 875 | #ifdef CONFIG_PM |
| 876 | − .suspend = oxygen_pci_suspend, | |
| 877 | − .resume = oxygen_pci_resume, | |
| 876 | + .driver = { | |
| 877 | + .pm = &oxygen_pci_pm, | |
| 878 | + }, | |
| 878 | 879 | #endif |
| 879 | 880 | }; |
| 880 | 881 | |
| @@ -162,8 +162,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, · 161 unmodified lines | ||
| 162 | 162 | ); |
| 163 | 163 | void oxygen_pci_remove(struct pci_dev *pci); |
| 164 | 164 | #ifdef CONFIG_PM |
| 165 | −int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state); | |
| 166 | −int oxygen_pci_resume(struct pci_dev *pci); | |
| 165 | +extern const struct dev_pm_ops oxygen_pci_pm; | |
| 167 | 166 | #endif |
| 168 | 167 | void oxygen_pci_shutdown(struct pci_dev *pci); |
| 169 | 168 | |
| @@ -727,9 +727,10 @@ void oxygen_pci_remove(struct pci_dev *pci) · 726 unmodified lines | ||
| 727 | 727 | EXPORT_SYMBOL(oxygen_pci_remove); |
| 728 | 728 | |
| 729 | 729 | #ifdef CONFIG_PM |
| 730 | −int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state) | |
| 730 | +static int oxygen_pci_suspend(struct device *dev) | |
| 731 | 731 | { |
| 732 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 732 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 733 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 733 | 734 | struct oxygen *chip = card->private_data; |
| 734 | 735 | unsigned int i, saved_interrupt_mask; |
| 735 | 736 | |
| @@ -756,10 +757,9 @@ int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state) · 20 unmodified lines | ||
| 756 | 757 | |
| 757 | 758 | pci_disable_device(pci); |
| 758 | 759 | pci_save_state(pci); |
| 759 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 760 | + pci_set_power_state(pci, PCI_D3hot); | |
| 760 | 761 | return 0; |
| 761 | 762 | } |
| 762 | −EXPORT_SYMBOL(oxygen_pci_suspend); | |
| 763 | 763 | |
| 764 | 764 | static const u32 registers_to_restore[OXYGEN_IO_SIZE / 32] = { |
| 765 | 765 | 0xffffffff, 0x00ff077f, 0x00011d08, 0x007f00ff, |
| @@ -787,9 +787,10 @@ static void oxygen_restore_ac97(struct oxygen *chip, unsigned int codec) · 21 unmodified lines | ||
| 787 | 787 | chip->saved_ac97_registers[codec][i]); |
| 788 | 788 | } |
| 789 | 789 | |
| 790 | −int oxygen_pci_resume(struct pci_dev *pci) | |
| 790 | +static int oxygen_pci_resume(struct device *dev) | |
| 791 | 791 | { |
| 792 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 792 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 793 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 793 | 794 | struct oxygen *chip = card->private_data; |
| 794 | 795 | unsigned int i; |
| 795 | 796 | |
| @@ -820,7 +821,9 @@ int oxygen_pci_resume(struct pci_dev *pci) · 24 unmodified lines | ||
| 820 | 821 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 821 | 822 | return 0; |
| 822 | 823 | } |
| 823 | −EXPORT_SYMBOL(oxygen_pci_resume); | |
| 824 | + | |
| 825 | +SIMPLE_DEV_PM_OPS(oxygen_pci_pm, oxygen_pci_suspend, oxygen_pci_resume); | |
| 826 | +EXPORT_SYMBOL(oxygen_pci_pm); | |
| 824 | 827 | #endif /* CONFIG_PM */ |
| 825 | 828 | |
| 826 | 829 | void oxygen_pci_shutdown(struct pci_dev *pci) |
| @@ -94,8 +94,9 @@ static struct pci_driver xonar_driver = { · 93 unmodified lines | ||
| 94 | 94 | .probe = xonar_probe, |
| 95 | 95 | .remove = __devexit_p(oxygen_pci_remove), |
| 96 | 96 | #ifdef CONFIG_PM |
| 97 | − .suspend = oxygen_pci_suspend, | |
| 98 | − .resume = oxygen_pci_resume, | |
| 97 | + .driver = { | |
| 98 | + .pm = &oxygen_pci_pm, | |
| 99 | + }, | |
| 99 | 100 | #endif |
| 100 | 101 | .shutdown = oxygen_pci_shutdown, |
| 101 | 102 | }; |
| @@ -1368,6 +1368,67 @@ static void pcxhr_proc_gpo_write(struct snd_info_entry *entry, · 1367 unmodified lines | ||
| 1368 | 1368 | } |
| 1369 | 1369 | } |
| 1370 | 1370 | |
| 1371 | +/* Access to the results of the CMD_GET_TIME_CODE RMH */ | |
| 1372 | +#define TIME_CODE_VALID_MASK 0x00800000 | |
| 1373 | +#define TIME_CODE_NEW_MASK 0x00400000 | |
| 1374 | +#define TIME_CODE_BACK_MASK 0x00200000 | |
| 1375 | +#define TIME_CODE_WAIT_MASK 0x00100000 | |
| 1376 | + | |
| 1377 | +/* Values for the CMD_MANAGE_SIGNAL RMH */ | |
| 1378 | +#define MANAGE_SIGNAL_TIME_CODE 0x01 | |
| 1379 | +#define MANAGE_SIGNAL_MIDI 0x02 | |
| 1380 | + | |
| 1381 | +/* linear time code read proc*/ | |
| 1382 | +static void pcxhr_proc_ltc(struct snd_info_entry *entry, | |
| 1383 | + struct snd_info_buffer *buffer) | |
| 1384 | +{ | |
| 1385 | + struct snd_pcxhr *chip = entry->private_data; | |
| 1386 | + struct pcxhr_mgr *mgr = chip->mgr; | |
| 1387 | + struct pcxhr_rmh rmh; | |
| 1388 | + unsigned int ltcHrs, ltcMin, ltcSec, ltcFrm; | |
| 1389 | + int err; | |
| 1390 | + /* commands available when embedded DSP is running */ | |
| 1391 | + if (!(mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX))) { | |
| 1392 | + snd_iprintf(buffer, "no firmware loaded\n"); | |
| 1393 | + return; | |
| 1394 | + } | |
| 1395 | + if (!mgr->capture_ltc) { | |
| 1396 | + pcxhr_init_rmh(&rmh, CMD_MANAGE_SIGNAL); | |
| 1397 | + rmh.cmd[0] |= MANAGE_SIGNAL_TIME_CODE; | |
| 1398 | + err = pcxhr_send_msg(mgr, &rmh); | |
| 1399 | + if (err) { | |
| 1400 | + snd_iprintf(buffer, "ltc not activated (%d)\n", err); | |
| 1401 | + return; | |
| 1402 | + } | |
| 1403 | + if (mgr->is_hr_stereo) | |
| 1404 | + hr222_manage_timecode(mgr, 1); | |
| 1405 | + else | |
| 1406 | + pcxhr_write_io_num_reg_cont(mgr, REG_CONT_VALSMPTE, | |
| 1407 | + REG_CONT_VALSMPTE, NULL); | |
| 1408 | + mgr->capture_ltc = 1; | |
| 1409 | + } | |
| 1410 | + pcxhr_init_rmh(&rmh, CMD_GET_TIME_CODE); | |
| 1411 | + err = pcxhr_send_msg(mgr, &rmh); | |
| 1412 | + if (err) { | |
| 1413 | + snd_iprintf(buffer, "ltc read error (err=%d)\n", err); | |
| 1414 | + return ; | |
| 1415 | + } | |
| 1416 | + ltcHrs = 10*((rmh.stat[0] >> 8) & 0x3) + (rmh.stat[0] & 0xf); | |
| 1417 | + ltcMin = 10*((rmh.stat[1] >> 16) & 0x7) + ((rmh.stat[1] >> 8) & 0xf); | |
| 1418 | + ltcSec = 10*(rmh.stat[1] & 0x7) + ((rmh.stat[2] >> 16) & 0xf); | |
| 1419 | + ltcFrm = 10*((rmh.stat[2] >> 8) & 0x3) + (rmh.stat[2] & 0xf); | |
| 1420 | + | |
| 1421 | + snd_iprintf(buffer, "timecode: %02u:%02u:%02u-%02u\n", | |
| 1422 | + ltcHrs, ltcMin, ltcSec, ltcFrm); | |
| 1423 | + snd_iprintf(buffer, "raw: 0x%04x%06x%06x\n", rmh.stat[0] & 0x00ffff, | |
| 1424 | + rmh.stat[1] & 0xffffff, rmh.stat[2] & 0xffffff); | |
| 1425 | + /*snd_iprintf(buffer, "dsp ref time: 0x%06x%06x\n", | |
| 1426 | + rmh.stat[3] & 0xffffff, rmh.stat[4] & 0xffffff);*/ | |
| 1427 | + if (!(rmh.stat[0] & TIME_CODE_VALID_MASK)) { | |
| 1428 | + snd_iprintf(buffer, "warning: linear timecode not valid\n"); | |
| 1429 | + } | |
| 1430 | +} | |
| 1431 | + | |
| 1371 | 1432 | static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip) |
| 1372 | 1433 | { |
| 1373 | 1434 | struct snd_info_entry *entry; |
| @@ -1383,6 +1444,8 @@ static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip) · 9 unmodified lines | ||
| 1383 | 1444 | entry->c.text.write = pcxhr_proc_gpo_write; |
| 1384 | 1445 | entry->mode |= S_IWUSR; |
| 1385 | 1446 | } |
| 1447 | + if (!snd_card_proc_new(chip->card, "ltc", &entry)) | |
| 1448 | + snd_info_set_text_ops(entry, chip, pcxhr_proc_ltc); | |
| 1386 | 1449 | } |
| 1387 | 1450 | /* end of proc interface */ |
| 1388 | 1451 | |
| @@ -103,6 +103,7 @@ struct pcxhr_mgr { · 102 unmodified lines | ||
| 103 | 103 | unsigned int board_has_mic:1; /* if 1 the board has microphone input */ |
| 104 | 104 | unsigned int board_aes_in_192k:1;/* if 1 the aes input plugs do support 192kHz */ |
| 105 | 105 | unsigned int mono_capture:1; /* if 1 the board does mono capture */ |
| 106 | + unsigned int capture_ltc:1; /* if 1 the board captures LTC input */ | |
| 106 | 107 | |
| 107 | 108 | struct snd_dma_buffer hostport; |
| 108 | 109 | |
| @@ -504,6 +504,8 @@ static struct pcxhr_cmd_info pcxhr_dsp_cmds[] = { · 503 unmodified lines | ||
| 504 | 504 | [CMD_FORMAT_STREAM_IN] = { 0x870000, 0, RMH_SSIZE_FIXED }, |
| 505 | 505 | [CMD_STREAM_SAMPLE_COUNT] = { 0x902000, 2, RMH_SSIZE_FIXED }, |
| 506 | 506 | [CMD_AUDIO_LEVEL_ADJUST] = { 0xc22000, 0, RMH_SSIZE_FIXED }, |
| 507 | +[CMD_GET_TIME_CODE] = { 0x060000, 5, RMH_SSIZE_FIXED }, | |
| 508 | +[CMD_MANAGE_SIGNAL] = { 0x0f0000, 0, RMH_SSIZE_FIXED }, | |
| 507 | 509 | }; |
| 508 | 510 | |
| 509 | 511 | #ifdef CONFIG_SND_DEBUG_VERBOSE |
| @@ -533,6 +535,8 @@ static char* cmd_names[] = { · 23 unmodified lines | ||
| 533 | 535 | [CMD_FORMAT_STREAM_IN] = "CMD_FORMAT_STREAM_IN", |
| 534 | 536 | [CMD_STREAM_SAMPLE_COUNT] = "CMD_STREAM_SAMPLE_COUNT", |
| 535 | 537 | [CMD_AUDIO_LEVEL_ADJUST] = "CMD_AUDIO_LEVEL_ADJUST", |
| 538 | +[CMD_GET_TIME_CODE] = "CMD_GET_TIME_CODE", | |
| 539 | +[CMD_MANAGE_SIGNAL] = "CMD_MANAGE_SIGNAL", | |
| 536 | 540 | }; |
| 537 | 541 | #endif |
| 538 | 542 | |
| @@ -1133,13 +1137,12 @@ static u_int64_t pcxhr_stream_read_position(struct pcxhr_mgr *mgr, · 594 unmodified lines | ||
| 1133 | 1137 | hw_sample_count = ((u_int64_t)rmh.stat[0]) << 24; |
| 1134 | 1138 | hw_sample_count += (u_int64_t)rmh.stat[1]; |
| 1135 | 1139 | |
| 1136 | − snd_printdd("stream %c%d : abs samples real(%ld) timer(%ld)\n", | |
| 1140 | + snd_printdd("stream %c%d : abs samples real(%llu) timer(%llu)\n", | |
| 1137 | 1141 | stream->pipe->is_capture ? 'C' : 'P', |
| 1138 | 1142 | stream->substream->number, |
| 1139 | − (long unsigned int)hw_sample_count, | |
| 1140 | − (long unsigned int)(stream->timer_abs_periods + | |
| 1141 | − stream->timer_period_frag + | |
| 1142 | − mgr->granularity)); | |
| 1143 | + hw_sample_count, | |
| 1144 | + stream->timer_abs_periods + stream->timer_period_frag + | |
| 1145 | + mgr->granularity); | |
| 1143 | 1146 | return hw_sample_count; |
| 1144 | 1147 | } |
| 1145 | 1148 | |
| @@ -1243,10 +1246,18 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id) · 97 unmodified lines | ||
| 1243 | 1246 | |
| 1244 | 1247 | if ((dsp_time_diff < 0) && |
| 1245 | 1248 | (mgr->dsp_time_last != PCXHR_DSP_TIME_INVALID)) { |
| 1246 | − snd_printdd("ERROR DSP TIME old(%d) new(%d) -> " | |
| 1247 | − "resynchronize all streams\n", | |
| 1249 | + /* handle dsp counter wraparound without resync */ | |
| 1250 | + int tmp_diff = dsp_time_diff + PCXHR_DSP_TIME_MASK + 1; | |
| 1251 | + snd_printdd("WARNING DSP timestamp old(%d) new(%d)", | |
| 1248 | 1252 | mgr->dsp_time_last, dsp_time_new); |
| 1249 | − mgr->dsp_time_err++; | |
| 1253 | + if (tmp_diff > 0 && tmp_diff <= (2*mgr->granularity)) { | |
| 1254 | + snd_printdd("-> timestamp wraparound OK: " | |
| 1255 | + "diff=%d\n", tmp_diff); | |
| 1256 | + dsp_time_diff = tmp_diff; | |
| 1257 | + } else { | |
| 1258 | + snd_printdd("-> resynchronize all streams\n"); | |
| 1259 | + mgr->dsp_time_err++; | |
| 1260 | + } | |
| 1250 | 1261 | } |
| 1251 | 1262 | #ifdef CONFIG_SND_DEBUG_VERBOSE |
| 1252 | 1263 | if (dsp_time_diff == 0) |
| @@ -79,6 +79,8 @@ enum { · 78 unmodified lines | ||
| 79 | 79 | CMD_FORMAT_STREAM_IN, /* cmd_len >= 4 stat_len = 0 */ |
| 80 | 80 | CMD_STREAM_SAMPLE_COUNT, /* cmd_len = 2 stat_len = (2 * nb_stream) */ |
| 81 | 81 | CMD_AUDIO_LEVEL_ADJUST, /* cmd_len = 3 stat_len = 0 */ |
| 82 | + CMD_GET_TIME_CODE, /* cmd_len = 1 stat_len = 5 */ | |
| 83 | + CMD_MANAGE_SIGNAL, /* cmd_len = 1 stat_len = 0 */ | |
| 82 | 84 | CMD_LAST_INDEX |
| 83 | 85 | }; |
| 84 | 86 | |
| @@ -116,7 +118,7 @@ int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh); · 31 unmodified lines | ||
| 116 | 118 | #define IO_NUM_REG_OUT_ANA_LEVEL 20 |
| 117 | 119 | #define IO_NUM_REG_IN_ANA_LEVEL 21 |
| 118 | 120 | |
| 119 | − | |
| 121 | +#define REG_CONT_VALSMPTE 0x000800 | |
| 120 | 122 | #define REG_CONT_UNMUTE_INPUTS 0x020000 |
| 121 | 123 | |
| 122 | 124 | /* parameters used with register IO_NUM_REG_STATUS */ |
| @@ -53,6 +53,7 @@ · 52 unmodified lines | ||
| 53 | 53 | #define PCXHR_DSP_RESET_DSP 0x01 |
| 54 | 54 | #define PCXHR_DSP_RESET_MUTE 0x02 |
| 55 | 55 | #define PCXHR_DSP_RESET_CODEC 0x08 |
| 56 | +#define PCXHR_DSP_RESET_SMPTE 0x10 | |
| 56 | 57 | #define PCXHR_DSP_RESET_GPO_OFFSET 5 |
| 57 | 58 | #define PCXHR_DSP_RESET_GPO_MASK 0x60 |
| 58 | 59 | |
| @@ -527,6 +528,16 @@ int hr222_write_gpo(struct pcxhr_mgr *mgr, int value) · 468 unmodified lines | ||
| 527 | 528 | return 0; |
| 528 | 529 | } |
| 529 | 530 | |
| 531 | +int hr222_manage_timecode(struct pcxhr_mgr *mgr, int enable) | |
| 532 | +{ | |
| 533 | + if (enable) | |
| 534 | + mgr->dsp_reset |= PCXHR_DSP_RESET_SMPTE; | |
| 535 | + else | |
| 536 | + mgr->dsp_reset &= ~PCXHR_DSP_RESET_SMPTE; | |
| 537 | + | |
| 538 | + PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, mgr->dsp_reset); | |
| 539 | + return 0; | |
| 540 | +} | |
| 530 | 541 | |
| 531 | 542 | int hr222_update_analog_audio_level(struct snd_pcxhr *chip, |
| 532 | 543 | int is_capture, int channel) |
| @@ -34,6 +34,7 @@ int hr222_get_external_clock(struct pcxhr_mgr *mgr, · 33 unmodified lines | ||
| 34 | 34 | |
| 35 | 35 | int hr222_read_gpio(struct pcxhr_mgr *mgr, int is_gpi, int *value); |
| 36 | 36 | int hr222_write_gpo(struct pcxhr_mgr *mgr, int value); |
| 37 | +int hr222_manage_timecode(struct pcxhr_mgr *mgr, int enable); | |
| 37 | 38 | |
| 38 | 39 | #define HR222_LINE_PLAYBACK_LEVEL_MIN 0 /* -25.5 dB */ |
| 39 | 40 | #define HR222_LINE_PLAYBACK_ZERO_LEVEL 51 /* 0.0 dB */ |
| @@ -1151,9 +1151,10 @@ static void riptide_handleirq(unsigned long dev_id) · 1150 unmodified lines | ||
| 1151 | 1151 | } |
| 1152 | 1152 | |
| 1153 | 1153 | #ifdef CONFIG_PM |
| 1154 | −static int riptide_suspend(struct pci_dev *pci, pm_message_t state) | |
| 1154 | +static int riptide_suspend(struct device *dev) | |
| 1155 | 1155 | { |
| 1156 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 1156 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 1157 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 1157 | 1158 | struct snd_riptide *chip = card->private_data; |
| 1158 | 1159 | |
| 1159 | 1160 | chip->in_suspend = 1; |
| @@ -1162,13 +1163,14 @@ static int riptide_suspend(struct pci_dev *pci, pm_message_t state) · 2 unmodified lines | ||
| 1162 | 1163 | snd_ac97_suspend(chip->ac97); |
| 1163 | 1164 | pci_disable_device(pci); |
| 1164 | 1165 | pci_save_state(pci); |
| 1165 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 1166 | + pci_set_power_state(pci, PCI_D3hot); | |
| 1166 | 1167 | return 0; |
| 1167 | 1168 | } |
| 1168 | 1169 | |
| 1169 | −static int riptide_resume(struct pci_dev *pci) | |
| 1170 | +static int riptide_resume(struct device *dev) | |
| 1170 | 1171 | { |
| 1171 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 1172 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 1173 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 1172 | 1174 | struct snd_riptide *chip = card->private_data; |
| 1173 | 1175 | |
| 1174 | 1176 | pci_set_power_state(pci, PCI_D0); |
| @@ -1186,7 +1188,12 @@ static int riptide_resume(struct pci_dev *pci) · 11 unmodified lines | ||
| 1186 | 1188 | chip->in_suspend = 0; |
| 1187 | 1189 | return 0; |
| 1188 | 1190 | } |
| 1189 | −#endif | |
| 1191 | + | |
| 1192 | +static SIMPLE_DEV_PM_OPS(riptide_pm, riptide_suspend, riptide_resume); | |
| 1193 | +#define RIPTIDE_PM_OPS &riptide_pm | |
| 1194 | +#else | |
| 1195 | +#define RIPTIDE_PM_OPS NULL | |
| 1196 | +#endif /* CONFIG_PM */ | |
| 1190 | 1197 | |
| 1191 | 1198 | static int try_to_load_firmware(struct cmdif *cif, struct snd_riptide *chip) |
| 1192 | 1199 | { |
| @@ -2180,10 +2187,9 @@ static struct pci_driver driver = { · 987 unmodified lines | ||
| 2180 | 2187 | .id_table = snd_riptide_ids, |
| 2181 | 2188 | .probe = snd_card_riptide_probe, |
| 2182 | 2189 | .remove = __devexit_p(snd_card_riptide_remove), |
| 2183 | −#ifdef CONFIG_PM | |
| 2184 | − .suspend = riptide_suspend, | |
| 2185 | − .resume = riptide_resume, | |
| 2186 | −#endif | |
| 2190 | + .driver = { | |
| 2191 | + .pm = RIPTIDE_PM_OPS, | |
| 2192 | + }, | |
| 2187 | 2193 | }; |
| 2188 | 2194 | |
| 2189 | 2195 | #ifdef SUPPORT_JOYSTICK |
| @@ -1209,9 +1209,10 @@ static int sis_chip_init(struct sis7019 *sis) · 1208 unmodified lines | ||
| 1209 | 1209 | } |
| 1210 | 1210 | |
| 1211 | 1211 | #ifdef CONFIG_PM |
| 1212 | −static int sis_suspend(struct pci_dev *pci, pm_message_t state) | |
| 1212 | +static int sis_suspend(struct device *dev) | |
| 1213 | 1213 | { |
| 1214 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 1214 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 1215 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 1215 | 1216 | struct sis7019 *sis = card->private_data; |
| 1216 | 1217 | void __iomem *ioaddr = sis->ioaddr; |
| 1217 | 1218 | int i; |
| @@ -1241,13 +1242,14 @@ static int sis_suspend(struct pci_dev *pci, pm_message_t state) · 23 unmodified lines | ||
| 1241 | 1242 | |
| 1242 | 1243 | pci_disable_device(pci); |
| 1243 | 1244 | pci_save_state(pci); |
| 1244 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 1245 | + pci_set_power_state(pci, PCI_D3hot); | |
| 1245 | 1246 | return 0; |
| 1246 | 1247 | } |
| 1247 | 1248 | |
| 1248 | −static int sis_resume(struct pci_dev *pci) | |
| 1249 | +static int sis_resume(struct device *dev) | |
| 1249 | 1250 | { |
| 1250 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 1251 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 1252 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 1251 | 1253 | struct sis7019 *sis = card->private_data; |
| 1252 | 1254 | void __iomem *ioaddr = sis->ioaddr; |
| 1253 | 1255 | int i; |
| @@ -1298,6 +1300,11 @@ error: · 44 unmodified lines | ||
| 1298 | 1300 | snd_card_disconnect(card); |
| 1299 | 1301 | return -EIO; |
| 1300 | 1302 | } |
| 1303 | + | |
| 1304 | +static SIMPLE_DEV_PM_OPS(sis_pm, sis_suspend, sis_resume); | |
| 1305 | +#define SIS_PM_OPS &sis_pm | |
| 1306 | +#else | |
| 1307 | +#define SIS_PM_OPS NULL | |
| 1301 | 1308 | #endif /* CONFIG_PM */ |
| 1302 | 1309 | |
| 1303 | 1310 | static int sis_alloc_suspend(struct sis7019 *sis) |
| @@ -1481,11 +1488,9 @@ static struct pci_driver sis7019_driver = { · 177 unmodified lines | ||
| 1481 | 1488 | .id_table = snd_sis7019_ids, |
| 1482 | 1489 | .probe = snd_sis7019_probe, |
| 1483 | 1490 | .remove = __devexit_p(snd_sis7019_remove), |
| 1484 | − | |
| 1485 | −#ifdef CONFIG_PM | |
| 1486 | − .suspend = sis_suspend, | |
| 1487 | − .resume = sis_resume, | |
| 1488 | −#endif | |
| 1491 | + .driver = { | |
| 1492 | + .pm = SIS_PM_OPS, | |
| 1493 | + }, | |
| 1489 | 1494 | }; |
| 1490 | 1495 | |
| 1491 | 1496 | module_pci_driver(sis7019_driver); |
| @@ -26,7 +26,7 @@ · 25 unmodified lines | ||
| 26 | 26 | #include <linux/time.h> |
| 27 | 27 | #include <linux/module.h> |
| 28 | 28 | #include <sound/core.h> |
| 29 | −#include <sound/trident.h> | |
| 29 | +#include "trident.h" | |
| 30 | 30 | #include <sound/initval.h> |
| 31 | 31 | |
| 32 | 32 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, <audio@tridentmicro.com>"); |
| @@ -178,8 +178,9 @@ static struct pci_driver trident_driver = { · 145 unmodified lines | ||
| 178 | 178 | .probe = snd_trident_probe, |
| 179 | 179 | .remove = __devexit_p(snd_trident_remove), |
| 180 | 180 | #ifdef CONFIG_PM |
| 181 | − .suspend = snd_trident_suspend, | |
| 182 | − .resume = snd_trident_resume, | |
| 181 | + .driver = { | |
| 182 | + .pm = &snd_trident_pm, | |
| 183 | + }, | |
| 183 | 184 | #endif |
| 184 | 185 | }; |
| 185 | 186 | |
| @@ -23,10 +23,10 @@ · 22 unmodified lines | ||
| 23 | 23 | * |
| 24 | 24 | */ |
| 25 | 25 | |
| 26 | −#include "pcm.h" | |
| 27 | −#include "mpu401.h" | |
| 28 | −#include "ac97_codec.h" | |
| 29 | −#include "util_mem.h" | |
| 26 | +#include <sound/pcm.h> | |
| 27 | +#include <sound/mpu401.h> | |
| 28 | +#include <sound/ac97_codec.h> | |
| 29 | +#include <sound/util_mem.h> | |
| 30 | 30 | |
| 31 | 31 | #define TRIDENT_DEVICE_ID_DX ((PCI_VENDOR_ID_TRIDENT<<16)|PCI_DEVICE_ID_TRIDENT_4DWAVE_DX) |
| 32 | 32 | #define TRIDENT_DEVICE_ID_NX ((PCI_VENDOR_ID_TRIDENT<<16)|PCI_DEVICE_ID_TRIDENT_4DWAVE_NX) |
| @@ -430,8 +430,7 @@ void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voi · 397 unmodified lines | ||
| 430 | 430 | void snd_trident_start_voice(struct snd_trident * trident, unsigned int voice); |
| 431 | 431 | void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice); |
| 432 | 432 | void snd_trident_write_voice_regs(struct snd_trident * trident, struct snd_trident_voice *voice); |
| 433 | −int snd_trident_suspend(struct pci_dev *pci, pm_message_t state); | |
| 434 | −int snd_trident_resume(struct pci_dev *pci); | |
| 433 | +extern const struct dev_pm_ops snd_trident_pm; | |
| 435 | 434 | |
| 436 | 435 | /* TLB memory allocation */ |
| 437 | 436 | struct snd_util_memblk *snd_trident_alloc_pages(struct snd_trident *trident, |
| @@ -41,7 +41,7 @@ · 40 unmodified lines | ||
| 41 | 41 | #include <sound/info.h> |
| 42 | 42 | #include <sound/control.h> |
| 43 | 43 | #include <sound/tlv.h> |
| 44 | −#include <sound/trident.h> | |
| 44 | +#include "trident.h" | |
| 45 | 45 | #include <sound/asoundef.h> |
| 46 | 46 | |
| 47 | 47 | #include <asm/io.h> |
| @@ -3920,9 +3920,10 @@ static void snd_trident_clear_voices(struct snd_trident * trident, unsigned shor · 3872 unmodified lines | ||
| 3920 | 3920 | } |
| 3921 | 3921 | |
| 3922 | 3922 | #ifdef CONFIG_PM |
| 3923 | −int snd_trident_suspend(struct pci_dev *pci, pm_message_t state) | |
| 3923 | +static int snd_trident_suspend(struct device *dev) | |
| 3924 | 3924 | { |
| 3925 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 3925 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 3926 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 3926 | 3927 | struct snd_trident *trident = card->private_data; |
| 3927 | 3928 | |
| 3928 | 3929 | trident->in_suspend = 1; |
| @@ -3936,13 +3937,14 @@ int snd_trident_suspend(struct pci_dev *pci, pm_message_t state) · 7 unmodified lines | ||
| 3936 | 3937 | |
| 3937 | 3938 | pci_disable_device(pci); |
| 3938 | 3939 | pci_save_state(pci); |
| 3939 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 3940 | + pci_set_power_state(pci, PCI_D3hot); | |
| 3940 | 3941 | return 0; |
| 3941 | 3942 | } |
| 3942 | 3943 | |
| 3943 | −int snd_trident_resume(struct pci_dev *pci) | |
| 3944 | +static int snd_trident_resume(struct device *dev) | |
| 3944 | 3945 | { |
| 3945 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 3946 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 3947 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 3946 | 3948 | struct snd_trident *trident = card->private_data; |
| 3947 | 3949 | |
| 3948 | 3950 | pci_set_power_state(pci, PCI_D0); |
| @@ -3979,4 +3981,6 @@ int snd_trident_resume(struct pci_dev *pci) · 30 unmodified lines | ||
| 3979 | 3981 | trident->in_suspend = 0; |
| 3980 | 3982 | return 0; |
| 3981 | 3983 | } |
| 3984 | + | |
| 3985 | +SIMPLE_DEV_PM_OPS(snd_trident_pm, snd_trident_suspend, snd_trident_resume); | |
| 3982 | 3986 | #endif /* CONFIG_PM */ |
| @@ -29,7 +29,7 @@ · 28 unmodified lines | ||
| 29 | 29 | #include <linux/mutex.h> |
| 30 | 30 | |
| 31 | 31 | #include <sound/core.h> |
| 32 | −#include <sound/trident.h> | |
| 32 | +#include "trident.h" | |
| 33 | 33 | |
| 34 | 34 | /* page arguments of these two macros are Trident page (4096 bytes), not like |
| 35 | 35 | * aligned pages in others |
| @@ -2242,9 +2242,10 @@ static int snd_via82xx_chip_init(struct via82xx *chip) · 2241 unmodified lines | ||
| 2242 | 2242 | /* |
| 2243 | 2243 | * power management |
| 2244 | 2244 | */ |
| 2245 | −static int snd_via82xx_suspend(struct pci_dev *pci, pm_message_t state) | |
| 2245 | +static int snd_via82xx_suspend(struct device *dev) | |
| 2246 | 2246 | { |
| 2247 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 2247 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 2248 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 2248 | 2249 | struct via82xx *chip = card->private_data; |
| 2249 | 2250 | int i; |
| 2250 | 2251 | |
| @@ -2265,13 +2266,14 @@ static int snd_via82xx_suspend(struct pci_dev *pci, pm_message_t state) · 14 unmodified lines | ||
| 2265 | 2266 | |
| 2266 | 2267 | pci_disable_device(pci); |
| 2267 | 2268 | pci_save_state(pci); |
| 2268 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 2269 | + pci_set_power_state(pci, PCI_D3hot); | |
| 2269 | 2270 | return 0; |
| 2270 | 2271 | } |
| 2271 | 2272 | |
| 2272 | −static int snd_via82xx_resume(struct pci_dev *pci) | |
| 2273 | +static int snd_via82xx_resume(struct device *dev) | |
| 2273 | 2274 | { |
| 2274 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 2275 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 2276 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 2275 | 2277 | struct via82xx *chip = card->private_data; |
| 2276 | 2278 | int i; |
| 2277 | 2279 | |
| @@ -2306,6 +2308,11 @@ static int snd_via82xx_resume(struct pci_dev *pci) · 28 unmodified lines | ||
| 2306 | 2308 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 2307 | 2309 | return 0; |
| 2308 | 2310 | } |
| 2311 | + | |
| 2312 | +static SIMPLE_DEV_PM_OPS(snd_via82xx_pm, snd_via82xx_suspend, snd_via82xx_resume); | |
| 2313 | +#define SND_VIA82XX_PM_OPS &snd_via82xx_pm | |
| 2314 | +#else | |
| 2315 | +#define SND_VIA82XX_PM_OPS NULL | |
| 2309 | 2316 | #endif /* CONFIG_PM */ |
| 2310 | 2317 | |
| 2311 | 2318 | static int snd_via82xx_free(struct via82xx *chip) |
| @@ -2624,10 +2631,9 @@ static struct pci_driver via82xx_driver = { · 312 unmodified lines | ||
| 2624 | 2631 | .id_table = snd_via82xx_ids, |
| 2625 | 2632 | .probe = snd_via82xx_probe, |
| 2626 | 2633 | .remove = __devexit_p(snd_via82xx_remove), |
| 2627 | −#ifdef CONFIG_PM | |
| 2628 | − .suspend = snd_via82xx_suspend, | |
| 2629 | − .resume = snd_via82xx_resume, | |
| 2630 | −#endif | |
| 2634 | + .driver = { | |
| 2635 | + .pm = SND_VIA82XX_PM_OPS, | |
| 2636 | + }, | |
| 2631 | 2637 | }; |
| 2632 | 2638 | |
| 2633 | 2639 | module_pci_driver(via82xx_driver); |
| @@ -1023,9 +1023,10 @@ static int snd_via82xx_chip_init(struct via82xx_modem *chip) · 1022 unmodified lines | ||
| 1023 | 1023 | /* |
| 1024 | 1024 | * power management |
| 1025 | 1025 | */ |
| 1026 | −static int snd_via82xx_suspend(struct pci_dev *pci, pm_message_t state) | |
| 1026 | +static int snd_via82xx_suspend(struct device *dev) | |
| 1027 | 1027 | { |
| 1028 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 1028 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 1029 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 1029 | 1030 | struct via82xx_modem *chip = card->private_data; |
| 1030 | 1031 | int i; |
| 1031 | 1032 | |
| @@ -1039,13 +1040,14 @@ static int snd_via82xx_suspend(struct pci_dev *pci, pm_message_t state) · 7 unmodified lines | ||
| 1039 | 1040 | |
| 1040 | 1041 | pci_disable_device(pci); |
| 1041 | 1042 | pci_save_state(pci); |
| 1042 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 1043 | + pci_set_power_state(pci, PCI_D3hot); | |
| 1043 | 1044 | return 0; |
| 1044 | 1045 | } |
| 1045 | 1046 | |
| 1046 | −static int snd_via82xx_resume(struct pci_dev *pci) | |
| 1047 | +static int snd_via82xx_resume(struct device *dev) | |
| 1047 | 1048 | { |
| 1048 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 1049 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 1050 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 1049 | 1051 | struct via82xx_modem *chip = card->private_data; |
| 1050 | 1052 | int i; |
| 1051 | 1053 | |
| @@ -1069,6 +1071,11 @@ static int snd_via82xx_resume(struct pci_dev *pci) · 17 unmodified lines | ||
| 1069 | 1071 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 1070 | 1072 | return 0; |
| 1071 | 1073 | } |
| 1074 | + | |
| 1075 | +static SIMPLE_DEV_PM_OPS(snd_via82xx_pm, snd_via82xx_suspend, snd_via82xx_resume); | |
| 1076 | +#define SND_VIA82XX_PM_OPS &snd_via82xx_pm | |
| 1077 | +#else | |
| 1078 | +#define SND_VIA82XX_PM_OPS NULL | |
| 1072 | 1079 | #endif /* CONFIG_PM */ |
| 1073 | 1080 | |
| 1074 | 1081 | static int snd_via82xx_free(struct via82xx_modem *chip) |
| @@ -1228,10 +1235,9 @@ static struct pci_driver via82xx_modem_driver = { · 153 unmodified lines | ||
| 1228 | 1235 | .id_table = snd_via82xx_modem_ids, |
| 1229 | 1236 | .probe = snd_via82xx_probe, |
| 1230 | 1237 | .remove = __devexit_p(snd_via82xx_remove), |
| 1231 | −#ifdef CONFIG_PM | |
| 1232 | − .suspend = snd_via82xx_suspend, | |
| 1233 | − .resume = snd_via82xx_resume, | |
| 1234 | −#endif | |
| 1238 | + .driver = { | |
| 1239 | + .pm = SND_VIA82XX_PM_OPS, | |
| 1240 | + }, | |
| 1235 | 1241 | }; |
| 1236 | 1242 | |
| 1237 | 1243 | module_pci_driver(via82xx_modem_driver); |
| @@ -258,22 +258,24 @@ static void __devexit snd_vx222_remove(struct pci_dev *pci) · 257 unmodified lines | ||
| 258 | 258 | } |
| 259 | 259 | |
| 260 | 260 | #ifdef CONFIG_PM |
| 261 | −static int snd_vx222_suspend(struct pci_dev *pci, pm_message_t state) | |
| 261 | +static int snd_vx222_suspend(struct device *dev) | |
| 262 | 262 | { |
| 263 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 263 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 264 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 264 | 265 | struct snd_vx222 *vx = card->private_data; |
| 265 | 266 | int err; |
| 266 | 267 | |
| 267 | − err = snd_vx_suspend(&vx->core, state); | |
| 268 | + err = snd_vx_suspend(&vx->core); | |
| 268 | 269 | pci_disable_device(pci); |
| 269 | 270 | pci_save_state(pci); |
| 270 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 271 | + pci_set_power_state(pci, PCI_D3hot); | |
| 271 | 272 | return err; |
| 272 | 273 | } |
| 273 | 274 | |
| 274 | −static int snd_vx222_resume(struct pci_dev *pci) | |
| 275 | +static int snd_vx222_resume(struct device *dev) | |
| 275 | 276 | { |
| 276 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 277 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 278 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 277 | 279 | struct snd_vx222 *vx = card->private_data; |
| 278 | 280 | |
| 279 | 281 | pci_set_power_state(pci, PCI_D0); |
| @@ -287,6 +289,11 @@ static int snd_vx222_resume(struct pci_dev *pci) · 7 unmodified lines | ||
| 287 | 289 | pci_set_master(pci); |
| 288 | 290 | return snd_vx_resume(&vx->core); |
| 289 | 291 | } |
| 292 | + | |
| 293 | +static SIMPLE_DEV_PM_OPS(snd_vx222_pm, snd_vx222_suspend, snd_vx222_resume); | |
| 294 | +#define SND_VX222_PM_OPS &snd_vx222_pm | |
| 295 | +#else | |
| 296 | +#define SND_VX222_PM_OPS NULL | |
| 290 | 297 | #endif |
| 291 | 298 | |
| 292 | 299 | static struct pci_driver vx222_driver = { |
| @@ -294,10 +301,9 @@ static struct pci_driver vx222_driver = { · 1 unmodified line | ||
| 294 | 301 | .id_table = snd_vx222_ids, |
| 295 | 302 | .probe = snd_vx222_probe, |
| 296 | 303 | .remove = __devexit_p(snd_vx222_remove), |
| 297 | −#ifdef CONFIG_PM | |
| 298 | − .suspend = snd_vx222_suspend, | |
| 299 | − .resume = snd_vx222_resume, | |
| 300 | −#endif | |
| 304 | + .driver = { | |
| 305 | + .pm = SND_VX222_PM_OPS, | |
| 306 | + }, | |
| 301 | 307 | }; |
| 302 | 308 | |
| 303 | 309 | module_pci_driver(vx222_driver); |
| @@ -24,7 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | #include <linux/time.h> |
| 25 | 25 | #include <linux/module.h> |
| 26 | 26 | #include <sound/core.h> |
| 27 | −#include <sound/ymfpci.h> | |
| 27 | +#include "ymfpci.h" | |
| 28 | 28 | #include <sound/mpu401.h> |
| 29 | 29 | #include <sound/opl3.h> |
| 30 | 30 | #include <sound/initval.h> |
| @@ -356,8 +356,9 @@ static struct pci_driver ymfpci_driver = { · 325 unmodified lines | ||
| 356 | 356 | .probe = snd_card_ymfpci_probe, |
| 357 | 357 | .remove = __devexit_p(snd_card_ymfpci_remove), |
| 358 | 358 | #ifdef CONFIG_PM |
| 359 | − .suspend = snd_ymfpci_suspend, | |
| 360 | − .resume = snd_ymfpci_resume, | |
| 359 | + .driver = { | |
| 360 | + .pm = &snd_ymfpci_pm, | |
| 361 | + }, | |
| 361 | 362 | #endif |
| 362 | 363 | }; |
| 363 | 364 | |
| @@ -22,10 +22,10 @@ · 21 unmodified lines | ||
| 22 | 22 | * |
| 23 | 23 | */ |
| 24 | 24 | |
| 25 | −#include "pcm.h" | |
| 26 | −#include "rawmidi.h" | |
| 27 | −#include "ac97_codec.h" | |
| 28 | −#include "timer.h" | |
| 25 | +#include <sound/pcm.h> | |
| 26 | +#include <sound/rawmidi.h> | |
| 27 | +#include <sound/ac97_codec.h> | |
| 28 | +#include <sound/timer.h> | |
| 29 | 29 | #include <linux/gameport.h> |
| 30 | 30 | |
| 31 | 31 | /* |
| @@ -377,8 +377,7 @@ int snd_ymfpci_create(struct snd_card *card, · 345 unmodified lines | ||
| 377 | 377 | struct snd_ymfpci ** rcodec); |
| 378 | 378 | void snd_ymfpci_free_gameport(struct snd_ymfpci *chip); |
| 379 | 379 | |
| 380 | −int snd_ymfpci_suspend(struct pci_dev *pci, pm_message_t state); | |
| 381 | −int snd_ymfpci_resume(struct pci_dev *pci); | |
| 380 | +extern const struct dev_pm_ops snd_ymfpci_pm; | |
| 382 | 381 | |
| 383 | 382 | int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm); |
| 384 | 383 | int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm); |
| @@ -33,7 +33,7 @@ · 32 unmodified lines | ||
| 33 | 33 | #include <sound/control.h> |
| 34 | 34 | #include <sound/info.h> |
| 35 | 35 | #include <sound/tlv.h> |
| 36 | −#include <sound/ymfpci.h> | |
| 36 | +#include "ymfpci.h" | |
| 37 | 37 | #include <sound/asoundef.h> |
| 38 | 38 | #include <sound/mpu401.h> |
| 39 | 39 | |
| @@ -2302,9 +2302,10 @@ static int saved_regs_index[] = { · 2262 unmodified lines | ||
| 2302 | 2302 | }; |
| 2303 | 2303 | #define YDSXGR_NUM_SAVED_REGS ARRAY_SIZE(saved_regs_index) |
| 2304 | 2304 | |
| 2305 | −int snd_ymfpci_suspend(struct pci_dev *pci, pm_message_t state) | |
| 2305 | +static int snd_ymfpci_suspend(struct device *dev) | |
| 2306 | 2306 | { |
| 2307 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 2307 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 2308 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 2308 | 2309 | struct snd_ymfpci *chip = card->private_data; |
| 2309 | 2310 | unsigned int i; |
| 2310 | 2311 | |
| @@ -2326,13 +2327,14 @@ int snd_ymfpci_suspend(struct pci_dev *pci, pm_message_t state) · 15 unmodified lines | ||
| 2326 | 2327 | snd_ymfpci_disable_dsp(chip); |
| 2327 | 2328 | pci_disable_device(pci); |
| 2328 | 2329 | pci_save_state(pci); |
| 2329 | − pci_set_power_state(pci, pci_choose_state(pci, state)); | |
| 2330 | + pci_set_power_state(pci, PCI_D3hot); | |
| 2330 | 2331 | return 0; |
| 2331 | 2332 | } |
| 2332 | 2333 | |
| 2333 | −int snd_ymfpci_resume(struct pci_dev *pci) | |
| 2334 | +static int snd_ymfpci_resume(struct device *dev) | |
| 2334 | 2335 | { |
| 2335 | − struct snd_card *card = pci_get_drvdata(pci); | |
| 2336 | + struct pci_dev *pci = to_pci_dev(dev); | |
| 2337 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 2336 | 2338 | struct snd_ymfpci *chip = card->private_data; |
| 2337 | 2339 | unsigned int i; |
| 2338 | 2340 | |
| @@ -2370,6 +2372,8 @@ int snd_ymfpci_resume(struct pci_dev *pci) · 31 unmodified lines | ||
| 2370 | 2372 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 2371 | 2373 | return 0; |
| 2372 | 2374 | } |
| 2375 | + | |
| 2376 | +SIMPLE_DEV_PM_OPS(snd_ymfpci_pm, snd_ymfpci_suspend, snd_ymfpci_resume); | |
| 2373 | 2377 | #endif /* CONFIG_PM */ |
| 2374 | 2378 | |
| 2375 | 2379 | int __devinit snd_ymfpci_create(struct snd_card *card, |
| @@ -251,7 +251,7 @@ static int pdacf_suspend(struct pcmcia_device *link) · 250 unmodified lines | ||
| 251 | 251 | snd_printdd(KERN_DEBUG "SUSPEND\n"); |
| 252 | 252 | if (chip) { |
| 253 | 253 | snd_printdd(KERN_DEBUG "snd_pdacf_suspend calling\n"); |
| 254 | − snd_pdacf_suspend(chip, PMSG_SUSPEND); | |
| 254 | + snd_pdacf_suspend(chip); | |
| 255 | 255 | } |
| 256 | 256 | |
| 257 | 257 | return 0; |
| @@ -131,7 +131,7 @@ struct snd_pdacf *snd_pdacf_create(struct snd_card *card); · 130 unmodified lines | ||
| 131 | 131 | int snd_pdacf_ak4117_create(struct snd_pdacf *pdacf); |
| 132 | 132 | void snd_pdacf_powerdown(struct snd_pdacf *chip); |
| 133 | 133 | #ifdef CONFIG_PM |
| 134 | −int snd_pdacf_suspend(struct snd_pdacf *chip, pm_message_t state); | |
| 134 | +int snd_pdacf_suspend(struct snd_pdacf *chip); | |
| 135 | 135 | int snd_pdacf_resume(struct snd_pdacf *chip); |
| 136 | 136 | #endif |
| 137 | 137 | int snd_pdacf_pcm_new(struct snd_pdacf *chip); |
| @@ -262,7 +262,7 @@ void snd_pdacf_powerdown(struct snd_pdacf *chip) · 261 unmodified lines | ||
| 262 | 262 | |
| 263 | 263 | #ifdef CONFIG_PM |
| 264 | 264 | |
| 265 | −int snd_pdacf_suspend(struct snd_pdacf *chip, pm_message_t state) | |
| 265 | +int snd_pdacf_suspend(struct snd_pdacf *chip) | |
| 266 | 266 | { |
| 267 | 267 | u16 val; |
| 268 | 268 | |
| @@ -260,7 +260,7 @@ static int vxp_suspend(struct pcmcia_device *link) · 259 unmodified lines | ||
| 260 | 260 | snd_printdd(KERN_DEBUG "SUSPEND\n"); |
| 261 | 261 | if (chip) { |
| 262 | 262 | snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n"); |
| 263 | − snd_vx_suspend(chip, PMSG_SUSPEND); | |
| 263 | + snd_vx_suspend(chip); | |
| 264 | 264 | } |
| 265 | 265 | |
| 266 | 266 | return 0; |
| @@ -144,19 +144,24 @@ static int __devexit snd_pmac_remove(struct platform_device *devptr) · 143 unmodified lines | ||
| 144 | 144 | } |
| 145 | 145 | |
| 146 | 146 | #ifdef CONFIG_PM |
| 147 | −static int snd_pmac_driver_suspend(struct platform_device *devptr, pm_message_t state) | |
| 147 | +static int snd_pmac_driver_suspend(struct device *dev) | |
| 148 | 148 | { |
| 149 | − struct snd_card *card = platform_get_drvdata(devptr); | |
| 149 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 150 | 150 | snd_pmac_suspend(card->private_data); |
| 151 | 151 | return 0; |
| 152 | 152 | } |
| 153 | 153 | |
| 154 | −static int snd_pmac_driver_resume(struct platform_device *devptr) | |
| 154 | +static int snd_pmac_driver_resume(struct device *dev) | |
| 155 | 155 | { |
| 156 | − struct snd_card *card = platform_get_drvdata(devptr); | |
| 156 | + struct snd_card *card = dev_get_drvdata(dev); | |
| 157 | 157 | snd_pmac_resume(card->private_data); |
| 158 | 158 | return 0; |
| 159 | 159 | } |
| 160 | + | |
| 161 | +static SIMPLE_DEV_PM_OPS(snd_pmac_pm, snd_pmac_driver_suspend, snd_pmac_driver_resume); | |
| 162 | +#define SND_PMAC_PM_OPS &snd_pmac_pm | |
| 163 | +#else | |
| 164 | +#define SND_PMAC_PM_OPS NULL | |
| 160 | 165 | #endif |
| 161 | 166 | |
| 162 | 167 | #define SND_PMAC_DRIVER "snd_powermac" |
| @@ -164,12 +169,10 @@ static int snd_pmac_driver_resume(struct platform_device *devptr) · 1 unmodified line | ||
| 164 | 169 | static struct platform_driver snd_pmac_driver = { |
| 165 | 170 | .probe = snd_pmac_probe, |
| 166 | 171 | .remove = __devexit_p(snd_pmac_remove), |
| 167 | −#ifdef CONFIG_PM | |
| 168 | − .suspend = snd_pmac_driver_suspend, | |
| 169 | − .resume = snd_pmac_driver_resume, | |
| 170 | −#endif | |
| 171 | 172 | .driver = { |
| 172 | − .name = SND_PMAC_DRIVER | |
| 173 | + .name = SND_PMAC_DRIVER, | |
| 174 | + .owner = THIS_MODULE, | |
| 175 | + .pm = SND_PMAC_PM_OPS, | |
| 173 | 176 | }, |
| 174 | 177 | }; |
| 175 | 178 | |
| @@ -654,7 +654,9 @@ static struct platform_driver snd_aica_driver = { · 653 unmodified lines | ||
| 654 | 654 | .probe = snd_aica_probe, |
| 655 | 655 | .remove = __devexit_p(snd_aica_remove), |
| 656 | 656 | .driver = { |
| 657 | − .name = SND_AICA_DRIVER}, | |
| 657 | + .name = SND_AICA_DRIVER, | |
| 658 | + .owner = THIS_MODULE, | |
| 659 | + }, | |
| 658 | 660 | }; |
| 659 | 661 | |
| 660 | 662 | static int __init aica_init(void) |
| @@ -438,6 +438,7 @@ static struct platform_driver sh_dac_driver = { · 437 unmodified lines | ||
| 438 | 438 | .remove = snd_sh_dac_remove, |
| 439 | 439 | .driver = { |
| 440 | 440 | .name = "dac_audio", |
| 441 | + .owner = THIS_MODULE, | |
| 441 | 442 | }, |
| 442 | 443 | }; |
| 443 | 444 | |
| @@ -33,6 +33,7 @@ source "sound/soc/atmel/Kconfig" · 32 unmodified lines | ||
| 33 | 33 | source "sound/soc/au1x/Kconfig" |
| 34 | 34 | source "sound/soc/blackfin/Kconfig" |
| 35 | 35 | source "sound/soc/davinci/Kconfig" |
| 36 | +source "sound/soc/dwc/Kconfig" | |
| 36 | 37 | source "sound/soc/ep93xx/Kconfig" |
| 37 | 38 | source "sound/soc/fsl/Kconfig" |
| 38 | 39 | source "sound/soc/jz4740/Kconfig" |
| @@ -11,6 +11,7 @@ obj-$(CONFIG_SND_SOC) += atmel/ · 10 unmodified lines | ||
| 11 | 11 | obj-$(CONFIG_SND_SOC) += au1x/ |
| 12 | 12 | obj-$(CONFIG_SND_SOC) += blackfin/ |
| 13 | 13 | obj-$(CONFIG_SND_SOC) += davinci/ |
| 14 | +obj-$(CONFIG_SND_SOC) += dwc/ | |
| 14 | 15 | obj-$(CONFIG_SND_SOC) += ep93xx/ |
| 15 | 16 | obj-$(CONFIG_SND_SOC) += fsl/ |
| 16 | 17 | obj-$(CONFIG_SND_SOC) += jz4740/ |
| @@ -1,7 +1,8 @@ | ||
| 1 | 1 | config SND_BF5XX_I2S |
| 2 | − tristate "SoC I2S Audio for the ADI BF5xx chip" | |
| 2 | + tristate "SoC I2S Audio for the ADI Blackfin chip" | |
| 3 | 3 | depends on BLACKFIN |
| 4 | − select SND_BF5XX_SOC_SPORT | |
| 4 | + select SND_BF5XX_SOC_SPORT if !BF60x | |
| 5 | + select SND_BF6XX_SOC_SPORT if BF60x | |
| 5 | 6 | help |
| 6 | 7 | Say Y or M if you want to add support for codecs attached to |
| 7 | 8 | the Blackfin SPORT (synchronous serial ports) interface in I2S |
| @@ -9,12 +10,14 @@ config SND_BF5XX_I2S · 1 unmodified line | ||
| 9 | 10 | You will also need to select the audio interfaces to support below. |
| 10 | 11 | |
| 11 | 12 | config SND_BF5XX_SOC_SSM2602 |
| 12 | − tristate "SoC SSM2602 Audio support for BF52x ezkit" | |
| 13 | + tristate "SoC SSM2602 Audio Codec Add-On Card support" | |
| 13 | 14 | depends on SND_BF5XX_I2S && (SPI_MASTER || I2C) |
| 14 | − select SND_BF5XX_SOC_I2S | |
| 15 | + select SND_BF5XX_SOC_I2S if !BF60x | |
| 16 | + select SND_BF6XX_SOC_I2S if BF60x | |
| 15 | 17 | select SND_SOC_SSM2602 |
| 16 | 18 | help |
| 17 | − Say Y if you want to add support for SoC audio on BF527-EZKIT. | |
| 19 | + Say Y if you want to add support for the Analog Devices | |
| 20 | + SSM2602 Audio Codec Add-On Card. | |
| 18 | 21 | |
| 19 | 22 | config SND_SOC_BFIN_EVAL_ADAU1701 |
| 20 | 23 | tristate "Support for the EVAL-ADAU1701MINIZ board on Blackfin eval boards" |
| @@ -162,9 +165,15 @@ config SND_BF5XX_SOC_AD1980 · 141 unmodified lines | ||
| 162 | 165 | config SND_BF5XX_SOC_SPORT |
| 163 | 166 | tristate |
| 164 | 167 | |
| 168 | +config SND_BF6XX_SOC_SPORT | |
| 169 | + tristate | |
| 170 | + | |
| 165 | 171 | config SND_BF5XX_SOC_I2S |
| 166 | 172 | tristate |
| 167 | 173 | |
| 174 | +config SND_BF6XX_SOC_I2S | |
| 175 | + tristate | |
| 176 | + | |
| 168 | 177 | config SND_BF5XX_SOC_TDM |
| 169 | 178 | tristate |
| 170 | 179 | |
| @@ -173,7 +182,7 @@ config SND_BF5XX_SOC_AC97 · 2 unmodified lines | ||
| 173 | 182 | |
| 174 | 183 | config SND_BF5XX_SPORT_NUM |
| 175 | 184 | int "Set a SPORT for Sound chip" |
| 176 | − depends on (SND_BF5XX_I2S || SND_BF5XX_AC97 || SND_BF5XX_TDM) | |
| 185 | + depends on (SND_BF5XX_SOC_SPORT || SND_BF6XX_SOC_SPORT) | |
| 177 | 186 | range 0 3 if BF54x |
| 178 | 187 | range 0 1 if !BF54x |
| 179 | 188 | default 0 |
| @@ -3,16 +3,20 @@ snd-bf5xx-ac97-objs := bf5xx-ac97-pcm.o · 2 unmodified lines | ||
| 3 | 3 | snd-bf5xx-i2s-objs := bf5xx-i2s-pcm.o |
| 4 | 4 | snd-bf5xx-tdm-objs := bf5xx-tdm-pcm.o |
| 5 | 5 | snd-soc-bf5xx-sport-objs := bf5xx-sport.o |
| 6 | +snd-soc-bf6xx-sport-objs := bf6xx-sport.o | |
| 6 | 7 | snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o |
| 7 | 8 | snd-soc-bf5xx-i2s-objs := bf5xx-i2s.o |
| 9 | +snd-soc-bf6xx-i2s-objs := bf6xx-i2s.o | |
| 8 | 10 | snd-soc-bf5xx-tdm-objs := bf5xx-tdm.o |
| 9 | 11 | |
| 10 | 12 | obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o |
| 11 | 13 | obj-$(CONFIG_SND_BF5XX_I2S) += snd-bf5xx-i2s.o |
| 12 | 14 | obj-$(CONFIG_SND_BF5XX_TDM) += snd-bf5xx-tdm.o |
| 13 | 15 | obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o |
| 16 | +obj-$(CONFIG_SND_BF6XX_SOC_SPORT) += snd-soc-bf6xx-sport.o | |
| 14 | 17 | obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o |
| 15 | 18 | obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o |
| 19 | +obj-$(CONFIG_SND_BF6XX_SOC_I2S) += snd-soc-bf6xx-i2s.o | |
| 16 | 20 | obj-$(CONFIG_SND_BF5XX_SOC_TDM) += snd-soc-bf5xx-tdm.o |
| 17 | 21 | |
| 18 | 22 | # Blackfin Machine Support |
| @@ -0,0 +1,234 @@ | ||
| 1 | +/* | |
| 2 | + * bf6xx-i2s.c - Analog Devices BF6XX i2s interface driver | |
| 3 | + * | |
| 4 | + * Copyright (c) 2012 Analog Devices Inc. | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License version 2 as | |
| 8 | + * published by the Free Software Foundation. | |
| 9 | + * | |
| 10 | + * This program is distributed in the hope that it will be useful, | |
| 11 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 12 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 13 | + * GNU General Public License for more details. | |
| 14 | + * | |
| 15 | + * You should have received a copy of the GNU General Public License | |
| 16 | + * along with this program; if not, write to the Free Software | |
| 17 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
| 18 | + */ | |
| 19 | + | |
| 20 | +#include <linux/device.h> | |
| 21 | +#include <linux/init.h> | |
| 22 | +#include <linux/module.h> | |
| 23 | +#include <linux/platform_device.h> | |
| 24 | +#include <sound/pcm.h> | |
| 25 | +#include <sound/pcm_params.h> | |
| 26 | +#include <sound/soc.h> | |
| 27 | +#include <sound/soc-dai.h> | |
| 28 | + | |
| 29 | +#include "bf6xx-sport.h" | |
| 30 | + | |
| 31 | +struct sport_params param; | |
| 32 | + | |
| 33 | +static int bfin_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |
| 34 | + unsigned int fmt) | |
| 35 | +{ | |
| 36 | + struct sport_device *sport = snd_soc_dai_get_drvdata(cpu_dai); | |
| 37 | + struct device *dev = &sport->pdev->dev; | |
| 38 | + int ret = 0; | |
| 39 | + | |
| 40 | + param.spctl &= ~(SPORT_CTL_OPMODE | SPORT_CTL_CKRE | SPORT_CTL_FSR | |
| 41 | + | SPORT_CTL_LFS | SPORT_CTL_LAFS); | |
| 42 | + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | |
| 43 | + case SND_SOC_DAIFMT_I2S: | |
| 44 | + param.spctl |= SPORT_CTL_OPMODE | SPORT_CTL_CKRE | |
| 45 | + | SPORT_CTL_LFS; | |
| 46 | + break; | |
| 47 | + case SND_SOC_DAIFMT_DSP_A: | |
| 48 | + param.spctl |= SPORT_CTL_FSR; | |
| 49 | + break; | |
| 50 | + case SND_SOC_DAIFMT_LEFT_J: | |
| 51 | + param.spctl |= SPORT_CTL_OPMODE | SPORT_CTL_LFS | |
| 52 | + | SPORT_CTL_LAFS; | |
| 53 | + break; | |
| 54 | + default: | |
| 55 | + dev_err(dev, "%s: Unknown DAI format type\n", __func__); | |
| 56 | + ret = -EINVAL; | |
| 57 | + break; | |
| 58 | + } | |
| 59 | + | |
| 60 | + param.spctl &= ~(SPORT_CTL_ICLK | SPORT_CTL_IFS); | |
| 61 | + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | |
| 62 | + case SND_SOC_DAIFMT_CBM_CFM: | |
| 63 | + break; | |
| 64 | + case SND_SOC_DAIFMT_CBS_CFS: | |
| 65 | + case SND_SOC_DAIFMT_CBM_CFS: | |
| 66 | + case SND_SOC_DAIFMT_CBS_CFM: | |
| 67 | + ret = -EINVAL; | |
| 68 | + break; | |
| 69 | + default: | |
| 70 | + dev_err(dev, "%s: Unknown DAI master type\n", __func__); | |
| 71 | + ret = -EINVAL; | |
| 72 | + break; | |
| 73 | + } | |
| 74 | + | |
| 75 | + return ret; | |
| 76 | +} | |
| 77 | + | |
| 78 | +static int bfin_i2s_hw_params(struct snd_pcm_substream *substream, | |
| 79 | + struct snd_pcm_hw_params *params, | |
| 80 | + struct snd_soc_dai *dai) | |
| 81 | +{ | |
| 82 | + struct sport_device *sport = snd_soc_dai_get_drvdata(dai); | |
| 83 | + struct device *dev = &sport->pdev->dev; | |
| 84 | + int ret = 0; | |
| 85 | + | |
| 86 | + param.spctl &= ~SPORT_CTL_SLEN; | |
| 87 | + switch (params_format(params)) { | |
| 88 | + case SNDRV_PCM_FORMAT_S8: | |
| 89 | + param.spctl |= 0x70; | |
| 90 | + sport->wdsize = 1; | |
| 91 | + case SNDRV_PCM_FORMAT_S16_LE: | |
| 92 | + param.spctl |= 0xf0; | |
| 93 | + sport->wdsize = 2; | |
| 94 | + break; | |
| 95 | + case SNDRV_PCM_FORMAT_S24_LE: | |
| 96 | + param.spctl |= 0x170; | |
| 97 | + sport->wdsize = 3; | |
| 98 | + break; | |
| 99 | + case SNDRV_PCM_FORMAT_S32_LE: | |
| 100 | + param.spctl |= 0x1f0; | |
| 101 | + sport->wdsize = 4; | |
| 102 | + break; | |
| 103 | + } | |
| 104 | + | |
| 105 | + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | |
| 106 | + ret = sport_set_tx_params(sport, ¶m); | |
| 107 | + if (ret) { | |
| 108 | + dev_err(dev, "SPORT tx is busy!\n"); | |
| 109 | + return ret; | |
| 110 | + } | |
| 111 | + } else { | |
| 112 | + ret = sport_set_rx_params(sport, ¶m); | |
| 113 | + if (ret) { | |
| 114 | + dev_err(dev, "SPORT rx is busy!\n"); | |
| 115 | + return ret; | |
| 116 | + } | |
| 117 | + } | |
| 118 | + return 0; | |
| 119 | +} | |
| 120 | + | |
| 121 | +#ifdef CONFIG_PM | |
| 122 | +static int bfin_i2s_suspend(struct snd_soc_dai *dai) | |
| 123 | +{ | |
| 124 | + struct sport_device *sport = snd_soc_dai_get_drvdata(dai); | |
| 125 | + | |
| 126 | + if (dai->capture_active) | |
| 127 | + sport_rx_stop(sport); | |
| 128 | + if (dai->playback_active) | |
| 129 | + sport_tx_stop(sport); | |
| 130 | + return 0; | |
| 131 | +} | |
| 132 | + | |
| 133 | +static int bfin_i2s_resume(struct snd_soc_dai *dai) | |
| 134 | +{ | |
| 135 | + struct sport_device *sport = snd_soc_dai_get_drvdata(dai); | |
| 136 | + struct device *dev = &sport->pdev->dev; | |
| 137 | + int ret; | |
| 138 | + | |
| 139 | + ret = sport_set_tx_params(sport, ¶m); | |
| 140 | + if (ret) { | |
| 141 | + dev_err(dev, "SPORT tx is busy!\n"); | |
| 142 | + return ret; | |
| 143 | + } | |
| 144 | + ret = sport_set_rx_params(sport, ¶m); | |
| 145 | + if (ret) { | |
| 146 | + dev_err(dev, "SPORT rx is busy!\n"); | |
| 147 | + return ret; | |
| 148 | + } | |
| 149 | + | |
| 150 | + return 0; | |
| 151 | +} | |
| 152 | + | |
| 153 | +#else | |
| 154 | +#define bfin_i2s_suspend NULL | |
| 155 | +#define bfin_i2s_resume NULL | |
| 156 | +#endif | |
| 157 | + | |
| 158 | +#define BFIN_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ | |
| 159 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ | |
| 160 | + SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \ | |
| 161 | + SNDRV_PCM_RATE_96000) | |
| 162 | + | |
| 163 | +#define BFIN_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \ | |
| 164 | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | |
| 165 | + | |
| 166 | +static struct snd_soc_dai_ops bfin_i2s_dai_ops = { | |
| 167 | + .hw_params = bfin_i2s_hw_params, | |
| 168 | + .set_fmt = bfin_i2s_set_dai_fmt, | |
| 169 | +}; | |
| 170 | + | |
| 171 | +static struct snd_soc_dai_driver bfin_i2s_dai = { | |
| 172 | + .suspend = bfin_i2s_suspend, | |
| 173 | + .resume = bfin_i2s_resume, | |
| 174 | + .playback = { | |
| 175 | + .channels_min = 1, | |
| 176 | + .channels_max = 2, | |
| 177 | + .rates = BFIN_I2S_RATES, | |
| 178 | + .formats = BFIN_I2S_FORMATS, | |
| 179 | + }, | |
| 180 | + .capture = { | |
| 181 | + .channels_min = 1, | |
| 182 | + .channels_max = 2, | |
| 183 | + .rates = BFIN_I2S_RATES, | |
| 184 | + .formats = BFIN_I2S_FORMATS, | |
| 185 | + }, | |
| 186 | + .ops = &bfin_i2s_dai_ops, | |
| 187 | +}; | |
| 188 | + | |
| 189 | +static int __devinit bfin_i2s_probe(struct platform_device *pdev) | |
| 190 | +{ | |
| 191 | + struct sport_device *sport; | |
| 192 | + struct device *dev = &pdev->dev; | |
| 193 | + int ret; | |
| 194 | + | |
| 195 | + sport = sport_create(pdev); | |
| 196 | + if (!sport) | |
| 197 | + return -ENODEV; | |
| 198 | + | |
| 199 | + /* register with the ASoC layers */ | |
| 200 | + ret = snd_soc_register_dai(dev, &bfin_i2s_dai); | |
| 201 | + if (ret) { | |
| 202 | + dev_err(dev, "Failed to register DAI: %d\n", ret); | |
| 203 | + sport_delete(sport); | |
| 204 | + return ret; | |
| 205 | + } | |
| 206 | + platform_set_drvdata(pdev, sport); | |
| 207 | + | |
| 208 | + return 0; | |
| 209 | +} | |
| 210 | + | |
| 211 | +static int __devexit bfin_i2s_remove(struct platform_device *pdev) | |
| 212 | +{ | |
| 213 | + struct sport_device *sport = platform_get_drvdata(pdev); | |
| 214 | + | |
| 215 | + snd_soc_unregister_dai(&pdev->dev); | |
| 216 | + sport_delete(sport); | |
| 217 | + | |
| 218 | + return 0; | |
| 219 | +} | |
| 220 | + | |
| 221 | +static struct platform_driver bfin_i2s_driver = { | |
| 222 | + .probe = bfin_i2s_probe, | |
| 223 | + .remove = __devexit_p(bfin_i2s_remove), | |
| 224 | + .driver = { | |
| 225 | + .name = "bfin-i2s", | |
| 226 | + .owner = THIS_MODULE, | |
| 227 | + }, | |
| 228 | +}; | |
| 229 | + | |
| 230 | +module_platform_driver(bfin_i2s_driver); | |
| 231 | + | |
| 232 | +MODULE_DESCRIPTION("Analog Devices BF6XX i2s interface driver"); | |
| 233 | +MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>"); | |
| 234 | +MODULE_LICENSE("GPL v2"); | |
| @@ -0,0 +1,422 @@ | ||
| 1 | +/* | |
| 2 | + * bf6xx_sport.c Analog Devices BF6XX SPORT driver | |
| 3 | + * | |
| 4 | + * Copyright (c) 2012 Analog Devices Inc. | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License version 2 as | |
| 8 | + * published by the Free Software Foundation. | |
| 9 | + * | |
| 10 | + * This program is distributed in the hope that it will be useful, | |
| 11 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 12 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 13 | + * GNU General Public License for more details. | |
| 14 | + * | |
| 15 | + * You should have received a copy of the GNU General Public License | |
| 16 | + * along with this program; if not, write to the Free Software | |
| 17 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
| 18 | + */ | |
| 19 | + | |
| 20 | +#include <linux/device.h> | |
| 21 | +#include <linux/dma-mapping.h> | |
| 22 | +#include <linux/interrupt.h> | |
| 23 | +#include <linux/module.h> | |
| 24 | +#include <linux/platform_device.h> | |
| 25 | +#include <linux/slab.h> | |
| 26 | + | |
| 27 | +#include <asm/blackfin.h> | |
| 28 | +#include <asm/dma.h> | |
| 29 | +#include <asm/portmux.h> | |
| 30 | + | |
| 31 | +#include "bf6xx-sport.h" | |
| 32 | + | |
| 33 | +int sport_set_tx_params(struct sport_device *sport, | |
| 34 | + struct sport_params *params) | |
| 35 | +{ | |
| 36 | + if (sport->tx_regs->spctl & SPORT_CTL_SPENPRI) | |
| 37 | + return -EBUSY; | |
| 38 | + sport->tx_regs->spctl = params->spctl | SPORT_CTL_SPTRAN; | |
| 39 | + sport->tx_regs->div = params->div; | |
| 40 | + SSYNC(); | |
| 41 | + return 0; | |
| 42 | +} | |
| 43 | +EXPORT_SYMBOL(sport_set_tx_params); | |
| 44 | + | |
| 45 | +int sport_set_rx_params(struct sport_device *sport, | |
| 46 | + struct sport_params *params) | |
| 47 | +{ | |
| 48 | + if (sport->rx_regs->spctl & SPORT_CTL_SPENPRI) | |
| 49 | + return -EBUSY; | |
| 50 | + sport->rx_regs->spctl = params->spctl & ~SPORT_CTL_SPTRAN; | |
| 51 | + sport->rx_regs->div = params->div; | |
| 52 | + SSYNC(); | |
| 53 | + return 0; | |
| 54 | +} | |
| 55 | +EXPORT_SYMBOL(sport_set_rx_params); | |
| 56 | + | |
| 57 | +static int compute_wdsize(size_t wdsize) | |
| 58 | +{ | |
| 59 | + switch (wdsize) { | |
| 60 | + case 1: | |
| 61 | + return WDSIZE_8 | PSIZE_8; | |
| 62 | + case 2: | |
| 63 | + return WDSIZE_16 | PSIZE_16; | |
| 64 | + default: | |
| 65 | + return WDSIZE_32 | PSIZE_32; | |
| 66 | + } | |
| 67 | +} | |
| 68 | + | |
| 69 | +void sport_tx_start(struct sport_device *sport) | |
| 70 | +{ | |
| 71 | + set_dma_next_desc_addr(sport->tx_dma_chan, sport->tx_desc); | |
| 72 | + set_dma_config(sport->tx_dma_chan, DMAFLOW_LIST | DI_EN | |
| 73 | + | compute_wdsize(sport->wdsize) | NDSIZE_6); | |
| 74 | + enable_dma(sport->tx_dma_chan); | |
| 75 | + sport->tx_regs->spctl |= SPORT_CTL_SPENPRI; | |
| 76 | + SSYNC(); | |
| 77 | +} | |
| 78 | +EXPORT_SYMBOL(sport_tx_start); | |
| 79 | + | |
| 80 | +void sport_rx_start(struct sport_device *sport) | |
| 81 | +{ | |
| 82 | + set_dma_next_desc_addr(sport->rx_dma_chan, sport->rx_desc); | |
| 83 | + set_dma_config(sport->rx_dma_chan, DMAFLOW_LIST | DI_EN | WNR | |
| 84 | + | compute_wdsize(sport->wdsize) | NDSIZE_6); | |
| 85 | + enable_dma(sport->rx_dma_chan); | |
| 86 | + sport->rx_regs->spctl |= SPORT_CTL_SPENPRI; | |
| 87 | + SSYNC(); | |
| 88 | +} | |
| 89 | +EXPORT_SYMBOL(sport_rx_start); | |
| 90 | + | |
| 91 | +void sport_tx_stop(struct sport_device *sport) | |
| 92 | +{ | |
| 93 | + sport->tx_regs->spctl &= ~SPORT_CTL_SPENPRI; | |
| 94 | + SSYNC(); | |
| 95 | + disable_dma(sport->tx_dma_chan); | |
| 96 | +} | |
| 97 | +EXPORT_SYMBOL(sport_tx_stop); | |
| 98 | + | |
| 99 | +void sport_rx_stop(struct sport_device *sport) | |
| 100 | +{ | |
| 101 | + sport->rx_regs->spctl &= ~SPORT_CTL_SPENPRI; | |
| 102 | + SSYNC(); | |
| 103 | + disable_dma(sport->rx_dma_chan); | |
| 104 | +} | |
| 105 | +EXPORT_SYMBOL(sport_rx_stop); | |
| 106 | + | |
| 107 | +void sport_set_tx_callback(struct sport_device *sport, | |
| 108 | + void (*tx_callback)(void *), void *tx_data) | |
| 109 | +{ | |
| 110 | + sport->tx_callback = tx_callback; | |
| 111 | + sport->tx_data = tx_data; | |
| 112 | +} | |
| 113 | +EXPORT_SYMBOL(sport_set_tx_callback); | |
| 114 | + | |
| 115 | +void sport_set_rx_callback(struct sport_device *sport, | |
| 116 | + void (*rx_callback)(void *), void *rx_data) | |
| 117 | +{ | |
| 118 | + sport->rx_callback = rx_callback; | |
| 119 | + sport->rx_data = rx_data; | |
| 120 | +} | |
| 121 | +EXPORT_SYMBOL(sport_set_rx_callback); | |
| 122 | + | |
| 123 | +static void setup_desc(struct dmasg *desc, void *buf, int fragcount, | |
| 124 | + size_t fragsize, unsigned int cfg, | |
| 125 | + unsigned int count, size_t wdsize) | |
| 126 | +{ | |
| 127 | + | |
| 128 | + int i; | |
| 129 | + | |
| 130 | + for (i = 0; i < fragcount; ++i) { | |
| 131 | + desc[i].next_desc_addr = &(desc[i + 1]); | |
| 132 | + desc[i].start_addr = (unsigned long)buf + i*fragsize; | |
| 133 | + desc[i].cfg = cfg; | |
| 134 | + desc[i].x_count = count; | |
| 135 | + desc[i].x_modify = wdsize; | |
| 136 | + desc[i].y_count = 0; | |
| 137 | + desc[i].y_modify = 0; | |
| 138 | + } | |
| 139 | + | |
| 140 | + /* make circular */ | |
| 141 | + desc[fragcount-1].next_desc_addr = desc; | |
| 142 | +} | |
| 143 | + | |
| 144 | +int sport_config_tx_dma(struct sport_device *sport, void *buf, | |
| 145 | + int fragcount, size_t fragsize) | |
| 146 | +{ | |
| 147 | + unsigned int count; | |
| 148 | + unsigned int cfg; | |
| 149 | + dma_addr_t addr; | |
| 150 | + | |
| 151 | + count = fragsize/sport->wdsize; | |
| 152 | + | |
| 153 | + if (sport->tx_desc) | |
| 154 | + dma_free_coherent(NULL, sport->tx_desc_size, | |
| 155 | + sport->tx_desc, 0); | |
| 156 | + | |
| 157 | + sport->tx_desc = dma_alloc_coherent(NULL, | |
| 158 | + fragcount * sizeof(struct dmasg), &addr, 0); | |
| 159 | + sport->tx_desc_size = fragcount * sizeof(struct dmasg); | |
| 160 | + if (!sport->tx_desc) | |
| 161 | + return -ENOMEM; | |
| 162 | + | |
| 163 | + sport->tx_buf = buf; | |
| 164 | + sport->tx_fragsize = fragsize; | |
| 165 | + sport->tx_frags = fragcount; | |
| 166 | + cfg = DMAFLOW_LIST | DI_EN | compute_wdsize(sport->wdsize) | NDSIZE_6; | |
| 167 | + | |
| 168 | + setup_desc(sport->tx_desc, buf, fragcount, fragsize, | |
| 169 | + cfg|DMAEN, count, sport->wdsize); | |
| 170 | + | |
| 171 | + return 0; | |
| 172 | +} | |
| 173 | +EXPORT_SYMBOL(sport_config_tx_dma); | |
| 174 | + | |
| 175 | +int sport_config_rx_dma(struct sport_device *sport, void *buf, | |
| 176 | + int fragcount, size_t fragsize) | |
| 177 | +{ | |
| 178 | + unsigned int count; | |
| 179 | + unsigned int cfg; | |
| 180 | + dma_addr_t addr; | |
| 181 | + | |
| 182 | + count = fragsize/sport->wdsize; | |
| 183 | + | |
| 184 | + if (sport->rx_desc) | |
| 185 | + dma_free_coherent(NULL, sport->rx_desc_size, | |
| 186 | + sport->rx_desc, 0); | |
| 187 | + | |
| 188 | + sport->rx_desc = dma_alloc_coherent(NULL, | |
| 189 | + fragcount * sizeof(struct dmasg), &addr, 0); | |
| 190 | + sport->rx_desc_size = fragcount * sizeof(struct dmasg); | |
| 191 | + if (!sport->rx_desc) | |
| 192 | + return -ENOMEM; | |
| 193 | + | |
| 194 | + sport->rx_buf = buf; | |
| 195 | + sport->rx_fragsize = fragsize; | |
| 196 | + sport->rx_frags = fragcount; | |
| 197 | + cfg = DMAFLOW_LIST | DI_EN | compute_wdsize(sport->wdsize) | |
| 198 | + | WNR | NDSIZE_6; | |
| 199 | + | |
| 200 | + setup_desc(sport->rx_desc, buf, fragcount, fragsize, | |
| 201 | + cfg|DMAEN, count, sport->wdsize); | |
| 202 | + | |
| 203 | + return 0; | |
| 204 | +} | |
| 205 | +EXPORT_SYMBOL(sport_config_rx_dma); | |
| 206 | + | |
| 207 | +unsigned long sport_curr_offset_tx(struct sport_device *sport) | |
| 208 | +{ | |
| 209 | + unsigned long curr = get_dma_curr_addr(sport->tx_dma_chan); | |
| 210 | + | |
| 211 | + return (unsigned char *)curr - sport->tx_buf; | |
| 212 | +} | |
| 213 | +EXPORT_SYMBOL(sport_curr_offset_tx); | |
| 214 | + | |
| 215 | +unsigned long sport_curr_offset_rx(struct sport_device *sport) | |
| 216 | +{ | |
| 217 | + unsigned long curr = get_dma_curr_addr(sport->rx_dma_chan); | |
| 218 | + | |
| 219 | + return (unsigned char *)curr - sport->rx_buf; | |
| 220 | +} | |
| 221 | +EXPORT_SYMBOL(sport_curr_offset_rx); | |
| 222 | + | |
| 223 | +static irqreturn_t sport_tx_irq(int irq, void *dev_id) | |
| 224 | +{ | |
| 225 | + struct sport_device *sport = dev_id; | |
| 226 | + static unsigned long status; | |
| 227 | + | |
| 228 | + status = get_dma_curr_irqstat(sport->tx_dma_chan); | |
| 229 | + if (status & (DMA_DONE|DMA_ERR)) { | |
| 230 | + clear_dma_irqstat(sport->tx_dma_chan); | |
| 231 | + SSYNC(); | |
| 232 | + } | |
| 233 | + if (sport->tx_callback) | |
| 234 | + sport->tx_callback(sport->tx_data); | |
| 235 | + return IRQ_HANDLED; | |
| 236 | +} | |
| 237 | + | |
| 238 | +static irqreturn_t sport_rx_irq(int irq, void *dev_id) | |
| 239 | +{ | |
| 240 | + struct sport_device *sport = dev_id; | |
| 241 | + unsigned long status; | |
| 242 | + | |
| 243 | + status = get_dma_curr_irqstat(sport->rx_dma_chan); | |
| 244 | + if (status & (DMA_DONE|DMA_ERR)) { | |
| 245 | + clear_dma_irqstat(sport->rx_dma_chan); | |
| 246 | + SSYNC(); | |
| 247 | + } | |
| 248 | + if (sport->rx_callback) | |
| 249 | + sport->rx_callback(sport->rx_data); | |
| 250 | + return IRQ_HANDLED; | |
| 251 | +} | |
| 252 | + | |
| 253 | +static irqreturn_t sport_err_irq(int irq, void *dev_id) | |
| 254 | +{ | |
| 255 | + struct sport_device *sport = dev_id; | |
| 256 | + struct device *dev = &sport->pdev->dev; | |
| 257 | + | |
| 258 | + if (sport->tx_regs->spctl & SPORT_CTL_DERRPRI) | |
| 259 | + dev_err(dev, "sport error: TUVF\n"); | |
| 260 | + if (sport->rx_regs->spctl & SPORT_CTL_DERRPRI) | |
| 261 | + dev_err(dev, "sport error: ROVF\n"); | |
| 262 | + | |
| 263 | + return IRQ_HANDLED; | |
| 264 | +} | |
| 265 | + | |
| 266 | +static int sport_get_resource(struct sport_device *sport) | |
| 267 | +{ | |
| 268 | + struct platform_device *pdev = sport->pdev; | |
| 269 | + struct device *dev = &pdev->dev; | |
| 270 | + struct bfin_snd_platform_data *pdata = dev->platform_data; | |
| 271 | + struct resource *res; | |
| 272 | + | |
| 273 | + if (!pdata) { | |
| 274 | + dev_err(dev, "No platform data\n"); | |
| 275 | + return -ENODEV; | |
| 276 | + } | |
| 277 | + sport->pin_req = pdata->pin_req; | |
| 278 | + | |
| 279 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 280 | + if (!res) { | |
| 281 | + dev_err(dev, "No tx MEM resource\n"); | |
| 282 | + return -ENODEV; | |
| 283 | + } | |
| 284 | + sport->tx_regs = (struct sport_register *)res->start; | |
| 285 | + | |
| 286 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | |
| 287 | + if (!res) { | |
| 288 | + dev_err(dev, "No rx MEM resource\n"); | |
| 289 | + return -ENODEV; | |
| 290 | + } | |
| 291 | + sport->rx_regs = (struct sport_register *)res->start; | |
| 292 | + | |
| 293 | + res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | |
| 294 | + if (!res) { | |
| 295 | + dev_err(dev, "No tx DMA resource\n"); | |
| 296 | + return -ENODEV; | |
| 297 | + } | |
| 298 | + sport->tx_dma_chan = res->start; | |
| 299 | + | |
| 300 | + res = platform_get_resource(pdev, IORESOURCE_DMA, 1); | |
| 301 | + if (!res) { | |
| 302 | + dev_err(dev, "No rx DMA resource\n"); | |
| 303 | + return -ENODEV; | |
| 304 | + } | |
| 305 | + sport->rx_dma_chan = res->start; | |
| 306 | + | |
| 307 | + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | |
| 308 | + if (!res) { | |
| 309 | + dev_err(dev, "No tx error irq resource\n"); | |
| 310 | + return -ENODEV; | |
| 311 | + } | |
| 312 | + sport->tx_err_irq = res->start; | |
| 313 | + | |
| 314 | + res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); | |
| 315 | + if (!res) { | |
| 316 | + dev_err(dev, "No rx error irq resource\n"); | |
| 317 | + return -ENODEV; | |
| 318 | + } | |
| 319 | + sport->rx_err_irq = res->start; | |
| 320 | + | |
| 321 | + return 0; | |
| 322 | +} | |
| 323 | + | |
| 324 | +static int sport_request_resource(struct sport_device *sport) | |
| 325 | +{ | |
| 326 | + struct device *dev = &sport->pdev->dev; | |
| 327 | + int ret; | |
| 328 | + | |
| 329 | + ret = peripheral_request_list(sport->pin_req, "soc-audio"); | |
| 330 | + if (ret) { | |
| 331 | + dev_err(dev, "Unable to request sport pin\n"); | |
| 332 | + return ret; | |
| 333 | + } | |
| 334 | + | |
| 335 | + ret = request_dma(sport->tx_dma_chan, "SPORT TX Data"); | |
| 336 | + if (ret) { | |
| 337 | + dev_err(dev, "Unable to allocate DMA channel for sport tx\n"); | |
| 338 | + goto err_tx_dma; | |
| 339 | + } | |
| 340 | + set_dma_callback(sport->tx_dma_chan, sport_tx_irq, sport); | |
| 341 | + | |
| 342 | + ret = request_dma(sport->rx_dma_chan, "SPORT RX Data"); | |
| 343 | + if (ret) { | |
| 344 | + dev_err(dev, "Unable to allocate DMA channel for sport rx\n"); | |
| 345 | + goto err_rx_dma; | |
| 346 | + } | |
| 347 | + set_dma_callback(sport->rx_dma_chan, sport_rx_irq, sport); | |
| 348 | + | |
| 349 | + ret = request_irq(sport->tx_err_irq, sport_err_irq, | |
| 350 | + 0, "SPORT TX ERROR", sport); | |
| 351 | + if (ret) { | |
| 352 | + dev_err(dev, "Unable to allocate tx error IRQ for sport\n"); | |
| 353 | + goto err_tx_irq; | |
| 354 | + } | |
| 355 | + | |
| 356 | + ret = request_irq(sport->rx_err_irq, sport_err_irq, | |
| 357 | + 0, "SPORT RX ERROR", sport); | |
| 358 | + if (ret) { | |
| 359 | + dev_err(dev, "Unable to allocate rx error IRQ for sport\n"); | |
| 360 | + goto err_rx_irq; | |
| 361 | + } | |
| 362 | + | |
| 363 | + return 0; | |
| 364 | +err_rx_irq: | |
| 365 | + free_irq(sport->tx_err_irq, sport); | |
| 366 | +err_tx_irq: | |
| 367 | + free_dma(sport->rx_dma_chan); | |
| 368 | +err_rx_dma: | |
| 369 | + free_dma(sport->tx_dma_chan); | |
| 370 | +err_tx_dma: | |
| 371 | + peripheral_free_list(sport->pin_req); | |
| 372 | + return ret; | |
| 373 | +} | |
| 374 | + | |
| 375 | +static void sport_free_resource(struct sport_device *sport) | |
| 376 | +{ | |
| 377 | + free_irq(sport->rx_err_irq, sport); | |
| 378 | + free_irq(sport->tx_err_irq, sport); | |
| 379 | + free_dma(sport->rx_dma_chan); | |
| 380 | + free_dma(sport->tx_dma_chan); | |
| 381 | + peripheral_free_list(sport->pin_req); | |
| 382 | +} | |
| 383 | + | |
| 384 | +struct sport_device *sport_create(struct platform_device *pdev) | |
| 385 | +{ | |
| 386 | + struct device *dev = &pdev->dev; | |
| 387 | + struct sport_device *sport; | |
| 388 | + int ret; | |
| 389 | + | |
| 390 | + sport = kzalloc(sizeof(*sport), GFP_KERNEL); | |
| 391 | + if (!sport) { | |
| 392 | + dev_err(dev, "Unable to allocate memory for sport device\n"); | |
| 393 | + return NULL; | |
| 394 | + } | |
| 395 | + sport->pdev = pdev; | |
| 396 | + | |
| 397 | + ret = sport_get_resource(sport); | |
| 398 | + if (ret) { | |
| 399 | + kfree(sport); | |
| 400 | + return NULL; | |
| 401 | + } | |
| 402 | + | |
| 403 | + ret = sport_request_resource(sport); | |
| 404 | + if (ret) { | |
| 405 | + kfree(sport); | |
| 406 | + return NULL; | |
| 407 | + } | |
| 408 | + | |
| 409 | + dev_dbg(dev, "SPORT create success\n"); | |
| 410 | + return sport; | |
| 411 | +} | |
| 412 | +EXPORT_SYMBOL(sport_create); | |
| 413 | + | |
| 414 | +void sport_delete(struct sport_device *sport) | |
| 415 | +{ | |
| 416 | + sport_free_resource(sport); | |
| 417 | +} | |
| 418 | +EXPORT_SYMBOL(sport_delete); | |
| 419 | + | |
| 420 | +MODULE_DESCRIPTION("Analog Devices BF6XX SPORT driver"); | |
| 421 | +MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>"); | |
| 422 | +MODULE_LICENSE("GPL v2"); | |
| @@ -0,0 +1,82 @@ | ||
| 1 | +/* | |
| 2 | + * bf6xx_sport - Analog Devices BF6XX SPORT driver | |
| 3 | + * | |
| 4 | + * Copyright (c) 2012 Analog Devices Inc. | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License version 2 as | |
| 8 | + * published by the Free Software Foundation. | |
| 9 | + * | |
| 10 | + * This program is distributed in the hope that it will be useful, | |
| 11 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 12 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 13 | + * GNU General Public License for more details. | |
| 14 | + * | |
| 15 | + * You should have received a copy of the GNU General Public License | |
| 16 | + * along with this program; if not, write to the Free Software | |
| 17 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
| 18 | + */ | |
| 19 | + | |
| 20 | +#ifndef _BF6XX_SPORT_H_ | |
| 21 | +#define _BF6XX_SPORT_H_ | |
| 22 | + | |
| 23 | +#include <linux/platform_device.h> | |
| 24 | +#include <asm/bfin_sport3.h> | |
| 25 | + | |
| 26 | +struct sport_device { | |
| 27 | + struct platform_device *pdev; | |
| 28 | + const unsigned short *pin_req; | |
| 29 | + struct sport_register *tx_regs; | |
| 30 | + struct sport_register *rx_regs; | |
| 31 | + int tx_dma_chan; | |
| 32 | + int rx_dma_chan; | |
| 33 | + int tx_err_irq; | |
| 34 | + int rx_err_irq; | |
| 35 | + | |
| 36 | + void (*tx_callback)(void *data); | |
| 37 | + void *tx_data; | |
| 38 | + void (*rx_callback)(void *data); | |
| 39 | + void *rx_data; | |
| 40 | + | |
| 41 | + struct dmasg *tx_desc; | |
| 42 | + struct dmasg *rx_desc; | |
| 43 | + unsigned int tx_desc_size; | |
| 44 | + unsigned int rx_desc_size; | |
| 45 | + unsigned char *tx_buf; | |
| 46 | + unsigned char *rx_buf; | |
| 47 | + unsigned int tx_fragsize; | |
| 48 | + unsigned int rx_fragsize; | |
| 49 | + unsigned int tx_frags; | |
| 50 | + unsigned int rx_frags; | |
| 51 | + unsigned int wdsize; | |
| 52 | +}; | |
| 53 | + | |
| 54 | +struct sport_params { | |
| 55 | + u32 spctl; | |
| 56 | + u32 div; | |
| 57 | +}; | |
| 58 | + | |
| 59 | +struct sport_device *sport_create(struct platform_device *pdev); | |
| 60 | +void sport_delete(struct sport_device *sport); | |
| 61 | +int sport_set_tx_params(struct sport_device *sport, | |
| 62 | + struct sport_params *params); | |
| 63 | +int sport_set_rx_params(struct sport_device *sport, | |
| 64 | + struct sport_params *params); | |
| 65 | +void sport_tx_start(struct sport_device *sport); | |
| 66 | +void sport_rx_start(struct sport_device *sport); | |
| 67 | +void sport_tx_stop(struct sport_device *sport); | |
| 68 | +void sport_rx_stop(struct sport_device *sport); | |
| 69 | +void sport_set_tx_callback(struct sport_device *sport, | |
| 70 | + void (*tx_callback)(void *), void *tx_data); | |
| 71 | +void sport_set_rx_callback(struct sport_device *sport, | |
| 72 | + void (*rx_callback)(void *), void *rx_data); | |
| 73 | +int sport_config_tx_dma(struct sport_device *sport, void *buf, | |
| 74 | + int fragcount, size_t fragsize); | |
| 75 | +int sport_config_rx_dma(struct sport_device *sport, void *buf, | |
| 76 | + int fragcount, size_t fragsize); | |
| 77 | +unsigned long sport_curr_offset_tx(struct sport_device *sport); | |
| 78 | +unsigned long sport_curr_offset_rx(struct sport_device *sport); | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | +#endif | |
| @@ -12,6 +12,7 @@ config SND_SOC_ALL_CODECS · 11 unmodified lines | ||
| 12 | 12 | tristate "Build all ASoC CODEC drivers" |
| 13 | 13 | select SND_SOC_88PM860X if MFD_88PM860X |
| 14 | 14 | select SND_SOC_L3 |
| 15 | + select SND_SOC_AB8500_CODEC if ABX500_CORE | |
| 15 | 16 | select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS |
| 16 | 17 | select SND_SOC_AD1836 if SPI_MASTER |
| 17 | 18 | select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI |
| @@ -35,7 +36,9 @@ config SND_SOC_ALL_CODECS · 17 unmodified lines | ||
| 35 | 36 | select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI |
| 36 | 37 | select SND_SOC_CX20442 |
| 37 | 38 | select SND_SOC_DA7210 if I2C |
| 39 | + select SND_SOC_DA732X if I2C | |
| 38 | 40 | select SND_SOC_DFBMCS320 |
| 41 | + select SND_SOC_ISABELLE if I2C | |
| 39 | 42 | select SND_SOC_JZ4740_CODEC |
| 40 | 43 | select SND_SOC_LM4857 if I2C |
| 41 | 44 | select SND_SOC_LM49453 if I2C |
| @@ -54,6 +57,7 @@ config SND_SOC_ALL_CODECS · 12 unmodified lines | ||
| 54 | 57 | select SND_SOC_SPDIF |
| 55 | 58 | select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI |
| 56 | 59 | select SND_SOC_STA32X if I2C |
| 60 | + select SND_SOC_STA529 if I2C | |
| 57 | 61 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS |
| 58 | 62 | select SND_SOC_TLV320AIC23 if I2C |
| 59 | 63 | select SND_SOC_TLV320AIC26 if SPI_MASTER |
| @@ -70,6 +74,8 @@ config SND_SOC_ALL_CODECS · 10 unmodified lines | ||
| 70 | 74 | select SND_SOC_WM2000 if I2C |
| 71 | 75 | select SND_SOC_WM2200 if I2C |
| 72 | 76 | select SND_SOC_WM5100 if I2C |
| 77 | + select SND_SOC_WM5102 if MFD_WM5102 | |
| 78 | + select SND_SOC_WM5110 if MFD_WM5110 | |
| 73 | 79 | select SND_SOC_WM8350 if MFD_WM8350 |
| 74 | 80 | select SND_SOC_WM8400 if MFD_WM8400 |
| 75 | 81 | select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI |
| @@ -126,11 +132,21 @@ config SND_SOC_ALL_CODECS · 50 unmodified lines | ||
| 126 | 132 | config SND_SOC_88PM860X |
| 127 | 133 | tristate |
| 128 | 134 | |
| 135 | +config SND_SOC_ARIZONA | |
| 136 | + tristate | |
| 137 | + default y if SND_SOC_WM5102=y | |
| 138 | + default y if SND_SOC_WM5110=y | |
| 139 | + default m if SND_SOC_WM5102=m | |
| 140 | + default m if SND_SOC_WM5110=m | |
| 141 | + | |
| 129 | 142 | config SND_SOC_WM_HUBS |
| 130 | 143 | tristate |
| 131 | 144 | default y if SND_SOC_WM8993=y || SND_SOC_WM8994=y |
| 132 | 145 | default m if SND_SOC_WM8993=m || SND_SOC_WM8994=m |
| 133 | 146 | |
| 147 | +config SND_SOC_AB8500_CODEC | |
| 148 | + tristate | |
| 149 | + | |
| 134 | 150 | config SND_SOC_AC97_CODEC |
| 135 | 151 | tristate |
| 136 | 152 | select SND_AC97_CODEC |
| @@ -219,12 +235,18 @@ config SND_SOC_L3 · 82 unmodified lines | ||
| 219 | 235 | config SND_SOC_DA7210 |
| 220 | 236 | tristate |
| 221 | 237 | |
| 238 | +config SND_SOC_DA732X | |
| 239 | + tristate | |
| 240 | + | |
| 222 | 241 | config SND_SOC_DFBMCS320 |
| 223 | 242 | tristate |
| 224 | 243 | |
| 225 | 244 | config SND_SOC_DMIC |
| 226 | 245 | tristate |
| 227 | 246 | |
| 247 | +config SND_SOC_ISABELLE | |
| 248 | + tristate | |
| 249 | + | |
| 228 | 250 | config SND_SOC_LM49453 |
| 229 | 251 | tristate |
| 230 | 252 | |
| @@ -266,6 +288,9 @@ config SND_SOC_SSM2602 · 35 unmodified lines | ||
| 266 | 288 | config SND_SOC_STA32X |
| 267 | 289 | tristate |
| 268 | 290 | |
| 291 | +config SND_SOC_STA529 | |
| 292 | + tristate | |
| 293 | + | |
| 269 | 294 | config SND_SOC_STAC9766 |
| 270 | 295 | tristate |
| 271 | 296 | |
| @@ -313,6 +338,12 @@ config SND_SOC_WM2200 · 41 unmodified lines | ||
| 313 | 338 | config SND_SOC_WM5100 |
| 314 | 339 | tristate |
| 315 | 340 | |
| 341 | +config SND_SOC_WM5102 | |
| 342 | + tristate | |
| 343 | + | |
| 344 | +config SND_SOC_WM5110 | |
| 345 | + tristate | |
| 346 | + | |
| 316 | 347 | config SND_SOC_WM8350 |
| 317 | 348 | tristate |
| 318 | 349 | |
| @@ -1,4 +1,5 @@ | ||
| 1 | 1 | snd-soc-88pm860x-objs := 88pm860x-codec.o |
| 2 | +snd-soc-ab8500-codec-objs := ab8500-codec.o | |
| 2 | 3 | snd-soc-ac97-objs := ac97.o |
| 3 | 4 | snd-soc-ad1836-objs := ad1836.o |
| 4 | 5 | snd-soc-ad193x-objs := ad193x.o |
| @@ -13,6 +14,7 @@ snd-soc-ak4535-objs := ak4535.o · 8 unmodified lines | ||
| 13 | 14 | snd-soc-ak4641-objs := ak4641.o |
| 14 | 15 | snd-soc-ak4642-objs := ak4642.o |
| 15 | 16 | snd-soc-ak4671-objs := ak4671.o |
| 17 | +snd-soc-arizona-objs := arizona.o | |
| 16 | 18 | snd-soc-cq93vc-objs := cq93vc.o |
| 17 | 19 | snd-soc-cs42l51-objs := cs42l51.o |
| 18 | 20 | snd-soc-cs42l52-objs := cs42l52.o |
| @@ -21,8 +23,10 @@ snd-soc-cs4270-objs := cs4270.o · 2 unmodified lines | ||
| 21 | 23 | snd-soc-cs4271-objs := cs4271.o |
| 22 | 24 | snd-soc-cx20442-objs := cx20442.o |
| 23 | 25 | snd-soc-da7210-objs := da7210.o |
| 26 | +snd-soc-da732x-objs := da732x.o | |
| 24 | 27 | snd-soc-dfbmcs320-objs := dfbmcs320.o |
| 25 | 28 | snd-soc-dmic-objs := dmic.o |
| 29 | +snd-soc-isabelle-objs := isabelle.o | |
| 26 | 30 | snd-soc-jz4740-codec-objs := jz4740.o |
| 27 | 31 | snd-soc-l3-objs := l3.o |
| 28 | 32 | snd-soc-lm4857-objs := lm4857.o |
| @@ -41,9 +45,11 @@ snd-soc-alc5623-objs := alc5623.o · 12 unmodified lines | ||
| 41 | 45 | snd-soc-alc5632-objs := alc5632.o |
| 42 | 46 | snd-soc-sigmadsp-objs := sigmadsp.o |
| 43 | 47 | snd-soc-sn95031-objs := sn95031.o |
| 44 | −snd-soc-spdif-objs := spdif_transciever.o | |
| 48 | +snd-soc-spdif-tx-objs := spdif_transciever.o | |
| 49 | +snd-soc-spdif-rx-objs := spdif_receiver.o | |
| 45 | 50 | snd-soc-ssm2602-objs := ssm2602.o |
| 46 | 51 | snd-soc-sta32x-objs := sta32x.o |
| 52 | +snd-soc-sta529-objs := sta529.o | |
| 47 | 53 | snd-soc-stac9766-objs := stac9766.o |
| 48 | 54 | snd-soc-tlv320aic23-objs := tlv320aic23.o |
| 49 | 55 | snd-soc-tlv320aic26-objs := tlv320aic26.o |
| @@ -59,6 +65,8 @@ snd-soc-wm1250-ev1-objs := wm1250-ev1.o · 9 unmodified lines | ||
| 59 | 65 | snd-soc-wm2000-objs := wm2000.o |
| 60 | 66 | snd-soc-wm2200-objs := wm2200.o |
| 61 | 67 | snd-soc-wm5100-objs := wm5100.o wm5100-tables.o |
| 68 | +snd-soc-wm5102-objs := wm5102.o | |
| 69 | +snd-soc-wm5110-objs := wm5110.o | |
| 62 | 70 | snd-soc-wm8350-objs := wm8350.o |
| 63 | 71 | snd-soc-wm8400-objs := wm8400.o |
| 64 | 72 | snd-soc-wm8510-objs := wm8510.o |
| @@ -108,6 +116,7 @@ snd-soc-max9877-objs := max9877.o · 43 unmodified lines | ||
| 108 | 116 | snd-soc-tpa6130a2-objs := tpa6130a2.o |
| 109 | 117 | |
| 110 | 118 | obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o |
| 119 | +obj-$(CONFIG_SND_SOC_AB8500_CODEC) += snd-soc-ab8500-codec.o | |
| 111 | 120 | obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o |
| 112 | 121 | obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o |
| 113 | 122 | obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o |
| @@ -124,6 +133,7 @@ obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o · 10 unmodified lines | ||
| 124 | 133 | obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o |
| 125 | 134 | obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o |
| 126 | 135 | obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o |
| 136 | +obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o | |
| 127 | 137 | obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o |
| 128 | 138 | obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o |
| 129 | 139 | obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o |
| @@ -132,8 +142,10 @@ obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o · 2 unmodified lines | ||
| 132 | 142 | obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o |
| 133 | 143 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o |
| 134 | 144 | obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o |
| 145 | +obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o | |
| 135 | 146 | obj-$(CONFIG_SND_SOC_DFBMCS320) += snd-soc-dfbmcs320.o |
| 136 | 147 | obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o |
| 148 | +obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o | |
| 137 | 149 | obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o |
| 138 | 150 | obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o |
| 139 | 151 | obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o |
| @@ -150,9 +162,10 @@ obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o · 10 unmodified lines | ||
| 150 | 162 | obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o |
| 151 | 163 | obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o |
| 152 | 164 | obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o |
| 153 | −obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o | |
| 165 | +obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o | |
| 154 | 166 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o |
| 155 | 167 | obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o |
| 168 | +obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o | |
| 156 | 169 | obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o |
| 157 | 170 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o |
| 158 | 171 | obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o |
| @@ -168,6 +181,8 @@ obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o · 9 unmodified lines | ||
| 168 | 181 | obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o |
| 169 | 182 | obj-$(CONFIG_SND_SOC_WM2200) += snd-soc-wm2200.o |
| 170 | 183 | obj-$(CONFIG_SND_SOC_WM5100) += snd-soc-wm5100.o |
| 184 | +obj-$(CONFIG_SND_SOC_WM5102) += snd-soc-wm5102.o | |
| 185 | +obj-$(CONFIG_SND_SOC_WM5110) += snd-soc-wm5110.o | |
| 171 | 186 | obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o |
| 172 | 187 | obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o |
| 173 | 188 | obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o |
| @@ -0,0 +1,2522 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C) ST-Ericsson SA 2012 | |
| 3 | + * | |
| 4 | + * Author: Ola Lilja <ola.o.lilja@stericsson.com>, | |
| 5 | + * Kristoffer Karlsson <kristoffer.karlsson@stericsson.com>, | |
| 6 | + * Roger Nilsson <roger.xr.nilsson@stericsson.com>, | |
| 7 | + * for ST-Ericsson. | |
| 8 | + * | |
| 9 | + * Based on the early work done by: | |
| 10 | + * Mikko J. Lehto <mikko.lehto@symbio.com>, | |
| 11 | + * Mikko Sarmanne <mikko.sarmanne@symbio.com>, | |
| 12 | + * Jarmo K. Kuronen <jarmo.kuronen@symbio.com>, | |
| 13 | + * for ST-Ericsson. | |
| 14 | + * | |
| 15 | + * License terms: | |
| 16 | + * | |
| 17 | + * This program is free software; you can redistribute it and/or modify it | |
| 18 | + * under the terms of the GNU General Public License version 2 as published | |
| 19 | + * by the Free Software Foundation. | |
| 20 | + */ | |
| 21 | + | |
| 22 | +#include <linux/kernel.h> | |
| 23 | +#include <linux/module.h> | |
| 24 | +#include <linux/device.h> | |
| 25 | +#include <linux/slab.h> | |
| 26 | +#include <linux/moduleparam.h> | |
| 27 | +#include <linux/init.h> | |
| 28 | +#include <linux/delay.h> | |
| 29 | +#include <linux/pm.h> | |
| 30 | +#include <linux/platform_device.h> | |
| 31 | +#include <linux/mutex.h> | |
| 32 | +#include <linux/mfd/abx500/ab8500.h> | |
| 33 | +#include <linux/mfd/abx500.h> | |
| 34 | +#include <linux/mfd/abx500/ab8500-sysctrl.h> | |
| 35 | +#include <linux/mfd/abx500/ab8500-codec.h> | |
| 36 | +#include <linux/regulator/consumer.h> | |
| 37 | + | |
| 38 | +#include <sound/core.h> | |
| 39 | +#include <sound/pcm.h> | |
| 40 | +#include <sound/pcm_params.h> | |
| 41 | +#include <sound/initval.h> | |
| 42 | +#include <sound/soc.h> | |
| 43 | +#include <sound/soc-dapm.h> | |
| 44 | +#include <sound/tlv.h> | |
| 45 | + | |
| 46 | +#include "ab8500-codec.h" | |
| 47 | + | |
| 48 | +/* Macrocell value definitions */ | |
| 49 | +#define CLK_32K_OUT2_DISABLE 0x01 | |
| 50 | +#define INACTIVE_RESET_AUDIO 0x02 | |
| 51 | +#define ENABLE_AUDIO_CLK_TO_AUDIO_BLK 0x10 | |
| 52 | +#define ENABLE_VINTCORE12_SUPPLY 0x04 | |
| 53 | +#define GPIO27_DIR_OUTPUT 0x04 | |
| 54 | +#define GPIO29_DIR_OUTPUT 0x10 | |
| 55 | +#define GPIO31_DIR_OUTPUT 0x40 | |
| 56 | + | |
| 57 | +/* Macrocell register definitions */ | |
| 58 | +#define AB8500_CTRL3_REG 0x0200 | |
| 59 | +#define AB8500_GPIO_DIR4_REG 0x1013 | |
| 60 | + | |
| 61 | +/* Nr of FIR/IIR-coeff banks in ANC-block */ | |
| 62 | +#define AB8500_NR_OF_ANC_COEFF_BANKS 2 | |
| 63 | + | |
| 64 | +/* Minimum duration to keep ANC IIR Init bit high or | |
| 65 | +low before proceeding with the configuration sequence */ | |
| 66 | +#define AB8500_ANC_SM_DELAY 2000 | |
| 67 | + | |
| 68 | +#define AB8500_FILTER_CONTROL(xname, xcount, xmin, xmax) \ | |
| 69 | +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | |
| 70 | + .info = filter_control_info, \ | |
| 71 | + .get = filter_control_get, .put = filter_control_put, \ | |
| 72 | + .private_value = (unsigned long)&(struct filter_control) \ | |
| 73 | + {.count = xcount, .min = xmin, .max = xmax} } | |
| 74 | + | |
| 75 | +struct filter_control { | |
| 76 | + long min, max; | |
| 77 | + unsigned int count; | |
| 78 | + long value[128]; | |
| 79 | +}; | |
| 80 | + | |
| 81 | +/* Sidetone states */ | |
| 82 | +static const char * const enum_sid_state[] = { | |
| 83 | + "Unconfigured", | |
| 84 | + "Apply FIR", | |
| 85 | + "FIR is configured", | |
| 86 | +}; | |
| 87 | +enum sid_state { | |
| 88 | + SID_UNCONFIGURED = 0, | |
| 89 | + SID_APPLY_FIR = 1, | |
| 90 | + SID_FIR_CONFIGURED = 2, | |
| 91 | +}; | |
| 92 | + | |
| 93 | +static const char * const enum_anc_state[] = { | |
| 94 | + "Unconfigured", | |
| 95 | + "Apply FIR and IIR", | |
| 96 | + "FIR and IIR are configured", | |
| 97 | + "Apply FIR", | |
| 98 | + "FIR is configured", | |
| 99 | + "Apply IIR", | |
| 100 | + "IIR is configured" | |
| 101 | +}; | |
| 102 | +enum anc_state { | |
| 103 | + ANC_UNCONFIGURED = 0, | |
| 104 | + ANC_APPLY_FIR_IIR = 1, | |
| 105 | + ANC_FIR_IIR_CONFIGURED = 2, | |
| 106 | + ANC_APPLY_FIR = 3, | |
| 107 | + ANC_FIR_CONFIGURED = 4, | |
| 108 | + ANC_APPLY_IIR = 5, | |
| 109 | + ANC_IIR_CONFIGURED = 6 | |
| 110 | +}; | |
| 111 | + | |
| 112 | +/* Analog microphones */ | |
| 113 | +enum amic_idx { | |
| 114 | + AMIC_IDX_1A, | |
| 115 | + AMIC_IDX_1B, | |
| 116 | + AMIC_IDX_2 | |
| 117 | +}; | |
| 118 | + | |
| 119 | +struct ab8500_codec_drvdata_dbg { | |
| 120 | + struct regulator *vaud; | |
| 121 | + struct regulator *vamic1; | |
| 122 | + struct regulator *vamic2; | |
| 123 | + struct regulator *vdmic; | |
| 124 | +}; | |
| 125 | + | |
| 126 | +/* Private data for AB8500 device-driver */ | |
| 127 | +struct ab8500_codec_drvdata { | |
| 128 | + /* Sidetone */ | |
| 129 | + long *sid_fir_values; | |
| 130 | + enum sid_state sid_status; | |
| 131 | + | |
| 132 | + /* ANC */ | |
| 133 | + struct mutex anc_lock; | |
| 134 | + long *anc_fir_values; | |
| 135 | + long *anc_iir_values; | |
| 136 | + enum anc_state anc_status; | |
| 137 | +}; | |
| 138 | + | |
| 139 | +static inline const char *amic_micbias_str(enum amic_micbias micbias) | |
| 140 | +{ | |
| 141 | + switch (micbias) { | |
| 142 | + case AMIC_MICBIAS_VAMIC1: | |
| 143 | + return "VAMIC1"; | |
| 144 | + case AMIC_MICBIAS_VAMIC2: | |
| 145 | + return "VAMIC2"; | |
| 146 | + default: | |
| 147 | + return "Unknown"; | |
| 148 | + } | |
| 149 | +} | |
| 150 | + | |
| 151 | +static inline const char *amic_type_str(enum amic_type type) | |
| 152 | +{ | |
| 153 | + switch (type) { | |
| 154 | + case AMIC_TYPE_DIFFERENTIAL: | |
| 155 | + return "DIFFERENTIAL"; | |
| 156 | + case AMIC_TYPE_SINGLE_ENDED: | |
| 157 | + return "SINGLE ENDED"; | |
| 158 | + default: | |
| 159 | + return "Unknown"; | |
| 160 | + } | |
| 161 | +} | |
| 162 | + | |
| 163 | +/* | |
| 164 | + * Read'n'write functions | |
| 165 | + */ | |
| 166 | + | |
| 167 | +/* Read a register from the audio-bank of AB8500 */ | |
| 168 | +static unsigned int ab8500_codec_read_reg(struct snd_soc_codec *codec, | |
| 169 | + unsigned int reg) | |
| 170 | +{ | |
| 171 | + int status; | |
| 172 | + unsigned int value = 0; | |
| 173 | + | |
| 174 | + u8 value8; | |
| 175 | + status = abx500_get_register_interruptible(codec->dev, AB8500_AUDIO, | |
| 176 | + reg, &value8); | |
| 177 | + if (status < 0) { | |
| 178 | + dev_err(codec->dev, | |
| 179 | + "%s: ERROR: Register (0x%02x:0x%02x) read failed (%d).\n", | |
| 180 | + __func__, (u8)AB8500_AUDIO, (u8)reg, status); | |
| 181 | + } else { | |
| 182 | + dev_dbg(codec->dev, | |
| 183 | + "%s: Read 0x%02x from register 0x%02x:0x%02x\n", | |
| 184 | + __func__, value8, (u8)AB8500_AUDIO, (u8)reg); | |
| 185 | + value = (unsigned int)value8; | |
| 186 | + } | |
| 187 | + | |
| 188 | + return value; | |
| 189 | +} | |
| 190 | + | |
| 191 | +/* Write to a register in the audio-bank of AB8500 */ | |
| 192 | +static int ab8500_codec_write_reg(struct snd_soc_codec *codec, | |
| 193 | + unsigned int reg, unsigned int value) | |
| 194 | +{ | |
| 195 | + int status; | |
| 196 | + | |
| 197 | + status = abx500_set_register_interruptible(codec->dev, AB8500_AUDIO, | |
| 198 | + reg, value); | |
| 199 | + if (status < 0) | |
| 200 | + dev_err(codec->dev, | |
| 201 | + "%s: ERROR: Register (%02x:%02x) write failed (%d).\n", | |
| 202 | + __func__, (u8)AB8500_AUDIO, (u8)reg, status); | |
| 203 | + else | |
| 204 | + dev_dbg(codec->dev, | |
| 205 | + "%s: Wrote 0x%02x into register %02x:%02x\n", | |
| 206 | + __func__, (u8)value, (u8)AB8500_AUDIO, (u8)reg); | |
| 207 | + | |
| 208 | + return status; | |
| 209 | +} | |
| 210 | + | |
| 211 | +/* | |
| 212 | + * Controls - DAPM | |
| 213 | + */ | |
| 214 | + | |
| 215 | +/* Earpiece */ | |
| 216 | + | |
| 217 | +/* Earpiece source selector */ | |
| 218 | +static const char * const enum_ear_lineout_source[] = {"Headset Left", | |
| 219 | + "Speaker Left"}; | |
| 220 | +static SOC_ENUM_SINGLE_DECL(dapm_enum_ear_lineout_source, AB8500_DMICFILTCONF, | |
| 221 | + AB8500_DMICFILTCONF_DA3TOEAR, enum_ear_lineout_source); | |
| 222 | +static const struct snd_kcontrol_new dapm_ear_lineout_source = | |
| 223 | + SOC_DAPM_ENUM("Earpiece or LineOut Mono Source", | |
| 224 | + dapm_enum_ear_lineout_source); | |
| 225 | + | |
| 226 | +/* LineOut */ | |
| 227 | + | |
| 228 | +/* LineOut source selector */ | |
| 229 | +static const char * const enum_lineout_source[] = {"Mono Path", "Stereo Path"}; | |
| 230 | +static SOC_ENUM_DOUBLE_DECL(dapm_enum_lineout_source, AB8500_ANACONF5, | |
| 231 | + AB8500_ANACONF5_HSLDACTOLOL, | |
| 232 | + AB8500_ANACONF5_HSRDACTOLOR, enum_lineout_source); | |
| 233 | +static const struct snd_kcontrol_new dapm_lineout_source[] = { | |
| 234 | + SOC_DAPM_ENUM("LineOut Source", dapm_enum_lineout_source), | |
| 235 | +}; | |
| 236 | + | |
| 237 | +/* Handsfree */ | |
| 238 | + | |
| 239 | +/* Speaker Left - ANC selector */ | |
| 240 | +static const char * const enum_HFx_sel[] = {"Audio Path", "ANC"}; | |
| 241 | +static SOC_ENUM_SINGLE_DECL(dapm_enum_HFl_sel, AB8500_DIGMULTCONF2, | |
| 242 | + AB8500_DIGMULTCONF2_HFLSEL, enum_HFx_sel); | |
| 243 | +static const struct snd_kcontrol_new dapm_HFl_select[] = { | |
| 244 | + SOC_DAPM_ENUM("Speaker Left Source", dapm_enum_HFl_sel), | |
| 245 | +}; | |
| 246 | + | |
| 247 | +/* Speaker Right - ANC selector */ | |
| 248 | +static SOC_ENUM_SINGLE_DECL(dapm_enum_HFr_sel, AB8500_DIGMULTCONF2, | |
| 249 | + AB8500_DIGMULTCONF2_HFRSEL, enum_HFx_sel); | |
| 250 | +static const struct snd_kcontrol_new dapm_HFr_select[] = { | |
| 251 | + SOC_DAPM_ENUM("Speaker Right Source", dapm_enum_HFr_sel), | |
| 252 | +}; | |
| 253 | + | |
| 254 | +/* Mic 1 */ | |
| 255 | + | |
| 256 | +/* Mic 1 - Mic 1a or 1b selector */ | |
| 257 | +static const char * const enum_mic1ab_sel[] = {"Mic 1b", "Mic 1a"}; | |
| 258 | +static SOC_ENUM_SINGLE_DECL(dapm_enum_mic1ab_sel, AB8500_ANACONF3, | |
| 259 | + AB8500_ANACONF3_MIC1SEL, enum_mic1ab_sel); | |
| 260 | +static const struct snd_kcontrol_new dapm_mic1ab_mux[] = { | |
| 261 | + SOC_DAPM_ENUM("Mic 1a or 1b Select", dapm_enum_mic1ab_sel), | |
| 262 | +}; | |
| 263 | + | |
| 264 | +/* Mic 1 - AD3 - Mic 1 or DMic 3 selector */ | |
| 265 | +static const char * const enum_ad3_sel[] = {"Mic 1", "DMic 3"}; | |
| 266 | +static SOC_ENUM_SINGLE_DECL(dapm_enum_ad3_sel, AB8500_DIGMULTCONF1, | |
| 267 | + AB8500_DIGMULTCONF1_AD3SEL, enum_ad3_sel); | |
| 268 | +static const struct snd_kcontrol_new dapm_ad3_select[] = { | |
| 269 | + SOC_DAPM_ENUM("AD3 Source Select", dapm_enum_ad3_sel), | |
| 270 | +}; | |
| 271 | + | |
| 272 | +/* Mic 1 - AD6 - Mic 1 or DMic 6 selector */ | |
| 273 | +static const char * const enum_ad6_sel[] = {"Mic 1", "DMic 6"}; | |
| 274 | +static SOC_ENUM_SINGLE_DECL(dapm_enum_ad6_sel, AB8500_DIGMULTCONF1, | |
| 275 | + AB8500_DIGMULTCONF1_AD6SEL, enum_ad6_sel); | |
| 276 | +static const struct snd_kcontrol_new dapm_ad6_select[] = { | |
| 277 | + SOC_DAPM_ENUM("AD6 Source Select", dapm_enum_ad6_sel), | |
| 278 | +}; | |
| 279 | + | |
| 280 | +/* Mic 2 */ | |
| 281 | + | |
| 282 | +/* Mic 2 - AD5 - Mic 2 or DMic 5 selector */ | |
| 283 | +static const char * const enum_ad5_sel[] = {"Mic 2", "DMic 5"}; | |
| 284 | +static SOC_ENUM_SINGLE_DECL(dapm_enum_ad5_sel, AB8500_DIGMULTCONF1, | |
| 285 | + AB8500_DIGMULTCONF1_AD5SEL, enum_ad5_sel); | |
| 286 | +static const struct snd_kcontrol_new dapm_ad5_select[] = { | |
| 287 | + SOC_DAPM_ENUM("AD5 Source Select", dapm_enum_ad5_sel), | |
| 288 | +}; | |
| 289 | + | |
| 290 | +/* LineIn */ | |
| 291 | + | |
| 292 | +/* LineIn left - AD1 - LineIn Left or DMic 1 selector */ | |
| 293 | +static const char * const enum_ad1_sel[] = {"LineIn Left", "DMic 1"}; | |
| 294 | +static SOC_ENUM_SINGLE_DECL(dapm_enum_ad1_sel, AB8500_DIGMULTCONF1, | |
| 295 | + AB8500_DIGMULTCONF1_AD1SEL, enum_ad1_sel); | |
| 296 | +static const struct snd_kcontrol_new dapm_ad1_select[] = { | |
| 297 | + SOC_DAPM_ENUM("AD1 Source Select", dapm_enum_ad1_sel), | |
| 298 | +}; | |
| 299 | + | |
| 300 | +/* LineIn right - Mic 2 or LineIn Right selector */ | |
| 301 | +static const char * const enum_mic2lr_sel[] = {"Mic 2", "LineIn Right"}; | |
| 302 | +static SOC_ENUM_SINGLE_DECL(dapm_enum_mic2lr_sel, AB8500_ANACONF3, | |
| 303 | + AB8500_ANACONF3_LINRSEL, enum_mic2lr_sel); | |
| 304 | +static const struct snd_kcontrol_new dapm_mic2lr_select[] = { | |
| 305 | + SOC_DAPM_ENUM("Mic 2 or LINR Select", dapm_enum_mic2lr_sel), | |
| 306 | +}; | |
| 307 | + | |
| 308 | +/* LineIn right - AD2 - LineIn Right or DMic2 selector */ | |
| 309 | +static const char * const enum_ad2_sel[] = {"LineIn Right", "DMic 2"}; | |
| 310 | +static SOC_ENUM_SINGLE_DECL(dapm_enum_ad2_sel, AB8500_DIGMULTCONF1, | |
| 311 | + AB8500_DIGMULTCONF1_AD2SEL, enum_ad2_sel); | |
| 312 | +static const struct snd_kcontrol_new dapm_ad2_select[] = { | |
| 313 | + SOC_DAPM_ENUM("AD2 Source Select", dapm_enum_ad2_sel), | |
| 314 | +}; | |
| 315 | + | |
| 316 | + | |
| 317 | +/* ANC */ | |
| 318 | + | |
| 319 | +static const char * const enum_anc_in_sel[] = {"Mic 1 / DMic 6", | |
| 320 | + "Mic 2 / DMic 5"}; | |
| 321 | +static SOC_ENUM_SINGLE_DECL(dapm_enum_anc_in_sel, AB8500_DMICFILTCONF, | |
| 322 | + AB8500_DMICFILTCONF_ANCINSEL, enum_anc_in_sel); | |
| 323 | +static const struct snd_kcontrol_new dapm_anc_in_select[] = { | |
| 324 | + SOC_DAPM_ENUM("ANC Source", dapm_enum_anc_in_sel), | |
| 325 | +}; | |
| 326 | + | |
| 327 | +/* ANC - Enable/Disable */ | |
| 328 | +static const struct snd_kcontrol_new dapm_anc_enable[] = { | |
| 329 | + SOC_DAPM_SINGLE("Switch", AB8500_ANCCONF1, | |
| 330 | + AB8500_ANCCONF1_ENANC, 0, 0), | |
| 331 | +}; | |
| 332 | + | |
| 333 | +/* ANC to Earpiece - Mute */ | |
| 334 | +static const struct snd_kcontrol_new dapm_anc_ear_mute[] = { | |
| 335 | + SOC_DAPM_SINGLE("Switch", AB8500_DIGMULTCONF1, | |
| 336 | + AB8500_DIGMULTCONF1_ANCSEL, 1, 0), | |
| 337 | +}; | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | +/* Sidetone left */ | |
| 342 | + | |
| 343 | +/* Sidetone left - Input selector */ | |
| 344 | +static const char * const enum_stfir1_in_sel[] = { | |
| 345 | + "LineIn Left", "LineIn Right", "Mic 1", "Headset Left" | |
| 346 | +}; | |
| 347 | +static SOC_ENUM_SINGLE_DECL(dapm_enum_stfir1_in_sel, AB8500_DIGMULTCONF2, | |
| 348 | + AB8500_DIGMULTCONF2_FIRSID1SEL, enum_stfir1_in_sel); | |
| 349 | +static const struct snd_kcontrol_new dapm_stfir1_in_select[] = { | |
| 350 | + SOC_DAPM_ENUM("Sidetone Left Source", dapm_enum_stfir1_in_sel), | |
| 351 | +}; | |
| 352 | + | |
| 353 | +/* Sidetone right path */ | |
| 354 | + | |
| 355 | +/* Sidetone right - Input selector */ | |
| 356 | +static const char * const enum_stfir2_in_sel[] = { | |
| 357 | + "LineIn Right", "Mic 1", "DMic 4", "Headset Right" | |
| 358 | +}; | |
| 359 | +static SOC_ENUM_SINGLE_DECL(dapm_enum_stfir2_in_sel, AB8500_DIGMULTCONF2, | |
| 360 | + AB8500_DIGMULTCONF2_FIRSID2SEL, enum_stfir2_in_sel); | |
| 361 | +static const struct snd_kcontrol_new dapm_stfir2_in_select[] = { | |
| 362 | + SOC_DAPM_ENUM("Sidetone Right Source", dapm_enum_stfir2_in_sel), | |
| 363 | +}; | |
| 364 | + | |
| 365 | +/* Vibra */ | |
| 366 | + | |
| 367 | +static const char * const enum_pwm2vibx[] = {"Audio Path", "PWM Generator"}; | |
| 368 | + | |
| 369 | +static SOC_ENUM_SINGLE_DECL(dapm_enum_pwm2vib1, AB8500_PWMGENCONF1, | |
| 370 | + AB8500_PWMGENCONF1_PWMTOVIB1, enum_pwm2vibx); | |
| 371 | + | |
| 372 | +static const struct snd_kcontrol_new dapm_pwm2vib1[] = { | |
| 373 | + SOC_DAPM_ENUM("Vibra 1 Controller", dapm_enum_pwm2vib1), | |
| 374 | +}; | |
| 375 | + | |
| 376 | +static SOC_ENUM_SINGLE_DECL(dapm_enum_pwm2vib2, AB8500_PWMGENCONF1, | |
| 377 | + AB8500_PWMGENCONF1_PWMTOVIB2, enum_pwm2vibx); | |
| 378 | + | |
| 379 | +static const struct snd_kcontrol_new dapm_pwm2vib2[] = { | |
| 380 | + SOC_DAPM_ENUM("Vibra 2 Controller", dapm_enum_pwm2vib2), | |
| 381 | +}; | |
| 382 | + | |
| 383 | +/* | |
| 384 | + * DAPM-widgets | |
| 385 | + */ | |
| 386 | + | |
| 387 | +static const struct snd_soc_dapm_widget ab8500_dapm_widgets[] = { | |
| 388 | + | |
| 389 | + /* Clocks */ | |
| 390 | + SND_SOC_DAPM_CLOCK_SUPPLY("audioclk"), | |
| 391 | + | |
| 392 | + /* Regulators */ | |
| 393 | + SND_SOC_DAPM_REGULATOR_SUPPLY("V-AUD", 0), | |
| 394 | + SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC1", 0), | |
| 395 | + SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC2", 0), | |
| 396 | + SND_SOC_DAPM_REGULATOR_SUPPLY("V-DMIC", 0), | |
| 397 | + | |
| 398 | + /* Power */ | |
| 399 | + SND_SOC_DAPM_SUPPLY("Audio Power", | |
| 400 | + AB8500_POWERUP, AB8500_POWERUP_POWERUP, 0, | |
| 401 | + NULL, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | |
| 402 | + SND_SOC_DAPM_SUPPLY("Audio Analog Power", | |
| 403 | + AB8500_POWERUP, AB8500_POWERUP_ENANA, 0, | |
| 404 | + NULL, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | |
| 405 | + | |
| 406 | + /* Main supply node */ | |
| 407 | + SND_SOC_DAPM_SUPPLY("Main Supply", SND_SOC_NOPM, 0, 0, | |
| 408 | + NULL, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | |
| 409 | + | |
| 410 | + /* DA/AD */ | |
| 411 | + | |
| 412 | + SND_SOC_DAPM_INPUT("ADC Input"), | |
| 413 | + SND_SOC_DAPM_ADC("ADC", "ab8500_0c", SND_SOC_NOPM, 0, 0), | |
| 414 | + | |
| 415 | + SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), | |
| 416 | + SND_SOC_DAPM_OUTPUT("DAC Output"), | |
| 417 | + | |
| 418 | + SND_SOC_DAPM_AIF_IN("DA_IN1", NULL, 0, SND_SOC_NOPM, 0, 0), | |
| 419 | + SND_SOC_DAPM_AIF_IN("DA_IN2", NULL, 0, SND_SOC_NOPM, 0, 0), | |
| 420 | + SND_SOC_DAPM_AIF_IN("DA_IN3", NULL, 0, SND_SOC_NOPM, 0, 0), | |
| 421 | + SND_SOC_DAPM_AIF_IN("DA_IN4", NULL, 0, SND_SOC_NOPM, 0, 0), | |
| 422 | + SND_SOC_DAPM_AIF_IN("DA_IN5", NULL, 0, SND_SOC_NOPM, 0, 0), | |
| 423 | + SND_SOC_DAPM_AIF_IN("DA_IN6", NULL, 0, SND_SOC_NOPM, 0, 0), | |
| 424 | + SND_SOC_DAPM_AIF_OUT("AD_OUT1", NULL, 0, SND_SOC_NOPM, 0, 0), | |
| 425 | + SND_SOC_DAPM_AIF_OUT("AD_OUT2", NULL, 0, SND_SOC_NOPM, 0, 0), | |
| 426 | + SND_SOC_DAPM_AIF_OUT("AD_OUT3", NULL, 0, SND_SOC_NOPM, 0, 0), | |
| 427 | + SND_SOC_DAPM_AIF_OUT("AD_OUT4", NULL, 0, SND_SOC_NOPM, 0, 0), | |
| 428 | + SND_SOC_DAPM_AIF_OUT("AD_OUT57", NULL, 0, SND_SOC_NOPM, 0, 0), | |
| 429 | + SND_SOC_DAPM_AIF_OUT("AD_OUT68", NULL, 0, SND_SOC_NOPM, 0, 0), | |
| 430 | + | |
| 431 | + /* Headset path */ | |
| 432 | + | |
| 433 | + SND_SOC_DAPM_SUPPLY("Charge Pump", AB8500_ANACONF5, | |
| 434 | + AB8500_ANACONF5_ENCPHS, 0, NULL, 0), | |
| 435 | + | |
| 436 | + SND_SOC_DAPM_DAC("DA1 Enable", "ab8500_0p", | |
| 437 | + AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA1, 0), | |
| 438 | + SND_SOC_DAPM_DAC("DA2 Enable", "ab8500_0p", | |
| 439 | + AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA2, 0), | |
| 440 | + | |
| 441 | + SND_SOC_DAPM_PGA("HSL Digital Volume", SND_SOC_NOPM, 0, 0, | |
| 442 | + NULL, 0), | |
| 443 | + SND_SOC_DAPM_PGA("HSR Digital Volume", SND_SOC_NOPM, 0, 0, | |
| 444 | + NULL, 0), | |
| 445 | + | |
| 446 | + SND_SOC_DAPM_DAC("HSL DAC", "ab8500_0p", | |
| 447 | + AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACHSL, 0), | |
| 448 | + SND_SOC_DAPM_DAC("HSR DAC", "ab8500_0p", | |
| 449 | + AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACHSR, 0), | |
| 450 | + SND_SOC_DAPM_MIXER("HSL DAC Mute", AB8500_MUTECONF, | |
| 451 | + AB8500_MUTECONF_MUTDACHSL, 1, | |
| 452 | + NULL, 0), | |
| 453 | + SND_SOC_DAPM_MIXER("HSR DAC Mute", AB8500_MUTECONF, | |
| 454 | + AB8500_MUTECONF_MUTDACHSR, 1, | |
| 455 | + NULL, 0), | |
| 456 | + SND_SOC_DAPM_DAC("HSL DAC Driver", "ab8500_0p", | |
| 457 | + AB8500_ANACONF3, AB8500_ANACONF3_ENDRVHSL, 0), | |
| 458 | + SND_SOC_DAPM_DAC("HSR DAC Driver", "ab8500_0p", | |
| 459 | + AB8500_ANACONF3, AB8500_ANACONF3_ENDRVHSR, 0), | |
| 460 | + | |
| 461 | + SND_SOC_DAPM_MIXER("HSL Mute", | |
| 462 | + AB8500_MUTECONF, AB8500_MUTECONF_MUTHSL, 1, | |
| 463 | + NULL, 0), | |
| 464 | + SND_SOC_DAPM_MIXER("HSR Mute", | |
| 465 | + AB8500_MUTECONF, AB8500_MUTECONF_MUTHSR, 1, | |
| 466 | + NULL, 0), | |
| 467 | + SND_SOC_DAPM_MIXER("HSL Enable", | |
| 468 | + AB8500_ANACONF4, AB8500_ANACONF4_ENHSL, 0, | |
| 469 | + NULL, 0), | |
| 470 | + SND_SOC_DAPM_MIXER("HSR Enable", | |
| 471 | + AB8500_ANACONF4, AB8500_ANACONF4_ENHSR, 0, | |
| 472 | + NULL, 0), | |
| 473 | + SND_SOC_DAPM_PGA("HSL Volume", | |
| 474 | + SND_SOC_NOPM, 0, 0, | |
| 475 | + NULL, 0), | |
| 476 | + SND_SOC_DAPM_PGA("HSR Volume", | |
| 477 | + SND_SOC_NOPM, 0, 0, | |
| 478 | + NULL, 0), | |
| 479 | + | |
| 480 | + SND_SOC_DAPM_OUTPUT("Headset Left"), | |
| 481 | + SND_SOC_DAPM_OUTPUT("Headset Right"), | |
| 482 | + | |
| 483 | + /* LineOut path */ | |
| 484 | + | |
| 485 | + SND_SOC_DAPM_MUX("LineOut Source", | |
| 486 | + SND_SOC_NOPM, 0, 0, dapm_lineout_source), | |
| 487 | + | |
| 488 | + SND_SOC_DAPM_MIXER("LOL Disable HFL", | |
| 489 | + AB8500_ANACONF4, AB8500_ANACONF4_ENHFL, 1, | |
| 490 | + NULL, 0), | |
| 491 | + SND_SOC_DAPM_MIXER("LOR Disable HFR", | |
| 492 | + AB8500_ANACONF4, AB8500_ANACONF4_ENHFR, 1, | |
| 493 | + NULL, 0), | |
| 494 | + | |
| 495 | + SND_SOC_DAPM_MIXER("LOL Enable", | |
| 496 | + AB8500_ANACONF5, AB8500_ANACONF5_ENLOL, 0, | |
| 497 | + NULL, 0), | |
| 498 | + SND_SOC_DAPM_MIXER("LOR Enable", | |
| 499 | + AB8500_ANACONF5, AB8500_ANACONF5_ENLOR, 0, | |
| 500 | + NULL, 0), | |
| 501 | + | |
| 502 | + SND_SOC_DAPM_OUTPUT("LineOut Left"), | |
| 503 | + SND_SOC_DAPM_OUTPUT("LineOut Right"), | |
| 504 | + | |
| 505 | + /* Earpiece path */ | |
| 506 | + | |
| 507 | + SND_SOC_DAPM_MUX("Earpiece or LineOut Mono Source", | |
| 508 | + SND_SOC_NOPM, 0, 0, &dapm_ear_lineout_source), | |
| 509 | + SND_SOC_DAPM_MIXER("EAR DAC", | |
| 510 | + AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACEAR, 0, | |
| 511 | + NULL, 0), | |
| 512 | + SND_SOC_DAPM_MIXER("EAR Mute", | |
| 513 | + AB8500_MUTECONF, AB8500_MUTECONF_MUTEAR, 1, | |
| 514 | + NULL, 0), | |
| 515 | + SND_SOC_DAPM_MIXER("EAR Enable", | |
| 516 | + AB8500_ANACONF4, AB8500_ANACONF4_ENEAR, 0, | |
| 517 | + NULL, 0), | |
| 518 | + | |
| 519 | + SND_SOC_DAPM_OUTPUT("Earpiece"), | |
| 520 | + | |
| 521 | + /* Handsfree path */ | |
| 522 | + | |
| 523 | + SND_SOC_DAPM_MIXER("DA3 Channel Volume", | |
| 524 | + AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA3, 0, | |
| 525 | + NULL, 0), | |
| 526 | + SND_SOC_DAPM_MIXER("DA4 Channel Volume", | |
| 527 | + AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA4, 0, | |
| 528 | + NULL, 0), | |
| 529 | + SND_SOC_DAPM_MUX("Speaker Left Source", | |
| 530 | + SND_SOC_NOPM, 0, 0, dapm_HFl_select), | |
| 531 | + SND_SOC_DAPM_MUX("Speaker Right Source", | |
| 532 | + SND_SOC_NOPM, 0, 0, dapm_HFr_select), | |
| 533 | + SND_SOC_DAPM_MIXER("HFL DAC", AB8500_DAPATHCONF, | |
| 534 | + AB8500_DAPATHCONF_ENDACHFL, 0, | |
| 535 | + NULL, 0), | |
| 536 | + SND_SOC_DAPM_MIXER("HFR DAC", | |
| 537 | + AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACHFR, 0, | |
| 538 | + NULL, 0), | |
| 539 | + SND_SOC_DAPM_MIXER("DA4 or ANC path to HfR", | |
| 540 | + AB8500_DIGMULTCONF2, AB8500_DIGMULTCONF2_DATOHFREN, 0, | |
| 541 | + NULL, 0), | |
| 542 | + SND_SOC_DAPM_MIXER("DA3 or ANC path to HfL", | |
| 543 | + AB8500_DIGMULTCONF2, AB8500_DIGMULTCONF2_DATOHFLEN, 0, | |
| 544 | + NULL, 0), | |
| 545 | + SND_SOC_DAPM_MIXER("HFL Enable", | |
| 546 | + AB8500_ANACONF4, AB8500_ANACONF4_ENHFL, 0, | |
| 547 | + NULL, 0), | |
| 548 | + SND_SOC_DAPM_MIXER("HFR Enable", | |
| 549 | + AB8500_ANACONF4, AB8500_ANACONF4_ENHFR, 0, | |
| 550 | + NULL, 0), | |
| 551 | + | |
| 552 | + SND_SOC_DAPM_OUTPUT("Speaker Left"), | |
| 553 | + SND_SOC_DAPM_OUTPUT("Speaker Right"), | |
| 554 | + | |
| 555 | + /* Vibrator path */ | |
| 556 | + | |
| 557 | + SND_SOC_DAPM_INPUT("PWMGEN1"), | |
| 558 | + SND_SOC_DAPM_INPUT("PWMGEN2"), | |
| 559 | + | |
| 560 | + SND_SOC_DAPM_MIXER("DA5 Channel Volume", | |
| 561 | + AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA5, 0, | |
| 562 | + NULL, 0), | |
| 563 | + SND_SOC_DAPM_MIXER("DA6 Channel Volume", | |
| 564 | + AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA6, 0, | |
| 565 | + NULL, 0), | |
| 566 | + SND_SOC_DAPM_MIXER("VIB1 DAC", | |
| 567 | + AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACVIB1, 0, | |
| 568 | + NULL, 0), | |
| 569 | + SND_SOC_DAPM_MIXER("VIB2 DAC", | |
| 570 | + AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACVIB2, 0, | |
| 571 | + NULL, 0), | |
| 572 | + SND_SOC_DAPM_MUX("Vibra 1 Controller", | |
| 573 | + SND_SOC_NOPM, 0, 0, dapm_pwm2vib1), | |
| 574 | + SND_SOC_DAPM_MUX("Vibra 2 Controller", | |
| 575 | + SND_SOC_NOPM, 0, 0, dapm_pwm2vib2), | |
| 576 | + SND_SOC_DAPM_MIXER("VIB1 Enable", | |
| 577 | + AB8500_ANACONF4, AB8500_ANACONF4_ENVIB1, 0, | |
| 578 | + NULL, 0), | |
| 579 | + SND_SOC_DAPM_MIXER("VIB2 Enable", | |
| 580 | + AB8500_ANACONF4, AB8500_ANACONF4_ENVIB2, 0, | |
| 581 | + NULL, 0), | |
| 582 | + | |
| 583 | + SND_SOC_DAPM_OUTPUT("Vibra 1"), | |
| 584 | + SND_SOC_DAPM_OUTPUT("Vibra 2"), | |
| 585 | + | |
| 586 | + /* Mic 1 */ | |
| 587 | + | |
| 588 | + SND_SOC_DAPM_INPUT("Mic 1"), | |
| 589 | + | |
| 590 | + SND_SOC_DAPM_MUX("Mic 1a or 1b Select", | |
| 591 | + SND_SOC_NOPM, 0, 0, dapm_mic1ab_mux), | |
| 592 | + SND_SOC_DAPM_MIXER("MIC1 Mute", | |
| 593 | + AB8500_ANACONF2, AB8500_ANACONF2_MUTMIC1, 1, | |
| 594 | + NULL, 0), | |
| 595 | + SND_SOC_DAPM_MIXER("MIC1A V-AMICx Enable", | |
| 596 | + AB8500_ANACONF2, AB8500_ANACONF2_ENMIC1, 0, | |
| 597 | + NULL, 0), | |
| 598 | + SND_SOC_DAPM_MIXER("MIC1B V-AMICx Enable", | |
| 599 | + AB8500_ANACONF2, AB8500_ANACONF2_ENMIC1, 0, | |
| 600 | + NULL, 0), | |
| 601 | + SND_SOC_DAPM_MIXER("MIC1 ADC", | |
| 602 | + AB8500_ANACONF3, AB8500_ANACONF3_ENADCMIC, 0, | |
| 603 | + NULL, 0), | |
| 604 | + SND_SOC_DAPM_MUX("AD3 Source Select", | |
| 605 | + SND_SOC_NOPM, 0, 0, dapm_ad3_select), | |
| 606 | + SND_SOC_DAPM_MIXER("AD3 Channel Volume", | |
| 607 | + SND_SOC_NOPM, 0, 0, | |
| 608 | + NULL, 0), | |
| 609 | + SND_SOC_DAPM_MIXER("AD3 Enable", | |
| 610 | + AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD34, 0, | |
| 611 | + NULL, 0), | |
| 612 | + | |
| 613 | + /* Mic 2 */ | |
| 614 | + | |
| 615 | + SND_SOC_DAPM_INPUT("Mic 2"), | |
| 616 | + | |
| 617 | + SND_SOC_DAPM_MIXER("MIC2 Mute", | |
| 618 | + AB8500_ANACONF2, AB8500_ANACONF2_MUTMIC2, 1, | |
| 619 | + NULL, 0), | |
| 620 | + SND_SOC_DAPM_MIXER("MIC2 V-AMICx Enable", AB8500_ANACONF2, | |
| 621 | + AB8500_ANACONF2_ENMIC2, 0, | |
| 622 | + NULL, 0), | |
| 623 | + | |
| 624 | + /* LineIn */ | |
| 625 | + | |
| 626 | + SND_SOC_DAPM_INPUT("LineIn Left"), | |
| 627 | + SND_SOC_DAPM_INPUT("LineIn Right"), | |
| 628 | + | |
| 629 | + SND_SOC_DAPM_MIXER("LINL Mute", | |
| 630 | + AB8500_ANACONF2, AB8500_ANACONF2_MUTLINL, 1, | |
| 631 | + NULL, 0), | |
| 632 | + SND_SOC_DAPM_MIXER("LINR Mute", | |
| 633 | + AB8500_ANACONF2, AB8500_ANACONF2_MUTLINR, 1, | |
| 634 | + NULL, 0), | |
| 635 | + SND_SOC_DAPM_MIXER("LINL Enable", AB8500_ANACONF2, | |
| 636 | + AB8500_ANACONF2_ENLINL, 0, | |
| 637 | + NULL, 0), | |
| 638 | + SND_SOC_DAPM_MIXER("LINR Enable", AB8500_ANACONF2, | |
| 639 | + AB8500_ANACONF2_ENLINR, 0, | |
| 640 | + NULL, 0), | |
| 641 | + | |
| 642 | + /* LineIn Bypass path */ | |
| 643 | + SND_SOC_DAPM_MIXER("LINL to HSL Volume", | |
| 644 | + SND_SOC_NOPM, 0, 0, | |
| 645 | + NULL, 0), | |
| 646 | + SND_SOC_DAPM_MIXER("LINR to HSR Volume", | |
| 647 | + SND_SOC_NOPM, 0, 0, | |
| 648 | + NULL, 0), | |
| 649 | + | |
| 650 | + /* LineIn, Mic 2 */ | |
| 651 | + SND_SOC_DAPM_MUX("Mic 2 or LINR Select", | |
| 652 | + SND_SOC_NOPM, 0, 0, dapm_mic2lr_select), | |
| 653 | + SND_SOC_DAPM_MIXER("LINL ADC", AB8500_ANACONF3, | |
| 654 | + AB8500_ANACONF3_ENADCLINL, 0, | |
| 655 | + NULL, 0), | |
| 656 | + SND_SOC_DAPM_MIXER("LINR ADC", AB8500_ANACONF3, | |
| 657 | + AB8500_ANACONF3_ENADCLINR, 0, | |
| 658 | + NULL, 0), | |
| 659 | + SND_SOC_DAPM_MUX("AD1 Source Select", | |
| 660 | + SND_SOC_NOPM, 0, 0, dapm_ad1_select), | |
| 661 | + SND_SOC_DAPM_MUX("AD2 Source Select", | |
| 662 | + SND_SOC_NOPM, 0, 0, dapm_ad2_select), | |
| 663 | + SND_SOC_DAPM_MIXER("AD1 Channel Volume", | |
| 664 | + SND_SOC_NOPM, 0, 0, | |
| 665 | + NULL, 0), | |
| 666 | + SND_SOC_DAPM_MIXER("AD2 Channel Volume", | |
| 667 | + SND_SOC_NOPM, 0, 0, | |
| 668 | + NULL, 0), | |
| 669 | + | |
| 670 | + SND_SOC_DAPM_MIXER("AD12 Enable", | |
| 671 | + AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD12, 0, | |
| 672 | + NULL, 0), | |
| 673 | + | |
| 674 | + /* HD Capture path */ | |
| 675 | + | |
| 676 | + SND_SOC_DAPM_MUX("AD5 Source Select", | |
| 677 | + SND_SOC_NOPM, 0, 0, dapm_ad5_select), | |
| 678 | + SND_SOC_DAPM_MUX("AD6 Source Select", | |
| 679 | + SND_SOC_NOPM, 0, 0, dapm_ad6_select), | |
| 680 | + SND_SOC_DAPM_MIXER("AD5 Channel Volume", | |
| 681 | + SND_SOC_NOPM, 0, 0, | |
| 682 | + NULL, 0), | |
| 683 | + SND_SOC_DAPM_MIXER("AD6 Channel Volume", | |
| 684 | + SND_SOC_NOPM, 0, 0, | |
| 685 | + NULL, 0), | |
| 686 | + SND_SOC_DAPM_MIXER("AD57 Enable", | |
| 687 | + AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD5768, 0, | |
| 688 | + NULL, 0), | |
| 689 | + SND_SOC_DAPM_MIXER("AD68 Enable", | |
| 690 | + AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD5768, 0, | |
| 691 | + NULL, 0), | |
| 692 | + | |
| 693 | + /* Digital Microphone path */ | |
| 694 | + | |
| 695 | + SND_SOC_DAPM_INPUT("DMic 1"), | |
| 696 | + SND_SOC_DAPM_INPUT("DMic 2"), | |
| 697 | + SND_SOC_DAPM_INPUT("DMic 3"), | |
| 698 | + SND_SOC_DAPM_INPUT("DMic 4"), | |
| 699 | + SND_SOC_DAPM_INPUT("DMic 5"), | |
| 700 | + SND_SOC_DAPM_INPUT("DMic 6"), | |
| 701 | + | |
| 702 | + SND_SOC_DAPM_MIXER("DMIC1", | |
| 703 | + AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC1, 0, | |
| 704 | + NULL, 0), | |
| 705 | + SND_SOC_DAPM_MIXER("DMIC2", | |
| 706 | + AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC2, 0, | |
| 707 | + NULL, 0), | |
| 708 | + SND_SOC_DAPM_MIXER("DMIC3", | |
| 709 | + AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC3, 0, | |
| 710 | + NULL, 0), | |
| 711 | + SND_SOC_DAPM_MIXER("DMIC4", | |
| 712 | + AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC4, 0, | |
| 713 | + NULL, 0), | |
| 714 | + SND_SOC_DAPM_MIXER("DMIC5", | |
| 715 | + AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC5, 0, | |
| 716 | + NULL, 0), | |
| 717 | + SND_SOC_DAPM_MIXER("DMIC6", | |
| 718 | + AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC6, 0, | |
| 719 | + NULL, 0), | |
| 720 | + SND_SOC_DAPM_MIXER("AD4 Channel Volume", | |
| 721 | + SND_SOC_NOPM, 0, 0, | |
| 722 | + NULL, 0), | |
| 723 | + SND_SOC_DAPM_MIXER("AD4 Enable", | |
| 724 | + AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD34, | |
| 725 | + 0, NULL, 0), | |
| 726 | + | |
| 727 | + /* Acoustical Noise Cancellation path */ | |
| 728 | + | |
| 729 | + SND_SOC_DAPM_INPUT("ANC Configure Input"), | |
| 730 | + SND_SOC_DAPM_OUTPUT("ANC Configure Output"), | |
| 731 | + | |
| 732 | + SND_SOC_DAPM_MUX("ANC Source", | |
| 733 | + SND_SOC_NOPM, 0, 0, | |
| 734 | + dapm_anc_in_select), | |
| 735 | + SND_SOC_DAPM_SWITCH("ANC", | |
| 736 | + SND_SOC_NOPM, 0, 0, | |
| 737 | + dapm_anc_enable), | |
| 738 | + SND_SOC_DAPM_SWITCH("ANC to Earpiece", | |
| 739 | + SND_SOC_NOPM, 0, 0, | |
| 740 | + dapm_anc_ear_mute), | |
| 741 | + | |
| 742 | + /* Sidetone Filter path */ | |
| 743 | + | |
| 744 | + SND_SOC_DAPM_MUX("Sidetone Left Source", | |
| 745 | + SND_SOC_NOPM, 0, 0, | |
| 746 | + dapm_stfir1_in_select), | |
| 747 | + SND_SOC_DAPM_MUX("Sidetone Right Source", | |
| 748 | + SND_SOC_NOPM, 0, 0, | |
| 749 | + dapm_stfir2_in_select), | |
| 750 | + SND_SOC_DAPM_MIXER("STFIR1 Control", | |
| 751 | + SND_SOC_NOPM, 0, 0, | |
| 752 | + NULL, 0), | |
| 753 | + SND_SOC_DAPM_MIXER("STFIR2 Control", | |
| 754 | + SND_SOC_NOPM, 0, 0, | |
| 755 | + NULL, 0), | |
| 756 | + SND_SOC_DAPM_MIXER("STFIR1 Volume", | |
| 757 | + SND_SOC_NOPM, 0, 0, | |
| 758 | + NULL, 0), | |
| 759 | + SND_SOC_DAPM_MIXER("STFIR2 Volume", | |
| 760 | + SND_SOC_NOPM, 0, 0, | |
| 761 | + NULL, 0), | |
| 762 | +}; | |
| 763 | + | |
| 764 | +/* | |
| 765 | + * DAPM-routes | |
| 766 | + */ | |
| 767 | +static const struct snd_soc_dapm_route ab8500_dapm_routes[] = { | |
| 768 | + /* Power AB8500 audio-block when AD/DA is active */ | |
| 769 | + {"Main Supply", NULL, "V-AUD"}, | |
| 770 | + {"Main Supply", NULL, "audioclk"}, | |
| 771 | + {"Main Supply", NULL, "Audio Power"}, | |
| 772 | + {"Main Supply", NULL, "Audio Analog Power"}, | |
| 773 | + | |
| 774 | + {"DAC", NULL, "ab8500_0p"}, | |
| 775 | + {"DAC", NULL, "Main Supply"}, | |
| 776 | + {"ADC", NULL, "ab8500_0c"}, | |
| 777 | + {"ADC", NULL, "Main Supply"}, | |
| 778 | + | |
| 779 | + /* ANC Configure */ | |
| 780 | + {"ANC Configure Input", NULL, "Main Supply"}, | |
| 781 | + {"ANC Configure Output", NULL, "ANC Configure Input"}, | |
| 782 | + | |
| 783 | + /* AD/DA */ | |
| 784 | + {"ADC", NULL, "ADC Input"}, | |
| 785 | + {"DAC Output", NULL, "DAC"}, | |
| 786 | + | |
| 787 | + /* Powerup charge pump if DA1/2 is in use */ | |
| 788 | + | |
| 789 | + {"DA_IN1", NULL, "ab8500_0p"}, | |
| 790 | + {"DA_IN1", NULL, "Charge Pump"}, | |
| 791 | + {"DA_IN2", NULL, "ab8500_0p"}, | |
| 792 | + {"DA_IN2", NULL, "Charge Pump"}, | |
| 793 | + | |
| 794 | + /* Headset path */ | |
| 795 | + | |
| 796 | + {"DA1 Enable", NULL, "DA_IN1"}, | |
| 797 | + {"DA2 Enable", NULL, "DA_IN2"}, | |
| 798 | + | |
| 799 | + {"HSL Digital Volume", NULL, "DA1 Enable"}, | |
| 800 | + {"HSR Digital Volume", NULL, "DA2 Enable"}, | |
| 801 | + | |
| 802 | + {"HSL DAC", NULL, "HSL Digital Volume"}, | |
| 803 | + {"HSR DAC", NULL, "HSR Digital Volume"}, | |
| 804 | + | |
| 805 | + {"HSL DAC Mute", NULL, "HSL DAC"}, | |
| 806 | + {"HSR DAC Mute", NULL, "HSR DAC"}, | |
| 807 | + | |
| 808 | + {"HSL DAC Driver", NULL, "HSL DAC Mute"}, | |
| 809 | + {"HSR DAC Driver", NULL, "HSR DAC Mute"}, | |
| 810 | + | |
| 811 | + {"HSL Mute", NULL, "HSL DAC Driver"}, | |
| 812 | + {"HSR Mute", NULL, "HSR DAC Driver"}, | |
| 813 | + | |
| 814 | + {"HSL Enable", NULL, "HSL Mute"}, | |
| 815 | + {"HSR Enable", NULL, "HSR Mute"}, | |
| 816 | + | |
| 817 | + {"HSL Volume", NULL, "HSL Enable"}, | |
| 818 | + {"HSR Volume", NULL, "HSR Enable"}, | |
| 819 | + | |
| 820 | + {"Headset Left", NULL, "HSL Volume"}, | |
| 821 | + {"Headset Right", NULL, "HSR Volume"}, | |
| 822 | + | |
| 823 | + /* HF or LineOut path */ | |
| 824 | + | |
| 825 | + {"DA_IN3", NULL, "ab8500_0p"}, | |
| 826 | + {"DA3 Channel Volume", NULL, "DA_IN3"}, | |
| 827 | + {"DA_IN4", NULL, "ab8500_0p"}, | |
| 828 | + {"DA4 Channel Volume", NULL, "DA_IN4"}, | |
| 829 | + | |
| 830 | + {"Speaker Left Source", "Audio Path", "DA3 Channel Volume"}, | |
| 831 | + {"Speaker Right Source", "Audio Path", "DA4 Channel Volume"}, | |
| 832 | + | |
| 833 | + {"DA3 or ANC path to HfL", NULL, "Speaker Left Source"}, | |
| 834 | + {"DA4 or ANC path to HfR", NULL, "Speaker Right Source"}, | |
| 835 | + | |
| 836 | + /* HF path */ | |
| 837 | + | |
| 838 | + {"HFL DAC", NULL, "DA3 or ANC path to HfL"}, | |
| 839 | + {"HFR DAC", NULL, "DA4 or ANC path to HfR"}, | |
| 840 | + | |
| 841 | + {"HFL Enable", NULL, "HFL DAC"}, | |
| 842 | + {"HFR Enable", NULL, "HFR DAC"}, | |
| 843 | + | |
| 844 | + {"Speaker Left", NULL, "HFL Enable"}, | |
| 845 | + {"Speaker Right", NULL, "HFR Enable"}, | |
| 846 | + | |
| 847 | + /* Earpiece path */ | |
| 848 | + | |
| 849 | + {"Earpiece or LineOut Mono Source", "Headset Left", | |
| 850 | + "HSL Digital Volume"}, | |
| 851 | + {"Earpiece or LineOut Mono Source", "Speaker Left", | |
| 852 | + "DA3 or ANC path to HfL"}, | |
| 853 | + | |
| 854 | + {"EAR DAC", NULL, "Earpiece or LineOut Mono Source"}, | |
| 855 | + | |
| 856 | + {"EAR Mute", NULL, "EAR DAC"}, | |
| 857 | + | |
| 858 | + {"EAR Enable", NULL, "EAR Mute"}, | |
| 859 | + | |
| 860 | + {"Earpiece", NULL, "EAR Enable"}, | |
| 861 | + | |
| 862 | + /* LineOut path stereo */ | |
| 863 | + | |
| 864 | + {"LineOut Source", "Stereo Path", "HSL DAC Driver"}, | |
| 865 | + {"LineOut Source", "Stereo Path", "HSR DAC Driver"}, | |
| 866 | + | |
| 867 | + /* LineOut path mono */ | |
| 868 | + | |
| 869 | + {"LineOut Source", "Mono Path", "EAR DAC"}, | |
| 870 | + | |
| 871 | + /* LineOut path */ | |
| 872 | + | |
| 873 | + {"LOL Disable HFL", NULL, "LineOut Source"}, | |
| 874 | + {"LOR Disable HFR", NULL, "LineOut Source"}, | |
| 875 | + | |
| 876 | + {"LOL Enable", NULL, "LOL Disable HFL"}, | |
| 877 | + {"LOR Enable", NULL, "LOR Disable HFR"}, | |
| 878 | + | |
| 879 | + {"LineOut Left", NULL, "LOL Enable"}, | |
| 880 | + {"LineOut Right", NULL, "LOR Enable"}, | |
| 881 | + | |
| 882 | + /* Vibrator path */ | |
| 883 | + | |
| 884 | + {"DA_IN5", NULL, "ab8500_0p"}, | |
| 885 | + {"DA5 Channel Volume", NULL, "DA_IN5"}, | |
| 886 | + {"DA_IN6", NULL, "ab8500_0p"}, | |
| 887 | + {"DA6 Channel Volume", NULL, "DA_IN6"}, | |
| 888 | + | |
| 889 | + {"VIB1 DAC", NULL, "DA5 Channel Volume"}, | |
| 890 | + {"VIB2 DAC", NULL, "DA6 Channel Volume"}, | |
| 891 | + | |
| 892 | + {"Vibra 1 Controller", "Audio Path", "VIB1 DAC"}, | |
| 893 | + {"Vibra 2 Controller", "Audio Path", "VIB2 DAC"}, | |
| 894 | + {"Vibra 1 Controller", "PWM Generator", "PWMGEN1"}, | |
| 895 | + {"Vibra 2 Controller", "PWM Generator", "PWMGEN2"}, | |
| 896 | + | |
| 897 | + {"VIB1 Enable", NULL, "Vibra 1 Controller"}, | |
| 898 | + {"VIB2 Enable", NULL, "Vibra 2 Controller"}, | |
| 899 | + | |
| 900 | + {"Vibra 1", NULL, "VIB1 Enable"}, | |
| 901 | + {"Vibra 2", NULL, "VIB2 Enable"}, | |
| 902 | + | |
| 903 | + | |
| 904 | + /* Mic 2 */ | |
| 905 | + | |
| 906 | + {"MIC2 V-AMICx Enable", NULL, "Mic 2"}, | |
| 907 | + | |
| 908 | + /* LineIn */ | |
| 909 | + {"LINL Mute", NULL, "LineIn Left"}, | |
| 910 | + {"LINR Mute", NULL, "LineIn Right"}, | |
| 911 | + | |
| 912 | + {"LINL Enable", NULL, "LINL Mute"}, | |
| 913 | + {"LINR Enable", NULL, "LINR Mute"}, | |
| 914 | + | |
| 915 | + /* LineIn, Mic 2 */ | |
| 916 | + {"Mic 2 or LINR Select", "LineIn Right", "LINR Enable"}, | |
| 917 | + {"Mic 2 or LINR Select", "Mic 2", "MIC2 V-AMICx Enable"}, | |
| 918 | + | |
| 919 | + {"LINL ADC", NULL, "LINL Enable"}, | |
| 920 | + {"LINR ADC", NULL, "Mic 2 or LINR Select"}, | |
| 921 | + | |
| 922 | + {"AD1 Source Select", "LineIn Left", "LINL ADC"}, | |
| 923 | + {"AD2 Source Select", "LineIn Right", "LINR ADC"}, | |
| 924 | + | |
| 925 | + {"AD1 Channel Volume", NULL, "AD1 Source Select"}, | |
| 926 | + {"AD2 Channel Volume", NULL, "AD2 Source Select"}, | |
| 927 | + | |
| 928 | + {"AD12 Enable", NULL, "AD1 Channel Volume"}, | |
| 929 | + {"AD12 Enable", NULL, "AD2 Channel Volume"}, | |
| 930 | + | |
| 931 | + {"AD_OUT1", NULL, "ab8500_0c"}, | |
| 932 | + {"AD_OUT1", NULL, "AD12 Enable"}, | |
| 933 | + {"AD_OUT2", NULL, "ab8500_0c"}, | |
| 934 | + {"AD_OUT2", NULL, "AD12 Enable"}, | |
| 935 | + | |
| 936 | + /* Mic 1 */ | |
| 937 | + | |
| 938 | + {"MIC1 Mute", NULL, "Mic 1"}, | |
| 939 | + | |
| 940 | + {"MIC1A V-AMICx Enable", NULL, "MIC1 Mute"}, | |
| 941 | + {"MIC1B V-AMICx Enable", NULL, "MIC1 Mute"}, | |
| 942 | + | |
| 943 | + {"Mic 1a or 1b Select", "Mic 1a", "MIC1A V-AMICx Enable"}, | |
| 944 | + {"Mic 1a or 1b Select", "Mic 1b", "MIC1B V-AMICx Enable"}, | |
| 945 | + | |
| 946 | + {"MIC1 ADC", NULL, "Mic 1a or 1b Select"}, | |
| 947 | + | |
| 948 | + {"AD3 Source Select", "Mic 1", "MIC1 ADC"}, | |
| 949 | + | |
| 950 | + {"AD3 Channel Volume", NULL, "AD3 Source Select"}, | |
| 951 | + | |
| 952 | + {"AD3 Enable", NULL, "AD3 Channel Volume"}, | |
| 953 | + | |
| 954 | + {"AD_OUT3", NULL, "ab8500_0c"}, | |
| 955 | + {"AD_OUT3", NULL, "AD3 Enable"}, | |
| 956 | + | |
| 957 | + /* HD Capture path */ | |
| 958 | + | |
| 959 | + {"AD5 Source Select", "Mic 2", "LINR ADC"}, | |
| 960 | + {"AD6 Source Select", "Mic 1", "MIC1 ADC"}, | |
| 961 | + | |
| 962 | + {"AD5 Channel Volume", NULL, "AD5 Source Select"}, | |
| 963 | + {"AD6 Channel Volume", NULL, "AD6 Source Select"}, | |
| 964 | + | |
| 965 | + {"AD57 Enable", NULL, "AD5 Channel Volume"}, | |
| 966 | + {"AD68 Enable", NULL, "AD6 Channel Volume"}, | |
| 967 | + | |
| 968 | + {"AD_OUT57", NULL, "ab8500_0c"}, | |
| 969 | + {"AD_OUT57", NULL, "AD57 Enable"}, | |
| 970 | + {"AD_OUT68", NULL, "ab8500_0c"}, | |
| 971 | + {"AD_OUT68", NULL, "AD68 Enable"}, | |
| 972 | + | |
| 973 | + /* Digital Microphone path */ | |
| 974 | + | |
| 975 | + {"DMic 1", NULL, "V-DMIC"}, | |
| 976 | + {"DMic 2", NULL, "V-DMIC"}, | |
| 977 | + {"DMic 3", NULL, "V-DMIC"}, | |
| 978 | + {"DMic 4", NULL, "V-DMIC"}, | |
| 979 | + {"DMic 5", NULL, "V-DMIC"}, | |
| 980 | + {"DMic 6", NULL, "V-DMIC"}, | |
| 981 | + | |
| 982 | + {"AD1 Source Select", NULL, "DMic 1"}, | |
| 983 | + {"AD2 Source Select", NULL, "DMic 2"}, | |
| 984 | + {"AD3 Source Select", NULL, "DMic 3"}, | |
| 985 | + {"AD5 Source Select", NULL, "DMic 5"}, | |
| 986 | + {"AD6 Source Select", NULL, "DMic 6"}, | |
| 987 | + | |
| 988 | + {"AD4 Channel Volume", NULL, "DMic 4"}, | |
| 989 | + {"AD4 Enable", NULL, "AD4 Channel Volume"}, | |
| 990 | + | |
| 991 | + {"AD_OUT4", NULL, "ab8500_0c"}, | |
| 992 | + {"AD_OUT4", NULL, "AD4 Enable"}, | |
| 993 | + | |
| 994 | + /* LineIn Bypass path */ | |
| 995 | + | |
| 996 | + {"LINL to HSL Volume", NULL, "LINL Enable"}, | |
| 997 | + {"LINR to HSR Volume", NULL, "LINR Enable"}, | |
| 998 | + | |
| 999 | + {"HSL DAC Driver", NULL, "LINL to HSL Volume"}, | |
| 1000 | + {"HSR DAC Driver", NULL, "LINR to HSR Volume"}, | |
| 1001 | + | |
| 1002 | + /* ANC path (Acoustic Noise Cancellation) */ | |
| 1003 | + | |
| 1004 | + {"ANC Source", "Mic 2 / DMic 5", "AD5 Channel Volume"}, | |
| 1005 | + {"ANC Source", "Mic 1 / DMic 6", "AD6 Channel Volume"}, | |
| 1006 | + | |
| 1007 | + {"ANC", "Switch", "ANC Source"}, | |
| 1008 | + | |
| 1009 | + {"Speaker Left Source", "ANC", "ANC"}, | |
| 1010 | + {"Speaker Right Source", "ANC", "ANC"}, | |
| 1011 | + {"ANC to Earpiece", "Switch", "ANC"}, | |
| 1012 | + | |
| 1013 | + {"HSL Digital Volume", NULL, "ANC to Earpiece"}, | |
| 1014 | + | |
| 1015 | + /* Sidetone Filter path */ | |
| 1016 | + | |
| 1017 | + {"Sidetone Left Source", "LineIn Left", "AD12 Enable"}, | |
| 1018 | + {"Sidetone Left Source", "LineIn Right", "AD12 Enable"}, | |
| 1019 | + {"Sidetone Left Source", "Mic 1", "AD3 Enable"}, | |
| 1020 | + {"Sidetone Left Source", "Headset Left", "DA_IN1"}, | |
| 1021 | + {"Sidetone Right Source", "LineIn Right", "AD12 Enable"}, | |
| 1022 | + {"Sidetone Right Source", "Mic 1", "AD3 Enable"}, | |
| 1023 | + {"Sidetone Right Source", "DMic 4", "AD4 Enable"}, | |
| 1024 | + {"Sidetone Right Source", "Headset Right", "DA_IN2"}, | |
| 1025 | + | |
| 1026 | + {"STFIR1 Control", NULL, "Sidetone Left Source"}, | |
| 1027 | + {"STFIR2 Control", NULL, "Sidetone Right Source"}, | |
| 1028 | + | |
| 1029 | + {"STFIR1 Volume", NULL, "STFIR1 Control"}, | |
| 1030 | + {"STFIR2 Volume", NULL, "STFIR2 Control"}, | |
| 1031 | + | |
| 1032 | + {"DA1 Enable", NULL, "STFIR1 Volume"}, | |
| 1033 | + {"DA2 Enable", NULL, "STFIR2 Volume"}, | |
| 1034 | +}; | |
| 1035 | + | |
| 1036 | +static const struct snd_soc_dapm_route ab8500_dapm_routes_mic1a_vamicx[] = { | |
| 1037 | + {"MIC1A V-AMICx Enable", NULL, "V-AMIC1"}, | |
| 1038 | + {"MIC1A V-AMICx Enable", NULL, "V-AMIC2"}, | |
| 1039 | +}; | |
| 1040 | + | |
| 1041 | +static const struct snd_soc_dapm_route ab8500_dapm_routes_mic1b_vamicx[] = { | |
| 1042 | + {"MIC1B V-AMICx Enable", NULL, "V-AMIC1"}, | |
| 1043 | + {"MIC1B V-AMICx Enable", NULL, "V-AMIC2"}, | |
| 1044 | +}; | |
| 1045 | + | |
| 1046 | +static const struct snd_soc_dapm_route ab8500_dapm_routes_mic2_vamicx[] = { | |
| 1047 | + {"MIC2 V-AMICx Enable", NULL, "V-AMIC1"}, | |
| 1048 | + {"MIC2 V-AMICx Enable", NULL, "V-AMIC2"}, | |
| 1049 | +}; | |
| 1050 | + | |
| 1051 | +/* ANC FIR-coefficients configuration sequence */ | |
| 1052 | +static void anc_fir(struct snd_soc_codec *codec, | |
| 1053 | + unsigned int bnk, unsigned int par, unsigned int val) | |
| 1054 | +{ | |
| 1055 | + if (par == 0 && bnk == 0) | |
| 1056 | + snd_soc_update_bits(codec, AB8500_ANCCONF1, | |
| 1057 | + BIT(AB8500_ANCCONF1_ANCFIRUPDATE), | |
| 1058 | + BIT(AB8500_ANCCONF1_ANCFIRUPDATE)); | |
| 1059 | + | |
| 1060 | + snd_soc_write(codec, AB8500_ANCCONF5, val >> 8 & 0xff); | |
| 1061 | + snd_soc_write(codec, AB8500_ANCCONF6, val & 0xff); | |
| 1062 | + | |
| 1063 | + if (par == AB8500_ANC_FIR_COEFFS - 1 && bnk == 1) | |
| 1064 | + snd_soc_update_bits(codec, AB8500_ANCCONF1, | |
| 1065 | + BIT(AB8500_ANCCONF1_ANCFIRUPDATE), 0); | |
| 1066 | +} | |
| 1067 | + | |
| 1068 | +/* ANC IIR-coefficients configuration sequence */ | |
| 1069 | +static void anc_iir(struct snd_soc_codec *codec, unsigned int bnk, | |
| 1070 | + unsigned int par, unsigned int val) | |
| 1071 | +{ | |
| 1072 | + if (par == 0) { | |
| 1073 | + if (bnk == 0) { | |
| 1074 | + snd_soc_update_bits(codec, AB8500_ANCCONF1, | |
| 1075 | + BIT(AB8500_ANCCONF1_ANCIIRINIT), | |
| 1076 | + BIT(AB8500_ANCCONF1_ANCIIRINIT)); | |
| 1077 | + usleep_range(AB8500_ANC_SM_DELAY, AB8500_ANC_SM_DELAY); | |
| 1078 | + snd_soc_update_bits(codec, AB8500_ANCCONF1, | |
| 1079 | + BIT(AB8500_ANCCONF1_ANCIIRINIT), 0); | |
| 1080 | + usleep_range(AB8500_ANC_SM_DELAY, AB8500_ANC_SM_DELAY); | |
| 1081 | + } else { | |
| 1082 | + snd_soc_update_bits(codec, AB8500_ANCCONF1, | |
| 1083 | + BIT(AB8500_ANCCONF1_ANCIIRUPDATE), | |
| 1084 | + BIT(AB8500_ANCCONF1_ANCIIRUPDATE)); | |
| 1085 | + } | |
| 1086 | + } else if (par > 3) { | |
| 1087 | + snd_soc_write(codec, AB8500_ANCCONF7, 0); | |
| 1088 | + snd_soc_write(codec, AB8500_ANCCONF8, val >> 16 & 0xff); | |
| 1089 | + } | |
| 1090 | + | |
| 1091 | + snd_soc_write(codec, AB8500_ANCCONF7, val >> 8 & 0xff); | |
| 1092 | + snd_soc_write(codec, AB8500_ANCCONF8, val & 0xff); | |
| 1093 | + | |
| 1094 | + if (par == AB8500_ANC_IIR_COEFFS - 1 && bnk == 1) | |
| 1095 | + snd_soc_update_bits(codec, AB8500_ANCCONF1, | |
| 1096 | + BIT(AB8500_ANCCONF1_ANCIIRUPDATE), 0); | |
| 1097 | +} | |
| 1098 | + | |
| 1099 | +/* ANC IIR-/FIR-coefficients configuration sequence */ | |
| 1100 | +static void anc_configure(struct snd_soc_codec *codec, | |
| 1101 | + bool apply_fir, bool apply_iir) | |
| 1102 | +{ | |
| 1103 | + struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); | |
| 1104 | + unsigned int bnk, par, val; | |
| 1105 | + | |
| 1106 | + dev_dbg(codec->dev, "%s: Enter.\n", __func__); | |
| 1107 | + | |
| 1108 | + if (apply_fir) | |
| 1109 | + snd_soc_update_bits(codec, AB8500_ANCCONF1, | |
| 1110 | + BIT(AB8500_ANCCONF1_ENANC), 0); | |
| 1111 | + | |
| 1112 | + snd_soc_update_bits(codec, AB8500_ANCCONF1, | |
| 1113 | + BIT(AB8500_ANCCONF1_ENANC), BIT(AB8500_ANCCONF1_ENANC)); | |
| 1114 | + | |
| 1115 | + if (apply_fir) | |
| 1116 | + for (bnk = 0; bnk < AB8500_NR_OF_ANC_COEFF_BANKS; bnk++) | |
| 1117 | + for (par = 0; par < AB8500_ANC_FIR_COEFFS; par++) { | |
| 1118 | + val = snd_soc_read(codec, | |
| 1119 | + drvdata->anc_fir_values[par]); | |
| 1120 | + anc_fir(codec, bnk, par, val); | |
| 1121 | + } | |
| 1122 | + | |
| 1123 | + if (apply_iir) | |
| 1124 | + for (bnk = 0; bnk < AB8500_NR_OF_ANC_COEFF_BANKS; bnk++) | |
| 1125 | + for (par = 0; par < AB8500_ANC_IIR_COEFFS; par++) { | |
| 1126 | + val = snd_soc_read(codec, | |
| 1127 | + drvdata->anc_iir_values[par]); | |
| 1128 | + anc_iir(codec, bnk, par, val); | |
| 1129 | + } | |
| 1130 | + | |
| 1131 | + dev_dbg(codec->dev, "%s: Exit.\n", __func__); | |
| 1132 | +} | |
| 1133 | + | |
| 1134 | +/* | |
| 1135 | + * Control-events | |
| 1136 | + */ | |
| 1137 | + | |
| 1138 | +static int sid_status_control_get(struct snd_kcontrol *kcontrol, | |
| 1139 | + struct snd_ctl_elem_value *ucontrol) | |
| 1140 | +{ | |
| 1141 | + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | |
| 1142 | + struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); | |
| 1143 | + | |
| 1144 | + mutex_lock(&codec->mutex); | |
| 1145 | + ucontrol->value.integer.value[0] = drvdata->sid_status; | |
| 1146 | + mutex_unlock(&codec->mutex); | |
| 1147 | + | |
| 1148 | + return 0; | |
| 1149 | +} | |
| 1150 | + | |
| 1151 | +/* Write sidetone FIR-coefficients configuration sequence */ | |
| 1152 | +static int sid_status_control_put(struct snd_kcontrol *kcontrol, | |
| 1153 | + struct snd_ctl_elem_value *ucontrol) | |
| 1154 | +{ | |
| 1155 | + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | |
| 1156 | + struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); | |
| 1157 | + unsigned int param, sidconf, val; | |
| 1158 | + int status = 1; | |
| 1159 | + | |
| 1160 | + dev_dbg(codec->dev, "%s: Enter\n", __func__); | |
| 1161 | + | |
| 1162 | + if (ucontrol->value.integer.value[0] != SID_APPLY_FIR) { | |
| 1163 | + dev_err(codec->dev, | |
| 1164 | + "%s: ERROR: This control supports '%s' only!\n", | |
| 1165 | + __func__, enum_sid_state[SID_APPLY_FIR]); | |
| 1166 | + return -EIO; | |
| 1167 | + } | |
| 1168 | + | |
| 1169 | + mutex_lock(&codec->mutex); | |
| 1170 | + | |
| 1171 | + sidconf = snd_soc_read(codec, AB8500_SIDFIRCONF); | |
| 1172 | + if (((sidconf & BIT(AB8500_SIDFIRCONF_FIRSIDBUSY)) != 0)) { | |
| 1173 | + if ((sidconf & BIT(AB8500_SIDFIRCONF_ENFIRSIDS)) == 0) { | |
| 1174 | + dev_err(codec->dev, "%s: Sidetone busy while off!\n", | |
| 1175 | + __func__); | |
| 1176 | + status = -EPERM; | |
| 1177 | + } else { | |
| 1178 | + status = -EBUSY; | |
| 1179 | + } | |
| 1180 | + goto out; | |
| 1181 | + } | |
| 1182 | + | |
| 1183 | + snd_soc_write(codec, AB8500_SIDFIRADR, 0); | |
| 1184 | + | |
| 1185 | + for (param = 0; param < AB8500_SID_FIR_COEFFS; param++) { | |
| 1186 | + val = snd_soc_read(codec, drvdata->sid_fir_values[param]); | |
| 1187 | + snd_soc_write(codec, AB8500_SIDFIRCOEF1, val >> 8 & 0xff); | |
| 1188 | + snd_soc_write(codec, AB8500_SIDFIRCOEF2, val & 0xff); | |
| 1189 | + } | |
| 1190 | + | |
| 1191 | + snd_soc_update_bits(codec, AB8500_SIDFIRADR, | |
| 1192 | + BIT(AB8500_SIDFIRADR_FIRSIDSET), | |
| 1193 | + BIT(AB8500_SIDFIRADR_FIRSIDSET)); | |
| 1194 | + snd_soc_update_bits(codec, AB8500_SIDFIRADR, | |
| 1195 | + BIT(AB8500_SIDFIRADR_FIRSIDSET), 0); | |
| 1196 | + | |
| 1197 | + drvdata->sid_status = SID_FIR_CONFIGURED; | |
| 1198 | + | |
| 1199 | +out: | |
| 1200 | + mutex_unlock(&codec->mutex); | |
| 1201 | + | |
| 1202 | + dev_dbg(codec->dev, "%s: Exit\n", __func__); | |
| 1203 | + | |
| 1204 | + return status; | |
| 1205 | +} | |
| 1206 | + | |
| 1207 | +static int anc_status_control_get(struct snd_kcontrol *kcontrol, | |
| 1208 | + struct snd_ctl_elem_value *ucontrol) | |
| 1209 | +{ | |
| 1210 | + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | |
| 1211 | + struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); | |
| 1212 | + | |
| 1213 | + mutex_lock(&codec->mutex); | |
| 1214 | + ucontrol->value.integer.value[0] = drvdata->anc_status; | |
| 1215 | + mutex_unlock(&codec->mutex); | |
| 1216 | + | |
| 1217 | + return 0; | |
| 1218 | +} | |
| 1219 | + | |
| 1220 | +static int anc_status_control_put(struct snd_kcontrol *kcontrol, | |
| 1221 | + struct snd_ctl_elem_value *ucontrol) | |
| 1222 | +{ | |
| 1223 | + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | |
| 1224 | + struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); | |
| 1225 | + struct device *dev = codec->dev; | |
| 1226 | + bool apply_fir, apply_iir; | |
| 1227 | + int req, status; | |
| 1228 | + | |
| 1229 | + dev_dbg(dev, "%s: Enter.\n", __func__); | |
| 1230 | + | |
| 1231 | + mutex_lock(&drvdata->anc_lock); | |
| 1232 | + | |
| 1233 | + req = ucontrol->value.integer.value[0]; | |
| 1234 | + if (req != ANC_APPLY_FIR_IIR && req != ANC_APPLY_FIR && | |
| 1235 | + req != ANC_APPLY_IIR) { | |
| 1236 | + dev_err(dev, "%s: ERROR: Unsupported status to set '%s'!\n", | |
| 1237 | + __func__, enum_anc_state[req]); | |
| 1238 | + status = -EINVAL; | |
| 1239 | + goto cleanup; | |
| 1240 | + } | |
| 1241 | + apply_fir = req == ANC_APPLY_FIR || req == ANC_APPLY_FIR_IIR; | |
| 1242 | + apply_iir = req == ANC_APPLY_IIR || req == ANC_APPLY_FIR_IIR; | |
| 1243 | + | |
| 1244 | + status = snd_soc_dapm_force_enable_pin(&codec->dapm, | |
| 1245 | + "ANC Configure Input"); | |
| 1246 | + if (status < 0) { | |
| 1247 | + dev_err(dev, | |
| 1248 | + "%s: ERROR: Failed to enable power (status = %d)!\n", | |
| 1249 | + __func__, status); | |
| 1250 | + goto cleanup; | |
| 1251 | + } | |
| 1252 | + snd_soc_dapm_sync(&codec->dapm); | |
| 1253 | + | |
| 1254 | + mutex_lock(&codec->mutex); | |
| 1255 | + anc_configure(codec, apply_fir, apply_iir); | |
| 1256 | + mutex_unlock(&codec->mutex); | |
| 1257 | + | |
| 1258 | + if (apply_fir) { | |
| 1259 | + if (drvdata->anc_status == ANC_IIR_CONFIGURED) | |
| 1260 | + drvdata->anc_status = ANC_FIR_IIR_CONFIGURED; | |
| 1261 | + else if (drvdata->anc_status != ANC_FIR_IIR_CONFIGURED) | |
| 1262 | + drvdata->anc_status = ANC_FIR_CONFIGURED; | |
| 1263 | + } | |
| 1264 | + if (apply_iir) { | |
| 1265 | + if (drvdata->anc_status == ANC_FIR_CONFIGURED) | |
| 1266 | + drvdata->anc_status = ANC_FIR_IIR_CONFIGURED; | |
| 1267 | + else if (drvdata->anc_status != ANC_FIR_IIR_CONFIGURED) | |
| 1268 | + drvdata->anc_status = ANC_IIR_CONFIGURED; | |
| 1269 | + } | |
| 1270 | + | |
| 1271 | + status = snd_soc_dapm_disable_pin(&codec->dapm, "ANC Configure Input"); | |
| 1272 | + snd_soc_dapm_sync(&codec->dapm); | |
| 1273 | + | |
| 1274 | +cleanup: | |
| 1275 | + mutex_unlock(&drvdata->anc_lock); | |
| 1276 | + | |
| 1277 | + if (status < 0) | |
| 1278 | + dev_err(dev, "%s: Unable to configure ANC! (status = %d)\n", | |
| 1279 | + __func__, status); | |
| 1280 | + | |
| 1281 | + dev_dbg(dev, "%s: Exit.\n", __func__); | |
| 1282 | + | |
| 1283 | + return (status < 0) ? status : 1; | |
| 1284 | +} | |
| 1285 | + | |
| 1286 | +static int filter_control_info(struct snd_kcontrol *kcontrol, | |
| 1287 | + struct snd_ctl_elem_info *uinfo) | |
| 1288 | +{ | |
| 1289 | + struct filter_control *fc = | |
| 1290 | + (struct filter_control *)kcontrol->private_value; | |
| 1291 | + | |
| 1292 | + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | |
| 1293 | + uinfo->count = fc->count; | |
| 1294 | + uinfo->value.integer.min = fc->min; | |
| 1295 | + uinfo->value.integer.max = fc->max; | |
| 1296 | + | |
| 1297 | + return 0; | |
| 1298 | +} | |
| 1299 | + | |
| 1300 | +static int filter_control_get(struct snd_kcontrol *kcontrol, | |
| 1301 | + struct snd_ctl_elem_value *ucontrol) | |
| 1302 | +{ | |
| 1303 | + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | |
| 1304 | + struct filter_control *fc = | |
| 1305 | + (struct filter_control *)kcontrol->private_value; | |
| 1306 | + unsigned int i; | |
| 1307 | + | |
| 1308 | + mutex_lock(&codec->mutex); | |
| 1309 | + for (i = 0; i < fc->count; i++) | |
| 1310 | + ucontrol->value.integer.value[i] = fc->value[i]; | |
| 1311 | + mutex_unlock(&codec->mutex); | |
| 1312 | + | |
| 1313 | + return 0; | |
| 1314 | +} | |
| 1315 | + | |
| 1316 | +static int filter_control_put(struct snd_kcontrol *kcontrol, | |
| 1317 | + struct snd_ctl_elem_value *ucontrol) | |
| 1318 | +{ | |
| 1319 | + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | |
| 1320 | + struct filter_control *fc = | |
| 1321 | + (struct filter_control *)kcontrol->private_value; | |
| 1322 | + unsigned int i; | |
| 1323 | + | |
| 1324 | + mutex_lock(&codec->mutex); | |
| 1325 | + for (i = 0; i < fc->count; i++) | |
| 1326 | + fc->value[i] = ucontrol->value.integer.value[i]; | |
| 1327 | + mutex_unlock(&codec->mutex); | |
| 1328 | + | |
| 1329 | + return 0; | |
| 1330 | +} | |
| 1331 | + | |
| 1332 | +/* | |
| 1333 | + * Controls - Non-DAPM ASoC | |
| 1334 | + */ | |
| 1335 | + | |
| 1336 | +static DECLARE_TLV_DB_SCALE(adx_dig_gain_tlv, -3200, 100, 1); | |
| 1337 | +/* -32dB = Mute */ | |
| 1338 | + | |
| 1339 | +static DECLARE_TLV_DB_SCALE(dax_dig_gain_tlv, -6300, 100, 1); | |
| 1340 | +/* -63dB = Mute */ | |
| 1341 | + | |
| 1342 | +static DECLARE_TLV_DB_SCALE(hs_ear_dig_gain_tlv, -100, 100, 1); | |
| 1343 | +/* -1dB = Mute */ | |
| 1344 | + | |
| 1345 | +static const unsigned int hs_gain_tlv[] = { | |
| 1346 | + TLV_DB_RANGE_HEAD(2), | |
| 1347 | + 0, 3, TLV_DB_SCALE_ITEM(-3200, 400, 0), | |
| 1348 | + 4, 15, TLV_DB_SCALE_ITEM(-1800, 200, 0), | |
| 1349 | +}; | |
| 1350 | + | |
| 1351 | +static DECLARE_TLV_DB_SCALE(mic_gain_tlv, 0, 100, 0); | |
| 1352 | + | |
| 1353 | +static DECLARE_TLV_DB_SCALE(lin_gain_tlv, -1000, 200, 0); | |
| 1354 | + | |
| 1355 | +static DECLARE_TLV_DB_SCALE(lin2hs_gain_tlv, -3800, 200, 1); | |
| 1356 | +/* -38dB = Mute */ | |
| 1357 | + | |
| 1358 | +static const char * const enum_hsfadspeed[] = {"2ms", "0.5ms", "10.6ms", | |
| 1359 | + "5ms"}; | |
| 1360 | +static SOC_ENUM_SINGLE_DECL(soc_enum_hsfadspeed, | |
| 1361 | + AB8500_DIGMICCONF, AB8500_DIGMICCONF_HSFADSPEED, enum_hsfadspeed); | |
| 1362 | + | |
| 1363 | +static const char * const enum_envdetthre[] = { | |
| 1364 | + "250mV", "300mV", "350mV", "400mV", | |
| 1365 | + "450mV", "500mV", "550mV", "600mV", | |
| 1366 | + "650mV", "700mV", "750mV", "800mV", | |
| 1367 | + "850mV", "900mV", "950mV", "1.00V" }; | |
| 1368 | +static SOC_ENUM_SINGLE_DECL(soc_enum_envdeththre, | |
| 1369 | + AB8500_ENVCPCONF, AB8500_ENVCPCONF_ENVDETHTHRE, enum_envdetthre); | |
| 1370 | +static SOC_ENUM_SINGLE_DECL(soc_enum_envdetlthre, | |
| 1371 | + AB8500_ENVCPCONF, AB8500_ENVCPCONF_ENVDETLTHRE, enum_envdetthre); | |
| 1372 | +static const char * const enum_envdettime[] = { | |
| 1373 | + "26.6us", "53.2us", "106us", "213us", | |
| 1374 | + "426us", "851us", "1.70ms", "3.40ms", | |
| 1375 | + "6.81ms", "13.6ms", "27.2ms", "54.5ms", | |
| 1376 | + "109ms", "218ms", "436ms", "872ms" }; | |
| 1377 | +static SOC_ENUM_SINGLE_DECL(soc_enum_envdettime, | |
| 1378 | + AB8500_SIGENVCONF, AB8500_SIGENVCONF_ENVDETTIME, enum_envdettime); | |
| 1379 | + | |
| 1380 | +static const char * const enum_sinc31[] = {"Sinc 3", "Sinc 1"}; | |
| 1381 | +static SOC_ENUM_SINGLE_DECL(soc_enum_hsesinc, AB8500_HSLEARDIGGAIN, | |
| 1382 | + AB8500_HSLEARDIGGAIN_HSSINC1, enum_sinc31); | |
| 1383 | + | |
| 1384 | +static const char * const enum_fadespeed[] = {"1ms", "4ms", "8ms", "16ms"}; | |
| 1385 | +static SOC_ENUM_SINGLE_DECL(soc_enum_fadespeed, AB8500_HSRDIGGAIN, | |
| 1386 | + AB8500_HSRDIGGAIN_FADESPEED, enum_fadespeed); | |
| 1387 | + | |
| 1388 | +/* Earpiece */ | |
| 1389 | + | |
| 1390 | +static const char * const enum_lowpow[] = {"Normal", "Low Power"}; | |
| 1391 | +static SOC_ENUM_SINGLE_DECL(soc_enum_eardaclowpow, AB8500_ANACONF1, | |
| 1392 | + AB8500_ANACONF1_EARDACLOWPOW, enum_lowpow); | |
| 1393 | +static SOC_ENUM_SINGLE_DECL(soc_enum_eardrvlowpow, AB8500_ANACONF1, | |
| 1394 | + AB8500_ANACONF1_EARDRVLOWPOW, enum_lowpow); | |
| 1395 | + | |
| 1396 | +static const char * const enum_av_mode[] = {"Audio", "Voice"}; | |
| 1397 | +static SOC_ENUM_DOUBLE_DECL(soc_enum_ad12voice, AB8500_ADFILTCONF, | |
| 1398 | + AB8500_ADFILTCONF_AD1VOICE, AB8500_ADFILTCONF_AD2VOICE, enum_av_mode); | |
| 1399 | +static SOC_ENUM_DOUBLE_DECL(soc_enum_ad34voice, AB8500_ADFILTCONF, | |
| 1400 | + AB8500_ADFILTCONF_AD3VOICE, AB8500_ADFILTCONF_AD4VOICE, enum_av_mode); | |
| 1401 | + | |
| 1402 | +/* DA */ | |
| 1403 | + | |
| 1404 | +static SOC_ENUM_SINGLE_DECL(soc_enum_da12voice, | |
| 1405 | + AB8500_DASLOTCONF1, AB8500_DASLOTCONF1_DA12VOICE, | |
| 1406 | + enum_av_mode); | |
| 1407 | +static SOC_ENUM_SINGLE_DECL(soc_enum_da34voice, | |
| 1408 | + AB8500_DASLOTCONF3, AB8500_DASLOTCONF3_DA34VOICE, | |
| 1409 | + enum_av_mode); | |
| 1410 | +static SOC_ENUM_SINGLE_DECL(soc_enum_da56voice, | |
| 1411 | + AB8500_DASLOTCONF5, AB8500_DASLOTCONF5_DA56VOICE, | |
| 1412 | + enum_av_mode); | |
| 1413 | + | |
| 1414 | +static const char * const enum_da2hslr[] = {"Sidetone", "Audio Path"}; | |
| 1415 | +static SOC_ENUM_DOUBLE_DECL(soc_enum_da2hslr, AB8500_DIGMULTCONF1, | |
| 1416 | + AB8500_DIGMULTCONF1_DATOHSLEN, | |
| 1417 | + AB8500_DIGMULTCONF1_DATOHSREN, enum_da2hslr); | |
| 1418 | + | |
| 1419 | +static const char * const enum_sinc53[] = {"Sinc 5", "Sinc 3"}; | |
| 1420 | +static SOC_ENUM_DOUBLE_DECL(soc_enum_dmic12sinc, AB8500_DMICFILTCONF, | |
| 1421 | + AB8500_DMICFILTCONF_DMIC1SINC3, | |
| 1422 | + AB8500_DMICFILTCONF_DMIC2SINC3, enum_sinc53); | |
| 1423 | +static SOC_ENUM_DOUBLE_DECL(soc_enum_dmic34sinc, AB8500_DMICFILTCONF, | |
| 1424 | + AB8500_DMICFILTCONF_DMIC3SINC3, | |
| 1425 | + AB8500_DMICFILTCONF_DMIC4SINC3, enum_sinc53); | |
| 1426 | +static SOC_ENUM_DOUBLE_DECL(soc_enum_dmic56sinc, AB8500_DMICFILTCONF, | |
| 1427 | + AB8500_DMICFILTCONF_DMIC5SINC3, | |
| 1428 | + AB8500_DMICFILTCONF_DMIC6SINC3, enum_sinc53); | |
| 1429 | + | |
| 1430 | +/* Digital interface - DA from slot mapping */ | |
| 1431 | +static const char * const enum_da_from_slot_map[] = {"SLOT0", | |
| 1432 | + "SLOT1", | |
| 1433 | + "SLOT2", | |
| 1434 | + "SLOT3", | |
| 1435 | + "SLOT4", | |
| 1436 | + "SLOT5", | |
| 1437 | + "SLOT6", | |
| 1438 | + "SLOT7", | |
| 1439 | + "SLOT8", | |
| 1440 | + "SLOT9", | |
| 1441 | + "SLOT10", | |
| 1442 | + "SLOT11", | |
| 1443 | + "SLOT12", | |
| 1444 | + "SLOT13", | |
| 1445 | + "SLOT14", | |
| 1446 | + "SLOT15", | |
| 1447 | + "SLOT16", | |
| 1448 | + "SLOT17", | |
| 1449 | + "SLOT18", | |
| 1450 | + "SLOT19", | |
| 1451 | + "SLOT20", | |
| 1452 | + "SLOT21", | |
| 1453 | + "SLOT22", | |
| 1454 | + "SLOT23", | |
| 1455 | + "SLOT24", | |
| 1456 | + "SLOT25", | |
| 1457 | + "SLOT26", | |
| 1458 | + "SLOT27", | |
| 1459 | + "SLOT28", | |
| 1460 | + "SLOT29", | |
| 1461 | + "SLOT30", | |
| 1462 | + "SLOT31"}; | |
| 1463 | +static SOC_ENUM_SINGLE_DECL(soc_enum_da1slotmap, | |
| 1464 | + AB8500_DASLOTCONF1, AB8500_DASLOTCONFX_SLTODAX_SHIFT, | |
| 1465 | + enum_da_from_slot_map); | |
| 1466 | +static SOC_ENUM_SINGLE_DECL(soc_enum_da2slotmap, | |
| 1467 | + AB8500_DASLOTCONF2, AB8500_DASLOTCONFX_SLTODAX_SHIFT, | |
| 1468 | + enum_da_from_slot_map); | |
| 1469 | +static SOC_ENUM_SINGLE_DECL(soc_enum_da3slotmap, | |
| 1470 | + AB8500_DASLOTCONF3, AB8500_DASLOTCONFX_SLTODAX_SHIFT, | |
| 1471 | + enum_da_from_slot_map); | |
| 1472 | +static SOC_ENUM_SINGLE_DECL(soc_enum_da4slotmap, | |
| 1473 | + AB8500_DASLOTCONF4, AB8500_DASLOTCONFX_SLTODAX_SHIFT, | |
| 1474 | + enum_da_from_slot_map); | |
| 1475 | +static SOC_ENUM_SINGLE_DECL(soc_enum_da5slotmap, | |
| 1476 | + AB8500_DASLOTCONF5, AB8500_DASLOTCONFX_SLTODAX_SHIFT, | |
| 1477 | + enum_da_from_slot_map); | |
| 1478 | +static SOC_ENUM_SINGLE_DECL(soc_enum_da6slotmap, | |
| 1479 | + AB8500_DASLOTCONF6, AB8500_DASLOTCONFX_SLTODAX_SHIFT, | |
| 1480 | + enum_da_from_slot_map); | |
| 1481 | +static SOC_ENUM_SINGLE_DECL(soc_enum_da7slotmap, | |
| 1482 | + AB8500_DASLOTCONF7, AB8500_DASLOTCONFX_SLTODAX_SHIFT, | |
| 1483 | + enum_da_from_slot_map); | |
| 1484 | +static SOC_ENUM_SINGLE_DECL(soc_enum_da8slotmap, | |
| 1485 | + AB8500_DASLOTCONF8, AB8500_DASLOTCONFX_SLTODAX_SHIFT, | |
| 1486 | + enum_da_from_slot_map); | |
| 1487 | + | |
| 1488 | +/* Digital interface - AD to slot mapping */ | |
| 1489 | +static const char * const enum_ad_to_slot_map[] = {"AD_OUT1", | |
| 1490 | + "AD_OUT2", | |
| 1491 | + "AD_OUT3", | |
| 1492 | + "AD_OUT4", | |
| 1493 | + "AD_OUT5", | |
| 1494 | + "AD_OUT6", | |
| 1495 | + "AD_OUT7", | |
| 1496 | + "AD_OUT8", | |
| 1497 | + "zeroes", | |
| 1498 | + "tristate"}; | |
| 1499 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot0map, | |
| 1500 | + AB8500_ADSLOTSEL1, AB8500_ADSLOTSELX_EVEN_SHIFT, | |
| 1501 | + enum_ad_to_slot_map); | |
| 1502 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot1map, | |
| 1503 | + AB8500_ADSLOTSEL1, AB8500_ADSLOTSELX_ODD_SHIFT, | |
| 1504 | + enum_ad_to_slot_map); | |
| 1505 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot2map, | |
| 1506 | + AB8500_ADSLOTSEL2, AB8500_ADSLOTSELX_EVEN_SHIFT, | |
| 1507 | + enum_ad_to_slot_map); | |
| 1508 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot3map, | |
| 1509 | + AB8500_ADSLOTSEL2, AB8500_ADSLOTSELX_ODD_SHIFT, | |
| 1510 | + enum_ad_to_slot_map); | |
| 1511 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot4map, | |
| 1512 | + AB8500_ADSLOTSEL3, AB8500_ADSLOTSELX_EVEN_SHIFT, | |
| 1513 | + enum_ad_to_slot_map); | |
| 1514 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot5map, | |
| 1515 | + AB8500_ADSLOTSEL3, AB8500_ADSLOTSELX_ODD_SHIFT, | |
| 1516 | + enum_ad_to_slot_map); | |
| 1517 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot6map, | |
| 1518 | + AB8500_ADSLOTSEL4, AB8500_ADSLOTSELX_EVEN_SHIFT, | |
| 1519 | + enum_ad_to_slot_map); | |
| 1520 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot7map, | |
| 1521 | + AB8500_ADSLOTSEL4, AB8500_ADSLOTSELX_ODD_SHIFT, | |
| 1522 | + enum_ad_to_slot_map); | |
| 1523 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot8map, | |
| 1524 | + AB8500_ADSLOTSEL5, AB8500_ADSLOTSELX_EVEN_SHIFT, | |
| 1525 | + enum_ad_to_slot_map); | |
| 1526 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot9map, | |
| 1527 | + AB8500_ADSLOTSEL5, AB8500_ADSLOTSELX_ODD_SHIFT, | |
| 1528 | + enum_ad_to_slot_map); | |
| 1529 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot10map, | |
| 1530 | + AB8500_ADSLOTSEL6, AB8500_ADSLOTSELX_EVEN_SHIFT, | |
| 1531 | + enum_ad_to_slot_map); | |
| 1532 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot11map, | |
| 1533 | + AB8500_ADSLOTSEL6, AB8500_ADSLOTSELX_ODD_SHIFT, | |
| 1534 | + enum_ad_to_slot_map); | |
| 1535 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot12map, | |
| 1536 | + AB8500_ADSLOTSEL7, AB8500_ADSLOTSELX_EVEN_SHIFT, | |
| 1537 | + enum_ad_to_slot_map); | |
| 1538 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot13map, | |
| 1539 | + AB8500_ADSLOTSEL7, AB8500_ADSLOTSELX_ODD_SHIFT, | |
| 1540 | + enum_ad_to_slot_map); | |
| 1541 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot14map, | |
| 1542 | + AB8500_ADSLOTSEL8, AB8500_ADSLOTSELX_EVEN_SHIFT, | |
| 1543 | + enum_ad_to_slot_map); | |
| 1544 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot15map, | |
| 1545 | + AB8500_ADSLOTSEL8, AB8500_ADSLOTSELX_ODD_SHIFT, | |
| 1546 | + enum_ad_to_slot_map); | |
| 1547 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot16map, | |
| 1548 | + AB8500_ADSLOTSEL9, AB8500_ADSLOTSELX_EVEN_SHIFT, | |
| 1549 | + enum_ad_to_slot_map); | |
| 1550 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot17map, | |
| 1551 | + AB8500_ADSLOTSEL9, AB8500_ADSLOTSELX_ODD_SHIFT, | |
| 1552 | + enum_ad_to_slot_map); | |
| 1553 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot18map, | |
| 1554 | + AB8500_ADSLOTSEL10, AB8500_ADSLOTSELX_EVEN_SHIFT, | |
| 1555 | + enum_ad_to_slot_map); | |
| 1556 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot19map, | |
| 1557 | + AB8500_ADSLOTSEL10, AB8500_ADSLOTSELX_ODD_SHIFT, | |
| 1558 | + enum_ad_to_slot_map); | |
| 1559 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot20map, | |
| 1560 | + AB8500_ADSLOTSEL11, AB8500_ADSLOTSELX_EVEN_SHIFT, | |
| 1561 | + enum_ad_to_slot_map); | |
| 1562 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot21map, | |
| 1563 | + AB8500_ADSLOTSEL11, AB8500_ADSLOTSELX_ODD_SHIFT, | |
| 1564 | + enum_ad_to_slot_map); | |
| 1565 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot22map, | |
| 1566 | + AB8500_ADSLOTSEL12, AB8500_ADSLOTSELX_EVEN_SHIFT, | |
| 1567 | + enum_ad_to_slot_map); | |
| 1568 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot23map, | |
| 1569 | + AB8500_ADSLOTSEL12, AB8500_ADSLOTSELX_ODD_SHIFT, | |
| 1570 | + enum_ad_to_slot_map); | |
| 1571 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot24map, | |
| 1572 | + AB8500_ADSLOTSEL13, AB8500_ADSLOTSELX_EVEN_SHIFT, | |
| 1573 | + enum_ad_to_slot_map); | |
| 1574 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot25map, | |
| 1575 | + AB8500_ADSLOTSEL13, AB8500_ADSLOTSELX_ODD_SHIFT, | |
| 1576 | + enum_ad_to_slot_map); | |
| 1577 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot26map, | |
| 1578 | + AB8500_ADSLOTSEL14, AB8500_ADSLOTSELX_EVEN_SHIFT, | |
| 1579 | + enum_ad_to_slot_map); | |
| 1580 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot27map, | |
| 1581 | + AB8500_ADSLOTSEL14, AB8500_ADSLOTSELX_ODD_SHIFT, | |
| 1582 | + enum_ad_to_slot_map); | |
| 1583 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot28map, | |
| 1584 | + AB8500_ADSLOTSEL15, AB8500_ADSLOTSELX_EVEN_SHIFT, | |
| 1585 | + enum_ad_to_slot_map); | |
| 1586 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot29map, | |
| 1587 | + AB8500_ADSLOTSEL15, AB8500_ADSLOTSELX_ODD_SHIFT, | |
| 1588 | + enum_ad_to_slot_map); | |
| 1589 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot30map, | |
| 1590 | + AB8500_ADSLOTSEL16, AB8500_ADSLOTSELX_EVEN_SHIFT, | |
| 1591 | + enum_ad_to_slot_map); | |
| 1592 | +static SOC_ENUM_SINGLE_DECL(soc_enum_adslot31map, | |
| 1593 | + AB8500_ADSLOTSEL16, AB8500_ADSLOTSELX_ODD_SHIFT, | |
| 1594 | + enum_ad_to_slot_map); | |
| 1595 | + | |
| 1596 | +/* Digital interface - Burst mode */ | |
| 1597 | +static const char * const enum_mask[] = {"Unmasked", "Masked"}; | |
| 1598 | +static SOC_ENUM_SINGLE_DECL(soc_enum_bfifomask, | |
| 1599 | + AB8500_FIFOCONF1, AB8500_FIFOCONF1_BFIFOMASK, | |
| 1600 | + enum_mask); | |
| 1601 | +static const char * const enum_bitclk0[] = {"19_2_MHz", "38_4_MHz"}; | |
| 1602 | +static SOC_ENUM_SINGLE_DECL(soc_enum_bfifo19m2, | |
| 1603 | + AB8500_FIFOCONF1, AB8500_FIFOCONF1_BFIFO19M2, | |
| 1604 | + enum_bitclk0); | |
| 1605 | +static const char * const enum_slavemaster[] = {"Slave", "Master"}; | |
| 1606 | +static SOC_ENUM_SINGLE_DECL(soc_enum_bfifomast, | |
| 1607 | + AB8500_FIFOCONF3, AB8500_FIFOCONF3_BFIFOMAST_SHIFT, | |
| 1608 | + enum_slavemaster); | |
| 1609 | + | |
| 1610 | +/* Sidetone */ | |
| 1611 | +static SOC_ENUM_SINGLE_EXT_DECL(soc_enum_sidstate, enum_sid_state); | |
| 1612 | + | |
| 1613 | +/* ANC */ | |
| 1614 | +static SOC_ENUM_SINGLE_EXT_DECL(soc_enum_ancstate, enum_anc_state); | |
| 1615 | + | |
| 1616 | +static struct snd_kcontrol_new ab8500_ctrls[] = { | |
| 1617 | + /* Charge pump */ | |
| 1618 | + SOC_ENUM("Charge Pump High Threshold For Low Voltage", | |
| 1619 | + soc_enum_envdeththre), | |
| 1620 | + SOC_ENUM("Charge Pump Low Threshold For Low Voltage", | |
| 1621 | + soc_enum_envdetlthre), | |
| 1622 | + SOC_SINGLE("Charge Pump Envelope Detection Switch", | |
| 1623 | + AB8500_SIGENVCONF, AB8500_SIGENVCONF_ENVDETCPEN, | |
| 1624 | + 1, 0), | |
| 1625 | + SOC_ENUM("Charge Pump Envelope Detection Decay Time", | |
| 1626 | + soc_enum_envdettime), | |
| 1627 | + | |
| 1628 | + /* Headset */ | |
| 1629 | + SOC_ENUM("Headset Mode", soc_enum_da12voice), | |
| 1630 | + SOC_SINGLE("Headset High Pass Switch", | |
| 1631 | + AB8500_ANACONF1, AB8500_ANACONF1_HSHPEN, | |
| 1632 | + 1, 0), | |
| 1633 | + SOC_SINGLE("Headset Low Power Switch", | |
| 1634 | + AB8500_ANACONF1, AB8500_ANACONF1_HSLOWPOW, | |
| 1635 | + 1, 0), | |
| 1636 | + SOC_SINGLE("Headset DAC Low Power Switch", | |
| 1637 | + AB8500_ANACONF1, AB8500_ANACONF1_DACLOWPOW1, | |
| 1638 | + 1, 0), | |
| 1639 | + SOC_SINGLE("Headset DAC Drv Low Power Switch", | |
| 1640 | + AB8500_ANACONF1, AB8500_ANACONF1_DACLOWPOW0, | |
| 1641 | + 1, 0), | |
| 1642 | + SOC_ENUM("Headset Fade Speed", soc_enum_hsfadspeed), | |
| 1643 | + SOC_ENUM("Headset Source", soc_enum_da2hslr), | |
| 1644 | + SOC_ENUM("Headset Filter", soc_enum_hsesinc), | |
| 1645 | + SOC_DOUBLE_R_TLV("Headset Master Volume", | |
| 1646 | + AB8500_DADIGGAIN1, AB8500_DADIGGAIN2, | |
| 1647 | + 0, AB8500_DADIGGAINX_DAXGAIN_MAX, 1, dax_dig_gain_tlv), | |
| 1648 | + SOC_DOUBLE_R_TLV("Headset Digital Volume", | |
| 1649 | + AB8500_HSLEARDIGGAIN, AB8500_HSRDIGGAIN, | |
| 1650 | + 0, AB8500_HSLEARDIGGAIN_HSLDGAIN_MAX, 1, hs_ear_dig_gain_tlv), | |
| 1651 | + SOC_DOUBLE_TLV("Headset Volume", | |
| 1652 | + AB8500_ANAGAIN3, | |
| 1653 | + AB8500_ANAGAIN3_HSLGAIN, AB8500_ANAGAIN3_HSRGAIN, | |
| 1654 | + AB8500_ANAGAIN3_HSXGAIN_MAX, 1, hs_gain_tlv), | |
| 1655 | + | |
| 1656 | + /* Earpiece */ | |
| 1657 | + SOC_ENUM("Earpiece DAC Mode", | |
| 1658 | + soc_enum_eardaclowpow), | |
| 1659 | + SOC_ENUM("Earpiece DAC Drv Mode", | |
| 1660 | + soc_enum_eardrvlowpow), | |
| 1661 | + | |
| 1662 | + /* HandsFree */ | |
| 1663 | + SOC_ENUM("HF Mode", soc_enum_da34voice), | |
| 1664 | + SOC_SINGLE("HF and Headset Swap Switch", | |
| 1665 | + AB8500_DASLOTCONF1, AB8500_DASLOTCONF1_SWAPDA12_34, | |
| 1666 | + 1, 0), | |
| 1667 | + SOC_DOUBLE("HF Low EMI Mode Switch", | |
| 1668 | + AB8500_CLASSDCONF1, | |
| 1669 | + AB8500_CLASSDCONF1_HFLSWAPEN, AB8500_CLASSDCONF1_HFRSWAPEN, | |
| 1670 | + 1, 0), | |
| 1671 | + SOC_DOUBLE("HF FIR Bypass Switch", | |
| 1672 | + AB8500_CLASSDCONF2, | |
| 1673 | + AB8500_CLASSDCONF2_FIRBYP0, AB8500_CLASSDCONF2_FIRBYP1, | |
| 1674 | + 1, 0), | |
| 1675 | + SOC_DOUBLE("HF High Volume Switch", | |
| 1676 | + AB8500_CLASSDCONF2, | |
| 1677 | + AB8500_CLASSDCONF2_HIGHVOLEN0, AB8500_CLASSDCONF2_HIGHVOLEN1, | |
| 1678 | + 1, 0), | |
| 1679 | + SOC_SINGLE("HF L and R Bridge Switch", | |
| 1680 | + AB8500_CLASSDCONF1, AB8500_CLASSDCONF1_PARLHF, | |
| 1681 | + 1, 0), | |
| 1682 | + SOC_DOUBLE_R_TLV("HF Master Volume", | |
| 1683 | + AB8500_DADIGGAIN3, AB8500_DADIGGAIN4, | |
| 1684 | + 0, AB8500_DADIGGAINX_DAXGAIN_MAX, 1, dax_dig_gain_tlv), | |
| 1685 | + | |
| 1686 | + /* Vibra */ | |
| 1687 | + SOC_DOUBLE("Vibra High Volume Switch", | |
| 1688 | + AB8500_CLASSDCONF2, | |
| 1689 | + AB8500_CLASSDCONF2_HIGHVOLEN2, AB8500_CLASSDCONF2_HIGHVOLEN3, | |
| 1690 | + 1, 0), | |
| 1691 | + SOC_DOUBLE("Vibra Low EMI Mode Switch", | |
| 1692 | + AB8500_CLASSDCONF1, | |
| 1693 | + AB8500_CLASSDCONF1_VIB1SWAPEN, AB8500_CLASSDCONF1_VIB2SWAPEN, | |
| 1694 | + 1, 0), | |
| 1695 | + SOC_DOUBLE("Vibra FIR Bypass Switch", | |
| 1696 | + AB8500_CLASSDCONF2, | |
| 1697 | + AB8500_CLASSDCONF2_FIRBYP2, AB8500_CLASSDCONF2_FIRBYP3, | |
| 1698 | + 1, 0), | |
| 1699 | + SOC_ENUM("Vibra Mode", soc_enum_da56voice), | |
| 1700 | + SOC_DOUBLE_R("Vibra PWM Duty Cycle N", | |
| 1701 | + AB8500_PWMGENCONF3, AB8500_PWMGENCONF5, | |
| 1702 | + AB8500_PWMGENCONFX_PWMVIBXDUTCYC, | |
| 1703 | + AB8500_PWMGENCONFX_PWMVIBXDUTCYC_MAX, 0), | |
| 1704 | + SOC_DOUBLE_R("Vibra PWM Duty Cycle P", | |
| 1705 | + AB8500_PWMGENCONF2, AB8500_PWMGENCONF4, | |
| 1706 | + AB8500_PWMGENCONFX_PWMVIBXDUTCYC, | |
| 1707 | + AB8500_PWMGENCONFX_PWMVIBXDUTCYC_MAX, 0), | |
| 1708 | + SOC_SINGLE("Vibra 1 and 2 Bridge Switch", | |
| 1709 | + AB8500_CLASSDCONF1, AB8500_CLASSDCONF1_PARLVIB, | |
| 1710 | + 1, 0), | |
| 1711 | + SOC_DOUBLE_R_TLV("Vibra Master Volume", | |
| 1712 | + AB8500_DADIGGAIN5, AB8500_DADIGGAIN6, | |
| 1713 | + 0, AB8500_DADIGGAINX_DAXGAIN_MAX, 1, dax_dig_gain_tlv), | |
| 1714 | + | |
| 1715 | + /* HandsFree, Vibra */ | |
| 1716 | + SOC_SINGLE("ClassD High Pass Volume", | |
| 1717 | + AB8500_CLASSDCONF3, AB8500_CLASSDCONF3_DITHHPGAIN, | |
| 1718 | + AB8500_CLASSDCONF3_DITHHPGAIN_MAX, 0), | |
| 1719 | + SOC_SINGLE("ClassD White Volume", | |
| 1720 | + AB8500_CLASSDCONF3, AB8500_CLASSDCONF3_DITHWGAIN, | |
| 1721 | + AB8500_CLASSDCONF3_DITHWGAIN_MAX, 0), | |
| 1722 | + | |
| 1723 | + /* Mic 1, Mic 2, LineIn */ | |
| 1724 | + SOC_DOUBLE_R_TLV("Mic Master Volume", | |
| 1725 | + AB8500_ADDIGGAIN3, AB8500_ADDIGGAIN4, | |
| 1726 | + 0, AB8500_ADDIGGAINX_ADXGAIN_MAX, 1, adx_dig_gain_tlv), | |
| 1727 | + | |
| 1728 | + /* Mic 1 */ | |
| 1729 | + SOC_SINGLE_TLV("Mic 1", | |
| 1730 | + AB8500_ANAGAIN1, | |
| 1731 | + AB8500_ANAGAINX_MICXGAIN, | |
| 1732 | + AB8500_ANAGAINX_MICXGAIN_MAX, 0, mic_gain_tlv), | |
| 1733 | + SOC_SINGLE("Mic 1 Low Power Switch", | |
| 1734 | + AB8500_ANAGAIN1, AB8500_ANAGAINX_LOWPOWMICX, | |
| 1735 | + 1, 0), | |
| 1736 | + | |
| 1737 | + /* Mic 2 */ | |
| 1738 | + SOC_DOUBLE("Mic High Pass Switch", | |
| 1739 | + AB8500_ADFILTCONF, | |
| 1740 | + AB8500_ADFILTCONF_AD3NH, AB8500_ADFILTCONF_AD4NH, | |
| 1741 | + 1, 1), | |
| 1742 | + SOC_ENUM("Mic Mode", soc_enum_ad34voice), | |
| 1743 | + SOC_ENUM("Mic Filter", soc_enum_dmic34sinc), | |
| 1744 | + SOC_SINGLE_TLV("Mic 2", | |
| 1745 | + AB8500_ANAGAIN2, | |
| 1746 | + AB8500_ANAGAINX_MICXGAIN, | |
| 1747 | + AB8500_ANAGAINX_MICXGAIN_MAX, 0, mic_gain_tlv), | |
| 1748 | + SOC_SINGLE("Mic 2 Low Power Switch", | |
| 1749 | + AB8500_ANAGAIN2, AB8500_ANAGAINX_LOWPOWMICX, | |
| 1750 | + 1, 0), | |
| 1751 | + | |
| 1752 | + /* LineIn */ | |
| 1753 | + SOC_DOUBLE("LineIn High Pass Switch", | |
| 1754 | + AB8500_ADFILTCONF, | |
| 1755 | + AB8500_ADFILTCONF_AD1NH, AB8500_ADFILTCONF_AD2NH, | |
| 1756 | + 1, 1), | |
| 1757 | + SOC_ENUM("LineIn Filter", soc_enum_dmic12sinc), | |
| 1758 | + SOC_ENUM("LineIn Mode", soc_enum_ad12voice), | |
| 1759 | + SOC_DOUBLE_R_TLV("LineIn Master Volume", | |
| 1760 | + AB8500_ADDIGGAIN1, AB8500_ADDIGGAIN2, | |
| 1761 | + 0, AB8500_ADDIGGAINX_ADXGAIN_MAX, 1, adx_dig_gain_tlv), | |
| 1762 | + SOC_DOUBLE_TLV("LineIn", | |
| 1763 | + AB8500_ANAGAIN4, | |
| 1764 | + AB8500_ANAGAIN4_LINLGAIN, AB8500_ANAGAIN4_LINRGAIN, | |
| 1765 | + AB8500_ANAGAIN4_LINXGAIN_MAX, 0, lin_gain_tlv), | |
| 1766 | + SOC_DOUBLE_R_TLV("LineIn to Headset Volume", | |
| 1767 | + AB8500_DIGLINHSLGAIN, AB8500_DIGLINHSRGAIN, | |
| 1768 | + AB8500_DIGLINHSXGAIN_LINTOHSXGAIN, | |
| 1769 | + AB8500_DIGLINHSXGAIN_LINTOHSXGAIN_MAX, | |
| 1770 | + 1, lin2hs_gain_tlv), | |
| 1771 | + | |
| 1772 | + /* DMic */ | |
| 1773 | + SOC_ENUM("DMic Filter", soc_enum_dmic56sinc), | |
| 1774 | + SOC_DOUBLE_R_TLV("DMic Master Volume", | |
| 1775 | + AB8500_ADDIGGAIN5, AB8500_ADDIGGAIN6, | |
| 1776 | + 0, AB8500_ADDIGGAINX_ADXGAIN_MAX, 1, adx_dig_gain_tlv), | |
| 1777 | + | |
| 1778 | + /* Digital gains */ | |
| 1779 | + SOC_ENUM("Digital Gain Fade Speed", soc_enum_fadespeed), | |
| 1780 | + | |
| 1781 | + /* Analog loopback */ | |
| 1782 | + SOC_DOUBLE_R_TLV("Analog Loopback Volume", | |
| 1783 | + AB8500_ADDIGLOOPGAIN1, AB8500_ADDIGLOOPGAIN2, | |
| 1784 | + 0, AB8500_ADDIGLOOPGAINX_ADXLBGAIN_MAX, 1, dax_dig_gain_tlv), | |
| 1785 | + | |
| 1786 | + /* Digital interface - DA from slot mapping */ | |
| 1787 | + SOC_ENUM("Digital Interface DA 1 From Slot Map", soc_enum_da1slotmap), | |
| 1788 | + SOC_ENUM("Digital Interface DA 2 From Slot Map", soc_enum_da2slotmap), | |
| 1789 | + SOC_ENUM("Digital Interface DA 3 From Slot Map", soc_enum_da3slotmap), | |
| 1790 | + SOC_ENUM("Digital Interface DA 4 From Slot Map", soc_enum_da4slotmap), | |
| 1791 | + SOC_ENUM("Digital Interface DA 5 From Slot Map", soc_enum_da5slotmap), | |
| 1792 | + SOC_ENUM("Digital Interface DA 6 From Slot Map", soc_enum_da6slotmap), | |
| 1793 | + SOC_ENUM("Digital Interface DA 7 From Slot Map", soc_enum_da7slotmap), | |
| 1794 | + SOC_ENUM("Digital Interface DA 8 From Slot Map", soc_enum_da8slotmap), | |
| 1795 | + | |
| 1796 | + /* Digital interface - AD to slot mapping */ | |
| 1797 | + SOC_ENUM("Digital Interface AD To Slot 0 Map", soc_enum_adslot0map), | |
| 1798 | + SOC_ENUM("Digital Interface AD To Slot 1 Map", soc_enum_adslot1map), | |
| 1799 | + SOC_ENUM("Digital Interface AD To Slot 2 Map", soc_enum_adslot2map), | |
| 1800 | + SOC_ENUM("Digital Interface AD To Slot 3 Map", soc_enum_adslot3map), | |
| 1801 | + SOC_ENUM("Digital Interface AD To Slot 4 Map", soc_enum_adslot4map), | |
| 1802 | + SOC_ENUM("Digital Interface AD To Slot 5 Map", soc_enum_adslot5map), | |
| 1803 | + SOC_ENUM("Digital Interface AD To Slot 6 Map", soc_enum_adslot6map), | |
| 1804 | + SOC_ENUM("Digital Interface AD To Slot 7 Map", soc_enum_adslot7map), | |
| 1805 | + SOC_ENUM("Digital Interface AD To Slot 8 Map", soc_enum_adslot8map), | |
| 1806 | + SOC_ENUM("Digital Interface AD To Slot 9 Map", soc_enum_adslot9map), | |
| 1807 | + SOC_ENUM("Digital Interface AD To Slot 10 Map", soc_enum_adslot10map), | |
| 1808 | + SOC_ENUM("Digital Interface AD To Slot 11 Map", soc_enum_adslot11map), | |
| 1809 | + SOC_ENUM("Digital Interface AD To Slot 12 Map", soc_enum_adslot12map), | |
| 1810 | + SOC_ENUM("Digital Interface AD To Slot 13 Map", soc_enum_adslot13map), | |
| 1811 | + SOC_ENUM("Digital Interface AD To Slot 14 Map", soc_enum_adslot14map), | |
| 1812 | + SOC_ENUM("Digital Interface AD To Slot 15 Map", soc_enum_adslot15map), | |
| 1813 | + SOC_ENUM("Digital Interface AD To Slot 16 Map", soc_enum_adslot16map), | |
| 1814 | + SOC_ENUM("Digital Interface AD To Slot 17 Map", soc_enum_adslot17map), | |
| 1815 | + SOC_ENUM("Digital Interface AD To Slot 18 Map", soc_enum_adslot18map), | |
| 1816 | + SOC_ENUM("Digital Interface AD To Slot 19 Map", soc_enum_adslot19map), | |
| 1817 | + SOC_ENUM("Digital Interface AD To Slot 20 Map", soc_enum_adslot20map), | |
| 1818 | + SOC_ENUM("Digital Interface AD To Slot 21 Map", soc_enum_adslot21map), | |
| 1819 | + SOC_ENUM("Digital Interface AD To Slot 22 Map", soc_enum_adslot22map), | |
| 1820 | + SOC_ENUM("Digital Interface AD To Slot 23 Map", soc_enum_adslot23map), | |
| 1821 | + SOC_ENUM("Digital Interface AD To Slot 24 Map", soc_enum_adslot24map), | |
| 1822 | + SOC_ENUM("Digital Interface AD To Slot 25 Map", soc_enum_adslot25map), | |
| 1823 | + SOC_ENUM("Digital Interface AD To Slot 26 Map", soc_enum_adslot26map), | |
| 1824 | + SOC_ENUM("Digital Interface AD To Slot 27 Map", soc_enum_adslot27map), | |
| 1825 | + SOC_ENUM("Digital Interface AD To Slot 28 Map", soc_enum_adslot28map), | |
| 1826 | + SOC_ENUM("Digital Interface AD To Slot 29 Map", soc_enum_adslot29map), | |
| 1827 | + SOC_ENUM("Digital Interface AD To Slot 30 Map", soc_enum_adslot30map), | |
| 1828 | + SOC_ENUM("Digital Interface AD To Slot 31 Map", soc_enum_adslot31map), | |
| 1829 | + | |
| 1830 | + /* Digital interface - Loopback */ | |
| 1831 | + SOC_SINGLE("Digital Interface AD 1 Loopback Switch", | |
| 1832 | + AB8500_DASLOTCONF1, AB8500_DASLOTCONF1_DAI7TOADO1, | |
| 1833 | + 1, 0), | |
| 1834 | + SOC_SINGLE("Digital Interface AD 2 Loopback Switch", | |
| 1835 | + AB8500_DASLOTCONF2, AB8500_DASLOTCONF2_DAI8TOADO2, | |
| 1836 | + 1, 0), | |
| 1837 | + SOC_SINGLE("Digital Interface AD 3 Loopback Switch", | |
| 1838 | + AB8500_DASLOTCONF3, AB8500_DASLOTCONF3_DAI7TOADO3, | |
| 1839 | + 1, 0), | |
| 1840 | + SOC_SINGLE("Digital Interface AD 4 Loopback Switch", | |
| 1841 | + AB8500_DASLOTCONF4, AB8500_DASLOTCONF4_DAI8TOADO4, | |
| 1842 | + 1, 0), | |
| 1843 | + SOC_SINGLE("Digital Interface AD 5 Loopback Switch", | |
| 1844 | + AB8500_DASLOTCONF5, AB8500_DASLOTCONF5_DAI7TOADO5, | |
| 1845 | + 1, 0), | |
| 1846 | + SOC_SINGLE("Digital Interface AD 6 Loopback Switch", | |
| 1847 | + AB8500_DASLOTCONF6, AB8500_DASLOTCONF6_DAI8TOADO6, | |
| 1848 | + 1, 0), | |
| 1849 | + SOC_SINGLE("Digital Interface AD 7 Loopback Switch", | |
| 1850 | + AB8500_DASLOTCONF7, AB8500_DASLOTCONF7_DAI8TOADO7, | |
| 1851 | + 1, 0), | |
| 1852 | + SOC_SINGLE("Digital Interface AD 8 Loopback Switch", | |
| 1853 | + AB8500_DASLOTCONF8, AB8500_DASLOTCONF8_DAI7TOADO8, | |
| 1854 | + 1, 0), | |
| 1855 | + | |
| 1856 | + /* Digital interface - Burst FIFO */ | |
| 1857 | + SOC_SINGLE("Digital Interface 0 FIFO Enable Switch", | |
| 1858 | + AB8500_DIGIFCONF3, AB8500_DIGIFCONF3_IF0BFIFOEN, | |
| 1859 | + 1, 0), | |
| 1860 | + SOC_ENUM("Burst FIFO Mask", soc_enum_bfifomask), | |
| 1861 | + SOC_ENUM("Burst FIFO Bit-clock Frequency", soc_enum_bfifo19m2), | |
| 1862 | + SOC_SINGLE("Burst FIFO Threshold", | |
| 1863 | + AB8500_FIFOCONF1, AB8500_FIFOCONF1_BFIFOINT_SHIFT, | |
| 1864 | + AB8500_FIFOCONF1_BFIFOINT_MAX, 0), | |
| 1865 | + SOC_SINGLE("Burst FIFO Length", | |
| 1866 | + AB8500_FIFOCONF2, AB8500_FIFOCONF2_BFIFOTX_SHIFT, | |
| 1867 | + AB8500_FIFOCONF2_BFIFOTX_MAX, 0), | |
| 1868 | + SOC_SINGLE("Burst FIFO EOS Extra Slots", | |
| 1869 | + AB8500_FIFOCONF3, AB8500_FIFOCONF3_BFIFOEXSL_SHIFT, | |
| 1870 | + AB8500_FIFOCONF3_BFIFOEXSL_MAX, 0), | |
| 1871 | + SOC_SINGLE("Burst FIFO FS Extra Bit-clocks", | |
| 1872 | + AB8500_FIFOCONF3, AB8500_FIFOCONF3_PREBITCLK0_SHIFT, | |
| 1873 | + AB8500_FIFOCONF3_PREBITCLK0_MAX, 0), | |
| 1874 | + SOC_ENUM("Burst FIFO Interface Mode", soc_enum_bfifomast), | |
| 1875 | + | |
| 1876 | + SOC_SINGLE("Burst FIFO Interface Switch", | |
| 1877 | + AB8500_FIFOCONF3, AB8500_FIFOCONF3_BFIFORUN_SHIFT, | |
| 1878 | + 1, 0), | |
| 1879 | + SOC_SINGLE("Burst FIFO Switch Frame Number", | |
| 1880 | + AB8500_FIFOCONF4, AB8500_FIFOCONF4_BFIFOFRAMSW_SHIFT, | |
| 1881 | + AB8500_FIFOCONF4_BFIFOFRAMSW_MAX, 0), | |
| 1882 | + SOC_SINGLE("Burst FIFO Wake Up Delay", | |
| 1883 | + AB8500_FIFOCONF5, AB8500_FIFOCONF5_BFIFOWAKEUP_SHIFT, | |
| 1884 | + AB8500_FIFOCONF5_BFIFOWAKEUP_MAX, 0), | |
| 1885 | + SOC_SINGLE("Burst FIFO Samples In FIFO", | |
| 1886 | + AB8500_FIFOCONF6, AB8500_FIFOCONF6_BFIFOSAMPLE_SHIFT, | |
| 1887 | + AB8500_FIFOCONF6_BFIFOSAMPLE_MAX, 0), | |
| 1888 | + | |
| 1889 | + /* ANC */ | |
| 1890 | + SOC_ENUM_EXT("ANC Status", soc_enum_ancstate, | |
| 1891 | + anc_status_control_get, anc_status_control_put), | |
| 1892 | + SOC_SINGLE_XR_SX("ANC Warp Delay Shift", | |
| 1893 | + AB8500_ANCCONF2, 1, AB8500_ANCCONF2_SHIFT, | |
| 1894 | + AB8500_ANCCONF2_MIN, AB8500_ANCCONF2_MAX, 0), | |
| 1895 | + SOC_SINGLE_XR_SX("ANC FIR Output Shift", | |
| 1896 | + AB8500_ANCCONF3, 1, AB8500_ANCCONF3_SHIFT, | |
| 1897 | + AB8500_ANCCONF3_MIN, AB8500_ANCCONF3_MAX, 0), | |
| 1898 | + SOC_SINGLE_XR_SX("ANC IIR Output Shift", | |
| 1899 | + AB8500_ANCCONF4, 1, AB8500_ANCCONF4_SHIFT, | |
| 1900 | + AB8500_ANCCONF4_MIN, AB8500_ANCCONF4_MAX, 0), | |
| 1901 | + SOC_SINGLE_XR_SX("ANC Warp Delay", | |
| 1902 | + AB8500_ANCCONF9, 2, AB8500_ANC_WARP_DELAY_SHIFT, | |
| 1903 | + AB8500_ANC_WARP_DELAY_MIN, AB8500_ANC_WARP_DELAY_MAX, 0), | |
| 1904 | + | |
| 1905 | + /* Sidetone */ | |
| 1906 | + SOC_ENUM_EXT("Sidetone Status", soc_enum_sidstate, | |
| 1907 | + sid_status_control_get, sid_status_control_put), | |
| 1908 | + SOC_SINGLE_STROBE("Sidetone Reset", | |
| 1909 | + AB8500_SIDFIRADR, AB8500_SIDFIRADR_FIRSIDSET, 0), | |
| 1910 | +}; | |
| 1911 | + | |
| 1912 | +static struct snd_kcontrol_new ab8500_filter_controls[] = { | |
| 1913 | + AB8500_FILTER_CONTROL("ANC FIR Coefficients", AB8500_ANC_FIR_COEFFS, | |
| 1914 | + AB8500_ANC_FIR_COEFF_MIN, AB8500_ANC_FIR_COEFF_MAX), | |
| 1915 | + AB8500_FILTER_CONTROL("ANC IIR Coefficients", AB8500_ANC_IIR_COEFFS, | |
| 1916 | + AB8500_ANC_IIR_COEFF_MIN, AB8500_ANC_IIR_COEFF_MAX), | |
| 1917 | + AB8500_FILTER_CONTROL("Sidetone FIR Coefficients", | |
| 1918 | + AB8500_SID_FIR_COEFFS, AB8500_SID_FIR_COEFF_MIN, | |
| 1919 | + AB8500_SID_FIR_COEFF_MAX) | |
| 1920 | +}; | |
| 1921 | +enum ab8500_filter { | |
| 1922 | + AB8500_FILTER_ANC_FIR = 0, | |
| 1923 | + AB8500_FILTER_ANC_IIR = 1, | |
| 1924 | + AB8500_FILTER_SID_FIR = 2, | |
| 1925 | +}; | |
| 1926 | + | |
| 1927 | +/* | |
| 1928 | + * Extended interface for codec-driver | |
| 1929 | + */ | |
| 1930 | + | |
| 1931 | +static int ab8500_audio_init_audioblock(struct snd_soc_codec *codec) | |
| 1932 | +{ | |
| 1933 | + int status; | |
| 1934 | + | |
| 1935 | + dev_dbg(codec->dev, "%s: Enter.\n", __func__); | |
| 1936 | + | |
| 1937 | + /* Reset audio-registers and disable 32kHz-clock output 2 */ | |
| 1938 | + status = ab8500_sysctrl_write(AB8500_STW4500CTRL3, | |
| 1939 | + AB8500_STW4500CTRL3_CLK32KOUT2DIS | | |
| 1940 | + AB8500_STW4500CTRL3_RESETAUDN, | |
| 1941 | + AB8500_STW4500CTRL3_RESETAUDN); | |
| 1942 | + if (status < 0) | |
| 1943 | + return status; | |
| 1944 | + | |
| 1945 | + return 0; | |
| 1946 | +} | |
| 1947 | + | |
| 1948 | +static int ab8500_audio_setup_mics(struct snd_soc_codec *codec, | |
| 1949 | + struct amic_settings *amics) | |
| 1950 | +{ | |
| 1951 | + u8 value8; | |
| 1952 | + unsigned int value; | |
| 1953 | + int status; | |
| 1954 | + const struct snd_soc_dapm_route *route; | |
| 1955 | + | |
| 1956 | + dev_dbg(codec->dev, "%s: Enter.\n", __func__); | |
| 1957 | + | |
| 1958 | + /* Set DMic-clocks to outputs */ | |
| 1959 | + status = abx500_get_register_interruptible(codec->dev, (u8)AB8500_MISC, | |
| 1960 | + (u8)AB8500_GPIO_DIR4_REG, | |
| 1961 | + &value8); | |
| 1962 | + if (status < 0) | |
| 1963 | + return status; | |
| 1964 | + value = value8 | GPIO27_DIR_OUTPUT | GPIO29_DIR_OUTPUT | | |
| 1965 | + GPIO31_DIR_OUTPUT; | |
| 1966 | + status = abx500_set_register_interruptible(codec->dev, | |
| 1967 | + (u8)AB8500_MISC, | |
| 1968 | + (u8)AB8500_GPIO_DIR4_REG, | |
| 1969 | + value); | |
| 1970 | + if (status < 0) | |
| 1971 | + return status; | |
| 1972 | + | |
| 1973 | + /* Attach regulators to AMic DAPM-paths */ | |
| 1974 | + dev_dbg(codec->dev, "%s: Mic 1a regulator: %s\n", __func__, | |
| 1975 | + amic_micbias_str(amics->mic1a_micbias)); | |
| 1976 | + route = &ab8500_dapm_routes_mic1a_vamicx[amics->mic1a_micbias]; | |
| 1977 | + status = snd_soc_dapm_add_routes(&codec->dapm, route, 1); | |
| 1978 | + dev_dbg(codec->dev, "%s: Mic 1b regulator: %s\n", __func__, | |
| 1979 | + amic_micbias_str(amics->mic1b_micbias)); | |
| 1980 | + route = &ab8500_dapm_routes_mic1b_vamicx[amics->mic1b_micbias]; | |
| 1981 | + status |= snd_soc_dapm_add_routes(&codec->dapm, route, 1); | |
| 1982 | + dev_dbg(codec->dev, "%s: Mic 2 regulator: %s\n", __func__, | |
| 1983 | + amic_micbias_str(amics->mic2_micbias)); | |
| 1984 | + route = &ab8500_dapm_routes_mic2_vamicx[amics->mic2_micbias]; | |
| 1985 | + status |= snd_soc_dapm_add_routes(&codec->dapm, route, 1); | |
| 1986 | + if (status < 0) { | |
| 1987 | + dev_err(codec->dev, | |
| 1988 | + "%s: Failed to add AMic-regulator DAPM-routes (%d).\n", | |
| 1989 | + __func__, status); | |
| 1990 | + return status; | |
| 1991 | + } | |
| 1992 | + | |
| 1993 | + /* Set AMic-configuration */ | |
| 1994 | + dev_dbg(codec->dev, "%s: Mic 1 mic-type: %s\n", __func__, | |
| 1995 | + amic_type_str(amics->mic1_type)); | |
| 1996 | + snd_soc_update_bits(codec, AB8500_ANAGAIN1, AB8500_ANAGAINX_ENSEMICX, | |
| 1997 | + amics->mic1_type == AMIC_TYPE_DIFFERENTIAL ? | |
| 1998 | + 0 : AB8500_ANAGAINX_ENSEMICX); | |
| 1999 | + dev_dbg(codec->dev, "%s: Mic 2 mic-type: %s\n", __func__, | |
| 2000 | + amic_type_str(amics->mic2_type)); | |
| 2001 | + snd_soc_update_bits(codec, AB8500_ANAGAIN2, AB8500_ANAGAINX_ENSEMICX, | |
| 2002 | + amics->mic2_type == AMIC_TYPE_DIFFERENTIAL ? | |
| 2003 | + 0 : AB8500_ANAGAINX_ENSEMICX); | |
| 2004 | + | |
| 2005 | + return 0; | |
| 2006 | +} | |
| 2007 | +EXPORT_SYMBOL_GPL(ab8500_audio_setup_mics); | |
| 2008 | + | |
| 2009 | +static int ab8500_audio_set_ear_cmv(struct snd_soc_codec *codec, | |
| 2010 | + enum ear_cm_voltage ear_cmv) | |
| 2011 | +{ | |
| 2012 | + char *cmv_str; | |
| 2013 | + | |
| 2014 | + switch (ear_cmv) { | |
| 2015 | + case EAR_CMV_0_95V: | |
| 2016 | + cmv_str = "0.95V"; | |
| 2017 | + break; | |
| 2018 | + case EAR_CMV_1_10V: | |
| 2019 | + cmv_str = "1.10V"; | |
| 2020 | + break; | |
| 2021 | + case EAR_CMV_1_27V: | |
| 2022 | + cmv_str = "1.27V"; | |
| 2023 | + break; | |
| 2024 | + case EAR_CMV_1_58V: | |
| 2025 | + cmv_str = "1.58V"; | |
| 2026 | + break; | |
| 2027 | + default: | |
| 2028 | + dev_err(codec->dev, | |
| 2029 | + "%s: Unknown earpiece CM-voltage (%d)!\n", | |
| 2030 | + __func__, (int)ear_cmv); | |
| 2031 | + return -EINVAL; | |
| 2032 | + } | |
| 2033 | + dev_dbg(codec->dev, "%s: Earpiece CM-voltage: %s\n", __func__, | |
| 2034 | + cmv_str); | |
| 2035 | + snd_soc_update_bits(codec, AB8500_ANACONF1, AB8500_ANACONF1_EARSELCM, | |
| 2036 | + ear_cmv); | |
| 2037 | + | |
| 2038 | + return 0; | |
| 2039 | +} | |
| 2040 | +EXPORT_SYMBOL_GPL(ab8500_audio_set_ear_cmv); | |
| 2041 | + | |
| 2042 | +static int ab8500_audio_set_bit_delay(struct snd_soc_dai *dai, | |
| 2043 | + unsigned int delay) | |
| 2044 | +{ | |
| 2045 | + unsigned int mask, val; | |
| 2046 | + struct snd_soc_codec *codec = dai->codec; | |
| 2047 | + | |
| 2048 | + mask = BIT(AB8500_DIGIFCONF2_IF0DEL); | |
| 2049 | + val = 0; | |
| 2050 | + | |
| 2051 | + switch (delay) { | |
| 2052 | + case 0: | |
| 2053 | + break; | |
| 2054 | + case 1: | |
| 2055 | + val |= BIT(AB8500_DIGIFCONF2_IF0DEL); | |
| 2056 | + break; | |
| 2057 | + default: | |
| 2058 | + dev_err(dai->codec->dev, | |
| 2059 | + "%s: ERROR: Unsupported bit-delay (0x%x)!\n", | |
| 2060 | + __func__, delay); | |
| 2061 | + return -EINVAL; | |
| 2062 | + } | |
| 2063 | + | |
| 2064 | + dev_dbg(dai->codec->dev, "%s: IF0 Bit-delay: %d bits.\n", | |
| 2065 | + __func__, delay); | |
| 2066 | + snd_soc_update_bits(codec, AB8500_DIGIFCONF2, mask, val); | |
| 2067 | + | |
| 2068 | + return 0; | |
| 2069 | +} | |
| 2070 | + | |
| 2071 | +/* Gates clocking according format mask */ | |
| 2072 | +static int ab8500_codec_set_dai_clock_gate(struct snd_soc_codec *codec, | |
| 2073 | + unsigned int fmt) | |
| 2074 | +{ | |
| 2075 | + unsigned int mask; | |
| 2076 | + unsigned int val; | |
| 2077 | + | |
| 2078 | + mask = BIT(AB8500_DIGIFCONF1_ENMASTGEN) | | |
| 2079 | + BIT(AB8500_DIGIFCONF1_ENFSBITCLK0); | |
| 2080 | + | |
| 2081 | + val = BIT(AB8500_DIGIFCONF1_ENMASTGEN); | |
| 2082 | + | |
| 2083 | + switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) { | |
| 2084 | + case SND_SOC_DAIFMT_CONT: /* continuous clock */ | |
| 2085 | + dev_dbg(codec->dev, "%s: IF0 Clock is continuous.\n", | |
| 2086 | + __func__); | |
| 2087 | + val |= BIT(AB8500_DIGIFCONF1_ENFSBITCLK0); | |
| 2088 | + break; | |
| 2089 | + case SND_SOC_DAIFMT_GATED: /* clock is gated */ | |
| 2090 | + dev_dbg(codec->dev, "%s: IF0 Clock is gated.\n", | |
| 2091 | + __func__); | |
| 2092 | + break; | |
| 2093 | + default: | |
| 2094 | + dev_err(codec->dev, | |
| 2095 | + "%s: ERROR: Unsupported clock mask (0x%x)!\n", | |
| 2096 | + __func__, fmt & SND_SOC_DAIFMT_CLOCK_MASK); | |
| 2097 | + return -EINVAL; | |
| 2098 | + } | |
| 2099 | + | |
| 2100 | + snd_soc_update_bits(codec, AB8500_DIGIFCONF1, mask, val); | |
| 2101 | + | |
| 2102 | + return 0; | |
| 2103 | +} | |
| 2104 | + | |
| 2105 | +static int ab8500_codec_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |
| 2106 | +{ | |
| 2107 | + unsigned int mask; | |
| 2108 | + unsigned int val; | |
| 2109 | + struct snd_soc_codec *codec = dai->codec; | |
| 2110 | + int status; | |
| 2111 | + | |
| 2112 | + dev_dbg(codec->dev, "%s: Enter (fmt = 0x%x)\n", __func__, fmt); | |
| 2113 | + | |
| 2114 | + mask = BIT(AB8500_DIGIFCONF3_IF1DATOIF0AD) | | |
| 2115 | + BIT(AB8500_DIGIFCONF3_IF1CLKTOIF0CLK) | | |
| 2116 | + BIT(AB8500_DIGIFCONF3_IF0BFIFOEN) | | |
| 2117 | + BIT(AB8500_DIGIFCONF3_IF0MASTER); | |
| 2118 | + val = 0; | |
| 2119 | + | |
| 2120 | + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | |
| 2121 | + case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & FRM master */ | |
| 2122 | + dev_dbg(dai->codec->dev, | |
| 2123 | + "%s: IF0 Master-mode: AB8500 master.\n", __func__); | |
| 2124 | + val |= BIT(AB8500_DIGIFCONF3_IF0MASTER); | |
| 2125 | + break; | |
| 2126 | + case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & FRM slave */ | |
| 2127 | + dev_dbg(dai->codec->dev, | |
| 2128 | + "%s: IF0 Master-mode: AB8500 slave.\n", __func__); | |
| 2129 | + break; | |
| 2130 | + case SND_SOC_DAIFMT_CBS_CFM: /* codec clk slave & FRM master */ | |
| 2131 | + case SND_SOC_DAIFMT_CBM_CFS: /* codec clk master & frame slave */ | |
| 2132 | + dev_err(dai->codec->dev, | |
| 2133 | + "%s: ERROR: The device is either a master or a slave.\n", | |
| 2134 | + __func__); | |
| 2135 | + default: | |
| 2136 | + dev_err(dai->codec->dev, | |
| 2137 | + "%s: ERROR: Unsupporter master mask 0x%x\n", | |
| 2138 | + __func__, fmt & SND_SOC_DAIFMT_MASTER_MASK); | |
| 2139 | + return -EINVAL; | |
| 2140 | + break; | |
| 2141 | + } | |
| 2142 | + | |
| 2143 | + snd_soc_update_bits(codec, AB8500_DIGIFCONF3, mask, val); | |
| 2144 | + | |
| 2145 | + /* Set clock gating */ | |
| 2146 | + status = ab8500_codec_set_dai_clock_gate(codec, fmt); | |
| 2147 | + if (status) { | |
| 2148 | + dev_err(dai->codec->dev, | |
| 2149 | + "%s: ERRROR: Failed to set clock gate (%d).\n", | |
| 2150 | + __func__, status); | |
| 2151 | + return status; | |
| 2152 | + } | |
| 2153 | + | |
| 2154 | + /* Setting data transfer format */ | |
| 2155 | + | |
| 2156 | + mask = BIT(AB8500_DIGIFCONF2_IF0FORMAT0) | | |
| 2157 | + BIT(AB8500_DIGIFCONF2_IF0FORMAT1) | | |
| 2158 | + BIT(AB8500_DIGIFCONF2_FSYNC0P) | | |
| 2159 | + BIT(AB8500_DIGIFCONF2_BITCLK0P); | |
| 2160 | + val = 0; | |
| 2161 | + | |
| 2162 | + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | |
| 2163 | + case SND_SOC_DAIFMT_I2S: /* I2S mode */ | |
| 2164 | + dev_dbg(dai->codec->dev, "%s: IF0 Protocol: I2S\n", __func__); | |
| 2165 | + val |= BIT(AB8500_DIGIFCONF2_IF0FORMAT1); | |
| 2166 | + ab8500_audio_set_bit_delay(dai, 0); | |
| 2167 | + break; | |
| 2168 | + | |
| 2169 | + case SND_SOC_DAIFMT_DSP_A: /* L data MSB after FRM LRC */ | |
| 2170 | + dev_dbg(dai->codec->dev, | |
| 2171 | + "%s: IF0 Protocol: DSP A (TDM)\n", __func__); | |
| 2172 | + val |= BIT(AB8500_DIGIFCONF2_IF0FORMAT0); | |
| 2173 | + ab8500_audio_set_bit_delay(dai, 1); | |
| 2174 | + break; | |
| 2175 | + | |
| 2176 | + case SND_SOC_DAIFMT_DSP_B: /* L data MSB during FRM LRC */ | |
| 2177 | + dev_dbg(dai->codec->dev, | |
| 2178 | + "%s: IF0 Protocol: DSP B (TDM)\n", __func__); | |
| 2179 | + val |= BIT(AB8500_DIGIFCONF2_IF0FORMAT0); | |
| 2180 | + ab8500_audio_set_bit_delay(dai, 0); | |
| 2181 | + break; | |
| 2182 | + | |
| 2183 | + default: | |
| 2184 | + dev_err(dai->codec->dev, | |
| 2185 | + "%s: ERROR: Unsupported format (0x%x)!\n", | |
| 2186 | + __func__, fmt & SND_SOC_DAIFMT_FORMAT_MASK); | |
| 2187 | + return -EINVAL; | |
| 2188 | + } | |
| 2189 | + | |
| 2190 | + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | |
| 2191 | + case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */ | |
| 2192 | + dev_dbg(dai->codec->dev, | |
| 2193 | + "%s: IF0: Normal bit clock, normal frame\n", | |
| 2194 | + __func__); | |
| 2195 | + break; | |
| 2196 | + case SND_SOC_DAIFMT_NB_IF: /* normal BCLK + inv FRM */ | |
| 2197 | + dev_dbg(dai->codec->dev, | |
| 2198 | + "%s: IF0: Normal bit clock, inverted frame\n", | |
| 2199 | + __func__); | |
| 2200 | + val |= BIT(AB8500_DIGIFCONF2_FSYNC0P); | |
| 2201 | + break; | |
| 2202 | + case SND_SOC_DAIFMT_IB_NF: /* invert BCLK + nor FRM */ | |
| 2203 | + dev_dbg(dai->codec->dev, | |
| 2204 | + "%s: IF0: Inverted bit clock, normal frame\n", | |
| 2205 | + __func__); | |
| 2206 | + val |= BIT(AB8500_DIGIFCONF2_BITCLK0P); | |
| 2207 | + break; | |
| 2208 | + case SND_SOC_DAIFMT_IB_IF: /* invert BCLK + FRM */ | |
| 2209 | + dev_dbg(dai->codec->dev, | |
| 2210 | + "%s: IF0: Inverted bit clock, inverted frame\n", | |
| 2211 | + __func__); | |
| 2212 | + val |= BIT(AB8500_DIGIFCONF2_FSYNC0P); | |
| 2213 | + val |= BIT(AB8500_DIGIFCONF2_BITCLK0P); | |
| 2214 | + break; | |
| 2215 | + default: | |
| 2216 | + dev_err(dai->codec->dev, | |
| 2217 | + "%s: ERROR: Unsupported INV mask 0x%x\n", | |
| 2218 | + __func__, fmt & SND_SOC_DAIFMT_INV_MASK); | |
| 2219 | + return -EINVAL; | |
| 2220 | + } | |
| 2221 | + | |
| 2222 | + snd_soc_update_bits(codec, AB8500_DIGIFCONF2, mask, val); | |
| 2223 | + | |
| 2224 | + return 0; | |
| 2225 | +} | |
| 2226 | + | |
| 2227 | +static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai, | |
| 2228 | + unsigned int tx_mask, unsigned int rx_mask, | |
| 2229 | + int slots, int slot_width) | |
| 2230 | +{ | |
| 2231 | + struct snd_soc_codec *codec = dai->codec; | |
| 2232 | + unsigned int val, mask, slots_active; | |
| 2233 | + | |
| 2234 | + mask = BIT(AB8500_DIGIFCONF2_IF0WL0) | | |
| 2235 | + BIT(AB8500_DIGIFCONF2_IF0WL1); | |
| 2236 | + val = 0; | |
| 2237 | + | |
| 2238 | + switch (slot_width) { | |
| 2239 | + case 16: | |
| 2240 | + break; | |
| 2241 | + case 20: | |
| 2242 | + val |= BIT(AB8500_DIGIFCONF2_IF0WL0); | |
| 2243 | + break; | |
| 2244 | + case 24: | |
| 2245 | + val |= BIT(AB8500_DIGIFCONF2_IF0WL1); | |
| 2246 | + break; | |
| 2247 | + case 32: | |
| 2248 | + val |= BIT(AB8500_DIGIFCONF2_IF0WL1) | | |
| 2249 | + BIT(AB8500_DIGIFCONF2_IF0WL0); | |
| 2250 | + break; | |
| 2251 | + default: | |
| 2252 | + dev_err(dai->codec->dev, "%s: Unsupported slot-width 0x%x\n", | |
| 2253 | + __func__, slot_width); | |
| 2254 | + return -EINVAL; | |
| 2255 | + } | |
| 2256 | + | |
| 2257 | + dev_dbg(dai->codec->dev, "%s: IF0 slot-width: %d bits.\n", | |
| 2258 | + __func__, slot_width); | |
| 2259 | + snd_soc_update_bits(codec, AB8500_DIGIFCONF2, mask, val); | |
| 2260 | + | |
| 2261 | + /* Setup TDM clocking according to slot count */ | |
| 2262 | + dev_dbg(dai->codec->dev, "%s: Slots, total: %d\n", __func__, slots); | |
| 2263 | + mask = BIT(AB8500_DIGIFCONF1_IF0BITCLKOS0) | | |
| 2264 | + BIT(AB8500_DIGIFCONF1_IF0BITCLKOS1); | |
| 2265 | + switch (slots) { | |
| 2266 | + case 2: | |
| 2267 | + val = AB8500_MASK_NONE; | |
| 2268 | + break; | |
| 2269 | + case 4: | |
| 2270 | + val = BIT(AB8500_DIGIFCONF1_IF0BITCLKOS0); | |
| 2271 | + break; | |
| 2272 | + case 8: | |
| 2273 | + val = BIT(AB8500_DIGIFCONF1_IF0BITCLKOS1); | |
| 2274 | + break; | |
| 2275 | + case 16: | |
| 2276 | + val = BIT(AB8500_DIGIFCONF1_IF0BITCLKOS0) | | |
| 2277 | + BIT(AB8500_DIGIFCONF1_IF0BITCLKOS1); | |
| 2278 | + break; | |
| 2279 | + default: | |
| 2280 | + dev_err(dai->codec->dev, | |
| 2281 | + "%s: ERROR: Unsupported number of slots (%d)!\n", | |
| 2282 | + __func__, slots); | |
| 2283 | + return -EINVAL; | |
| 2284 | + } | |
| 2285 | + snd_soc_update_bits(codec, AB8500_DIGIFCONF1, mask, val); | |
| 2286 | + | |
| 2287 | + /* Setup TDM DA according to active tx slots */ | |
| 2288 | + mask = AB8500_DASLOTCONFX_SLTODAX_MASK; | |
| 2289 | + slots_active = hweight32(tx_mask); | |
| 2290 | + dev_dbg(dai->codec->dev, "%s: Slots, active, TX: %d\n", __func__, | |
| 2291 | + slots_active); | |
| 2292 | + switch (slots_active) { | |
| 2293 | + case 0: | |
| 2294 | + break; | |
| 2295 | + case 1: | |
| 2296 | + /* Slot 9 -> DA_IN1 & DA_IN3 */ | |
| 2297 | + snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, 11); | |
| 2298 | + snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, 11); | |
| 2299 | + snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, 11); | |
| 2300 | + snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, 11); | |
| 2301 | + break; | |
| 2302 | + case 2: | |
| 2303 | + /* Slot 9 -> DA_IN1 & DA_IN3, Slot 11 -> DA_IN2 & DA_IN4 */ | |
| 2304 | + snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, 9); | |
| 2305 | + snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, 9); | |
| 2306 | + snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, 11); | |
| 2307 | + snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, 11); | |
| 2308 | + | |
| 2309 | + break; | |
| 2310 | + case 8: | |
| 2311 | + dev_dbg(dai->codec->dev, | |
| 2312 | + "%s: In 8-channel mode DA-from-slot mapping is set manually.", | |
| 2313 | + __func__); | |
| 2314 | + break; | |
| 2315 | + default: | |
| 2316 | + dev_err(dai->codec->dev, | |
| 2317 | + "%s: Unsupported number of active TX-slots (%d)!\n", | |
| 2318 | + __func__, slots_active); | |
| 2319 | + return -EINVAL; | |
| 2320 | + } | |
| 2321 | + | |
| 2322 | + /* Setup TDM AD according to active RX-slots */ | |
| 2323 | + slots_active = hweight32(rx_mask); | |
| 2324 | + dev_dbg(dai->codec->dev, "%s: Slots, active, RX: %d\n", __func__, | |
| 2325 | + slots_active); | |
| 2326 | + switch (slots_active) { | |
| 2327 | + case 0: | |
| 2328 | + break; | |
| 2329 | + case 1: | |
| 2330 | + /* AD_OUT3 -> slot 0 & 1 */ | |
| 2331 | + snd_soc_update_bits(codec, AB8500_ADSLOTSEL1, AB8500_MASK_ALL, | |
| 2332 | + AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN | | |
| 2333 | + AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_ODD); | |
| 2334 | + break; | |
| 2335 | + case 2: | |
| 2336 | + /* AD_OUT3 -> slot 0, AD_OUT2 -> slot 1 */ | |
| 2337 | + snd_soc_update_bits(codec, | |
| 2338 | + AB8500_ADSLOTSEL1, | |
| 2339 | + AB8500_MASK_ALL, | |
| 2340 | + AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN | | |
| 2341 | + AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_ODD); | |
| 2342 | + break; | |
| 2343 | + case 8: | |
| 2344 | + dev_dbg(dai->codec->dev, | |
| 2345 | + "%s: In 8-channel mode AD-to-slot mapping is set manually.", | |
| 2346 | + __func__); | |
| 2347 | + break; | |
| 2348 | + default: | |
| 2349 | + dev_err(dai->codec->dev, | |
| 2350 | + "%s: Unsupported number of active RX-slots (%d)!\n", | |
| 2351 | + __func__, slots_active); | |
| 2352 | + return -EINVAL; | |
| 2353 | + } | |
| 2354 | + | |
| 2355 | + return 0; | |
| 2356 | +} | |
| 2357 | + | |
| 2358 | +struct snd_soc_dai_driver ab8500_codec_dai[] = { | |
| 2359 | + { | |
| 2360 | + .name = "ab8500-codec-dai.0", | |
| 2361 | + .id = 0, | |
| 2362 | + .playback = { | |
| 2363 | + .stream_name = "ab8500_0p", | |
| 2364 | + .channels_min = 1, | |
| 2365 | + .channels_max = 8, | |
| 2366 | + .rates = AB8500_SUPPORTED_RATE, | |
| 2367 | + .formats = AB8500_SUPPORTED_FMT, | |
| 2368 | + }, | |
| 2369 | + .ops = (struct snd_soc_dai_ops[]) { | |
| 2370 | + { | |
| 2371 | + .set_tdm_slot = ab8500_codec_set_dai_tdm_slot, | |
| 2372 | + .set_fmt = ab8500_codec_set_dai_fmt, | |
| 2373 | + } | |
| 2374 | + }, | |
| 2375 | + .symmetric_rates = 1 | |
| 2376 | + }, | |
| 2377 | + { | |
| 2378 | + .name = "ab8500-codec-dai.1", | |
| 2379 | + .id = 1, | |
| 2380 | + .capture = { | |
| 2381 | + .stream_name = "ab8500_0c", | |
| 2382 | + .channels_min = 1, | |
| 2383 | + .channels_max = 8, | |
| 2384 | + .rates = AB8500_SUPPORTED_RATE, | |
| 2385 | + .formats = AB8500_SUPPORTED_FMT, | |
| 2386 | + }, | |
| 2387 | + .ops = (struct snd_soc_dai_ops[]) { | |
| 2388 | + { | |
| 2389 | + .set_tdm_slot = ab8500_codec_set_dai_tdm_slot, | |
| 2390 | + .set_fmt = ab8500_codec_set_dai_fmt, | |
| 2391 | + } | |
| 2392 | + }, | |
| 2393 | + .symmetric_rates = 1 | |
| 2394 | + } | |
| 2395 | +}; | |
| 2396 | + | |
| 2397 | +static int ab8500_codec_probe(struct snd_soc_codec *codec) | |
| 2398 | +{ | |
| 2399 | + struct device *dev = codec->dev; | |
| 2400 | + struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(dev); | |
| 2401 | + struct ab8500_platform_data *pdata; | |
| 2402 | + struct filter_control *fc; | |
| 2403 | + int status; | |
| 2404 | + | |
| 2405 | + dev_dbg(dev, "%s: Enter.\n", __func__); | |
| 2406 | + | |
| 2407 | + /* Setup AB8500 according to board-settings */ | |
| 2408 | + pdata = (struct ab8500_platform_data *)dev_get_platdata(dev->parent); | |
| 2409 | + status = ab8500_audio_setup_mics(codec, &pdata->codec->amics); | |
| 2410 | + if (status < 0) { | |
| 2411 | + pr_err("%s: Failed to setup mics (%d)!\n", __func__, status); | |
| 2412 | + return status; | |
| 2413 | + } | |
| 2414 | + status = ab8500_audio_set_ear_cmv(codec, pdata->codec->ear_cmv); | |
| 2415 | + if (status < 0) { | |
| 2416 | + pr_err("%s: Failed to set earpiece CM-voltage (%d)!\n", | |
| 2417 | + __func__, status); | |
| 2418 | + return status; | |
| 2419 | + } | |
| 2420 | + | |
| 2421 | + status = ab8500_audio_init_audioblock(codec); | |
| 2422 | + if (status < 0) { | |
| 2423 | + dev_err(dev, "%s: failed to init audio-block (%d)!\n", | |
| 2424 | + __func__, status); | |
| 2425 | + return status; | |
| 2426 | + } | |
| 2427 | + | |
| 2428 | + /* Override HW-defaults */ | |
| 2429 | + ab8500_codec_write_reg(codec, | |
| 2430 | + AB8500_ANACONF5, | |
| 2431 | + BIT(AB8500_ANACONF5_HSAUTOEN)); | |
| 2432 | + ab8500_codec_write_reg(codec, | |
| 2433 | + AB8500_SHORTCIRCONF, | |
| 2434 | + BIT(AB8500_SHORTCIRCONF_HSZCDDIS)); | |
| 2435 | + | |
| 2436 | + /* Add filter controls */ | |
| 2437 | + status = snd_soc_add_codec_controls(codec, ab8500_filter_controls, | |
| 2438 | + ARRAY_SIZE(ab8500_filter_controls)); | |
| 2439 | + if (status < 0) { | |
| 2440 | + dev_err(dev, | |
| 2441 | + "%s: failed to add ab8500 filter controls (%d).\n", | |
| 2442 | + __func__, status); | |
| 2443 | + return status; | |
| 2444 | + } | |
| 2445 | + fc = (struct filter_control *) | |
| 2446 | + &ab8500_filter_controls[AB8500_FILTER_ANC_FIR].private_value; | |
| 2447 | + drvdata->anc_fir_values = (long *)fc->value; | |
| 2448 | + fc = (struct filter_control *) | |
| 2449 | + &ab8500_filter_controls[AB8500_FILTER_ANC_IIR].private_value; | |
| 2450 | + drvdata->anc_iir_values = (long *)fc->value; | |
| 2451 | + fc = (struct filter_control *) | |
| 2452 | + &ab8500_filter_controls[AB8500_FILTER_SID_FIR].private_value; | |
| 2453 | + drvdata->sid_fir_values = (long *)fc->value; | |
| 2454 | + | |
| 2455 | + (void)snd_soc_dapm_disable_pin(&codec->dapm, "ANC Configure Input"); | |
| 2456 | + | |
| 2457 | + mutex_init(&drvdata->anc_lock); | |
| 2458 | + | |
| 2459 | + return status; | |
| 2460 | +} | |
| 2461 | + | |
| 2462 | +static struct snd_soc_codec_driver ab8500_codec_driver = { | |
| 2463 | + .probe = ab8500_codec_probe, | |
| 2464 | + .read = ab8500_codec_read_reg, | |
| 2465 | + .write = ab8500_codec_write_reg, | |
| 2466 | + .reg_word_size = sizeof(u8), | |
| 2467 | + .controls = ab8500_ctrls, | |
| 2468 | + .num_controls = ARRAY_SIZE(ab8500_ctrls), | |
| 2469 | + .dapm_widgets = ab8500_dapm_widgets, | |
| 2470 | + .num_dapm_widgets = ARRAY_SIZE(ab8500_dapm_widgets), | |
| 2471 | + .dapm_routes = ab8500_dapm_routes, | |
| 2472 | + .num_dapm_routes = ARRAY_SIZE(ab8500_dapm_routes), | |
| 2473 | +}; | |
| 2474 | + | |
| 2475 | +static int __devinit ab8500_codec_driver_probe(struct platform_device *pdev) | |
| 2476 | +{ | |
| 2477 | + int status; | |
| 2478 | + struct ab8500_codec_drvdata *drvdata; | |
| 2479 | + | |
| 2480 | + dev_dbg(&pdev->dev, "%s: Enter.\n", __func__); | |
| 2481 | + | |
| 2482 | + /* Create driver private-data struct */ | |
| 2483 | + drvdata = devm_kzalloc(&pdev->dev, sizeof(struct ab8500_codec_drvdata), | |
| 2484 | + GFP_KERNEL); | |
| 2485 | + drvdata->sid_status = SID_UNCONFIGURED; | |
| 2486 | + drvdata->anc_status = ANC_UNCONFIGURED; | |
| 2487 | + dev_set_drvdata(&pdev->dev, drvdata); | |
| 2488 | + | |
| 2489 | + dev_dbg(&pdev->dev, "%s: Register codec.\n", __func__); | |
| 2490 | + status = snd_soc_register_codec(&pdev->dev, &ab8500_codec_driver, | |
| 2491 | + ab8500_codec_dai, | |
| 2492 | + ARRAY_SIZE(ab8500_codec_dai)); | |
| 2493 | + if (status < 0) | |
| 2494 | + dev_err(&pdev->dev, | |
| 2495 | + "%s: Error: Failed to register codec (%d).\n", | |
| 2496 | + __func__, status); | |
| 2497 | + | |
| 2498 | + return status; | |
| 2499 | +} | |
| 2500 | + | |
| 2501 | +static int __devexit ab8500_codec_driver_remove(struct platform_device *pdev) | |
| 2502 | +{ | |
| 2503 | + dev_info(&pdev->dev, "%s Enter.\n", __func__); | |
| 2504 | + | |
| 2505 | + snd_soc_unregister_codec(&pdev->dev); | |
| 2506 | + | |
| 2507 | + return 0; | |
| 2508 | +} | |
| 2509 | + | |
| 2510 | +static struct platform_driver ab8500_codec_platform_driver = { | |
| 2511 | + .driver = { | |
| 2512 | + .name = "ab8500-codec", | |
| 2513 | + .owner = THIS_MODULE, | |
| 2514 | + }, | |
| 2515 | + .probe = ab8500_codec_driver_probe, | |
| 2516 | + .remove = __devexit_p(ab8500_codec_driver_remove), | |
| 2517 | + .suspend = NULL, | |
| 2518 | + .resume = NULL, | |
| 2519 | +}; | |
| 2520 | +module_platform_driver(ab8500_codec_platform_driver); | |
| 2521 | + | |
| 2522 | +MODULE_LICENSE("GPL v2"); | |
| @@ -0,0 +1,590 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C) ST-Ericsson SA 2012 | |
| 3 | + * | |
| 4 | + * Author: Ola Lilja <ola.o.lilja@stericsson.com>, | |
| 5 | + * Kristoffer Karlsson <kristoffer.karlsson@stericsson.com>, | |
| 6 | + * Roger Nilsson <roger.xr.nilsson@stericsson.com>, | |
| 7 | + * for ST-Ericsson. | |
| 8 | + * | |
| 9 | + * Based on the early work done by: | |
| 10 | + * Mikko J. Lehto <mikko.lehto@symbio.com>, | |
| 11 | + * Mikko Sarmanne <mikko.sarmanne@symbio.com>, | |
| 12 | + * for ST-Ericsson. | |
| 13 | + * | |
| 14 | + * License terms: | |
| 15 | + * | |
| 16 | + * This program is free software; you can redistribute it and/or modify it | |
| 17 | + * under the terms of the GNU General Public License version 2 as published | |
| 18 | + * by the Free Software Foundation. | |
| 19 | + */ | |
| 20 | + | |
| 21 | +#ifndef AB8500_CODEC_REGISTERS_H | |
| 22 | +#define AB8500_CODEC_REGISTERS_H | |
| 23 | + | |
| 24 | +#define AB8500_SUPPORTED_RATE (SNDRV_PCM_RATE_48000) | |
| 25 | +#define AB8500_SUPPORTED_FMT (SNDRV_PCM_FMTBIT_S16_LE) | |
| 26 | + | |
| 27 | +/* AB8500 audio bank (0x0d) register definitions */ | |
| 28 | + | |
| 29 | +#define AB8500_POWERUP 0x00 | |
| 30 | +#define AB8500_AUDSWRESET 0x01 | |
| 31 | +#define AB8500_ADPATHENA 0x02 | |
| 32 | +#define AB8500_DAPATHENA 0x03 | |
| 33 | +#define AB8500_ANACONF1 0x04 | |
| 34 | +#define AB8500_ANACONF2 0x05 | |
| 35 | +#define AB8500_DIGMICCONF 0x06 | |
| 36 | +#define AB8500_ANACONF3 0x07 | |
| 37 | +#define AB8500_ANACONF4 0x08 | |
| 38 | +#define AB8500_DAPATHCONF 0x09 | |
| 39 | +#define AB8500_MUTECONF 0x0A | |
| 40 | +#define AB8500_SHORTCIRCONF 0x0B | |
| 41 | +#define AB8500_ANACONF5 0x0C | |
| 42 | +#define AB8500_ENVCPCONF 0x0D | |
| 43 | +#define AB8500_SIGENVCONF 0x0E | |
| 44 | +#define AB8500_PWMGENCONF1 0x0F | |
| 45 | +#define AB8500_PWMGENCONF2 0x10 | |
| 46 | +#define AB8500_PWMGENCONF3 0x11 | |
| 47 | +#define AB8500_PWMGENCONF4 0x12 | |
| 48 | +#define AB8500_PWMGENCONF5 0x13 | |
| 49 | +#define AB8500_ANAGAIN1 0x14 | |
| 50 | +#define AB8500_ANAGAIN2 0x15 | |
| 51 | +#define AB8500_ANAGAIN3 0x16 | |
| 52 | +#define AB8500_ANAGAIN4 0x17 | |
| 53 | +#define AB8500_DIGLINHSLGAIN 0x18 | |
| 54 | +#define AB8500_DIGLINHSRGAIN 0x19 | |
| 55 | +#define AB8500_ADFILTCONF 0x1A | |
| 56 | +#define AB8500_DIGIFCONF1 0x1B | |
| 57 | +#define AB8500_DIGIFCONF2 0x1C | |
| 58 | +#define AB8500_DIGIFCONF3 0x1D | |
| 59 | +#define AB8500_DIGIFCONF4 0x1E | |
| 60 | +#define AB8500_ADSLOTSEL1 0x1F | |
| 61 | +#define AB8500_ADSLOTSEL2 0x20 | |
| 62 | +#define AB8500_ADSLOTSEL3 0x21 | |
| 63 | +#define AB8500_ADSLOTSEL4 0x22 | |
| 64 | +#define AB8500_ADSLOTSEL5 0x23 | |
| 65 | +#define AB8500_ADSLOTSEL6 0x24 | |
| 66 | +#define AB8500_ADSLOTSEL7 0x25 | |
| 67 | +#define AB8500_ADSLOTSEL8 0x26 | |
| 68 | +#define AB8500_ADSLOTSEL9 0x27 | |
| 69 | +#define AB8500_ADSLOTSEL10 0x28 | |
| 70 | +#define AB8500_ADSLOTSEL11 0x29 | |
| 71 | +#define AB8500_ADSLOTSEL12 0x2A | |
| 72 | +#define AB8500_ADSLOTSEL13 0x2B | |
| 73 | +#define AB8500_ADSLOTSEL14 0x2C | |
| 74 | +#define AB8500_ADSLOTSEL15 0x2D | |
| 75 | +#define AB8500_ADSLOTSEL16 0x2E | |
| 76 | +#define AB8500_ADSLOTHIZCTRL1 0x2F | |
| 77 | +#define AB8500_ADSLOTHIZCTRL2 0x30 | |
| 78 | +#define AB8500_ADSLOTHIZCTRL3 0x31 | |
| 79 | +#define AB8500_ADSLOTHIZCTRL4 0x32 | |
| 80 | +#define AB8500_DASLOTCONF1 0x33 | |
| 81 | +#define AB8500_DASLOTCONF2 0x34 | |
| 82 | +#define AB8500_DASLOTCONF3 0x35 | |
| 83 | +#define AB8500_DASLOTCONF4 0x36 | |
| 84 | +#define AB8500_DASLOTCONF5 0x37 | |
| 85 | +#define AB8500_DASLOTCONF6 0x38 | |
| 86 | +#define AB8500_DASLOTCONF7 0x39 | |
| 87 | +#define AB8500_DASLOTCONF8 0x3A | |
| 88 | +#define AB8500_CLASSDCONF1 0x3B | |
| 89 | +#define AB8500_CLASSDCONF2 0x3C | |
| 90 | +#define AB8500_CLASSDCONF3 0x3D | |
| 91 | +#define AB8500_DMICFILTCONF 0x3E | |
| 92 | +#define AB8500_DIGMULTCONF1 0x3F | |
| 93 | +#define AB8500_DIGMULTCONF2 0x40 | |
| 94 | +#define AB8500_ADDIGGAIN1 0x41 | |
| 95 | +#define AB8500_ADDIGGAIN2 0x42 | |
| 96 | +#define AB8500_ADDIGGAIN3 0x43 | |
| 97 | +#define AB8500_ADDIGGAIN4 0x44 | |
| 98 | +#define AB8500_ADDIGGAIN5 0x45 | |
| 99 | +#define AB8500_ADDIGGAIN6 0x46 | |
| 100 | +#define AB8500_DADIGGAIN1 0x47 | |
| 101 | +#define AB8500_DADIGGAIN2 0x48 | |
| 102 | +#define AB8500_DADIGGAIN3 0x49 | |
| 103 | +#define AB8500_DADIGGAIN4 0x4A | |
| 104 | +#define AB8500_DADIGGAIN5 0x4B | |
| 105 | +#define AB8500_DADIGGAIN6 0x4C | |
| 106 | +#define AB8500_ADDIGLOOPGAIN1 0x4D | |
| 107 | +#define AB8500_ADDIGLOOPGAIN2 0x4E | |
| 108 | +#define AB8500_HSLEARDIGGAIN 0x4F | |
| 109 | +#define AB8500_HSRDIGGAIN 0x50 | |
| 110 | +#define AB8500_SIDFIRGAIN1 0x51 | |
| 111 | +#define AB8500_SIDFIRGAIN2 0x52 | |
| 112 | +#define AB8500_ANCCONF1 0x53 | |
| 113 | +#define AB8500_ANCCONF2 0x54 | |
| 114 | +#define AB8500_ANCCONF3 0x55 | |
| 115 | +#define AB8500_ANCCONF4 0x56 | |
| 116 | +#define AB8500_ANCCONF5 0x57 | |
| 117 | +#define AB8500_ANCCONF6 0x58 | |
| 118 | +#define AB8500_ANCCONF7 0x59 | |
| 119 | +#define AB8500_ANCCONF8 0x5A | |
| 120 | +#define AB8500_ANCCONF9 0x5B | |
| 121 | +#define AB8500_ANCCONF10 0x5C | |
| 122 | +#define AB8500_ANCCONF11 0x5D | |
| 123 | +#define AB8500_ANCCONF12 0x5E | |
| 124 | +#define AB8500_ANCCONF13 0x5F | |
| 125 | +#define AB8500_ANCCONF14 0x60 | |
| 126 | +#define AB8500_SIDFIRADR 0x61 | |
| 127 | +#define AB8500_SIDFIRCOEF1 0x62 | |
| 128 | +#define AB8500_SIDFIRCOEF2 0x63 | |
| 129 | +#define AB8500_SIDFIRCONF 0x64 | |
| 130 | +#define AB8500_AUDINTMASK1 0x65 | |
| 131 | +#define AB8500_AUDINTSOURCE1 0x66 | |
| 132 | +#define AB8500_AUDINTMASK2 0x67 | |
| 133 | +#define AB8500_AUDINTSOURCE2 0x68 | |
| 134 | +#define AB8500_FIFOCONF1 0x69 | |
| 135 | +#define AB8500_FIFOCONF2 0x6A | |
| 136 | +#define AB8500_FIFOCONF3 0x6B | |
| 137 | +#define AB8500_FIFOCONF4 0x6C | |
| 138 | +#define AB8500_FIFOCONF5 0x6D | |
| 139 | +#define AB8500_FIFOCONF6 0x6E | |
| 140 | +#define AB8500_AUDREV 0x6F | |
| 141 | + | |
| 142 | +#define AB8500_FIRST_REG AB8500_POWERUP | |
| 143 | +#define AB8500_LAST_REG AB8500_AUDREV | |
| 144 | +#define AB8500_CACHEREGNUM (AB8500_LAST_REG + 1) | |
| 145 | + | |
| 146 | +#define AB8500_MASK_ALL 0xFF | |
| 147 | +#define AB8500_MASK_NONE 0x00 | |
| 148 | + | |
| 149 | +/* AB8500_POWERUP */ | |
| 150 | +#define AB8500_POWERUP_POWERUP 7 | |
| 151 | +#define AB8500_POWERUP_ENANA 3 | |
| 152 | + | |
| 153 | +/* AB8500_AUDSWRESET */ | |
| 154 | +#define AB8500_AUDSWRESET_SWRESET 7 | |
| 155 | + | |
| 156 | +/* AB8500_ADPATHENA */ | |
| 157 | +#define AB8500_ADPATHENA_ENAD12 7 | |
| 158 | +#define AB8500_ADPATHENA_ENAD34 5 | |
| 159 | +#define AB8500_ADPATHENA_ENAD5768 3 | |
| 160 | + | |
| 161 | +/* AB8500_DAPATHENA */ | |
| 162 | +#define AB8500_DAPATHENA_ENDA1 7 | |
| 163 | +#define AB8500_DAPATHENA_ENDA2 6 | |
| 164 | +#define AB8500_DAPATHENA_ENDA3 5 | |
| 165 | +#define AB8500_DAPATHENA_ENDA4 4 | |
| 166 | +#define AB8500_DAPATHENA_ENDA5 3 | |
| 167 | +#define AB8500_DAPATHENA_ENDA6 2 | |
| 168 | + | |
| 169 | +/* AB8500_ANACONF1 */ | |
| 170 | +#define AB8500_ANACONF1_HSLOWPOW 7 | |
| 171 | +#define AB8500_ANACONF1_DACLOWPOW1 6 | |
| 172 | +#define AB8500_ANACONF1_DACLOWPOW0 5 | |
| 173 | +#define AB8500_ANACONF1_EARDACLOWPOW 4 | |
| 174 | +#define AB8500_ANACONF1_EARSELCM 2 | |
| 175 | +#define AB8500_ANACONF1_HSHPEN 1 | |
| 176 | +#define AB8500_ANACONF1_EARDRVLOWPOW 0 | |
| 177 | + | |
| 178 | +/* AB8500_ANACONF2 */ | |
| 179 | +#define AB8500_ANACONF2_ENMIC1 7 | |
| 180 | +#define AB8500_ANACONF2_ENMIC2 6 | |
| 181 | +#define AB8500_ANACONF2_ENLINL 5 | |
| 182 | +#define AB8500_ANACONF2_ENLINR 4 | |
| 183 | +#define AB8500_ANACONF2_MUTMIC1 3 | |
| 184 | +#define AB8500_ANACONF2_MUTMIC2 2 | |
| 185 | +#define AB8500_ANACONF2_MUTLINL 1 | |
| 186 | +#define AB8500_ANACONF2_MUTLINR 0 | |
| 187 | + | |
| 188 | +/* AB8500_DIGMICCONF */ | |
| 189 | +#define AB8500_DIGMICCONF_ENDMIC1 7 | |
| 190 | +#define AB8500_DIGMICCONF_ENDMIC2 6 | |
| 191 | +#define AB8500_DIGMICCONF_ENDMIC3 5 | |
| 192 | +#define AB8500_DIGMICCONF_ENDMIC4 4 | |
| 193 | +#define AB8500_DIGMICCONF_ENDMIC5 3 | |
| 194 | +#define AB8500_DIGMICCONF_ENDMIC6 2 | |
| 195 | +#define AB8500_DIGMICCONF_HSFADSPEED 0 | |
| 196 | + | |
| 197 | +/* AB8500_ANACONF3 */ | |
| 198 | +#define AB8500_ANACONF3_MIC1SEL 7 | |
| 199 | +#define AB8500_ANACONF3_LINRSEL 6 | |
| 200 | +#define AB8500_ANACONF3_ENDRVHSL 5 | |
| 201 | +#define AB8500_ANACONF3_ENDRVHSR 4 | |
| 202 | +#define AB8500_ANACONF3_ENADCMIC 2 | |
| 203 | +#define AB8500_ANACONF3_ENADCLINL 1 | |
| 204 | +#define AB8500_ANACONF3_ENADCLINR 0 | |
| 205 | + | |
| 206 | +/* AB8500_ANACONF4 */ | |
| 207 | +#define AB8500_ANACONF4_DISPDVSS 7 | |
| 208 | +#define AB8500_ANACONF4_ENEAR 6 | |
| 209 | +#define AB8500_ANACONF4_ENHSL 5 | |
| 210 | +#define AB8500_ANACONF4_ENHSR 4 | |
| 211 | +#define AB8500_ANACONF4_ENHFL 3 | |
| 212 | +#define AB8500_ANACONF4_ENHFR 2 | |
| 213 | +#define AB8500_ANACONF4_ENVIB1 1 | |
| 214 | +#define AB8500_ANACONF4_ENVIB2 0 | |
| 215 | + | |
| 216 | +/* AB8500_DAPATHCONF */ | |
| 217 | +#define AB8500_DAPATHCONF_ENDACEAR 6 | |
| 218 | +#define AB8500_DAPATHCONF_ENDACHSL 5 | |
| 219 | +#define AB8500_DAPATHCONF_ENDACHSR 4 | |
| 220 | +#define AB8500_DAPATHCONF_ENDACHFL 3 | |
| 221 | +#define AB8500_DAPATHCONF_ENDACHFR 2 | |
| 222 | +#define AB8500_DAPATHCONF_ENDACVIB1 1 | |
| 223 | +#define AB8500_DAPATHCONF_ENDACVIB2 0 | |
| 224 | + | |
| 225 | +/* AB8500_MUTECONF */ | |
| 226 | +#define AB8500_MUTECONF_MUTEAR 6 | |
| 227 | +#define AB8500_MUTECONF_MUTHSL 5 | |
| 228 | +#define AB8500_MUTECONF_MUTHSR 4 | |
| 229 | +#define AB8500_MUTECONF_MUTDACEAR 2 | |
| 230 | +#define AB8500_MUTECONF_MUTDACHSL 1 | |
| 231 | +#define AB8500_MUTECONF_MUTDACHSR 0 | |
| 232 | + | |
| 233 | +/* AB8500_SHORTCIRCONF */ | |
| 234 | +#define AB8500_SHORTCIRCONF_ENSHORTPWD 7 | |
| 235 | +#define AB8500_SHORTCIRCONF_EARSHORTDIS 6 | |
| 236 | +#define AB8500_SHORTCIRCONF_HSSHORTDIS 5 | |
| 237 | +#define AB8500_SHORTCIRCONF_HSPULLDEN 4 | |
| 238 | +#define AB8500_SHORTCIRCONF_HSOSCEN 2 | |
| 239 | +#define AB8500_SHORTCIRCONF_HSFADDIS 1 | |
| 240 | +#define AB8500_SHORTCIRCONF_HSZCDDIS 0 | |
| 241 | +/* Zero cross should be disabled */ | |
| 242 | + | |
| 243 | +/* AB8500_ANACONF5 */ | |
| 244 | +#define AB8500_ANACONF5_ENCPHS 7 | |
| 245 | +#define AB8500_ANACONF5_HSLDACTOLOL 5 | |
| 246 | +#define AB8500_ANACONF5_HSRDACTOLOR 4 | |
| 247 | +#define AB8500_ANACONF5_ENLOL 3 | |
| 248 | +#define AB8500_ANACONF5_ENLOR 2 | |
| 249 | +#define AB8500_ANACONF5_HSAUTOEN 0 | |
| 250 | + | |
| 251 | +/* AB8500_ENVCPCONF */ | |
| 252 | +#define AB8500_ENVCPCONF_ENVDETHTHRE 4 | |
| 253 | +#define AB8500_ENVCPCONF_ENVDETLTHRE 0 | |
| 254 | +#define AB8500_ENVCPCONF_ENVDETHTHRE_MAX 0x0F | |
| 255 | +#define AB8500_ENVCPCONF_ENVDETLTHRE_MAX 0x0F | |
| 256 | + | |
| 257 | +/* AB8500_SIGENVCONF */ | |
| 258 | +#define AB8500_SIGENVCONF_CPLVEN 5 | |
| 259 | +#define AB8500_SIGENVCONF_ENVDETCPEN 4 | |
| 260 | +#define AB8500_SIGENVCONF_ENVDETTIME 0 | |
| 261 | +#define AB8500_SIGENVCONF_ENVDETTIME_MAX 0x0F | |
| 262 | + | |
| 263 | +/* AB8500_PWMGENCONF1 */ | |
| 264 | +#define AB8500_PWMGENCONF1_PWMTOVIB1 7 | |
| 265 | +#define AB8500_PWMGENCONF1_PWMTOVIB2 6 | |
| 266 | +#define AB8500_PWMGENCONF1_PWM1CTRL 5 | |
| 267 | +#define AB8500_PWMGENCONF1_PWM2CTRL 4 | |
| 268 | +#define AB8500_PWMGENCONF1_PWM1NCTRL 3 | |
| 269 | +#define AB8500_PWMGENCONF1_PWM1PCTRL 2 | |
| 270 | +#define AB8500_PWMGENCONF1_PWM2NCTRL 1 | |
| 271 | +#define AB8500_PWMGENCONF1_PWM2PCTRL 0 | |
| 272 | + | |
| 273 | +/* AB8500_PWMGENCONF2 */ | |
| 274 | +/* AB8500_PWMGENCONF3 */ | |
| 275 | +/* AB8500_PWMGENCONF4 */ | |
| 276 | +/* AB8500_PWMGENCONF5 */ | |
| 277 | +#define AB8500_PWMGENCONFX_PWMVIBXPOL 7 | |
| 278 | +#define AB8500_PWMGENCONFX_PWMVIBXDUTCYC 0 | |
| 279 | +#define AB8500_PWMGENCONFX_PWMVIBXDUTCYC_MAX 0x64 | |
| 280 | + | |
| 281 | +/* AB8500_ANAGAIN1 */ | |
| 282 | +/* AB8500_ANAGAIN2 */ | |
| 283 | +#define AB8500_ANAGAINX_ENSEMICX 7 | |
| 284 | +#define AB8500_ANAGAINX_LOWPOWMICX 6 | |
| 285 | +#define AB8500_ANAGAINX_MICXGAIN 0 | |
| 286 | +#define AB8500_ANAGAINX_MICXGAIN_MAX 0x1F | |
| 287 | + | |
| 288 | +/* AB8500_ANAGAIN3 */ | |
| 289 | +#define AB8500_ANAGAIN3_HSLGAIN 4 | |
| 290 | +#define AB8500_ANAGAIN3_HSRGAIN 0 | |
| 291 | +#define AB8500_ANAGAIN3_HSXGAIN_MAX 0x0F | |
| 292 | + | |
| 293 | +/* AB8500_ANAGAIN4 */ | |
| 294 | +#define AB8500_ANAGAIN4_LINLGAIN 4 | |
| 295 | +#define AB8500_ANAGAIN4_LINRGAIN 0 | |
| 296 | +#define AB8500_ANAGAIN4_LINXGAIN_MAX 0x0F | |
| 297 | + | |
| 298 | +/* AB8500_DIGLINHSLGAIN */ | |
| 299 | +/* AB8500_DIGLINHSRGAIN */ | |
| 300 | +#define AB8500_DIGLINHSXGAIN_LINTOHSXGAIN 0 | |
| 301 | +#define AB8500_DIGLINHSXGAIN_LINTOHSXGAIN_MAX 0x13 | |
| 302 | + | |
| 303 | +/* AB8500_ADFILTCONF */ | |
| 304 | +#define AB8500_ADFILTCONF_AD1NH 7 | |
| 305 | +#define AB8500_ADFILTCONF_AD2NH 6 | |
| 306 | +#define AB8500_ADFILTCONF_AD3NH 5 | |
| 307 | +#define AB8500_ADFILTCONF_AD4NH 4 | |
| 308 | +#define AB8500_ADFILTCONF_AD1VOICE 3 | |
| 309 | +#define AB8500_ADFILTCONF_AD2VOICE 2 | |
| 310 | +#define AB8500_ADFILTCONF_AD3VOICE 1 | |
| 311 | +#define AB8500_ADFILTCONF_AD4VOICE 0 | |
| 312 | + | |
| 313 | +/* AB8500_DIGIFCONF1 */ | |
| 314 | +#define AB8500_DIGIFCONF1_ENMASTGEN 7 | |
| 315 | +#define AB8500_DIGIFCONF1_IF1BITCLKOS1 6 | |
| 316 | +#define AB8500_DIGIFCONF1_IF1BITCLKOS0 5 | |
| 317 | +#define AB8500_DIGIFCONF1_ENFSBITCLK1 4 | |
| 318 | +#define AB8500_DIGIFCONF1_IF0BITCLKOS1 2 | |
| 319 | +#define AB8500_DIGIFCONF1_IF0BITCLKOS0 1 | |
| 320 | +#define AB8500_DIGIFCONF1_ENFSBITCLK0 0 | |
| 321 | + | |
| 322 | +/* AB8500_DIGIFCONF2 */ | |
| 323 | +#define AB8500_DIGIFCONF2_FSYNC0P 6 | |
| 324 | +#define AB8500_DIGIFCONF2_BITCLK0P 5 | |
| 325 | +#define AB8500_DIGIFCONF2_IF0DEL 4 | |
| 326 | +#define AB8500_DIGIFCONF2_IF0FORMAT1 3 | |
| 327 | +#define AB8500_DIGIFCONF2_IF0FORMAT0 2 | |
| 328 | +#define AB8500_DIGIFCONF2_IF0WL1 1 | |
| 329 | +#define AB8500_DIGIFCONF2_IF0WL0 0 | |
| 330 | + | |
| 331 | +/* AB8500_DIGIFCONF3 */ | |
| 332 | +#define AB8500_DIGIFCONF3_IF0DATOIF1AD 7 | |
| 333 | +#define AB8500_DIGIFCONF3_IF0CLKTOIF1CLK 6 | |
| 334 | +#define AB8500_DIGIFCONF3_IF1MASTER 5 | |
| 335 | +#define AB8500_DIGIFCONF3_IF1DATOIF0AD 3 | |
| 336 | +#define AB8500_DIGIFCONF3_IF1CLKTOIF0CLK 2 | |
| 337 | +#define AB8500_DIGIFCONF3_IF0MASTER 1 | |
| 338 | +#define AB8500_DIGIFCONF3_IF0BFIFOEN 0 | |
| 339 | + | |
| 340 | +/* AB8500_DIGIFCONF4 */ | |
| 341 | +#define AB8500_DIGIFCONF4_FSYNC1P 6 | |
| 342 | +#define AB8500_DIGIFCONF4_BITCLK1P 5 | |
| 343 | +#define AB8500_DIGIFCONF4_IF1DEL 4 | |
| 344 | +#define AB8500_DIGIFCONF4_IF1FORMAT1 3 | |
| 345 | +#define AB8500_DIGIFCONF4_IF1FORMAT0 2 | |
| 346 | +#define AB8500_DIGIFCONF4_IF1WL1 1 | |
| 347 | +#define AB8500_DIGIFCONF4_IF1WL0 0 | |
| 348 | + | |
| 349 | +/* AB8500_ADSLOTSELX */ | |
| 350 | +#define AB8500_ADSLOTSELX_AD_OUT1_TO_SLOT_ODD 0x00 | |
| 351 | +#define AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_ODD 0x01 | |
| 352 | +#define AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_ODD 0x02 | |
| 353 | +#define AB8500_ADSLOTSELX_AD_OUT4_TO_SLOT_ODD 0x03 | |
| 354 | +#define AB8500_ADSLOTSELX_AD_OUT5_TO_SLOT_ODD 0x04 | |
| 355 | +#define AB8500_ADSLOTSELX_AD_OUT6_TO_SLOT_ODD 0x05 | |
| 356 | +#define AB8500_ADSLOTSELX_AD_OUT7_TO_SLOT_ODD 0x06 | |
| 357 | +#define AB8500_ADSLOTSELX_AD_OUT8_TO_SLOT_ODD 0x07 | |
| 358 | +#define AB8500_ADSLOTSELX_ZEROES_TO_SLOT_ODD 0x08 | |
| 359 | +#define AB8500_ADSLOTSELX_TRISTATE_TO_SLOT_ODD 0x0F | |
| 360 | +#define AB8500_ADSLOTSELX_AD_OUT1_TO_SLOT_EVEN 0x00 | |
| 361 | +#define AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_EVEN 0x10 | |
| 362 | +#define AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN 0x20 | |
| 363 | +#define AB8500_ADSLOTSELX_AD_OUT4_TO_SLOT_EVEN 0x30 | |
| 364 | +#define AB8500_ADSLOTSELX_AD_OUT5_TO_SLOT_EVEN 0x40 | |
| 365 | +#define AB8500_ADSLOTSELX_AD_OUT6_TO_SLOT_EVEN 0x50 | |
| 366 | +#define AB8500_ADSLOTSELX_AD_OUT7_TO_SLOT_EVEN 0x60 | |
| 367 | +#define AB8500_ADSLOTSELX_AD_OUT8_TO_SLOT_EVEN 0x70 | |
| 368 | +#define AB8500_ADSLOTSELX_ZEROES_TO_SLOT_EVEN 0x80 | |
| 369 | +#define AB8500_ADSLOTSELX_TRISTATE_TO_SLOT_EVEN 0xF0 | |
| 370 | +#define AB8500_ADSLOTSELX_EVEN_SHIFT 0 | |
| 371 | +#define AB8500_ADSLOTSELX_ODD_SHIFT 4 | |
| 372 | + | |
| 373 | +/* AB8500_ADSLOTHIZCTRL1 */ | |
| 374 | +/* AB8500_ADSLOTHIZCTRL2 */ | |
| 375 | +/* AB8500_ADSLOTHIZCTRL3 */ | |
| 376 | +/* AB8500_ADSLOTHIZCTRL4 */ | |
| 377 | +/* AB8500_DASLOTCONF1 */ | |
| 378 | +#define AB8500_DASLOTCONF1_DA12VOICE 7 | |
| 379 | +#define AB8500_DASLOTCONF1_SWAPDA12_34 6 | |
| 380 | +#define AB8500_DASLOTCONF1_DAI7TOADO1 5 | |
| 381 | + | |
| 382 | +/* AB8500_DASLOTCONF2 */ | |
| 383 | +#define AB8500_DASLOTCONF2_DAI8TOADO2 5 | |
| 384 | + | |
| 385 | +/* AB8500_DASLOTCONF3 */ | |
| 386 | +#define AB8500_DASLOTCONF3_DA34VOICE 7 | |
| 387 | +#define AB8500_DASLOTCONF3_DAI7TOADO3 5 | |
| 388 | + | |
| 389 | +/* AB8500_DASLOTCONF4 */ | |
| 390 | +#define AB8500_DASLOTCONF4_DAI8TOADO4 5 | |
| 391 | + | |
| 392 | +/* AB8500_DASLOTCONF5 */ | |
| 393 | +#define AB8500_DASLOTCONF5_DA56VOICE 7 | |
| 394 | +#define AB8500_DASLOTCONF5_DAI7TOADO5 5 | |
| 395 | + | |
| 396 | +/* AB8500_DASLOTCONF6 */ | |
| 397 | +#define AB8500_DASLOTCONF6_DAI8TOADO6 5 | |
| 398 | + | |
| 399 | +/* AB8500_DASLOTCONF7 */ | |
| 400 | +#define AB8500_DASLOTCONF7_DAI8TOADO7 5 | |
| 401 | + | |
| 402 | +/* AB8500_DASLOTCONF8 */ | |
| 403 | +#define AB8500_DASLOTCONF8_DAI7TOADO8 5 | |
| 404 | + | |
| 405 | +#define AB8500_DASLOTCONFX_SLTODAX_SHIFT 0 | |
| 406 | +#define AB8500_DASLOTCONFX_SLTODAX_MASK 0x1F | |
| 407 | + | |
| 408 | +/* AB8500_CLASSDCONF1 */ | |
| 409 | +#define AB8500_CLASSDCONF1_PARLHF 7 | |
| 410 | +#define AB8500_CLASSDCONF1_PARLVIB 6 | |
| 411 | +#define AB8500_CLASSDCONF1_VIB1SWAPEN 3 | |
| 412 | +#define AB8500_CLASSDCONF1_VIB2SWAPEN 2 | |
| 413 | +#define AB8500_CLASSDCONF1_HFLSWAPEN 1 | |
| 414 | +#define AB8500_CLASSDCONF1_HFRSWAPEN 0 | |
| 415 | + | |
| 416 | +/* AB8500_CLASSDCONF2 */ | |
| 417 | +#define AB8500_CLASSDCONF2_FIRBYP3 7 | |
| 418 | +#define AB8500_CLASSDCONF2_FIRBYP2 6 | |
| 419 | +#define AB8500_CLASSDCONF2_FIRBYP1 5 | |
| 420 | +#define AB8500_CLASSDCONF2_FIRBYP0 4 | |
| 421 | +#define AB8500_CLASSDCONF2_HIGHVOLEN3 3 | |
| 422 | +#define AB8500_CLASSDCONF2_HIGHVOLEN2 2 | |
| 423 | +#define AB8500_CLASSDCONF2_HIGHVOLEN1 1 | |
| 424 | +#define AB8500_CLASSDCONF2_HIGHVOLEN0 0 | |
| 425 | + | |
| 426 | +/* AB8500_CLASSDCONF3 */ | |
| 427 | +#define AB8500_CLASSDCONF3_DITHHPGAIN 4 | |
| 428 | +#define AB8500_CLASSDCONF3_DITHHPGAIN_MAX 0x0A | |
| 429 | +#define AB8500_CLASSDCONF3_DITHWGAIN 0 | |
| 430 | +#define AB8500_CLASSDCONF3_DITHWGAIN_MAX 0x0A | |
| 431 | + | |
| 432 | +/* AB8500_DMICFILTCONF */ | |
| 433 | +#define AB8500_DMICFILTCONF_ANCINSEL 7 | |
| 434 | +#define AB8500_DMICFILTCONF_DA3TOEAR 6 | |
| 435 | +#define AB8500_DMICFILTCONF_DMIC1SINC3 5 | |
| 436 | +#define AB8500_DMICFILTCONF_DMIC2SINC3 4 | |
| 437 | +#define AB8500_DMICFILTCONF_DMIC3SINC3 3 | |
| 438 | +#define AB8500_DMICFILTCONF_DMIC4SINC3 2 | |
| 439 | +#define AB8500_DMICFILTCONF_DMIC5SINC3 1 | |
| 440 | +#define AB8500_DMICFILTCONF_DMIC6SINC3 0 | |
| 441 | + | |
| 442 | +/* AB8500_DIGMULTCONF1 */ | |
| 443 | +#define AB8500_DIGMULTCONF1_DATOHSLEN 7 | |
| 444 | +#define AB8500_DIGMULTCONF1_DATOHSREN 6 | |
| 445 | +#define AB8500_DIGMULTCONF1_AD1SEL 5 | |
| 446 | +#define AB8500_DIGMULTCONF1_AD2SEL 4 | |
| 447 | +#define AB8500_DIGMULTCONF1_AD3SEL 3 | |
| 448 | +#define AB8500_DIGMULTCONF1_AD5SEL 2 | |
| 449 | +#define AB8500_DIGMULTCONF1_AD6SEL 1 | |
| 450 | +#define AB8500_DIGMULTCONF1_ANCSEL 0 | |
| 451 | + | |
| 452 | +/* AB8500_DIGMULTCONF2 */ | |
| 453 | +#define AB8500_DIGMULTCONF2_DATOHFREN 7 | |
| 454 | +#define AB8500_DIGMULTCONF2_DATOHFLEN 6 | |
| 455 | +#define AB8500_DIGMULTCONF2_HFRSEL 5 | |
| 456 | +#define AB8500_DIGMULTCONF2_HFLSEL 4 | |
| 457 | +#define AB8500_DIGMULTCONF2_FIRSID1SEL 2 | |
| 458 | +#define AB8500_DIGMULTCONF2_FIRSID2SEL 0 | |
| 459 | + | |
| 460 | +/* AB8500_ADDIGGAIN1 */ | |
| 461 | +/* AB8500_ADDIGGAIN2 */ | |
| 462 | +/* AB8500_ADDIGGAIN3 */ | |
| 463 | +/* AB8500_ADDIGGAIN4 */ | |
| 464 | +/* AB8500_ADDIGGAIN5 */ | |
| 465 | +/* AB8500_ADDIGGAIN6 */ | |
| 466 | +#define AB8500_ADDIGGAINX_FADEDISADX 6 | |
| 467 | +#define AB8500_ADDIGGAINX_ADXGAIN_MAX 0x3F | |
| 468 | + | |
| 469 | +/* AB8500_DADIGGAIN1 */ | |
| 470 | +/* AB8500_DADIGGAIN2 */ | |
| 471 | +/* AB8500_DADIGGAIN3 */ | |
| 472 | +/* AB8500_DADIGGAIN4 */ | |
| 473 | +/* AB8500_DADIGGAIN5 */ | |
| 474 | +/* AB8500_DADIGGAIN6 */ | |
| 475 | +#define AB8500_DADIGGAINX_FADEDISDAX 6 | |
| 476 | +#define AB8500_DADIGGAINX_DAXGAIN_MAX 0x3F | |
| 477 | + | |
| 478 | +/* AB8500_ADDIGLOOPGAIN1 */ | |
| 479 | +/* AB8500_ADDIGLOOPGAIN2 */ | |
| 480 | +#define AB8500_ADDIGLOOPGAINX_FADEDISADXL 6 | |
| 481 | +#define AB8500_ADDIGLOOPGAINX_ADXLBGAIN_MAX 0x3F | |
| 482 | + | |
| 483 | +/* AB8500_HSLEARDIGGAIN */ | |
| 484 | +#define AB8500_HSLEARDIGGAIN_HSSINC1 7 | |
| 485 | +#define AB8500_HSLEARDIGGAIN_FADEDISHSL 4 | |
| 486 | +#define AB8500_HSLEARDIGGAIN_HSLDGAIN_MAX 0x09 | |
| 487 | + | |
| 488 | +/* AB8500_HSRDIGGAIN */ | |
| 489 | +#define AB8500_HSRDIGGAIN_FADESPEED 6 | |
| 490 | +#define AB8500_HSRDIGGAIN_FADEDISHSR 4 | |
| 491 | +#define AB8500_HSRDIGGAIN_HSRDGAIN_MAX 0x09 | |
| 492 | + | |
| 493 | +/* AB8500_SIDFIRGAIN1 */ | |
| 494 | +/* AB8500_SIDFIRGAIN2 */ | |
| 495 | +#define AB8500_SIDFIRGAINX_FIRSIDXGAIN_MAX 0x1F | |
| 496 | + | |
| 497 | +/* AB8500_ANCCONF1 */ | |
| 498 | +#define AB8500_ANCCONF1_ANCIIRUPDATE 3 | |
| 499 | +#define AB8500_ANCCONF1_ENANC 2 | |
| 500 | +#define AB8500_ANCCONF1_ANCIIRINIT 1 | |
| 501 | +#define AB8500_ANCCONF1_ANCFIRUPDATE 0 | |
| 502 | + | |
| 503 | +/* AB8500_ANCCONF2 */ | |
| 504 | +#define AB8500_ANCCONF2_SHIFT 5 | |
| 505 | +#define AB8500_ANCCONF2_MIN -0x10 | |
| 506 | +#define AB8500_ANCCONF2_MAX 0xF | |
| 507 | + | |
| 508 | +/* AB8500_ANCCONF3 */ | |
| 509 | +#define AB8500_ANCCONF3_SHIFT 5 | |
| 510 | +#define AB8500_ANCCONF3_MIN -0x10 | |
| 511 | +#define AB8500_ANCCONF3_MAX 0xF | |
| 512 | + | |
| 513 | +/* AB8500_ANCCONF4 */ | |
| 514 | +#define AB8500_ANCCONF4_SHIFT 5 | |
| 515 | +#define AB8500_ANCCONF4_MIN -0x10 | |
| 516 | +#define AB8500_ANCCONF4_MAX 0xF | |
| 517 | + | |
| 518 | +/* AB8500_ANC_FIR_COEFFS */ | |
| 519 | +#define AB8500_ANC_FIR_COEFF_MIN -0x8000 | |
| 520 | +#define AB8500_ANC_FIR_COEFF_MAX 0x7FFF | |
| 521 | +#define AB8500_ANC_FIR_COEFFS 15 | |
| 522 | + | |
| 523 | +/* AB8500_ANC_IIR_COEFFS */ | |
| 524 | +#define AB8500_ANC_IIR_COEFF_MIN -0x800000 | |
| 525 | +#define AB8500_ANC_IIR_COEFF_MAX 0x7FFFFF | |
| 526 | +#define AB8500_ANC_IIR_COEFFS 24 | |
| 527 | +/* AB8500_ANC_WARP_DELAY */ | |
| 528 | +#define AB8500_ANC_WARP_DELAY_SHIFT 16 | |
| 529 | +#define AB8500_ANC_WARP_DELAY_MIN 0x0000 | |
| 530 | +#define AB8500_ANC_WARP_DELAY_MAX 0xFFFF | |
| 531 | + | |
| 532 | +/* AB8500_ANCCONF11 */ | |
| 533 | +/* AB8500_ANCCONF12 */ | |
| 534 | +/* AB8500_ANCCONF13 */ | |
| 535 | +/* AB8500_ANCCONF14 */ | |
| 536 | + | |
| 537 | +/* AB8500_SIDFIRADR */ | |
| 538 | +#define AB8500_SIDFIRADR_FIRSIDSET 7 | |
| 539 | +#define AB8500_SIDFIRADR_ADDRESS_SHIFT 0 | |
| 540 | +#define AB8500_SIDFIRADR_ADDRESS_MAX 0x7F | |
| 541 | + | |
| 542 | +/* AB8500_SIDFIRCOEF1 */ | |
| 543 | +/* AB8500_SIDFIRCOEF2 */ | |
| 544 | +#define AB8500_SID_FIR_COEFF_MIN 0 | |
| 545 | +#define AB8500_SID_FIR_COEFF_MAX 0xFFFF | |
| 546 | +#define AB8500_SID_FIR_COEFFS 128 | |
| 547 | + | |
| 548 | +/* AB8500_SIDFIRCONF */ | |
| 549 | +#define AB8500_SIDFIRCONF_ENFIRSIDS 2 | |
| 550 | +#define AB8500_SIDFIRCONF_FIRSIDSTOIF1 1 | |
| 551 | +#define AB8500_SIDFIRCONF_FIRSIDBUSY 0 | |
| 552 | + | |
| 553 | +/* AB8500_AUDINTMASK1 */ | |
| 554 | +/* AB8500_AUDINTSOURCE1 */ | |
| 555 | +/* AB8500_AUDINTMASK2 */ | |
| 556 | +/* AB8500_AUDINTSOURCE2 */ | |
| 557 | + | |
| 558 | +/* AB8500_FIFOCONF1 */ | |
| 559 | +#define AB8500_FIFOCONF1_BFIFOMASK 0x80 | |
| 560 | +#define AB8500_FIFOCONF1_BFIFO19M2 0x40 | |
| 561 | +#define AB8500_FIFOCONF1_BFIFOINT_SHIFT 0 | |
| 562 | +#define AB8500_FIFOCONF1_BFIFOINT_MAX 0x3F | |
| 563 | + | |
| 564 | +/* AB8500_FIFOCONF2 */ | |
| 565 | +#define AB8500_FIFOCONF2_BFIFOTX_SHIFT 0 | |
| 566 | +#define AB8500_FIFOCONF2_BFIFOTX_MAX 0xFF | |
| 567 | + | |
| 568 | +/* AB8500_FIFOCONF3 */ | |
| 569 | +#define AB8500_FIFOCONF3_BFIFOEXSL_SHIFT 5 | |
| 570 | +#define AB8500_FIFOCONF3_BFIFOEXSL_MAX 0x5 | |
| 571 | +#define AB8500_FIFOCONF3_PREBITCLK0_SHIFT 2 | |
| 572 | +#define AB8500_FIFOCONF3_PREBITCLK0_MAX 0x7 | |
| 573 | +#define AB8500_FIFOCONF3_BFIFOMAST_SHIFT 1 | |
| 574 | +#define AB8500_FIFOCONF3_BFIFORUN_SHIFT 0 | |
| 575 | + | |
| 576 | +/* AB8500_FIFOCONF4 */ | |
| 577 | +#define AB8500_FIFOCONF4_BFIFOFRAMSW_SHIFT 0 | |
| 578 | +#define AB8500_FIFOCONF4_BFIFOFRAMSW_MAX 0xFF | |
| 579 | + | |
| 580 | +/* AB8500_FIFOCONF5 */ | |
| 581 | +#define AB8500_FIFOCONF5_BFIFOWAKEUP_SHIFT 0 | |
| 582 | +#define AB8500_FIFOCONF5_BFIFOWAKEUP_MAX 0xFF | |
| 583 | + | |
| 584 | +/* AB8500_FIFOCONF6 */ | |
| 585 | +#define AB8500_FIFOCONF6_BFIFOSAMPLE_SHIFT 0 | |
| 586 | +#define AB8500_FIFOCONF6_BFIFOSAMPLE_MAX 0xFF | |
| 587 | + | |
| 588 | +/* AB8500_AUDREV */ | |
| 589 | + | |
| 590 | +#endif | |
| @@ -91,11 +91,6 @@ static int ac97_soc_probe(struct snd_soc_codec *codec) · 90 unmodified lines | ||
| 91 | 91 | return 0; |
| 92 | 92 | } |
| 93 | 93 | |
| 94 | −static int ac97_soc_remove(struct snd_soc_codec *codec) | |
| 95 | −{ | |
| 96 | − return 0; | |
| 97 | −} | |
| 98 | − | |
| 99 | 94 | #ifdef CONFIG_PM |
| 100 | 95 | static int ac97_soc_suspend(struct snd_soc_codec *codec) |
| 101 | 96 | { |
| @@ -119,7 +114,6 @@ static struct snd_soc_codec_driver soc_codec_dev_ac97 = { · 17 unmodified lines | ||
| 119 | 114 | .write = ac97_write, |
| 120 | 115 | .read = ac97_read, |
| 121 | 116 | .probe = ac97_soc_probe, |
| 122 | − .remove = ac97_soc_remove, | |
| 123 | 117 | .suspend = ac97_soc_suspend, |
| 124 | 118 | .resume = ac97_soc_resume, |
| 125 | 119 | }; |
| @@ -0,0 +1,937 @@ | ||
| 1 | +/* | |
| 2 | + * arizona.c - Wolfson Arizona class device shared support | |
| 3 | + * | |
| 4 | + * Copyright 2012 Wolfson Microelectronics plc | |
| 5 | + * | |
| 6 | + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | |
| 7 | + * | |
| 8 | + * This program is free software; you can redistribute it and/or modify | |
| 9 | + * it under the terms of the GNU General Public License version 2 as | |
| 10 | + * published by the Free Software Foundation. | |
| 11 | + */ | |
| 12 | + | |
| 13 | +#include <linux/gcd.h> | |
| 14 | +#include <linux/module.h> | |
| 15 | +#include <linux/pm_runtime.h> | |
| 16 | +#include <sound/pcm.h> | |
| 17 | +#include <sound/pcm_params.h> | |
| 18 | +#include <sound/tlv.h> | |
| 19 | + | |
| 20 | +#include <linux/mfd/arizona/core.h> | |
| 21 | +#include <linux/mfd/arizona/registers.h> | |
| 22 | + | |
| 23 | +#include "arizona.h" | |
| 24 | + | |
| 25 | +#define ARIZONA_AIF_BCLK_CTRL 0x00 | |
| 26 | +#define ARIZONA_AIF_TX_PIN_CTRL 0x01 | |
| 27 | +#define ARIZONA_AIF_RX_PIN_CTRL 0x02 | |
| 28 | +#define ARIZONA_AIF_RATE_CTRL 0x03 | |
| 29 | +#define ARIZONA_AIF_FORMAT 0x04 | |
| 30 | +#define ARIZONA_AIF_TX_BCLK_RATE 0x05 | |
| 31 | +#define ARIZONA_AIF_RX_BCLK_RATE 0x06 | |
| 32 | +#define ARIZONA_AIF_FRAME_CTRL_1 0x07 | |
| 33 | +#define ARIZONA_AIF_FRAME_CTRL_2 0x08 | |
| 34 | +#define ARIZONA_AIF_FRAME_CTRL_3 0x09 | |
| 35 | +#define ARIZONA_AIF_FRAME_CTRL_4 0x0A | |
| 36 | +#define ARIZONA_AIF_FRAME_CTRL_5 0x0B | |
| 37 | +#define ARIZONA_AIF_FRAME_CTRL_6 0x0C | |
| 38 | +#define ARIZONA_AIF_FRAME_CTRL_7 0x0D | |
| 39 | +#define ARIZONA_AIF_FRAME_CTRL_8 0x0E | |
| 40 | +#define ARIZONA_AIF_FRAME_CTRL_9 0x0F | |
| 41 | +#define ARIZONA_AIF_FRAME_CTRL_10 0x10 | |
| 42 | +#define ARIZONA_AIF_FRAME_CTRL_11 0x11 | |
| 43 | +#define ARIZONA_AIF_FRAME_CTRL_12 0x12 | |
| 44 | +#define ARIZONA_AIF_FRAME_CTRL_13 0x13 | |
| 45 | +#define ARIZONA_AIF_FRAME_CTRL_14 0x14 | |
| 46 | +#define ARIZONA_AIF_FRAME_CTRL_15 0x15 | |
| 47 | +#define ARIZONA_AIF_FRAME_CTRL_16 0x16 | |
| 48 | +#define ARIZONA_AIF_FRAME_CTRL_17 0x17 | |
| 49 | +#define ARIZONA_AIF_FRAME_CTRL_18 0x18 | |
| 50 | +#define ARIZONA_AIF_TX_ENABLES 0x19 | |
| 51 | +#define ARIZONA_AIF_RX_ENABLES 0x1A | |
| 52 | +#define ARIZONA_AIF_FORCE_WRITE 0x1B | |
| 53 | + | |
| 54 | +#define arizona_fll_err(_fll, fmt, ...) \ | |
| 55 | + dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) | |
| 56 | +#define arizona_fll_warn(_fll, fmt, ...) \ | |
| 57 | + dev_warn(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) | |
| 58 | +#define arizona_fll_dbg(_fll, fmt, ...) \ | |
| 59 | + dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) | |
| 60 | + | |
| 61 | +#define arizona_aif_err(_dai, fmt, ...) \ | |
| 62 | + dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__) | |
| 63 | +#define arizona_aif_warn(_dai, fmt, ...) \ | |
| 64 | + dev_warn(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__) | |
| 65 | +#define arizona_aif_dbg(_dai, fmt, ...) \ | |
| 66 | + dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__) | |
| 67 | + | |
| 68 | +const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = { | |
| 69 | + "None", | |
| 70 | + "Tone Generator 1", | |
| 71 | + "Tone Generator 2", | |
| 72 | + "Haptics", | |
| 73 | + "AEC", | |
| 74 | + "Mic Mute Mixer", | |
| 75 | + "Noise Generator", | |
| 76 | + "IN1L", | |
| 77 | + "IN1R", | |
| 78 | + "IN2L", | |
| 79 | + "IN2R", | |
| 80 | + "IN3L", | |
| 81 | + "IN3R", | |
| 82 | + "IN4L", | |
| 83 | + "IN4R", | |
| 84 | + "AIF1RX1", | |
| 85 | + "AIF1RX2", | |
| 86 | + "AIF1RX3", | |
| 87 | + "AIF1RX4", | |
| 88 | + "AIF1RX5", | |
| 89 | + "AIF1RX6", | |
| 90 | + "AIF1RX7", | |
| 91 | + "AIF1RX8", | |
| 92 | + "AIF2RX1", | |
| 93 | + "AIF2RX2", | |
| 94 | + "AIF3RX1", | |
| 95 | + "AIF3RX2", | |
| 96 | + "SLIMRX1", | |
| 97 | + "SLIMRX2", | |
| 98 | + "SLIMRX3", | |
| 99 | + "SLIMRX4", | |
| 100 | + "SLIMRX5", | |
| 101 | + "SLIMRX6", | |
| 102 | + "SLIMRX7", | |
| 103 | + "SLIMRX8", | |
| 104 | + "EQ1", | |
| 105 | + "EQ2", | |
| 106 | + "EQ3", | |
| 107 | + "EQ4", | |
| 108 | + "DRC1L", | |
| 109 | + "DRC1R", | |
| 110 | + "DRC2L", | |
| 111 | + "DRC2R", | |
| 112 | + "LHPF1", | |
| 113 | + "LHPF2", | |
| 114 | + "LHPF3", | |
| 115 | + "LHPF4", | |
| 116 | + "DSP1.1", | |
| 117 | + "DSP1.2", | |
| 118 | + "DSP1.3", | |
| 119 | + "DSP1.4", | |
| 120 | + "DSP1.5", | |
| 121 | + "DSP1.6", | |
| 122 | + "ASRC1L", | |
| 123 | + "ASRC1R", | |
| 124 | + "ASRC2L", | |
| 125 | + "ASRC2R", | |
| 126 | +}; | |
| 127 | +EXPORT_SYMBOL_GPL(arizona_mixer_texts); | |
| 128 | + | |
| 129 | +int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = { | |
| 130 | + 0x00, /* None */ | |
| 131 | + 0x04, /* Tone */ | |
| 132 | + 0x05, | |
| 133 | + 0x06, /* Haptics */ | |
| 134 | + 0x08, /* AEC */ | |
| 135 | + 0x0c, /* Noise mixer */ | |
| 136 | + 0x0d, /* Comfort noise */ | |
| 137 | + 0x10, /* IN1L */ | |
| 138 | + 0x11, | |
| 139 | + 0x12, | |
| 140 | + 0x13, | |
| 141 | + 0x14, | |
| 142 | + 0x15, | |
| 143 | + 0x16, | |
| 144 | + 0x17, | |
| 145 | + 0x20, /* AIF1RX1 */ | |
| 146 | + 0x21, | |
| 147 | + 0x22, | |
| 148 | + 0x23, | |
| 149 | + 0x24, | |
| 150 | + 0x25, | |
| 151 | + 0x26, | |
| 152 | + 0x27, | |
| 153 | + 0x28, /* AIF2RX1 */ | |
| 154 | + 0x29, | |
| 155 | + 0x30, /* AIF3RX1 */ | |
| 156 | + 0x31, | |
| 157 | + 0x38, /* SLIMRX1 */ | |
| 158 | + 0x39, | |
| 159 | + 0x3a, | |
| 160 | + 0x3b, | |
| 161 | + 0x3c, | |
| 162 | + 0x3d, | |
| 163 | + 0x3e, | |
| 164 | + 0x3f, | |
| 165 | + 0x50, /* EQ1 */ | |
| 166 | + 0x51, | |
| 167 | + 0x52, | |
| 168 | + 0x53, | |
| 169 | + 0x58, /* DRC1L */ | |
| 170 | + 0x59, | |
| 171 | + 0x5a, | |
| 172 | + 0x5b, | |
| 173 | + 0x60, /* LHPF1 */ | |
| 174 | + 0x61, | |
| 175 | + 0x62, | |
| 176 | + 0x63, | |
| 177 | + 0x68, /* DSP1.1 */ | |
| 178 | + 0x69, | |
| 179 | + 0x6a, | |
| 180 | + 0x6b, | |
| 181 | + 0x6c, | |
| 182 | + 0x6d, | |
| 183 | + 0x90, /* ASRC1L */ | |
| 184 | + 0x91, | |
| 185 | + 0x92, | |
| 186 | + 0x93, | |
| 187 | +}; | |
| 188 | +EXPORT_SYMBOL_GPL(arizona_mixer_values); | |
| 189 | + | |
| 190 | +const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0); | |
| 191 | +EXPORT_SYMBOL_GPL(arizona_mixer_tlv); | |
| 192 | + | |
| 193 | +static const char *arizona_lhpf_mode_text[] = { | |
| 194 | + "Low-pass", "High-pass" | |
| 195 | +}; | |
| 196 | + | |
| 197 | +const struct soc_enum arizona_lhpf1_mode = | |
| 198 | + SOC_ENUM_SINGLE(ARIZONA_HPLPF1_1, ARIZONA_LHPF1_MODE_SHIFT, 2, | |
| 199 | + arizona_lhpf_mode_text); | |
| 200 | +EXPORT_SYMBOL_GPL(arizona_lhpf1_mode); | |
| 201 | + | |
| 202 | +const struct soc_enum arizona_lhpf2_mode = | |
| 203 | + SOC_ENUM_SINGLE(ARIZONA_HPLPF2_1, ARIZONA_LHPF2_MODE_SHIFT, 2, | |
| 204 | + arizona_lhpf_mode_text); | |
| 205 | +EXPORT_SYMBOL_GPL(arizona_lhpf2_mode); | |
| 206 | + | |
| 207 | +const struct soc_enum arizona_lhpf3_mode = | |
| 208 | + SOC_ENUM_SINGLE(ARIZONA_HPLPF3_1, ARIZONA_LHPF3_MODE_SHIFT, 2, | |
| 209 | + arizona_lhpf_mode_text); | |
| 210 | +EXPORT_SYMBOL_GPL(arizona_lhpf3_mode); | |
| 211 | + | |
| 212 | +const struct soc_enum arizona_lhpf4_mode = | |
| 213 | + SOC_ENUM_SINGLE(ARIZONA_HPLPF4_1, ARIZONA_LHPF4_MODE_SHIFT, 2, | |
| 214 | + arizona_lhpf_mode_text); | |
| 215 | +EXPORT_SYMBOL_GPL(arizona_lhpf4_mode); | |
| 216 | + | |
| 217 | +int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, | |
| 218 | + int event) | |
| 219 | +{ | |
| 220 | + return 0; | |
| 221 | +} | |
| 222 | +EXPORT_SYMBOL_GPL(arizona_in_ev); | |
| 223 | + | |
| 224 | +int arizona_out_ev(struct snd_soc_dapm_widget *w, | |
| 225 | + struct snd_kcontrol *kcontrol, | |
| 226 | + int event) | |
| 227 | +{ | |
| 228 | + return 0; | |
| 229 | +} | |
| 230 | +EXPORT_SYMBOL_GPL(arizona_out_ev); | |
| 231 | + | |
| 232 | +int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, | |
| 233 | + int source, unsigned int freq, int dir) | |
| 234 | +{ | |
| 235 | + struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | |
| 236 | + struct arizona *arizona = priv->arizona; | |
| 237 | + char *name; | |
| 238 | + unsigned int reg; | |
| 239 | + unsigned int mask = ARIZONA_SYSCLK_FREQ_MASK | ARIZONA_SYSCLK_SRC_MASK; | |
| 240 | + unsigned int val = source << ARIZONA_SYSCLK_SRC_SHIFT; | |
| 241 | + unsigned int *clk; | |
| 242 | + | |
| 243 | + switch (clk_id) { | |
| 244 | + case ARIZONA_CLK_SYSCLK: | |
| 245 | + name = "SYSCLK"; | |
| 246 | + reg = ARIZONA_SYSTEM_CLOCK_1; | |
| 247 | + clk = &priv->sysclk; | |
| 248 | + mask |= ARIZONA_SYSCLK_FRAC; | |
| 249 | + break; | |
| 250 | + case ARIZONA_CLK_ASYNCCLK: | |
| 251 | + name = "ASYNCCLK"; | |
| 252 | + reg = ARIZONA_ASYNC_CLOCK_1; | |
| 253 | + clk = &priv->asyncclk; | |
| 254 | + break; | |
| 255 | + default: | |
| 256 | + return -EINVAL; | |
| 257 | + } | |
| 258 | + | |
| 259 | + switch (freq) { | |
| 260 | + case 5644800: | |
| 261 | + case 6144000: | |
| 262 | + break; | |
| 263 | + case 11289600: | |
| 264 | + case 12288000: | |
| 265 | + val |= 1 << ARIZONA_SYSCLK_FREQ_SHIFT; | |
| 266 | + break; | |
| 267 | + case 22579200: | |
| 268 | + case 24576000: | |
| 269 | + val |= 2 << ARIZONA_SYSCLK_FREQ_SHIFT; | |
| 270 | + break; | |
| 271 | + case 45158400: | |
| 272 | + case 49152000: | |
| 273 | + val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT; | |
| 274 | + break; | |
| 275 | + default: | |
| 276 | + return -EINVAL; | |
| 277 | + } | |
| 278 | + | |
| 279 | + *clk = freq; | |
| 280 | + | |
| 281 | + if (freq % 6144000) | |
| 282 | + val |= ARIZONA_SYSCLK_FRAC; | |
| 283 | + | |
| 284 | + dev_dbg(arizona->dev, "%s set to %uHz", name, freq); | |
| 285 | + | |
| 286 | + return regmap_update_bits(arizona->regmap, reg, mask, val); | |
| 287 | +} | |
| 288 | +EXPORT_SYMBOL_GPL(arizona_set_sysclk); | |
| 289 | + | |
| 290 | +static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |
| 291 | +{ | |
| 292 | + struct snd_soc_codec *codec = dai->codec; | |
| 293 | + int lrclk, bclk, mode, base; | |
| 294 | + | |
| 295 | + base = dai->driver->base; | |
| 296 | + | |
| 297 | + lrclk = 0; | |
| 298 | + bclk = 0; | |
| 299 | + | |
| 300 | + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | |
| 301 | + case SND_SOC_DAIFMT_DSP_A: | |
| 302 | + mode = 0; | |
| 303 | + break; | |
| 304 | + case SND_SOC_DAIFMT_DSP_B: | |
| 305 | + mode = 1; | |
| 306 | + break; | |
| 307 | + case SND_SOC_DAIFMT_I2S: | |
| 308 | + mode = 2; | |
| 309 | + break; | |
| 310 | + case SND_SOC_DAIFMT_LEFT_J: | |
| 311 | + mode = 3; | |
| 312 | + break; | |
| 313 | + default: | |
| 314 | + arizona_aif_err(dai, "Unsupported DAI format %d\n", | |
| 315 | + fmt & SND_SOC_DAIFMT_FORMAT_MASK); | |
| 316 | + return -EINVAL; | |
| 317 | + } | |
| 318 | + | |
| 319 | + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | |
| 320 | + case SND_SOC_DAIFMT_CBS_CFS: | |
| 321 | + break; | |
| 322 | + case SND_SOC_DAIFMT_CBS_CFM: | |
| 323 | + lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR; | |
| 324 | + break; | |
| 325 | + case SND_SOC_DAIFMT_CBM_CFS: | |
| 326 | + bclk |= ARIZONA_AIF1_BCLK_MSTR; | |
| 327 | + break; | |
| 328 | + case SND_SOC_DAIFMT_CBM_CFM: | |
| 329 | + bclk |= ARIZONA_AIF1_BCLK_MSTR; | |
| 330 | + lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR; | |
| 331 | + break; | |
| 332 | + default: | |
| 333 | + arizona_aif_err(dai, "Unsupported master mode %d\n", | |
| 334 | + fmt & SND_SOC_DAIFMT_MASTER_MASK); | |
| 335 | + return -EINVAL; | |
| 336 | + } | |
| 337 | + | |
| 338 | + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | |
| 339 | + case SND_SOC_DAIFMT_NB_NF: | |
| 340 | + break; | |
| 341 | + case SND_SOC_DAIFMT_IB_IF: | |
| 342 | + bclk |= ARIZONA_AIF1_BCLK_INV; | |
| 343 | + lrclk |= ARIZONA_AIF1TX_LRCLK_INV; | |
| 344 | + break; | |
| 345 | + case SND_SOC_DAIFMT_IB_NF: | |
| 346 | + bclk |= ARIZONA_AIF1_BCLK_INV; | |
| 347 | + break; | |
| 348 | + case SND_SOC_DAIFMT_NB_IF: | |
| 349 | + lrclk |= ARIZONA_AIF1TX_LRCLK_INV; | |
| 350 | + break; | |
| 351 | + default: | |
| 352 | + return -EINVAL; | |
| 353 | + } | |
| 354 | + | |
| 355 | + snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL, | |
| 356 | + ARIZONA_AIF1_BCLK_INV | ARIZONA_AIF1_BCLK_MSTR, | |
| 357 | + bclk); | |
| 358 | + snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_PIN_CTRL, | |
| 359 | + ARIZONA_AIF1TX_LRCLK_INV | | |
| 360 | + ARIZONA_AIF1TX_LRCLK_MSTR, lrclk); | |
| 361 | + snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_PIN_CTRL, | |
| 362 | + ARIZONA_AIF1RX_LRCLK_INV | | |
| 363 | + ARIZONA_AIF1RX_LRCLK_MSTR, lrclk); | |
| 364 | + snd_soc_update_bits(codec, base + ARIZONA_AIF_FORMAT, | |
| 365 | + ARIZONA_AIF1_FMT_MASK, mode); | |
| 366 | + | |
| 367 | + return 0; | |
| 368 | +} | |
| 369 | + | |
| 370 | +static const int arizona_48k_bclk_rates[] = { | |
| 371 | + -1, | |
| 372 | + 48000, | |
| 373 | + 64000, | |
| 374 | + 96000, | |
| 375 | + 128000, | |
| 376 | + 192000, | |
| 377 | + 256000, | |
| 378 | + 384000, | |
| 379 | + 512000, | |
| 380 | + 768000, | |
| 381 | + 1024000, | |
| 382 | + 1536000, | |
| 383 | + 2048000, | |
| 384 | + 3072000, | |
| 385 | + 4096000, | |
| 386 | + 6144000, | |
| 387 | + 8192000, | |
| 388 | + 12288000, | |
| 389 | + 24576000, | |
| 390 | +}; | |
| 391 | + | |
| 392 | +static const unsigned int arizona_48k_rates[] = { | |
| 393 | + 12000, | |
| 394 | + 24000, | |
| 395 | + 48000, | |
| 396 | + 96000, | |
| 397 | + 192000, | |
| 398 | + 384000, | |
| 399 | + 768000, | |
| 400 | + 4000, | |
| 401 | + 8000, | |
| 402 | + 16000, | |
| 403 | + 32000, | |
| 404 | + 64000, | |
| 405 | + 128000, | |
| 406 | + 256000, | |
| 407 | + 512000, | |
| 408 | +}; | |
| 409 | + | |
| 410 | +static const struct snd_pcm_hw_constraint_list arizona_48k_constraint = { | |
| 411 | + .count = ARRAY_SIZE(arizona_48k_rates), | |
| 412 | + .list = arizona_48k_rates, | |
| 413 | +}; | |
| 414 | + | |
| 415 | +static const int arizona_44k1_bclk_rates[] = { | |
| 416 | + -1, | |
| 417 | + 44100, | |
| 418 | + 58800, | |
| 419 | + 88200, | |
| 420 | + 117600, | |
| 421 | + 177640, | |
| 422 | + 235200, | |
| 423 | + 352800, | |
| 424 | + 470400, | |
| 425 | + 705600, | |
| 426 | + 940800, | |
| 427 | + 1411200, | |
| 428 | + 1881600, | |
| 429 | + 2882400, | |
| 430 | + 3763200, | |
| 431 | + 5644800, | |
| 432 | + 7526400, | |
| 433 | + 11289600, | |
| 434 | + 22579200, | |
| 435 | +}; | |
| 436 | + | |
| 437 | +static const unsigned int arizona_44k1_rates[] = { | |
| 438 | + 11025, | |
| 439 | + 22050, | |
| 440 | + 44100, | |
| 441 | + 88200, | |
| 442 | + 176400, | |
| 443 | + 352800, | |
| 444 | + 705600, | |
| 445 | +}; | |
| 446 | + | |
| 447 | +static const struct snd_pcm_hw_constraint_list arizona_44k1_constraint = { | |
| 448 | + .count = ARRAY_SIZE(arizona_44k1_rates), | |
| 449 | + .list = arizona_44k1_rates, | |
| 450 | +}; | |
| 451 | + | |
| 452 | +static int arizona_sr_vals[] = { | |
| 453 | + 0, | |
| 454 | + 12000, | |
| 455 | + 24000, | |
| 456 | + 48000, | |
| 457 | + 96000, | |
| 458 | + 192000, | |
| 459 | + 384000, | |
| 460 | + 768000, | |
| 461 | + 0, | |
| 462 | + 11025, | |
| 463 | + 22050, | |
| 464 | + 44100, | |
| 465 | + 88200, | |
| 466 | + 176400, | |
| 467 | + 352800, | |
| 468 | + 705600, | |
| 469 | + 4000, | |
| 470 | + 8000, | |
| 471 | + 16000, | |
| 472 | + 32000, | |
| 473 | + 64000, | |
| 474 | + 128000, | |
| 475 | + 256000, | |
| 476 | + 512000, | |
| 477 | +}; | |
| 478 | + | |
| 479 | +static int arizona_startup(struct snd_pcm_substream *substream, | |
| 480 | + struct snd_soc_dai *dai) | |
| 481 | +{ | |
| 482 | + struct snd_soc_codec *codec = dai->codec; | |
| 483 | + struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | |
| 484 | + struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1]; | |
| 485 | + const struct snd_pcm_hw_constraint_list *constraint; | |
| 486 | + unsigned int base_rate; | |
| 487 | + | |
| 488 | + switch (dai_priv->clk) { | |
| 489 | + case ARIZONA_CLK_SYSCLK: | |
| 490 | + base_rate = priv->sysclk; | |
| 491 | + break; | |
| 492 | + case ARIZONA_CLK_ASYNCCLK: | |
| 493 | + base_rate = priv->asyncclk; | |
| 494 | + break; | |
| 495 | + default: | |
| 496 | + return 0; | |
| 497 | + } | |
| 498 | + | |
| 499 | + if (base_rate % 8000) | |
| 500 | + constraint = &arizona_44k1_constraint; | |
| 501 | + else | |
| 502 | + constraint = &arizona_48k_constraint; | |
| 503 | + | |
| 504 | + return snd_pcm_hw_constraint_list(substream->runtime, 0, | |
| 505 | + SNDRV_PCM_HW_PARAM_RATE, | |
| 506 | + constraint); | |
| 507 | +} | |
| 508 | + | |
| 509 | +static int arizona_hw_params(struct snd_pcm_substream *substream, | |
| 510 | + struct snd_pcm_hw_params *params, | |
| 511 | + struct snd_soc_dai *dai) | |
| 512 | +{ | |
| 513 | + struct snd_soc_codec *codec = dai->codec; | |
| 514 | + struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | |
| 515 | + struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1]; | |
| 516 | + int base = dai->driver->base; | |
| 517 | + const int *rates; | |
| 518 | + int i; | |
| 519 | + int bclk, lrclk, wl, frame, sr_val; | |
| 520 | + | |
| 521 | + if (params_rate(params) % 8000) | |
| 522 | + rates = &arizona_44k1_bclk_rates[0]; | |
| 523 | + else | |
| 524 | + rates = &arizona_48k_bclk_rates[0]; | |
| 525 | + | |
| 526 | + for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) { | |
| 527 | + if (rates[i] >= snd_soc_params_to_bclk(params) && | |
| 528 | + rates[i] % params_rate(params) == 0) { | |
| 529 | + bclk = i; | |
| 530 | + break; | |
| 531 | + } | |
| 532 | + } | |
| 533 | + if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) { | |
| 534 | + arizona_aif_err(dai, "Unsupported sample rate %dHz\n", | |
| 535 | + params_rate(params)); | |
| 536 | + return -EINVAL; | |
| 537 | + } | |
| 538 | + | |
| 539 | + for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++) | |
| 540 | + if (arizona_sr_vals[i] == params_rate(params)) | |
| 541 | + break; | |
| 542 | + if (i == ARRAY_SIZE(arizona_sr_vals)) { | |
| 543 | + arizona_aif_err(dai, "Unsupported sample rate %dHz\n", | |
| 544 | + params_rate(params)); | |
| 545 | + return -EINVAL; | |
| 546 | + } | |
| 547 | + sr_val = i; | |
| 548 | + | |
| 549 | + lrclk = snd_soc_params_to_bclk(params) / params_rate(params); | |
| 550 | + | |
| 551 | + arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n", | |
| 552 | + rates[bclk], rates[bclk] / lrclk); | |
| 553 | + | |
| 554 | + wl = snd_pcm_format_width(params_format(params)); | |
| 555 | + frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl; | |
| 556 | + | |
| 557 | + /* | |
| 558 | + * We will need to be more flexible than this in future, | |
| 559 | + * currently we use a single sample rate for SYSCLK. | |
| 560 | + */ | |
| 561 | + switch (dai_priv->clk) { | |
| 562 | + case ARIZONA_CLK_SYSCLK: | |
| 563 | + snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1, | |
| 564 | + ARIZONA_SAMPLE_RATE_1_MASK, sr_val); | |
| 565 | + snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL, | |
| 566 | + ARIZONA_AIF1_RATE_MASK, 0); | |
| 567 | + break; | |
| 568 | + case ARIZONA_CLK_ASYNCCLK: | |
| 569 | + snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1, | |
| 570 | + ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val); | |
| 571 | + snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL, | |
| 572 | + ARIZONA_AIF1_RATE_MASK, 8); | |
| 573 | + break; | |
| 574 | + default: | |
| 575 | + arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk); | |
| 576 | + return -EINVAL; | |
| 577 | + } | |
| 578 | + | |
| 579 | + snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL, | |
| 580 | + ARIZONA_AIF1_BCLK_FREQ_MASK, bclk); | |
| 581 | + snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_BCLK_RATE, | |
| 582 | + ARIZONA_AIF1TX_BCPF_MASK, lrclk); | |
| 583 | + snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_BCLK_RATE, | |
| 584 | + ARIZONA_AIF1RX_BCPF_MASK, lrclk); | |
| 585 | + snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_1, | |
| 586 | + ARIZONA_AIF1TX_WL_MASK | | |
| 587 | + ARIZONA_AIF1TX_SLOT_LEN_MASK, frame); | |
| 588 | + snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_2, | |
| 589 | + ARIZONA_AIF1RX_WL_MASK | | |
| 590 | + ARIZONA_AIF1RX_SLOT_LEN_MASK, frame); | |
| 591 | + | |
| 592 | + return 0; | |
| 593 | +} | |
| 594 | + | |
| 595 | +static const char *arizona_dai_clk_str(int clk_id) | |
| 596 | +{ | |
| 597 | + switch (clk_id) { | |
| 598 | + case ARIZONA_CLK_SYSCLK: | |
| 599 | + return "SYSCLK"; | |
| 600 | + case ARIZONA_CLK_ASYNCCLK: | |
| 601 | + return "ASYNCCLK"; | |
| 602 | + default: | |
| 603 | + return "Unknown clock"; | |
| 604 | + } | |
| 605 | +} | |
| 606 | + | |
| 607 | +static int arizona_dai_set_sysclk(struct snd_soc_dai *dai, | |
| 608 | + int clk_id, unsigned int freq, int dir) | |
| 609 | +{ | |
| 610 | + struct snd_soc_codec *codec = dai->codec; | |
| 611 | + struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | |
| 612 | + struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1]; | |
| 613 | + struct snd_soc_dapm_route routes[2]; | |
| 614 | + | |
| 615 | + switch (clk_id) { | |
| 616 | + case ARIZONA_CLK_SYSCLK: | |
| 617 | + case ARIZONA_CLK_ASYNCCLK: | |
| 618 | + break; | |
| 619 | + default: | |
| 620 | + return -EINVAL; | |
| 621 | + } | |
| 622 | + | |
| 623 | + if (clk_id == dai_priv->clk) | |
| 624 | + return 0; | |
| 625 | + | |
| 626 | + if (dai->active) { | |
| 627 | + dev_err(codec->dev, "Can't change clock on active DAI %d\n", | |
| 628 | + dai->id); | |
| 629 | + return -EBUSY; | |
| 630 | + } | |
| 631 | + | |
| 632 | + memset(&routes, 0, sizeof(routes)); | |
| 633 | + routes[0].sink = dai->driver->capture.stream_name; | |
| 634 | + routes[1].sink = dai->driver->playback.stream_name; | |
| 635 | + | |
| 636 | + routes[0].source = arizona_dai_clk_str(dai_priv->clk); | |
| 637 | + routes[1].source = arizona_dai_clk_str(dai_priv->clk); | |
| 638 | + snd_soc_dapm_del_routes(&codec->dapm, routes, ARRAY_SIZE(routes)); | |
| 639 | + | |
| 640 | + routes[0].source = arizona_dai_clk_str(clk_id); | |
| 641 | + routes[1].source = arizona_dai_clk_str(clk_id); | |
| 642 | + snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes)); | |
| 643 | + | |
| 644 | + return snd_soc_dapm_sync(&codec->dapm); | |
| 645 | +} | |
| 646 | + | |
| 647 | +const struct snd_soc_dai_ops arizona_dai_ops = { | |
| 648 | + .startup = arizona_startup, | |
| 649 | + .set_fmt = arizona_set_fmt, | |
| 650 | + .hw_params = arizona_hw_params, | |
| 651 | + .set_sysclk = arizona_dai_set_sysclk, | |
| 652 | +}; | |
| 653 | +EXPORT_SYMBOL_GPL(arizona_dai_ops); | |
| 654 | + | |
| 655 | +int arizona_init_dai(struct arizona_priv *priv, int id) | |
| 656 | +{ | |
| 657 | + struct arizona_dai_priv *dai_priv = &priv->dai[id]; | |
| 658 | + | |
| 659 | + dai_priv->clk = ARIZONA_CLK_SYSCLK; | |
| 660 | + | |
| 661 | + return 0; | |
| 662 | +} | |
| 663 | +EXPORT_SYMBOL_GPL(arizona_init_dai); | |
| 664 | + | |
| 665 | +static irqreturn_t arizona_fll_lock(int irq, void *data) | |
| 666 | +{ | |
| 667 | + struct arizona_fll *fll = data; | |
| 668 | + | |
| 669 | + arizona_fll_dbg(fll, "Locked\n"); | |
| 670 | + | |
| 671 | + complete(&fll->lock); | |
| 672 | + | |
| 673 | + return IRQ_HANDLED; | |
| 674 | +} | |
| 675 | + | |
| 676 | +static irqreturn_t arizona_fll_clock_ok(int irq, void *data) | |
| 677 | +{ | |
| 678 | + struct arizona_fll *fll = data; | |
| 679 | + | |
| 680 | + arizona_fll_dbg(fll, "clock OK\n"); | |
| 681 | + | |
| 682 | + complete(&fll->ok); | |
| 683 | + | |
| 684 | + return IRQ_HANDLED; | |
| 685 | +} | |
| 686 | + | |
| 687 | +static struct { | |
| 688 | + unsigned int min; | |
| 689 | + unsigned int max; | |
| 690 | + u16 fratio; | |
| 691 | + int ratio; | |
| 692 | +} fll_fratios[] = { | |
| 693 | + { 0, 64000, 4, 16 }, | |
| 694 | + { 64000, 128000, 3, 8 }, | |
| 695 | + { 128000, 256000, 2, 4 }, | |
| 696 | + { 256000, 1000000, 1, 2 }, | |
| 697 | + { 1000000, 13500000, 0, 1 }, | |
| 698 | +}; | |
| 699 | + | |
| 700 | +struct arizona_fll_cfg { | |
| 701 | + int n; | |
| 702 | + int theta; | |
| 703 | + int lambda; | |
| 704 | + int refdiv; | |
| 705 | + int outdiv; | |
| 706 | + int fratio; | |
| 707 | +}; | |
| 708 | + | |
| 709 | +static int arizona_calc_fll(struct arizona_fll *fll, | |
| 710 | + struct arizona_fll_cfg *cfg, | |
| 711 | + unsigned int Fref, | |
| 712 | + unsigned int Fout) | |
| 713 | +{ | |
| 714 | + unsigned int target, div, gcd_fll; | |
| 715 | + int i, ratio; | |
| 716 | + | |
| 717 | + arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, Fout); | |
| 718 | + | |
| 719 | + /* Fref must be <=13.5MHz */ | |
| 720 | + div = 1; | |
| 721 | + cfg->refdiv = 0; | |
| 722 | + while ((Fref / div) > 13500000) { | |
| 723 | + div *= 2; | |
| 724 | + cfg->refdiv++; | |
| 725 | + | |
| 726 | + if (div > 8) { | |
| 727 | + arizona_fll_err(fll, | |
| 728 | + "Can't scale %dMHz in to <=13.5MHz\n", | |
| 729 | + Fref); | |
| 730 | + return -EINVAL; | |
| 731 | + } | |
| 732 | + } | |
| 733 | + | |
| 734 | + /* Apply the division for our remaining calculations */ | |
| 735 | + Fref /= div; | |
| 736 | + | |
| 737 | + /* Fvco should be over the targt; don't check the upper bound */ | |
| 738 | + div = 1; | |
| 739 | + while (Fout * div < 90000000 * fll->vco_mult) { | |
| 740 | + div++; | |
| 741 | + if (div > 7) { | |
| 742 | + arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n", | |
| 743 | + Fout); | |
| 744 | + return -EINVAL; | |
| 745 | + } | |
| 746 | + } | |
| 747 | + target = Fout * div / fll->vco_mult; | |
| 748 | + cfg->outdiv = div; | |
| 749 | + | |
| 750 | + arizona_fll_dbg(fll, "Fvco=%dHz\n", target); | |
| 751 | + | |
| 752 | + /* Find an appropraite FLL_FRATIO and factor it out of the target */ | |
| 753 | + for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { | |
| 754 | + if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { | |
| 755 | + cfg->fratio = fll_fratios[i].fratio; | |
| 756 | + ratio = fll_fratios[i].ratio; | |
| 757 | + break; | |
| 758 | + } | |
| 759 | + } | |
| 760 | + if (i == ARRAY_SIZE(fll_fratios)) { | |
| 761 | + arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n", | |
| 762 | + Fref); | |
| 763 | + return -EINVAL; | |
| 764 | + } | |
| 765 | + | |
| 766 | + cfg->n = target / (ratio * Fref); | |
| 767 | + | |
| 768 | + if (target % Fref) { | |
| 769 | + gcd_fll = gcd(target, ratio * Fref); | |
| 770 | + arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll); | |
| 771 | + | |
| 772 | + cfg->theta = (target - (cfg->n * ratio * Fref)) | |
| 773 | + / gcd_fll; | |
| 774 | + cfg->lambda = (ratio * Fref) / gcd_fll; | |
| 775 | + } else { | |
| 776 | + cfg->theta = 0; | |
| 777 | + cfg->lambda = 0; | |
| 778 | + } | |
| 779 | + | |
| 780 | + arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n", | |
| 781 | + cfg->n, cfg->theta, cfg->lambda); | |
| 782 | + arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n", | |
| 783 | + cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv); | |
| 784 | + | |
| 785 | + return 0; | |
| 786 | + | |
| 787 | +} | |
| 788 | + | |
| 789 | +static void arizona_apply_fll(struct arizona *arizona, unsigned int base, | |
| 790 | + struct arizona_fll_cfg *cfg, int source) | |
| 791 | +{ | |
| 792 | + regmap_update_bits(arizona->regmap, base + 3, | |
| 793 | + ARIZONA_FLL1_THETA_MASK, cfg->theta); | |
| 794 | + regmap_update_bits(arizona->regmap, base + 4, | |
| 795 | + ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda); | |
| 796 | + regmap_update_bits(arizona->regmap, base + 5, | |
| 797 | + ARIZONA_FLL1_FRATIO_MASK, | |
| 798 | + cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT); | |
| 799 | + regmap_update_bits(arizona->regmap, base + 6, | |
| 800 | + ARIZONA_FLL1_CLK_REF_DIV_MASK | | |
| 801 | + ARIZONA_FLL1_CLK_REF_SRC_MASK, | |
| 802 | + cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT | | |
| 803 | + source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT); | |
| 804 | + | |
| 805 | + regmap_update_bits(arizona->regmap, base + 2, | |
| 806 | + ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK, | |
| 807 | + ARIZONA_FLL1_CTRL_UPD | cfg->n); | |
| 808 | +} | |
| 809 | + | |
| 810 | +int arizona_set_fll(struct arizona_fll *fll, int source, | |
| 811 | + unsigned int Fref, unsigned int Fout) | |
| 812 | +{ | |
| 813 | + struct arizona *arizona = fll->arizona; | |
| 814 | + struct arizona_fll_cfg cfg, sync; | |
| 815 | + unsigned int reg, val; | |
| 816 | + int syncsrc; | |
| 817 | + bool ena; | |
| 818 | + int ret; | |
| 819 | + | |
| 820 | + ret = regmap_read(arizona->regmap, fll->base + 1, ®); | |
| 821 | + if (ret != 0) { | |
| 822 | + arizona_fll_err(fll, "Failed to read current state: %d\n", | |
| 823 | + ret); | |
| 824 | + return ret; | |
| 825 | + } | |
| 826 | + ena = reg & ARIZONA_FLL1_ENA; | |
| 827 | + | |
| 828 | + if (Fout) { | |
| 829 | + /* Do we have a 32kHz reference? */ | |
| 830 | + regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val); | |
| 831 | + switch (val & ARIZONA_CLK_32K_SRC_MASK) { | |
| 832 | + case ARIZONA_CLK_SRC_MCLK1: | |
| 833 | + case ARIZONA_CLK_SRC_MCLK2: | |
| 834 | + syncsrc = val & ARIZONA_CLK_32K_SRC_MASK; | |
| 835 | + break; | |
| 836 | + default: | |
| 837 | + syncsrc = -1; | |
| 838 | + } | |
| 839 | + | |
| 840 | + if (source == syncsrc) | |
| 841 | + syncsrc = -1; | |
| 842 | + | |
| 843 | + if (syncsrc >= 0) { | |
| 844 | + ret = arizona_calc_fll(fll, &sync, Fref, Fout); | |
| 845 | + if (ret != 0) | |
| 846 | + return ret; | |
| 847 | + | |
| 848 | + ret = arizona_calc_fll(fll, &cfg, 32768, Fout); | |
| 849 | + if (ret != 0) | |
| 850 | + return ret; | |
| 851 | + } else { | |
| 852 | + ret = arizona_calc_fll(fll, &cfg, Fref, Fout); | |
| 853 | + if (ret != 0) | |
| 854 | + return ret; | |
| 855 | + } | |
| 856 | + } else { | |
| 857 | + regmap_update_bits(arizona->regmap, fll->base + 1, | |
| 858 | + ARIZONA_FLL1_ENA, 0); | |
| 859 | + regmap_update_bits(arizona->regmap, fll->base + 0x11, | |
| 860 | + ARIZONA_FLL1_SYNC_ENA, 0); | |
| 861 | + | |
| 862 | + if (ena) | |
| 863 | + pm_runtime_put_autosuspend(arizona->dev); | |
| 864 | + | |
| 865 | + return 0; | |
| 866 | + } | |
| 867 | + | |
| 868 | + regmap_update_bits(arizona->regmap, fll->base + 5, | |
| 869 | + ARIZONA_FLL1_OUTDIV_MASK, | |
| 870 | + cfg.outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); | |
| 871 | + | |
| 872 | + if (syncsrc >= 0) { | |
| 873 | + arizona_apply_fll(arizona, fll->base, &cfg, syncsrc); | |
| 874 | + arizona_apply_fll(arizona, fll->base + 0x10, &sync, source); | |
| 875 | + } else { | |
| 876 | + arizona_apply_fll(arizona, fll->base, &cfg, source); | |
| 877 | + } | |
| 878 | + | |
| 879 | + if (!ena) | |
| 880 | + pm_runtime_get(arizona->dev); | |
| 881 | + | |
| 882 | + /* Clear any pending completions */ | |
| 883 | + try_wait_for_completion(&fll->ok); | |
| 884 | + | |
| 885 | + regmap_update_bits(arizona->regmap, fll->base + 1, | |
| 886 | + ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); | |
| 887 | + if (syncsrc >= 0) | |
| 888 | + regmap_update_bits(arizona->regmap, fll->base + 0x11, | |
| 889 | + ARIZONA_FLL1_SYNC_ENA, | |
| 890 | + ARIZONA_FLL1_SYNC_ENA); | |
| 891 | + | |
| 892 | + ret = wait_for_completion_timeout(&fll->ok, | |
| 893 | + msecs_to_jiffies(25)); | |
| 894 | + if (ret == 0) | |
| 895 | + arizona_fll_warn(fll, "Timed out waiting for lock\n"); | |
| 896 | + | |
| 897 | + return 0; | |
| 898 | +} | |
| 899 | +EXPORT_SYMBOL_GPL(arizona_set_fll); | |
| 900 | + | |
| 901 | +int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq, | |
| 902 | + int ok_irq, struct arizona_fll *fll) | |
| 903 | +{ | |
| 904 | + int ret; | |
| 905 | + | |
| 906 | + init_completion(&fll->lock); | |
| 907 | + init_completion(&fll->ok); | |
| 908 | + | |
| 909 | + fll->id = id; | |
| 910 | + fll->base = base; | |
| 911 | + fll->arizona = arizona; | |
| 912 | + | |
| 913 | + snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id); | |
| 914 | + snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name), | |
| 915 | + "FLL%d clock OK", id); | |
| 916 | + | |
| 917 | + ret = arizona_request_irq(arizona, lock_irq, fll->lock_name, | |
| 918 | + arizona_fll_lock, fll); | |
| 919 | + if (ret != 0) { | |
| 920 | + dev_err(arizona->dev, "Failed to get FLL%d lock IRQ: %d\n", | |
| 921 | + id, ret); | |
| 922 | + } | |
| 923 | + | |
| 924 | + ret = arizona_request_irq(arizona, ok_irq, fll->clock_ok_name, | |
| 925 | + arizona_fll_clock_ok, fll); | |
| 926 | + if (ret != 0) { | |
| 927 | + dev_err(arizona->dev, "Failed to get FLL%d clock OK IRQ: %d\n", | |
| 928 | + id, ret); | |
| 929 | + } | |
| 930 | + | |
| 931 | + return 0; | |
| 932 | +} | |
| 933 | +EXPORT_SYMBOL_GPL(arizona_init_fll); | |
| 934 | + | |
| 935 | +MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support"); | |
| 936 | +MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | |
| 937 | +MODULE_LICENSE("GPL"); | |
| @@ -0,0 +1,159 @@ | ||
| 1 | +/* | |
| 2 | + * arizona.h - Wolfson Arizona class device shared support | |
| 3 | + * | |
| 4 | + * Copyright 2012 Wolfson Microelectronics plc | |
| 5 | + * | |
| 6 | + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | |
| 7 | + * | |
| 8 | + * This program is free software; you can redistribute it and/or modify | |
| 9 | + * it under the terms of the GNU General Public License version 2 as | |
| 10 | + * published by the Free Software Foundation. | |
| 11 | + */ | |
| 12 | + | |
| 13 | +#ifndef _ASOC_ARIZONA_H | |
| 14 | +#define _ASOC_ARIZONA_H | |
| 15 | + | |
| 16 | +#include <linux/completion.h> | |
| 17 | + | |
| 18 | +#include <sound/soc.h> | |
| 19 | + | |
| 20 | +#define ARIZONA_CLK_SYSCLK 1 | |
| 21 | +#define ARIZONA_CLK_ASYNCCLK 2 | |
| 22 | + | |
| 23 | +#define ARIZONA_CLK_SRC_MCLK1 0x0 | |
| 24 | +#define ARIZONA_CLK_SRC_MCLK2 0x1 | |
| 25 | +#define ARIZONA_CLK_SRC_FLL1 0x4 | |
| 26 | +#define ARIZONA_CLK_SRC_FLL2 0x5 | |
| 27 | +#define ARIZONA_CLK_SRC_AIF1BCLK 0x8 | |
| 28 | +#define ARIZONA_CLK_SRC_AIF2BCLK 0x9 | |
| 29 | +#define ARIZONA_CLK_SRC_AIF3BCLK 0xa | |
| 30 | + | |
| 31 | +#define ARIZONA_FLL_SRC_MCLK1 0 | |
| 32 | +#define ARIZONA_FLL_SRC_MCLK2 1 | |
| 33 | +#define ARIZONA_FLL_SRC_SLIMCLK 2 | |
| 34 | +#define ARIZONA_FLL_SRC_FLL1 3 | |
| 35 | +#define ARIZONA_FLL_SRC_FLL2 4 | |
| 36 | +#define ARIZONA_FLL_SRC_AIF1BCLK 5 | |
| 37 | +#define ARIZONA_FLL_SRC_AIF2BCLK 6 | |
| 38 | +#define ARIZONA_FLL_SRC_AIF3BCLK 7 | |
| 39 | +#define ARIZONA_FLL_SRC_AIF1LRCLK 8 | |
| 40 | +#define ARIZONA_FLL_SRC_AIF2LRCLK 9 | |
| 41 | +#define ARIZONA_FLL_SRC_AIF3LRCLK 10 | |
| 42 | + | |
| 43 | +#define ARIZONA_MIXER_VOL_MASK 0x00FE | |
| 44 | +#define ARIZONA_MIXER_VOL_SHIFT 1 | |
| 45 | +#define ARIZONA_MIXER_VOL_WIDTH 7 | |
| 46 | + | |
| 47 | +#define ARIZONA_MAX_DAI 3 | |
| 48 | + | |
| 49 | +struct arizona; | |
| 50 | + | |
| 51 | +struct arizona_dai_priv { | |
| 52 | + int clk; | |
| 53 | +}; | |
| 54 | + | |
| 55 | +struct arizona_priv { | |
| 56 | + struct arizona *arizona; | |
| 57 | + int sysclk; | |
| 58 | + int asyncclk; | |
| 59 | + struct arizona_dai_priv dai[ARIZONA_MAX_DAI]; | |
| 60 | +}; | |
| 61 | + | |
| 62 | +#define ARIZONA_NUM_MIXER_INPUTS 57 | |
| 63 | + | |
| 64 | +extern const unsigned int arizona_mixer_tlv[]; | |
| 65 | +extern const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS]; | |
| 66 | +extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; | |
| 67 | + | |
| 68 | +#define ARIZONA_MIXER_CONTROLS(name, base) \ | |
| 69 | + SOC_SINGLE_RANGE_TLV(name " Input 1 Volume", base + 1, \ | |
| 70 | + ARIZONA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \ | |
| 71 | + arizona_mixer_tlv), \ | |
| 72 | + SOC_SINGLE_RANGE_TLV(name " Input 2 Volume", base + 3, \ | |
| 73 | + ARIZONA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \ | |
| 74 | + arizona_mixer_tlv), \ | |
| 75 | + SOC_SINGLE_RANGE_TLV(name " Input 3 Volume", base + 5, \ | |
| 76 | + ARIZONA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \ | |
| 77 | + arizona_mixer_tlv), \ | |
| 78 | + SOC_SINGLE_RANGE_TLV(name " Input 4 Volume", base + 7, \ | |
| 79 | + ARIZONA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \ | |
| 80 | + arizona_mixer_tlv) | |
| 81 | + | |
| 82 | +#define ARIZONA_MUX_ENUM_DECL(name, reg) \ | |
| 83 | + SOC_VALUE_ENUM_SINGLE_DECL(name, reg, 0, 0xff, \ | |
| 84 | + arizona_mixer_texts, arizona_mixer_values) | |
| 85 | + | |
| 86 | +#define ARIZONA_MUX_CTL_DECL(name) \ | |
| 87 | + const struct snd_kcontrol_new name##_mux = \ | |
| 88 | + SOC_DAPM_VALUE_ENUM("Route", name##_enum) | |
| 89 | + | |
| 90 | +#define ARIZONA_MIXER_ENUMS(name, base_reg) \ | |
| 91 | + static ARIZONA_MUX_ENUM_DECL(name##_in1_enum, base_reg); \ | |
| 92 | + static ARIZONA_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2); \ | |
| 93 | + static ARIZONA_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4); \ | |
| 94 | + static ARIZONA_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6); \ | |
| 95 | + static ARIZONA_MUX_CTL_DECL(name##_in1); \ | |
| 96 | + static ARIZONA_MUX_CTL_DECL(name##_in2); \ | |
| 97 | + static ARIZONA_MUX_CTL_DECL(name##_in3); \ | |
| 98 | + static ARIZONA_MUX_CTL_DECL(name##_in4) | |
| 99 | + | |
| 100 | +#define ARIZONA_MUX(name, ctrl) \ | |
| 101 | + SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl) | |
| 102 | + | |
| 103 | +#define ARIZONA_MIXER_WIDGETS(name, name_str) \ | |
| 104 | + ARIZONA_MUX(name_str " Input 1", &name##_in1_mux), \ | |
| 105 | + ARIZONA_MUX(name_str " Input 2", &name##_in2_mux), \ | |
| 106 | + ARIZONA_MUX(name_str " Input 3", &name##_in3_mux), \ | |
| 107 | + ARIZONA_MUX(name_str " Input 4", &name##_in4_mux), \ | |
| 108 | + SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0) | |
| 109 | + | |
| 110 | +#define ARIZONA_MIXER_ROUTES(widget, name) \ | |
| 111 | + { widget, NULL, name " Mixer" }, \ | |
| 112 | + { name " Mixer", NULL, name " Input 1" }, \ | |
| 113 | + { name " Mixer", NULL, name " Input 2" }, \ | |
| 114 | + { name " Mixer", NULL, name " Input 3" }, \ | |
| 115 | + { name " Mixer", NULL, name " Input 4" }, \ | |
| 116 | + ARIZONA_MIXER_INPUT_ROUTES(name " Input 1"), \ | |
| 117 | + ARIZONA_MIXER_INPUT_ROUTES(name " Input 2"), \ | |
| 118 | + ARIZONA_MIXER_INPUT_ROUTES(name " Input 3"), \ | |
| 119 | + ARIZONA_MIXER_INPUT_ROUTES(name " Input 4") | |
| 120 | + | |
| 121 | +extern const struct soc_enum arizona_lhpf1_mode; | |
| 122 | +extern const struct soc_enum arizona_lhpf2_mode; | |
| 123 | +extern const struct soc_enum arizona_lhpf3_mode; | |
| 124 | +extern const struct soc_enum arizona_lhpf4_mode; | |
| 125 | + | |
| 126 | +extern int arizona_in_ev(struct snd_soc_dapm_widget *w, | |
| 127 | + struct snd_kcontrol *kcontrol, | |
| 128 | + int event); | |
| 129 | +extern int arizona_out_ev(struct snd_soc_dapm_widget *w, | |
| 130 | + struct snd_kcontrol *kcontrol, | |
| 131 | + int event); | |
| 132 | + | |
| 133 | +extern int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, | |
| 134 | + int source, unsigned int freq, int dir); | |
| 135 | + | |
| 136 | +extern const struct snd_soc_dai_ops arizona_dai_ops; | |
| 137 | + | |
| 138 | +#define ARIZONA_FLL_NAME_LEN 20 | |
| 139 | + | |
| 140 | +struct arizona_fll { | |
| 141 | + struct arizona *arizona; | |
| 142 | + int id; | |
| 143 | + unsigned int base; | |
| 144 | + unsigned int vco_mult; | |
| 145 | + struct completion lock; | |
| 146 | + struct completion ok; | |
| 147 | + | |
| 148 | + char lock_name[ARIZONA_FLL_NAME_LEN]; | |
| 149 | + char clock_ok_name[ARIZONA_FLL_NAME_LEN]; | |
| 150 | +}; | |
| 151 | + | |
| 152 | +extern int arizona_init_fll(struct arizona *arizona, int id, int base, | |
| 153 | + int lock_irq, int ok_irq, struct arizona_fll *fll); | |
| 154 | +extern int arizona_set_fll(struct arizona_fll *fll, int source, | |
| 155 | + unsigned int Fref, unsigned int Fout); | |
| 156 | + | |
| 157 | +extern int arizona_init_dai(struct arizona_priv *priv, int dai); | |
| 158 | + | |
| 159 | +#endif | |
| @@ -14,7 +14,6 @@ · 13 unmodified lines | ||
| 14 | 14 | |
| 15 | 15 | #include <linux/module.h> |
| 16 | 16 | #include <linux/moduleparam.h> |
| 17 | −#include <linux/version.h> | |
| 18 | 17 | #include <linux/kernel.h> |
| 19 | 18 | #include <linux/init.h> |
| 20 | 19 | #include <linux/delay.h> |
| @@ -1217,11 +1216,11 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client, · 1196 unmodified lines | ||
| 1217 | 1216 | return -ENOMEM; |
| 1218 | 1217 | cs42l52->dev = &i2c_client->dev; |
| 1219 | 1218 | |
| 1220 | − cs42l52->regmap = regmap_init_i2c(i2c_client, &cs42l52_regmap); | |
| 1219 | + cs42l52->regmap = devm_regmap_init_i2c(i2c_client, &cs42l52_regmap); | |
| 1221 | 1220 | if (IS_ERR(cs42l52->regmap)) { |
| 1222 | 1221 | ret = PTR_ERR(cs42l52->regmap); |
| 1223 | 1222 | dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); |
| 1224 | − goto err; | |
| 1223 | + return ret; | |
| 1225 | 1224 | } |
| 1226 | 1225 | |
| 1227 | 1226 | i2c_set_clientdata(i2c_client, cs42l52); |
| @@ -1243,7 +1242,7 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client, · 15 unmodified lines | ||
| 1243 | 1242 | dev_err(&i2c_client->dev, |
| 1244 | 1243 | "CS42L52 Device ID (%X). Expected %X\n", |
| 1245 | 1244 | devid, CS42L52_CHIP_ID); |
| 1246 | − goto err_regmap; | |
| 1245 | + return ret; | |
| 1247 | 1246 | } |
| 1248 | 1247 | |
| 1249 | 1248 | regcache_cache_only(cs42l52->regmap, true); |
| @@ -1251,23 +1250,13 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client, · 1 unmodified line | ||
| 1251 | 1250 | ret = snd_soc_register_codec(&i2c_client->dev, |
| 1252 | 1251 | &soc_codec_dev_cs42l52, &cs42l52_dai, 1); |
| 1253 | 1252 | if (ret < 0) |
| 1254 | − goto err_regmap; | |
| 1253 | + return ret; | |
| 1255 | 1254 | return 0; |
| 1256 | − | |
| 1257 | −err_regmap: | |
| 1258 | − regmap_exit(cs42l52->regmap); | |
| 1259 | − | |
| 1260 | −err: | |
| 1261 | − return ret; | |
| 1262 | 1255 | } |
| 1263 | 1256 | |
| 1264 | 1257 | static int cs42l52_i2c_remove(struct i2c_client *client) |
| 1265 | 1258 | { |
| 1266 | − struct cs42l52_private *cs42l52 = i2c_get_clientdata(client); | |
| 1267 | − | |
| 1268 | 1259 | snd_soc_unregister_codec(&client->dev); |
| 1269 | − regmap_exit(cs42l52->regmap); | |
| 1270 | − | |
| 1271 | 1260 | return 0; |
| 1272 | 1261 | } |
| 1273 | 1262 | |
| @@ -1362,11 +1362,11 @@ static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client, · 1361 unmodified lines | ||
| 1362 | 1362 | |
| 1363 | 1363 | i2c_set_clientdata(i2c_client, cs42l73); |
| 1364 | 1364 | |
| 1365 | − cs42l73->regmap = regmap_init_i2c(i2c_client, &cs42l73_regmap); | |
| 1365 | + cs42l73->regmap = devm_regmap_init_i2c(i2c_client, &cs42l73_regmap); | |
| 1366 | 1366 | if (IS_ERR(cs42l73->regmap)) { |
| 1367 | 1367 | ret = PTR_ERR(cs42l73->regmap); |
| 1368 | 1368 | dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); |
| 1369 | − goto err; | |
| 1369 | + return ret; | |
| 1370 | 1370 | } |
| 1371 | 1371 | /* initialize codec */ |
| 1372 | 1372 | ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_AB, ®); |
| @@ -1384,13 +1384,13 @@ static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client, · 11 unmodified lines | ||
| 1384 | 1384 | dev_err(&i2c_client->dev, |
| 1385 | 1385 | "CS42L73 Device ID (%X). Expected %X\n", |
| 1386 | 1386 | devid, CS42L73_DEVID); |
| 1387 | − goto err_regmap; | |
| 1387 | + return ret; | |
| 1388 | 1388 | } |
| 1389 | 1389 | |
| 1390 | 1390 | ret = regmap_read(cs42l73->regmap, CS42L73_REVID, ®); |
| 1391 | 1391 | if (ret < 0) { |
| 1392 | 1392 | dev_err(&i2c_client->dev, "Get Revision ID failed\n"); |
| 1393 | − goto err_regmap; | |
| 1393 | + return ret;; | |
| 1394 | 1394 | } |
| 1395 | 1395 | |
| 1396 | 1396 | dev_info(&i2c_client->dev, |
| @@ -1402,23 +1402,13 @@ static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client, · 5 unmodified lines | ||
| 1402 | 1402 | &soc_codec_dev_cs42l73, cs42l73_dai, |
| 1403 | 1403 | ARRAY_SIZE(cs42l73_dai)); |
| 1404 | 1404 | if (ret < 0) |
| 1405 | − goto err_regmap; | |
| 1405 | + return ret; | |
| 1406 | 1406 | return 0; |
| 1407 | − | |
| 1408 | −err_regmap: | |
| 1409 | − regmap_exit(cs42l73->regmap); | |
| 1410 | − | |
| 1411 | −err: | |
| 1412 | − return ret; | |
| 1413 | 1407 | } |
| 1414 | 1408 | |
| 1415 | 1409 | static __devexit int cs42l73_i2c_remove(struct i2c_client *client) |
| 1416 | 1410 | { |
| 1417 | − struct cs42l73_private *cs42l73 = i2c_get_clientdata(client); | |
| 1418 | − | |
| 1419 | 1411 | snd_soc_unregister_codec(&client->dev); |
| 1420 | − regmap_exit(cs42l73->regmap); | |
| 1421 | − | |
| 1422 | 1412 | return 0; |
| 1423 | 1413 | } |
| 1424 | 1414 | |
| @@ -0,0 +1,1627 @@ | ||
| 1 | +/* | |
| 2 | + * da732x.c --- Dialog DA732X ALSA SoC Audio Driver | |
| 3 | + * | |
| 4 | + * Copyright (C) 2012 Dialog Semiconductor GmbH | |
| 5 | + * | |
| 6 | + * Author: Michal Hajduk <Michal.Hajduk@diasemi.com> | |
| 7 | + * | |
| 8 | + * This program is free software; you can redistribute it and/or modify | |
| 9 | + * it under the terms of the GNU General Public License version 2 as | |
| 10 | + * published by the Free Software Foundation. | |
| 11 | + */ | |
| 12 | + | |
| 13 | +#include <linux/module.h> | |
| 14 | +#include <linux/moduleparam.h> | |
| 15 | +#include <linux/init.h> | |
| 16 | +#include <linux/delay.h> | |
| 17 | +#include <linux/pm.h> | |
| 18 | +#include <linux/i2c.h> | |
| 19 | +#include <linux/regmap.h> | |
| 20 | +#include <linux/platform_device.h> | |
| 21 | +#include <linux/slab.h> | |
| 22 | +#include <linux/sysfs.h> | |
| 23 | +#include <sound/core.h> | |
| 24 | +#include <sound/pcm.h> | |
| 25 | +#include <sound/pcm_params.h> | |
| 26 | +#include <sound/soc.h> | |
| 27 | +#include <sound/soc-dapm.h> | |
| 28 | +#include <sound/initval.h> | |
| 29 | +#include <sound/tlv.h> | |
| 30 | +#include <asm/div64.h> | |
| 31 | + | |
| 32 | +#include "da732x.h" | |
| 33 | +#include "da732x_reg.h" | |
| 34 | + | |
| 35 | + | |
| 36 | +struct da732x_priv { | |
| 37 | + struct regmap *regmap; | |
| 38 | + struct snd_soc_codec *codec; | |
| 39 | + | |
| 40 | + unsigned int sysclk; | |
| 41 | + bool pll_en; | |
| 42 | +}; | |
| 43 | + | |
| 44 | +/* | |
| 45 | + * da732x register cache - default settings | |
| 46 | + */ | |
| 47 | +static struct reg_default da732x_reg_cache[] = { | |
| 48 | + { DA732X_REG_REF1 , 0x02 }, | |
| 49 | + { DA732X_REG_BIAS_EN , 0x80 }, | |
| 50 | + { DA732X_REG_BIAS1 , 0x00 }, | |
| 51 | + { DA732X_REG_BIAS2 , 0x00 }, | |
| 52 | + { DA732X_REG_BIAS3 , 0x00 }, | |
| 53 | + { DA732X_REG_BIAS4 , 0x00 }, | |
| 54 | + { DA732X_REG_MICBIAS2 , 0x00 }, | |
| 55 | + { DA732X_REG_MICBIAS1 , 0x00 }, | |
| 56 | + { DA732X_REG_MICDET , 0x00 }, | |
| 57 | + { DA732X_REG_MIC1_PRE , 0x01 }, | |
| 58 | + { DA732X_REG_MIC1 , 0x40 }, | |
| 59 | + { DA732X_REG_MIC2_PRE , 0x01 }, | |
| 60 | + { DA732X_REG_MIC2 , 0x40 }, | |
| 61 | + { DA732X_REG_AUX1L , 0x75 }, | |
| 62 | + { DA732X_REG_AUX1R , 0x75 }, | |
| 63 | + { DA732X_REG_MIC3_PRE , 0x01 }, | |
| 64 | + { DA732X_REG_MIC3 , 0x40 }, | |
| 65 | + { DA732X_REG_INP_PINBIAS , 0x00 }, | |
| 66 | + { DA732X_REG_INP_ZC_EN , 0x00 }, | |
| 67 | + { DA732X_REG_INP_MUX , 0x50 }, | |
| 68 | + { DA732X_REG_HP_DET , 0x00 }, | |
| 69 | + { DA732X_REG_HPL_DAC_OFFSET , 0x00 }, | |
| 70 | + { DA732X_REG_HPL_DAC_OFF_CNTL , 0x00 }, | |
| 71 | + { DA732X_REG_HPL_OUT_OFFSET , 0x00 }, | |
| 72 | + { DA732X_REG_HPL , 0x40 }, | |
| 73 | + { DA732X_REG_HPL_VOL , 0x0F }, | |
| 74 | + { DA732X_REG_HPR_DAC_OFFSET , 0x00 }, | |
| 75 | + { DA732X_REG_HPR_DAC_OFF_CNTL , 0x00 }, | |
| 76 | + { DA732X_REG_HPR_OUT_OFFSET , 0x00 }, | |
| 77 | + { DA732X_REG_HPR , 0x40 }, | |
| 78 | + { DA732X_REG_HPR_VOL , 0x0F }, | |
| 79 | + { DA732X_REG_LIN2 , 0x4F }, | |
| 80 | + { DA732X_REG_LIN3 , 0x4F }, | |
| 81 | + { DA732X_REG_LIN4 , 0x4F }, | |
| 82 | + { DA732X_REG_OUT_ZC_EN , 0x00 }, | |
| 83 | + { DA732X_REG_HP_LIN1_GNDSEL , 0x00 }, | |
| 84 | + { DA732X_REG_CP_HP1 , 0x0C }, | |
| 85 | + { DA732X_REG_CP_HP2 , 0x03 }, | |
| 86 | + { DA732X_REG_CP_CTRL1 , 0x00 }, | |
| 87 | + { DA732X_REG_CP_CTRL2 , 0x99 }, | |
| 88 | + { DA732X_REG_CP_CTRL3 , 0x25 }, | |
| 89 | + { DA732X_REG_CP_LEVEL_MASK , 0x3F }, | |
| 90 | + { DA732X_REG_CP_DET , 0x00 }, | |
| 91 | + { DA732X_REG_CP_STATUS , 0x00 }, | |
| 92 | + { DA732X_REG_CP_THRESH1 , 0x00 }, | |
| 93 | + { DA732X_REG_CP_THRESH2 , 0x00 }, | |
| 94 | + { DA732X_REG_CP_THRESH3 , 0x00 }, | |
| 95 | + { DA732X_REG_CP_THRESH4 , 0x00 }, | |
| 96 | + { DA732X_REG_CP_THRESH5 , 0x00 }, | |
| 97 | + { DA732X_REG_CP_THRESH6 , 0x00 }, | |
| 98 | + { DA732X_REG_CP_THRESH7 , 0x00 }, | |
| 99 | + { DA732X_REG_CP_THRESH8 , 0x00 }, | |
| 100 | + { DA732X_REG_PLL_DIV_LO , 0x00 }, | |
| 101 | + { DA732X_REG_PLL_DIV_MID , 0x00 }, | |
| 102 | + { DA732X_REG_PLL_DIV_HI , 0x00 }, | |
| 103 | + { DA732X_REG_PLL_CTRL , 0x02 }, | |
| 104 | + { DA732X_REG_CLK_CTRL , 0xaa }, | |
| 105 | + { DA732X_REG_CLK_DSP , 0x07 }, | |
| 106 | + { DA732X_REG_CLK_EN1 , 0x00 }, | |
| 107 | + { DA732X_REG_CLK_EN2 , 0x00 }, | |
| 108 | + { DA732X_REG_CLK_EN3 , 0x00 }, | |
| 109 | + { DA732X_REG_CLK_EN4 , 0x00 }, | |
| 110 | + { DA732X_REG_CLK_EN5 , 0x00 }, | |
| 111 | + { DA732X_REG_AIF_MCLK , 0x00 }, | |
| 112 | + { DA732X_REG_AIFA1 , 0x02 }, | |
| 113 | + { DA732X_REG_AIFA2 , 0x00 }, | |
| 114 | + { DA732X_REG_AIFA3 , 0x08 }, | |
| 115 | + { DA732X_REG_AIFB1 , 0x02 }, | |
| 116 | + { DA732X_REG_AIFB2 , 0x00 }, | |
| 117 | + { DA732X_REG_AIFB3 , 0x08 }, | |
| 118 | + { DA732X_REG_PC_CTRL , 0xC0 }, | |
| 119 | + { DA732X_REG_DATA_ROUTE , 0x00 }, | |
| 120 | + { DA732X_REG_DSP_CTRL , 0x00 }, | |
| 121 | + { DA732X_REG_CIF_CTRL2 , 0x00 }, | |
| 122 | + { DA732X_REG_HANDSHAKE , 0x00 }, | |
| 123 | + { DA732X_REG_SPARE1_OUT , 0x00 }, | |
| 124 | + { DA732X_REG_SPARE2_OUT , 0x00 }, | |
| 125 | + { DA732X_REG_SPARE1_IN , 0x00 }, | |
| 126 | + { DA732X_REG_ADC1_PD , 0x00 }, | |
| 127 | + { DA732X_REG_ADC1_HPF , 0x00 }, | |
| 128 | + { DA732X_REG_ADC1_SEL , 0x00 }, | |
| 129 | + { DA732X_REG_ADC1_EQ12 , 0x00 }, | |
| 130 | + { DA732X_REG_ADC1_EQ34 , 0x00 }, | |
| 131 | + { DA732X_REG_ADC1_EQ5 , 0x00 }, | |
| 132 | + { DA732X_REG_ADC2_PD , 0x00 }, | |
| 133 | + { DA732X_REG_ADC2_HPF , 0x00 }, | |
| 134 | + { DA732X_REG_ADC2_SEL , 0x00 }, | |
| 135 | + { DA732X_REG_ADC2_EQ12 , 0x00 }, | |
| 136 | + { DA732X_REG_ADC2_EQ34 , 0x00 }, | |
| 137 | + { DA732X_REG_ADC2_EQ5 , 0x00 }, | |
| 138 | + { DA732X_REG_DAC1_HPF , 0x00 }, | |
| 139 | + { DA732X_REG_DAC1_L_VOL , 0x00 }, | |
| 140 | + { DA732X_REG_DAC1_R_VOL , 0x00 }, | |
| 141 | + { DA732X_REG_DAC1_SEL , 0x00 }, | |
| 142 | + { DA732X_REG_DAC1_SOFTMUTE , 0x00 }, | |
| 143 | + { DA732X_REG_DAC1_EQ12 , 0x00 }, | |
| 144 | + { DA732X_REG_DAC1_EQ34 , 0x00 }, | |
| 145 | + { DA732X_REG_DAC1_EQ5 , 0x00 }, | |
| 146 | + { DA732X_REG_DAC2_HPF , 0x00 }, | |
| 147 | + { DA732X_REG_DAC2_L_VOL , 0x00 }, | |
| 148 | + { DA732X_REG_DAC2_R_VOL , 0x00 }, | |
| 149 | + { DA732X_REG_DAC2_SEL , 0x00 }, | |
| 150 | + { DA732X_REG_DAC2_SOFTMUTE , 0x00 }, | |
| 151 | + { DA732X_REG_DAC2_EQ12 , 0x00 }, | |
| 152 | + { DA732X_REG_DAC2_EQ34 , 0x00 }, | |
| 153 | + { DA732X_REG_DAC2_EQ5 , 0x00 }, | |
| 154 | + { DA732X_REG_DAC3_HPF , 0x00 }, | |
| 155 | + { DA732X_REG_DAC3_VOL , 0x00 }, | |
| 156 | + { DA732X_REG_DAC3_SEL , 0x00 }, | |
| 157 | + { DA732X_REG_DAC3_SOFTMUTE , 0x00 }, | |
| 158 | + { DA732X_REG_DAC3_EQ12 , 0x00 }, | |
| 159 | + { DA732X_REG_DAC3_EQ34 , 0x00 }, | |
| 160 | + { DA732X_REG_DAC3_EQ5 , 0x00 }, | |
| 161 | + { DA732X_REG_BIQ_BYP , 0x00 }, | |
| 162 | + { DA732X_REG_DMA_CMD , 0x00 }, | |
| 163 | + { DA732X_REG_DMA_ADDR0 , 0x00 }, | |
| 164 | + { DA732X_REG_DMA_ADDR1 , 0x00 }, | |
| 165 | + { DA732X_REG_DMA_DATA0 , 0x00 }, | |
| 166 | + { DA732X_REG_DMA_DATA1 , 0x00 }, | |
| 167 | + { DA732X_REG_DMA_DATA2 , 0x00 }, | |
| 168 | + { DA732X_REG_DMA_DATA3 , 0x00 }, | |
| 169 | + { DA732X_REG_UNLOCK , 0x00 }, | |
| 170 | +}; | |
| 171 | + | |
| 172 | +static inline int da732x_get_input_div(struct snd_soc_codec *codec, int sysclk) | |
| 173 | +{ | |
| 174 | + int val; | |
| 175 | + int ret; | |
| 176 | + | |
| 177 | + if (sysclk < DA732X_MCLK_10MHZ) { | |
| 178 | + val = DA732X_MCLK_RET_0_10MHZ; | |
| 179 | + ret = DA732X_MCLK_VAL_0_10MHZ; | |
| 180 | + } else if ((sysclk >= DA732X_MCLK_10MHZ) && | |
| 181 | + (sysclk < DA732X_MCLK_20MHZ)) { | |
| 182 | + val = DA732X_MCLK_RET_10_20MHZ; | |
| 183 | + ret = DA732X_MCLK_VAL_10_20MHZ; | |
| 184 | + } else if ((sysclk >= DA732X_MCLK_20MHZ) && | |
| 185 | + (sysclk < DA732X_MCLK_40MHZ)) { | |
| 186 | + val = DA732X_MCLK_RET_20_40MHZ; | |
| 187 | + ret = DA732X_MCLK_VAL_20_40MHZ; | |
| 188 | + } else if ((sysclk >= DA732X_MCLK_40MHZ) && | |
| 189 | + (sysclk <= DA732X_MCLK_54MHZ)) { | |
| 190 | + val = DA732X_MCLK_RET_40_54MHZ; | |
| 191 | + ret = DA732X_MCLK_VAL_40_54MHZ; | |
| 192 | + } else { | |
| 193 | + return -EINVAL; | |
| 194 | + } | |
| 195 | + | |
| 196 | + snd_soc_write(codec, DA732X_REG_PLL_CTRL, val); | |
| 197 | + | |
| 198 | + return ret; | |
| 199 | +} | |
| 200 | + | |
| 201 | +static void da732x_set_charge_pump(struct snd_soc_codec *codec, int state) | |
| 202 | +{ | |
| 203 | + switch (state) { | |
| 204 | + case DA732X_ENABLE_CP: | |
| 205 | + snd_soc_write(codec, DA732X_REG_CLK_EN2, DA732X_CP_CLK_EN); | |
| 206 | + snd_soc_write(codec, DA732X_REG_CP_HP2, DA732X_HP_CP_EN | | |
| 207 | + DA732X_HP_CP_REG | DA732X_HP_CP_PULSESKIP); | |
| 208 | + snd_soc_write(codec, DA732X_REG_CP_CTRL1, DA732X_CP_EN | | |
| 209 | + DA732X_CP_CTRL_CPVDD1); | |
| 210 | + snd_soc_write(codec, DA732X_REG_CP_CTRL2, | |
| 211 | + DA732X_CP_MANAGE_MAGNITUDE | DA732X_CP_BOOST); | |
| 212 | + snd_soc_write(codec, DA732X_REG_CP_CTRL3, DA732X_CP_1MHZ); | |
| 213 | + break; | |
| 214 | + case DA732X_DISABLE_CP: | |
| 215 | + snd_soc_write(codec, DA732X_REG_CLK_EN2, DA732X_CP_CLK_DIS); | |
| 216 | + snd_soc_write(codec, DA732X_REG_CP_HP2, DA732X_HP_CP_DIS); | |
| 217 | + snd_soc_write(codec, DA732X_REG_CP_CTRL1, DA723X_CP_DIS); | |
| 218 | + break; | |
| 219 | + default: | |
| 220 | + pr_err(KERN_ERR "Wrong charge pump state\n"); | |
| 221 | + break; | |
| 222 | + } | |
| 223 | +} | |
| 224 | + | |
| 225 | +static const DECLARE_TLV_DB_SCALE(mic_boost_tlv, DA732X_MIC_PRE_VOL_DB_MIN, | |
| 226 | + DA732X_MIC_PRE_VOL_DB_INC, 0); | |
| 227 | + | |
| 228 | +static const DECLARE_TLV_DB_SCALE(mic_pga_tlv, DA732X_MIC_VOL_DB_MIN, | |
| 229 | + DA732X_MIC_VOL_DB_INC, 0); | |
| 230 | + | |
| 231 | +static const DECLARE_TLV_DB_SCALE(aux_pga_tlv, DA732X_AUX_VOL_DB_MIN, | |
| 232 | + DA732X_AUX_VOL_DB_INC, 0); | |
| 233 | + | |
| 234 | +static const DECLARE_TLV_DB_SCALE(hp_pga_tlv, DA732X_HP_VOL_DB_MIN, | |
| 235 | + DA732X_AUX_VOL_DB_INC, 0); | |
| 236 | + | |
| 237 | +static const DECLARE_TLV_DB_SCALE(lin2_pga_tlv, DA732X_LIN2_VOL_DB_MIN, | |
| 238 | + DA732X_LIN2_VOL_DB_INC, 0); | |
| 239 | + | |
| 240 | +static const DECLARE_TLV_DB_SCALE(lin3_pga_tlv, DA732X_LIN3_VOL_DB_MIN, | |
| 241 | + DA732X_LIN3_VOL_DB_INC, 0); | |
| 242 | + | |
| 243 | +static const DECLARE_TLV_DB_SCALE(lin4_pga_tlv, DA732X_LIN4_VOL_DB_MIN, | |
| 244 | + DA732X_LIN4_VOL_DB_INC, 0); | |
| 245 | + | |
| 246 | +static const DECLARE_TLV_DB_SCALE(adc_pga_tlv, DA732X_ADC_VOL_DB_MIN, | |
| 247 | + DA732X_ADC_VOL_DB_INC, 0); | |
| 248 | + | |
| 249 | +static const DECLARE_TLV_DB_SCALE(dac_pga_tlv, DA732X_DAC_VOL_DB_MIN, | |
| 250 | + DA732X_DAC_VOL_DB_INC, 0); | |
| 251 | + | |
| 252 | +static const DECLARE_TLV_DB_SCALE(eq_band_pga_tlv, DA732X_EQ_BAND_VOL_DB_MIN, | |
| 253 | + DA732X_EQ_BAND_VOL_DB_INC, 0); | |
| 254 | + | |
| 255 | +static const DECLARE_TLV_DB_SCALE(eq_overall_tlv, DA732X_EQ_OVERALL_VOL_DB_MIN, | |
| 256 | + DA732X_EQ_OVERALL_VOL_DB_INC, 0); | |
| 257 | + | |
| 258 | +/* High Pass Filter */ | |
| 259 | +static const char *da732x_hpf_mode[] = { | |
| 260 | + "Disable", "Music", "Voice", | |
| 261 | +}; | |
| 262 | + | |
| 263 | +static const char *da732x_hpf_music[] = { | |
| 264 | + "1.8Hz", "3.75Hz", "7.5Hz", "15Hz", | |
| 265 | +}; | |
| 266 | + | |
| 267 | +static const char *da732x_hpf_voice[] = { | |
| 268 | + "2.5Hz", "25Hz", "50Hz", "100Hz", | |
| 269 | + "150Hz", "200Hz", "300Hz", "400Hz" | |
| 270 | +}; | |
| 271 | + | |
| 272 | +static const struct soc_enum da732x_dac1_hpf_mode_enum[] = { | |
| 273 | + SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MODE_SHIFT, | |
| 274 | + DA732X_HPF_MODE_MAX, da732x_hpf_mode) | |
| 275 | +}; | |
| 276 | + | |
| 277 | +static const struct soc_enum da732x_dac2_hpf_mode_enum[] = { | |
| 278 | + SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MODE_SHIFT, | |
| 279 | + DA732X_HPF_MODE_MAX, da732x_hpf_mode) | |
| 280 | +}; | |
| 281 | + | |
| 282 | +static const struct soc_enum da732x_dac3_hpf_mode_enum[] = { | |
| 283 | + SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MODE_SHIFT, | |
| 284 | + DA732X_HPF_MODE_MAX, da732x_hpf_mode) | |
| 285 | +}; | |
| 286 | + | |
| 287 | +static const struct soc_enum da732x_adc1_hpf_mode_enum[] = { | |
| 288 | + SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MODE_SHIFT, | |
| 289 | + DA732X_HPF_MODE_MAX, da732x_hpf_mode) | |
| 290 | +}; | |
| 291 | + | |
| 292 | +static const struct soc_enum da732x_adc2_hpf_mode_enum[] = { | |
| 293 | + SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MODE_SHIFT, | |
| 294 | + DA732X_HPF_MODE_MAX, da732x_hpf_mode) | |
| 295 | +}; | |
| 296 | + | |
| 297 | +static const struct soc_enum da732x_dac1_hp_filter_enum[] = { | |
| 298 | + SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MUSIC_SHIFT, | |
| 299 | + DA732X_HPF_MUSIC_MAX, da732x_hpf_music) | |
| 300 | +}; | |
| 301 | + | |
| 302 | +static const struct soc_enum da732x_dac2_hp_filter_enum[] = { | |
| 303 | + SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MUSIC_SHIFT, | |
| 304 | + DA732X_HPF_MUSIC_MAX, da732x_hpf_music) | |
| 305 | +}; | |
| 306 | + | |
| 307 | +static const struct soc_enum da732x_dac3_hp_filter_enum[] = { | |
| 308 | + SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MUSIC_SHIFT, | |
| 309 | + DA732X_HPF_MUSIC_MAX, da732x_hpf_music) | |
| 310 | +}; | |
| 311 | + | |
| 312 | +static const struct soc_enum da732x_adc1_hp_filter_enum[] = { | |
| 313 | + SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MUSIC_SHIFT, | |
| 314 | + DA732X_HPF_MUSIC_MAX, da732x_hpf_music) | |
| 315 | +}; | |
| 316 | + | |
| 317 | +static const struct soc_enum da732x_adc2_hp_filter_enum[] = { | |
| 318 | + SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MUSIC_SHIFT, | |
| 319 | + DA732X_HPF_MUSIC_MAX, da732x_hpf_music) | |
| 320 | +}; | |
| 321 | + | |
| 322 | +static const struct soc_enum da732x_dac1_voice_filter_enum[] = { | |
| 323 | + SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_VOICE_SHIFT, | |
| 324 | + DA732X_HPF_VOICE_MAX, da732x_hpf_voice) | |
| 325 | +}; | |
| 326 | + | |
| 327 | +static const struct soc_enum da732x_dac2_voice_filter_enum[] = { | |
| 328 | + SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_VOICE_SHIFT, | |
| 329 | + DA732X_HPF_VOICE_MAX, da732x_hpf_voice) | |
| 330 | +}; | |
| 331 | + | |
| 332 | +static const struct soc_enum da732x_dac3_voice_filter_enum[] = { | |
| 333 | + SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_VOICE_SHIFT, | |
| 334 | + DA732X_HPF_VOICE_MAX, da732x_hpf_voice) | |
| 335 | +}; | |
| 336 | + | |
| 337 | +static const struct soc_enum da732x_adc1_voice_filter_enum[] = { | |
| 338 | + SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_VOICE_SHIFT, | |
| 339 | + DA732X_HPF_VOICE_MAX, da732x_hpf_voice) | |
| 340 | +}; | |
| 341 | + | |
| 342 | +static const struct soc_enum da732x_adc2_voice_filter_enum[] = { | |
| 343 | + SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_VOICE_SHIFT, | |
| 344 | + DA732X_HPF_VOICE_MAX, da732x_hpf_voice) | |
| 345 | +}; | |
| 346 | + | |
| 347 | + | |
| 348 | +static int da732x_hpf_set(struct snd_kcontrol *kcontrol, | |
| 349 | + struct snd_ctl_elem_value *ucontrol) | |
| 350 | +{ | |
| 351 | + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | |
| 352 | + struct soc_enum *enum_ctrl = (struct soc_enum *)kcontrol->private_value; | |
| 353 | + unsigned int reg = enum_ctrl->reg; | |
| 354 | + unsigned int sel = ucontrol->value.integer.value[0]; | |
| 355 | + unsigned int bits; | |
| 356 | + | |
| 357 | + switch (sel) { | |
| 358 | + case DA732X_HPF_DISABLED: | |
| 359 | + bits = DA732X_HPF_DIS; | |
| 360 | + break; | |
| 361 | + case DA732X_HPF_VOICE: | |
| 362 | + bits = DA732X_HPF_VOICE_EN; | |
| 363 | + break; | |
| 364 | + case DA732X_HPF_MUSIC: | |
| 365 | + bits = DA732X_HPF_MUSIC_EN; | |
| 366 | + break; | |
| 367 | + default: | |
| 368 | + return -EINVAL; | |
| 369 | + } | |
| 370 | + | |
| 371 | + snd_soc_update_bits(codec, reg, DA732X_HPF_MASK, bits); | |
| 372 | + | |
| 373 | + return 0; | |
| 374 | +} | |
| 375 | + | |
| 376 | +static int da732x_hpf_get(struct snd_kcontrol *kcontrol, | |
| 377 | + struct snd_ctl_elem_value *ucontrol) | |
| 378 | +{ | |
| 379 | + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | |
| 380 | + struct soc_enum *enum_ctrl = (struct soc_enum *)kcontrol->private_value; | |
| 381 | + unsigned int reg = enum_ctrl->reg; | |
| 382 | + int val; | |
| 383 | + | |
| 384 | + val = snd_soc_read(codec, reg) & DA732X_HPF_MASK; | |
| 385 | + | |
| 386 | + switch (val) { | |
| 387 | + case DA732X_HPF_VOICE_EN: | |
| 388 | + ucontrol->value.integer.value[0] = DA732X_HPF_VOICE; | |
| 389 | + break; | |
| 390 | + case DA732X_HPF_MUSIC_EN: | |
| 391 | + ucontrol->value.integer.value[0] = DA732X_HPF_MUSIC; | |
| 392 | + break; | |
| 393 | + default: | |
| 394 | + ucontrol->value.integer.value[0] = DA732X_HPF_DISABLED; | |
| 395 | + break; | |
| 396 | + } | |
| 397 | + | |
| 398 | + return 0; | |
| 399 | +} | |
| 400 | + | |
| 401 | +static const struct snd_kcontrol_new da732x_snd_controls[] = { | |
| 402 | + /* Input PGAs */ | |
| 403 | + SOC_SINGLE_RANGE_TLV("MIC1 Boost Volume", DA732X_REG_MIC1_PRE, | |
| 404 | + DA732X_MICBOOST_SHIFT, DA732X_MICBOOST_MIN, | |
| 405 | + DA732X_MICBOOST_MAX, 0, mic_boost_tlv), | |
| 406 | + SOC_SINGLE_RANGE_TLV("MIC2 Boost Volume", DA732X_REG_MIC2_PRE, | |
| 407 | + DA732X_MICBOOST_SHIFT, DA732X_MICBOOST_MIN, | |
| 408 | + DA732X_MICBOOST_MAX, 0, mic_boost_tlv), | |
| 409 | + SOC_SINGLE_RANGE_TLV("MIC3 Boost Volume", DA732X_REG_MIC3_PRE, | |
| 410 | + DA732X_MICBOOST_SHIFT, DA732X_MICBOOST_MIN, | |
| 411 | + DA732X_MICBOOST_MAX, 0, mic_boost_tlv), | |
| 412 | + | |
| 413 | + /* MICs */ | |
| 414 | + SOC_SINGLE("MIC1 Switch", DA732X_REG_MIC1, DA732X_MIC_MUTE_SHIFT, | |
| 415 | + DA732X_SWITCH_MAX, DA732X_INVERT), | |
| 416 | + SOC_SINGLE_RANGE_TLV("MIC1 Volume", DA732X_REG_MIC1, | |
| 417 | + DA732X_MIC_VOL_SHIFT, DA732X_MIC_VOL_VAL_MIN, | |
| 418 | + DA732X_MIC_VOL_VAL_MAX, 0, mic_pga_tlv), | |
| 419 | + SOC_SINGLE("MIC2 Switch", DA732X_REG_MIC2, DA732X_MIC_MUTE_SHIFT, | |
| 420 | + DA732X_SWITCH_MAX, DA732X_INVERT), | |
| 421 | + SOC_SINGLE_RANGE_TLV("MIC2 Volume", DA732X_REG_MIC2, | |
| 422 | + DA732X_MIC_VOL_SHIFT, DA732X_MIC_VOL_VAL_MIN, | |
| 423 | + DA732X_MIC_VOL_VAL_MAX, 0, mic_pga_tlv), | |
| 424 | + SOC_SINGLE("MIC3 Switch", DA732X_REG_MIC3, DA732X_MIC_MUTE_SHIFT, | |
| 425 | + DA732X_SWITCH_MAX, DA732X_INVERT), | |
| 426 | + SOC_SINGLE_RANGE_TLV("MIC3 Volume", DA732X_REG_MIC3, | |
| 427 | + DA732X_MIC_VOL_SHIFT, DA732X_MIC_VOL_VAL_MIN, | |
| 428 | + DA732X_MIC_VOL_VAL_MAX, 0, mic_pga_tlv), | |
| 429 | + | |
| 430 | + /* AUXs */ | |
| 431 | + SOC_SINGLE("AUX1L Switch", DA732X_REG_AUX1L, DA732X_AUX_MUTE_SHIFT, | |
| 432 | + DA732X_SWITCH_MAX, DA732X_INVERT), | |
| 433 | + SOC_SINGLE_TLV("AUX1L Volume", DA732X_REG_AUX1L, | |
| 434 | + DA732X_AUX_VOL_SHIFT, DA732X_AUX_VOL_VAL_MAX, | |
| 435 | + DA732X_NO_INVERT, aux_pga_tlv), | |
| 436 | + SOC_SINGLE("AUX1R Switch", DA732X_REG_AUX1R, DA732X_AUX_MUTE_SHIFT, | |
| 437 | + DA732X_SWITCH_MAX, DA732X_INVERT), | |
| 438 | + SOC_SINGLE_TLV("AUX1R Volume", DA732X_REG_AUX1R, | |
| 439 | + DA732X_AUX_VOL_SHIFT, DA732X_AUX_VOL_VAL_MAX, | |
| 440 | + DA732X_NO_INVERT, aux_pga_tlv), | |
| 441 | + | |
| 442 | + /* ADCs */ | |
| 443 | + SOC_DOUBLE_TLV("ADC1 Volume", DA732X_REG_ADC1_SEL, | |
| 444 | + DA732X_ADCL_VOL_SHIFT, DA732X_ADCR_VOL_SHIFT, | |
| 445 | + DA732X_ADC_VOL_VAL_MAX, DA732X_INVERT, adc_pga_tlv), | |
| 446 | + | |
| 447 | + SOC_DOUBLE_TLV("ADC2 Volume", DA732X_REG_ADC2_SEL, | |
| 448 | + DA732X_ADCL_VOL_SHIFT, DA732X_ADCR_VOL_SHIFT, | |
| 449 | + DA732X_ADC_VOL_VAL_MAX, DA732X_INVERT, adc_pga_tlv), | |
| 450 | + | |
| 451 | + /* DACs */ | |
| 452 | + SOC_DOUBLE("Digital Playback DAC12 Switch", DA732X_REG_DAC1_SEL, | |
| 453 | + DA732X_DACL_MUTE_SHIFT, DA732X_DACR_MUTE_SHIFT, | |
| 454 | + DA732X_SWITCH_MAX, DA732X_INVERT), | |
| 455 | + SOC_DOUBLE_R_TLV("Digital Playback DAC12 Volume", DA732X_REG_DAC1_L_VOL, | |
| 456 | + DA732X_REG_DAC1_R_VOL, DA732X_DAC_VOL_SHIFT, | |
| 457 | + DA732X_DAC_VOL_VAL_MAX, DA732X_INVERT, dac_pga_tlv), | |
| 458 | + SOC_SINGLE("Digital Playback DAC3 Switch", DA732X_REG_DAC2_SEL, | |
| 459 | + DA732X_DACL_MUTE_SHIFT, DA732X_SWITCH_MAX, DA732X_INVERT), | |
| 460 | + SOC_SINGLE_TLV("Digital Playback DAC3 Volume", DA732X_REG_DAC2_L_VOL, | |
| 461 | + DA732X_DAC_VOL_SHIFT, DA732X_DAC_VOL_VAL_MAX, | |
| 462 | + DA732X_INVERT, dac_pga_tlv), | |
| 463 | + SOC_SINGLE("Digital Playback DAC4 Switch", DA732X_REG_DAC2_SEL, | |
| 464 | + DA732X_DACR_MUTE_SHIFT, DA732X_SWITCH_MAX, DA732X_INVERT), | |
| 465 | + SOC_SINGLE_TLV("Digital Playback DAC4 Volume", DA732X_REG_DAC2_R_VOL, | |
| 466 | + DA732X_DAC_VOL_SHIFT, DA732X_DAC_VOL_VAL_MAX, | |
| 467 | + DA732X_INVERT, dac_pga_tlv), | |
| 468 | + SOC_SINGLE("Digital Playback DAC5 Switch", DA732X_REG_DAC3_SEL, | |
| 469 | + DA732X_DACL_MUTE_SHIFT, DA732X_SWITCH_MAX, DA732X_INVERT), | |
| 470 | + SOC_SINGLE_TLV("Digital Playback DAC5 Volume", DA732X_REG_DAC3_VOL, | |
| 471 | + DA732X_DAC_VOL_SHIFT, DA732X_DAC_VOL_VAL_MAX, | |
| 472 | + DA732X_INVERT, dac_pga_tlv), | |
| 473 | + | |
| 474 | + /* High Pass Filters */ | |
| 475 | + SOC_ENUM_EXT("DAC1 High Pass Filter Mode", | |
| 476 | + da732x_dac1_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set), | |
| 477 | + SOC_ENUM("DAC1 High Pass Filter", da732x_dac1_hp_filter_enum), | |
| 478 | + SOC_ENUM("DAC1 Voice Filter", da732x_dac1_voice_filter_enum), | |
| 479 | + | |
| 480 | + SOC_ENUM_EXT("DAC2 High Pass Filter Mode", | |
| 481 | + da732x_dac2_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set), | |
| 482 | + SOC_ENUM("DAC2 High Pass Filter", da732x_dac2_hp_filter_enum), | |
| 483 | + SOC_ENUM("DAC2 Voice Filter", da732x_dac2_voice_filter_enum), | |
| 484 | + | |
| 485 | + SOC_ENUM_EXT("DAC3 High Pass Filter Mode", | |
| 486 | + da732x_dac3_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set), | |
| 487 | + SOC_ENUM("DAC3 High Pass Filter", da732x_dac3_hp_filter_enum), | |
| 488 | + SOC_ENUM("DAC3 Filter Mode", da732x_dac3_voice_filter_enum), | |
| 489 | + | |
| 490 | + SOC_ENUM_EXT("ADC1 High Pass Filter Mode", | |
| 491 | + da732x_adc1_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set), | |
| 492 | + SOC_ENUM("ADC1 High Pass Filter", da732x_adc1_hp_filter_enum), | |
| 493 | + SOC_ENUM("ADC1 Voice Filter", da732x_adc1_voice_filter_enum), | |
| 494 | + | |
| 495 | + SOC_ENUM_EXT("ADC2 High Pass Filter Mode", | |
| 496 | + da732x_adc2_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set), | |
| 497 | + SOC_ENUM("ADC2 High Pass Filter", da732x_adc2_hp_filter_enum), | |
| 498 | + SOC_ENUM("ADC2 Voice Filter", da732x_adc2_voice_filter_enum), | |
| 499 | + | |
| 500 | + /* Equalizers */ | |
| 501 | + SOC_SINGLE("ADC1 EQ Switch", DA732X_REG_ADC1_EQ5, | |
| 502 | + DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT), | |
| 503 | + SOC_SINGLE_TLV("ADC1 EQ Band 1 Volume", DA732X_REG_ADC1_EQ12, | |
| 504 | + DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 505 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 506 | + SOC_SINGLE_TLV("ADC1 EQ Band 2 Volume", DA732X_REG_ADC1_EQ12, | |
| 507 | + DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 508 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 509 | + SOC_SINGLE_TLV("ADC1 EQ Band 3 Volume", DA732X_REG_ADC1_EQ34, | |
| 510 | + DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 511 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 512 | + SOC_SINGLE_TLV("ADC1 EQ Band 4 Volume", DA732X_REG_ADC1_EQ34, | |
| 513 | + DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 514 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 515 | + SOC_SINGLE_TLV("ADC1 EQ Band 5 Volume", DA732X_REG_ADC1_EQ5, | |
| 516 | + DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 517 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 518 | + SOC_SINGLE_TLV("ADC1 EQ Overall Volume", DA732X_REG_ADC1_EQ5, | |
| 519 | + DA732X_EQ_OVERALL_SHIFT, DA732X_EQ_OVERALL_VOL_VAL_MAX, | |
| 520 | + DA732X_INVERT, eq_overall_tlv), | |
| 521 | + | |
| 522 | + SOC_SINGLE("ADC2 EQ Switch", DA732X_REG_ADC2_EQ5, | |
| 523 | + DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT), | |
| 524 | + SOC_SINGLE_TLV("ADC2 EQ Band 1 Volume", DA732X_REG_ADC2_EQ12, | |
| 525 | + DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 526 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 527 | + SOC_SINGLE_TLV("ADC2 EQ Band 2 Volume", DA732X_REG_ADC2_EQ12, | |
| 528 | + DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 529 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 530 | + SOC_SINGLE_TLV("ADC2 EQ Band 3 Volume", DA732X_REG_ADC2_EQ34, | |
| 531 | + DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 532 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 533 | + SOC_SINGLE_TLV("ACD2 EQ Band 4 Volume", DA732X_REG_ADC2_EQ34, | |
| 534 | + DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 535 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 536 | + SOC_SINGLE_TLV("ACD2 EQ Band 5 Volume", DA732X_REG_ADC2_EQ5, | |
| 537 | + DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 538 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 539 | + SOC_SINGLE_TLV("ADC2 EQ Overall Volume", DA732X_REG_ADC1_EQ5, | |
| 540 | + DA732X_EQ_OVERALL_SHIFT, DA732X_EQ_OVERALL_VOL_VAL_MAX, | |
| 541 | + DA732X_INVERT, eq_overall_tlv), | |
| 542 | + | |
| 543 | + SOC_SINGLE("DAC1 EQ Switch", DA732X_REG_DAC1_EQ5, | |
| 544 | + DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT), | |
| 545 | + SOC_SINGLE_TLV("DAC1 EQ Band 1 Volume", DA732X_REG_DAC1_EQ12, | |
| 546 | + DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 547 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 548 | + SOC_SINGLE_TLV("DAC1 EQ Band 2 Volume", DA732X_REG_DAC1_EQ12, | |
| 549 | + DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 550 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 551 | + SOC_SINGLE_TLV("DAC1 EQ Band 3 Volume", DA732X_REG_DAC1_EQ34, | |
| 552 | + DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 553 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 554 | + SOC_SINGLE_TLV("DAC1 EQ Band 4 Volume", DA732X_REG_DAC1_EQ34, | |
| 555 | + DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 556 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 557 | + SOC_SINGLE_TLV("DAC1 EQ Band 5 Volume", DA732X_REG_DAC1_EQ5, | |
| 558 | + DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 559 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 560 | + | |
| 561 | + SOC_SINGLE("DAC2 EQ Switch", DA732X_REG_DAC2_EQ5, | |
| 562 | + DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT), | |
| 563 | + SOC_SINGLE_TLV("DAC2 EQ Band 1 Volume", DA732X_REG_DAC2_EQ12, | |
| 564 | + DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 565 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 566 | + SOC_SINGLE_TLV("DAC2 EQ Band 2 Volume", DA732X_REG_DAC2_EQ12, | |
| 567 | + DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 568 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 569 | + SOC_SINGLE_TLV("DAC2 EQ Band 3 Volume", DA732X_REG_DAC2_EQ34, | |
| 570 | + DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 571 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 572 | + SOC_SINGLE_TLV("DAC2 EQ Band 4 Volume", DA732X_REG_DAC2_EQ34, | |
| 573 | + DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 574 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 575 | + SOC_SINGLE_TLV("DAC2 EQ Band 5 Volume", DA732X_REG_DAC2_EQ5, | |
| 576 | + DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 577 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 578 | + | |
| 579 | + SOC_SINGLE("DAC3 EQ Switch", DA732X_REG_DAC3_EQ5, | |
| 580 | + DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT), | |
| 581 | + SOC_SINGLE_TLV("DAC3 EQ Band 1 Volume", DA732X_REG_DAC3_EQ12, | |
| 582 | + DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 583 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 584 | + SOC_SINGLE_TLV("DAC3 EQ Band 2 Volume", DA732X_REG_DAC3_EQ12, | |
| 585 | + DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 586 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 587 | + SOC_SINGLE_TLV("DAC3 EQ Band 3 Volume", DA732X_REG_DAC3_EQ34, | |
| 588 | + DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 589 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 590 | + SOC_SINGLE_TLV("DAC3 EQ Band 4 Volume", DA732X_REG_DAC3_EQ34, | |
| 591 | + DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 592 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 593 | + SOC_SINGLE_TLV("DAC3 EQ Band 5 Volume", DA732X_REG_DAC3_EQ5, | |
| 594 | + DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX, | |
| 595 | + DA732X_INVERT, eq_band_pga_tlv), | |
| 596 | + | |
| 597 | + /* Lineout 2 Reciever*/ | |
| 598 | + SOC_SINGLE("Lineout 2 Switch", DA732X_REG_LIN2, DA732X_LOUT_MUTE_SHIFT, | |
| 599 | + DA732X_SWITCH_MAX, DA732X_INVERT), | |
| 600 | + SOC_SINGLE_TLV("Lineout 2 Volume", DA732X_REG_LIN2, | |
| 601 | + DA732X_LOUT_VOL_SHIFT, DA732X_LOUT_VOL_VAL_MAX, | |
| 602 | + DA732X_NO_INVERT, lin2_pga_tlv), | |
| 603 | + | |
| 604 | + /* Lineout 3 SPEAKER*/ | |
| 605 | + SOC_SINGLE("Lineout 3 Switch", DA732X_REG_LIN3, DA732X_LOUT_MUTE_SHIFT, | |
| 606 | + DA732X_SWITCH_MAX, DA732X_INVERT), | |
| 607 | + SOC_SINGLE_TLV("Lineout 3 Volume", DA732X_REG_LIN3, | |
| 608 | + DA732X_LOUT_VOL_SHIFT, DA732X_LOUT_VOL_VAL_MAX, | |
| 609 | + DA732X_NO_INVERT, lin3_pga_tlv), | |
| 610 | + | |
| 611 | + /* Lineout 4 */ | |
| 612 | + SOC_SINGLE("Lineout 4 Switch", DA732X_REG_LIN4, DA732X_LOUT_MUTE_SHIFT, | |
| 613 | + DA732X_SWITCH_MAX, DA732X_INVERT), | |
| 614 | + SOC_SINGLE_TLV("Lineout 4 Volume", DA732X_REG_LIN4, | |
| 615 | + DA732X_LOUT_VOL_SHIFT, DA732X_LOUT_VOL_VAL_MAX, | |
| 616 | + DA732X_NO_INVERT, lin4_pga_tlv), | |
| 617 | + | |
| 618 | + /* Headphones */ | |
| 619 | + SOC_DOUBLE_R("Headphone Switch", DA732X_REG_HPR, DA732X_REG_HPL, | |
| 620 | + DA732X_HP_MUTE_SHIFT, DA732X_SWITCH_MAX, DA732X_INVERT), | |
| 621 | + SOC_DOUBLE_R_TLV("Headphone Volume", DA732X_REG_HPL_VOL, | |
| 622 | + DA732X_REG_HPR_VOL, DA732X_HP_VOL_SHIFT, | |
| 623 | + DA732X_HP_VOL_VAL_MAX, DA732X_NO_INVERT, hp_pga_tlv), | |
| 624 | +}; | |
| 625 | + | |
| 626 | +static int da732x_adc_event(struct snd_soc_dapm_widget *w, | |
| 627 | + struct snd_kcontrol *kcontrol, int event) | |
| 628 | +{ | |
| 629 | + struct snd_soc_codec *codec = w->codec; | |
| 630 | + | |
| 631 | + switch (event) { | |
| 632 | + case SND_SOC_DAPM_POST_PMU: | |
| 633 | + switch (w->reg) { | |
| 634 | + case DA732X_REG_ADC1_PD: | |
| 635 | + snd_soc_update_bits(codec, DA732X_REG_CLK_EN3, | |
| 636 | + DA732X_ADCA_BB_CLK_EN, | |
| 637 | + DA732X_ADCA_BB_CLK_EN); | |
| 638 | + break; | |
| 639 | + case DA732X_REG_ADC2_PD: | |
| 640 | + snd_soc_update_bits(codec, DA732X_REG_CLK_EN3, | |
| 641 | + DA732X_ADCC_BB_CLK_EN, | |
| 642 | + DA732X_ADCC_BB_CLK_EN); | |
| 643 | + break; | |
| 644 | + default: | |
| 645 | + return -EINVAL; | |
| 646 | + } | |
| 647 | + | |
| 648 | + snd_soc_update_bits(codec, w->reg, DA732X_ADC_RST_MASK, | |
| 649 | + DA732X_ADC_SET_ACT); | |
| 650 | + snd_soc_update_bits(codec, w->reg, DA732X_ADC_PD_MASK, | |
| 651 | + DA732X_ADC_ON); | |
| 652 | + break; | |
| 653 | + case SND_SOC_DAPM_POST_PMD: | |
| 654 | + snd_soc_update_bits(codec, w->reg, DA732X_ADC_PD_MASK, | |
| 655 | + DA732X_ADC_OFF); | |
| 656 | + snd_soc_update_bits(codec, w->reg, DA732X_ADC_RST_MASK, | |
| 657 | + DA732X_ADC_SET_RST); | |
| 658 | + | |
| 659 | + switch (w->reg) { | |
| 660 | + case DA732X_REG_ADC1_PD: | |
| 661 | + snd_soc_update_bits(codec, DA732X_REG_CLK_EN3, | |
| 662 | + DA732X_ADCA_BB_CLK_EN, 0); | |
| 663 | + break; | |
| 664 | + case DA732X_REG_ADC2_PD: | |
| 665 | + snd_soc_update_bits(codec, DA732X_REG_CLK_EN3, | |
| 666 | + DA732X_ADCC_BB_CLK_EN, 0); | |
| 667 | + break; | |
| 668 | + default: | |
| 669 | + return -EINVAL; | |
| 670 | + } | |
| 671 | + | |
| 672 | + break; | |
| 673 | + default: | |
| 674 | + return -EINVAL; | |
| 675 | + } | |
| 676 | + | |
| 677 | + return 0; | |
| 678 | +} | |
| 679 | + | |
| 680 | +static int da732x_out_pga_event(struct snd_soc_dapm_widget *w, | |
| 681 | + struct snd_kcontrol *kcontrol, int event) | |
| 682 | +{ | |
| 683 | + struct snd_soc_codec *codec = w->codec; | |
| 684 | + | |
| 685 | + switch (event) { | |
| 686 | + case SND_SOC_DAPM_POST_PMU: | |
| 687 | + snd_soc_update_bits(codec, w->reg, | |
| 688 | + (1 << w->shift) | DA732X_OUT_HIZ_EN, | |
| 689 | + (1 << w->shift) | DA732X_OUT_HIZ_EN); | |
| 690 | + break; | |
| 691 | + case SND_SOC_DAPM_POST_PMD: | |
| 692 | + snd_soc_update_bits(codec, w->reg, | |
| 693 | + (1 << w->shift) | DA732X_OUT_HIZ_EN, | |
| 694 | + (1 << w->shift) | DA732X_OUT_HIZ_DIS); | |
| 695 | + break; | |
| 696 | + default: | |
| 697 | + return -EINVAL; | |
| 698 | + } | |
| 699 | + | |
| 700 | + return 0; | |
| 701 | +} | |
| 702 | + | |
| 703 | +static const char *adcl_text[] = { | |
| 704 | + "AUX1L", "MIC1" | |
| 705 | +}; | |
| 706 | + | |
| 707 | +static const char *adcr_text[] = { | |
| 708 | + "AUX1R", "MIC2", "MIC3" | |
| 709 | +}; | |
| 710 | + | |
| 711 | +static const char *enable_text[] = { | |
| 712 | + "Disabled", | |
| 713 | + "Enabled" | |
| 714 | +}; | |
| 715 | + | |
| 716 | +/* ADC1LMUX */ | |
| 717 | +static const struct soc_enum adc1l_enum = | |
| 718 | + SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1L_MUX_SEL_SHIFT, | |
| 719 | + DA732X_ADCL_MUX_MAX, adcl_text); | |
| 720 | +static const struct snd_kcontrol_new adc1l_mux = | |
| 721 | + SOC_DAPM_ENUM("ADC Route", adc1l_enum); | |
| 722 | + | |
| 723 | +/* ADC1RMUX */ | |
| 724 | +static const struct soc_enum adc1r_enum = | |
| 725 | + SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1R_MUX_SEL_SHIFT, | |
| 726 | + DA732X_ADCR_MUX_MAX, adcr_text); | |
| 727 | +static const struct snd_kcontrol_new adc1r_mux = | |
| 728 | + SOC_DAPM_ENUM("ADC Route", adc1r_enum); | |
| 729 | + | |
| 730 | +/* ADC2LMUX */ | |
| 731 | +static const struct soc_enum adc2l_enum = | |
| 732 | + SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2L_MUX_SEL_SHIFT, | |
| 733 | + DA732X_ADCL_MUX_MAX, adcl_text); | |
| 734 | +static const struct snd_kcontrol_new adc2l_mux = | |
| 735 | + SOC_DAPM_ENUM("ADC Route", adc2l_enum); | |
| 736 | + | |
| 737 | +/* ADC2RMUX */ | |
| 738 | +static const struct soc_enum adc2r_enum = | |
| 739 | + SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2R_MUX_SEL_SHIFT, | |
| 740 | + DA732X_ADCR_MUX_MAX, adcr_text); | |
| 741 | + | |
| 742 | +static const struct snd_kcontrol_new adc2r_mux = | |
| 743 | + SOC_DAPM_ENUM("ADC Route", adc2r_enum); | |
| 744 | + | |
| 745 | +static const struct soc_enum da732x_hp_left_output = | |
| 746 | + SOC_ENUM_SINGLE(DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN_SHIFT, | |
| 747 | + DA732X_DAC_EN_MAX, enable_text); | |
| 748 | + | |
| 749 | +static const struct snd_kcontrol_new hpl_mux = | |
| 750 | + SOC_DAPM_ENUM("HPL Switch", da732x_hp_left_output); | |
| 751 | + | |
| 752 | +static const struct soc_enum da732x_hp_right_output = | |
| 753 | + SOC_ENUM_SINGLE(DA732X_REG_HPR, DA732X_HP_OUT_DAC_EN_SHIFT, | |
| 754 | + DA732X_DAC_EN_MAX, enable_text); | |
| 755 | + | |
| 756 | +static const struct snd_kcontrol_new hpr_mux = | |
| 757 | + SOC_DAPM_ENUM("HPR Switch", da732x_hp_right_output); | |
| 758 | + | |
| 759 | +static const struct soc_enum da732x_speaker_output = | |
| 760 | + SOC_ENUM_SINGLE(DA732X_REG_LIN3, DA732X_LOUT_DAC_EN_SHIFT, | |
| 761 | + DA732X_DAC_EN_MAX, enable_text); | |
| 762 | + | |
| 763 | +static const struct snd_kcontrol_new spk_mux = | |
| 764 | + SOC_DAPM_ENUM("SPK Switch", da732x_speaker_output); | |
| 765 | + | |
| 766 | +static const struct soc_enum da732x_lout4_output = | |
| 767 | + SOC_ENUM_SINGLE(DA732X_REG_LIN4, DA732X_LOUT_DAC_EN_SHIFT, | |
| 768 | + DA732X_DAC_EN_MAX, enable_text); | |
| 769 | + | |
| 770 | +static const struct snd_kcontrol_new lout4_mux = | |
| 771 | + SOC_DAPM_ENUM("LOUT4 Switch", da732x_lout4_output); | |
| 772 | + | |
| 773 | +static const struct soc_enum da732x_lout2_output = | |
| 774 | + SOC_ENUM_SINGLE(DA732X_REG_LIN2, DA732X_LOUT_DAC_EN_SHIFT, | |
| 775 | + DA732X_DAC_EN_MAX, enable_text); | |
| 776 | + | |
| 777 | +static const struct snd_kcontrol_new lout2_mux = | |
| 778 | + SOC_DAPM_ENUM("LOUT2 Switch", da732x_lout2_output); | |
| 779 | + | |
| 780 | +static const struct snd_soc_dapm_widget da732x_dapm_widgets[] = { | |
| 781 | + /* Supplies */ | |
| 782 | + SND_SOC_DAPM_SUPPLY("ADC1 Supply", DA732X_REG_ADC1_PD, 0, | |
| 783 | + DA732X_NO_INVERT, da732x_adc_event, | |
| 784 | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | |
| 785 | + SND_SOC_DAPM_SUPPLY("ADC2 Supply", DA732X_REG_ADC2_PD, 0, | |
| 786 | + DA732X_NO_INVERT, da732x_adc_event, | |
| 787 | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | |
| 788 | + SND_SOC_DAPM_SUPPLY("DAC1 CLK", DA732X_REG_CLK_EN4, | |
| 789 | + DA732X_DACA_BB_CLK_SHIFT, DA732X_NO_INVERT, | |
| 790 | + NULL, 0), | |
| 791 | + SND_SOC_DAPM_SUPPLY("DAC2 CLK", DA732X_REG_CLK_EN4, | |
| 792 | + DA732X_DACC_BB_CLK_SHIFT, DA732X_NO_INVERT, | |
| 793 | + NULL, 0), | |
| 794 | + SND_SOC_DAPM_SUPPLY("DAC3 CLK", DA732X_REG_CLK_EN5, | |
| 795 | + DA732X_DACE_BB_CLK_SHIFT, DA732X_NO_INVERT, | |
| 796 | + NULL, 0), | |
| 797 | + | |
| 798 | + /* Micbias */ | |
| 799 | + SND_SOC_DAPM_SUPPLY("MICBIAS1", DA732X_REG_MICBIAS1, | |
| 800 | + DA732X_MICBIAS_EN_SHIFT, | |
| 801 | + DA732X_NO_INVERT, NULL, 0), | |
| 802 | + SND_SOC_DAPM_SUPPLY("MICBIAS2", DA732X_REG_MICBIAS2, | |
| 803 | + DA732X_MICBIAS_EN_SHIFT, | |
| 804 | + DA732X_NO_INVERT, NULL, 0), | |
| 805 | + | |
| 806 | + /* Inputs */ | |
| 807 | + SND_SOC_DAPM_INPUT("MIC1"), | |
| 808 | + SND_SOC_DAPM_INPUT("MIC2"), | |
| 809 | + SND_SOC_DAPM_INPUT("MIC3"), | |
| 810 | + SND_SOC_DAPM_INPUT("AUX1L"), | |
| 811 | + SND_SOC_DAPM_INPUT("AUX1R"), | |
| 812 | + | |
| 813 | + /* Outputs */ | |
| 814 | + SND_SOC_DAPM_OUTPUT("HPL"), | |
| 815 | + SND_SOC_DAPM_OUTPUT("HPR"), | |
| 816 | + SND_SOC_DAPM_OUTPUT("LOUTL"), | |
| 817 | + SND_SOC_DAPM_OUTPUT("LOUTR"), | |
| 818 | + SND_SOC_DAPM_OUTPUT("ClassD"), | |
| 819 | + | |
| 820 | + /* ADCs */ | |
| 821 | + SND_SOC_DAPM_ADC("ADC1L", NULL, DA732X_REG_ADC1_SEL, | |
| 822 | + DA732X_ADCL_EN_SHIFT, DA732X_NO_INVERT), | |
| 823 | + SND_SOC_DAPM_ADC("ADC1R", NULL, DA732X_REG_ADC1_SEL, | |
| 824 | + DA732X_ADCR_EN_SHIFT, DA732X_NO_INVERT), | |
| 825 | + SND_SOC_DAPM_ADC("ADC2L", NULL, DA732X_REG_ADC2_SEL, | |
| 826 | + DA732X_ADCL_EN_SHIFT, DA732X_NO_INVERT), | |
| 827 | + SND_SOC_DAPM_ADC("ADC2R", NULL, DA732X_REG_ADC2_SEL, | |
| 828 | + DA732X_ADCR_EN_SHIFT, DA732X_NO_INVERT), | |
| 829 | + | |
| 830 | + /* DACs */ | |
| 831 | + SND_SOC_DAPM_DAC("DAC1L", NULL, DA732X_REG_DAC1_SEL, | |
| 832 | + DA732X_DACL_EN_SHIFT, DA732X_NO_INVERT), | |
| 833 | + SND_SOC_DAPM_DAC("DAC1R", NULL, DA732X_REG_DAC1_SEL, | |
| 834 | + DA732X_DACR_EN_SHIFT, DA732X_NO_INVERT), | |
| 835 | + SND_SOC_DAPM_DAC("DAC2L", NULL, DA732X_REG_DAC2_SEL, | |
| 836 | + DA732X_DACL_EN_SHIFT, DA732X_NO_INVERT), | |
| 837 | + SND_SOC_DAPM_DAC("DAC2R", NULL, DA732X_REG_DAC2_SEL, | |
| 838 | + DA732X_DACR_EN_SHIFT, DA732X_NO_INVERT), | |
| 839 | + SND_SOC_DAPM_DAC("DAC3", NULL, DA732X_REG_DAC3_SEL, | |
| 840 | + DA732X_DACL_EN_SHIFT, DA732X_NO_INVERT), | |
| 841 | + | |
| 842 | + /* Input Pgas */ | |
| 843 | + SND_SOC_DAPM_PGA("MIC1 PGA", DA732X_REG_MIC1, DA732X_MIC_EN_SHIFT, | |
| 844 | + 0, NULL, 0), | |
| 845 | + SND_SOC_DAPM_PGA("MIC2 PGA", DA732X_REG_MIC2, DA732X_MIC_EN_SHIFT, | |
| 846 | + 0, NULL, 0), | |
| 847 | + SND_SOC_DAPM_PGA("MIC3 PGA", DA732X_REG_MIC3, DA732X_MIC_EN_SHIFT, | |
| 848 | + 0, NULL, 0), | |
| 849 | + SND_SOC_DAPM_PGA("AUX1L PGA", DA732X_REG_AUX1L, DA732X_AUX_EN_SHIFT, | |
| 850 | + 0, NULL, 0), | |
| 851 | + SND_SOC_DAPM_PGA("AUX1R PGA", DA732X_REG_AUX1R, DA732X_AUX_EN_SHIFT, | |
| 852 | + 0, NULL, 0), | |
| 853 | + | |
| 854 | + SND_SOC_DAPM_PGA_E("HP Left", DA732X_REG_HPL, DA732X_HP_OUT_EN_SHIFT, | |
| 855 | + 0, NULL, 0, da732x_out_pga_event, | |
| 856 | + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | |
| 857 | + SND_SOC_DAPM_PGA_E("HP Right", DA732X_REG_HPR, DA732X_HP_OUT_EN_SHIFT, | |
| 858 | + 0, NULL, 0, da732x_out_pga_event, | |
| 859 | + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | |
| 860 | + SND_SOC_DAPM_PGA_E("LIN2", DA732X_REG_LIN2, DA732X_LIN_OUT_EN_SHIFT, | |
| 861 | + 0, NULL, 0, da732x_out_pga_event, | |
| 862 | + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | |
| 863 | + SND_SOC_DAPM_PGA_E("LIN3", DA732X_REG_LIN3, DA732X_LIN_OUT_EN_SHIFT, | |
| 864 | + 0, NULL, 0, da732x_out_pga_event, | |
| 865 | + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | |
| 866 | + SND_SOC_DAPM_PGA_E("LIN4", DA732X_REG_LIN4, DA732X_LIN_OUT_EN_SHIFT, | |
| 867 | + 0, NULL, 0, da732x_out_pga_event, | |
| 868 | + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | |
| 869 | + | |
| 870 | + /* MUXs */ | |
| 871 | + SND_SOC_DAPM_MUX("ADC1 Left MUX", SND_SOC_NOPM, 0, 0, &adc1l_mux), | |
| 872 | + SND_SOC_DAPM_MUX("ADC1 Right MUX", SND_SOC_NOPM, 0, 0, &adc1r_mux), | |
| 873 | + SND_SOC_DAPM_MUX("ADC2 Left MUX", SND_SOC_NOPM, 0, 0, &adc2l_mux), | |
| 874 | + SND_SOC_DAPM_MUX("ADC2 Right MUX", SND_SOC_NOPM, 0, 0, &adc2r_mux), | |
| 875 | + | |
| 876 | + SND_SOC_DAPM_MUX("HP Left MUX", SND_SOC_NOPM, 0, 0, &hpl_mux), | |
| 877 | + SND_SOC_DAPM_MUX("HP Right MUX", SND_SOC_NOPM, 0, 0, &hpr_mux), | |
| 878 | + SND_SOC_DAPM_MUX("Speaker MUX", SND_SOC_NOPM, 0, 0, &spk_mux), | |
| 879 | + SND_SOC_DAPM_MUX("LOUT2 MUX", SND_SOC_NOPM, 0, 0, &lout2_mux), | |
| 880 | + SND_SOC_DAPM_MUX("LOUT4 MUX", SND_SOC_NOPM, 0, 0, &lout4_mux), | |
| 881 | + | |
| 882 | + /* AIF interfaces */ | |
| 883 | + SND_SOC_DAPM_AIF_OUT("AIFA Output", "AIFA Capture", 0, DA732X_REG_AIFA3, | |
| 884 | + DA732X_AIF_EN_SHIFT, 0), | |
| 885 | + SND_SOC_DAPM_AIF_IN("AIFA Input", "AIFA Playback", 0, DA732X_REG_AIFA3, | |
| 886 | + DA732X_AIF_EN_SHIFT, 0), | |
| 887 | + | |
| 888 | + SND_SOC_DAPM_AIF_OUT("AIFB Output", "AIFB Capture", 0, DA732X_REG_AIFB3, | |
| 889 | + DA732X_AIF_EN_SHIFT, 0), | |
| 890 | + SND_SOC_DAPM_AIF_IN("AIFB Input", "AIFB Playback", 0, DA732X_REG_AIFB3, | |
| 891 | + DA732X_AIF_EN_SHIFT, 0), | |
| 892 | +}; | |
| 893 | + | |
| 894 | +static const struct snd_soc_dapm_route da732x_dapm_routes[] = { | |
| 895 | + /* Inputs */ | |
| 896 | + {"AUX1L PGA", "NULL", "AUX1L"}, | |
| 897 | + {"AUX1R PGA", "NULL", "AUX1R"}, | |
| 898 | + {"MIC1 PGA", NULL, "MIC1"}, | |
| 899 | + {"MIC2 PGA", "NULL", "MIC2"}, | |
| 900 | + {"MIC3 PGA", "NULL", "MIC3"}, | |
| 901 | + | |
| 902 | + /* Capture Path */ | |
| 903 | + {"ADC1 Left MUX", "MIC1", "MIC1 PGA"}, | |
| 904 | + {"ADC1 Left MUX", "AUX1L", "AUX1L PGA"}, | |
| 905 | + | |
| 906 | + {"ADC1 Right MUX", "AUX1R", "AUX1R PGA"}, | |
| 907 | + {"ADC1 Right MUX", "MIC2", "MIC2 PGA"}, | |
| 908 | + {"ADC1 Right MUX", "MIC3", "MIC3 PGA"}, | |
| 909 | + | |
| 910 | + {"ADC2 Left MUX", "AUX1L", "AUX1L PGA"}, | |
| 911 | + {"ADC2 Left MUX", "MIC1", "MIC1 PGA"}, | |
| 912 | + | |
| 913 | + {"ADC2 Right MUX", "AUX1R", "AUX1R PGA"}, | |
| 914 | + {"ADC2 Right MUX", "MIC2", "MIC2 PGA"}, | |
| 915 | + {"ADC2 Right MUX", "MIC3", "MIC3 PGA"}, | |
| 916 | + | |
| 917 | + {"ADC1L", NULL, "ADC1 Supply"}, | |
| 918 | + {"ADC1R", NULL, "ADC1 Supply"}, | |
| 919 | + {"ADC2L", NULL, "ADC2 Supply"}, | |
| 920 | + {"ADC2R", NULL, "ADC2 Supply"}, | |
| 921 | + | |
| 922 | + {"ADC1L", NULL, "ADC1 Left MUX"}, | |
| 923 | + {"ADC1R", NULL, "ADC1 Right MUX"}, | |
| 924 | + {"ADC2L", NULL, "ADC2 Left MUX"}, | |
| 925 | + {"ADC2R", NULL, "ADC2 Right MUX"}, | |
| 926 | + | |
| 927 | + {"AIFA Output", NULL, "ADC1L"}, | |
| 928 | + {"AIFA Output", NULL, "ADC1R"}, | |
| 929 | + {"AIFB Output", NULL, "ADC2L"}, | |
| 930 | + {"AIFB Output", NULL, "ADC2R"}, | |
| 931 | + | |
| 932 | + {"HP Left MUX", "Enabled", "AIFA Input"}, | |
| 933 | + {"HP Right MUX", "Enabled", "AIFA Input"}, | |
| 934 | + {"Speaker MUX", "Enabled", "AIFB Input"}, | |
| 935 | + {"LOUT2 MUX", "Enabled", "AIFB Input"}, | |
| 936 | + {"LOUT4 MUX", "Enabled", "AIFB Input"}, | |
| 937 | + | |
| 938 | + {"DAC1L", NULL, "DAC1 CLK"}, | |
| 939 | + {"DAC1R", NULL, "DAC1 CLK"}, | |
| 940 | + {"DAC2L", NULL, "DAC2 CLK"}, | |
| 941 | + {"DAC2R", NULL, "DAC2 CLK"}, | |
| 942 | + {"DAC3", NULL, "DAC3 CLK"}, | |
| 943 | + | |
| 944 | + {"DAC1L", NULL, "HP Left MUX"}, | |
| 945 | + {"DAC1R", NULL, "HP Right MUX"}, | |
| 946 | + {"DAC2L", NULL, "Speaker MUX"}, | |
| 947 | + {"DAC2R", NULL, "LOUT4 MUX"}, | |
| 948 | + {"DAC3", NULL, "LOUT2 MUX"}, | |
| 949 | + | |
| 950 | + /* Output Pgas */ | |
| 951 | + {"HP Left", NULL, "DAC1L"}, | |
| 952 | + {"HP Right", NULL, "DAC1R"}, | |
| 953 | + {"LIN3", NULL, "DAC2L"}, | |
| 954 | + {"LIN4", NULL, "DAC2R"}, | |
| 955 | + {"LIN2", NULL, "DAC3"}, | |
| 956 | + | |
| 957 | + /* Outputs */ | |
| 958 | + {"ClassD", NULL, "LIN3"}, | |
| 959 | + {"LOUTL", NULL, "LIN2"}, | |
| 960 | + {"LOUTR", NULL, "LIN4"}, | |
| 961 | + {"HPL", NULL, "HP Left"}, | |
| 962 | + {"HPR", NULL, "HP Right"}, | |
| 963 | +}; | |
| 964 | + | |
| 965 | +static int da732x_hw_params(struct snd_pcm_substream *substream, | |
| 966 | + struct snd_pcm_hw_params *params, | |
| 967 | + struct snd_soc_dai *dai) | |
| 968 | +{ | |
| 969 | + struct snd_soc_codec *codec = dai->codec; | |
| 970 | + u32 aif = 0; | |
| 971 | + u32 reg_aif; | |
| 972 | + u32 fs; | |
| 973 | + | |
| 974 | + reg_aif = dai->driver->base; | |
| 975 | + | |
| 976 | + switch (params_format(params)) { | |
| 977 | + case SNDRV_PCM_FORMAT_S16_LE: | |
| 978 | + aif |= DA732X_AIF_WORD_16; | |
| 979 | + break; | |
| 980 | + case SNDRV_PCM_FORMAT_S20_3LE: | |
| 981 | + aif |= DA732X_AIF_WORD_20; | |
| 982 | + break; | |
| 983 | + case SNDRV_PCM_FORMAT_S24_LE: | |
| 984 | + aif |= DA732X_AIF_WORD_24; | |
| 985 | + break; | |
| 986 | + case SNDRV_PCM_FORMAT_S32_LE: | |
| 987 | + aif |= DA732X_AIF_WORD_32; | |
| 988 | + break; | |
| 989 | + default: | |
| 990 | + return -EINVAL; | |
| 991 | + } | |
| 992 | + | |
| 993 | + switch (params_rate(params)) { | |
| 994 | + case 8000: | |
| 995 | + fs = DA732X_SR_8KHZ; | |
| 996 | + break; | |
| 997 | + case 11025: | |
| 998 | + fs = DA732X_SR_11_025KHZ; | |
| 999 | + break; | |
| 1000 | + case 12000: | |
| 1001 | + fs = DA732X_SR_12KHZ; | |
| 1002 | + break; | |
| 1003 | + case 16000: | |
| 1004 | + fs = DA732X_SR_16KHZ; | |
| 1005 | + break; | |
| 1006 | + case 22050: | |
| 1007 | + fs = DA732X_SR_22_05KHZ; | |
| 1008 | + break; | |
| 1009 | + case 24000: | |
| 1010 | + fs = DA732X_SR_24KHZ; | |
| 1011 | + break; | |
| 1012 | + case 32000: | |
| 1013 | + fs = DA732X_SR_32KHZ; | |
| 1014 | + break; | |
| 1015 | + case 44100: | |
| 1016 | + fs = DA732X_SR_44_1KHZ; | |
| 1017 | + break; | |
| 1018 | + case 48000: | |
| 1019 | + fs = DA732X_SR_48KHZ; | |
| 1020 | + break; | |
| 1021 | + case 88100: | |
| 1022 | + fs = DA732X_SR_88_1KHZ; | |
| 1023 | + break; | |
| 1024 | + case 96000: | |
| 1025 | + fs = DA732X_SR_96KHZ; | |
| 1026 | + break; | |
| 1027 | + default: | |
| 1028 | + return -EINVAL; | |
| 1029 | + } | |
| 1030 | + | |
| 1031 | + snd_soc_update_bits(codec, reg_aif, DA732X_AIF_WORD_MASK, aif); | |
| 1032 | + snd_soc_update_bits(codec, DA732X_REG_CLK_CTRL, DA732X_SR1_MASK, fs); | |
| 1033 | + | |
| 1034 | + return 0; | |
| 1035 | +} | |
| 1036 | + | |
| 1037 | +static int da732x_set_dai_fmt(struct snd_soc_dai *dai, u32 fmt) | |
| 1038 | +{ | |
| 1039 | + struct snd_soc_codec *codec = dai->codec; | |
| 1040 | + u32 aif_mclk, pc_count; | |
| 1041 | + u32 reg_aif1, aif1; | |
| 1042 | + u32 reg_aif3, aif3; | |
| 1043 | + | |
| 1044 | + switch (dai->id) { | |
| 1045 | + case DA732X_DAI_ID1: | |
| 1046 | + reg_aif1 = DA732X_REG_AIFA1; | |
| 1047 | + reg_aif3 = DA732X_REG_AIFA3; | |
| 1048 | + pc_count = DA732X_PC_PULSE_AIFA | DA732X_PC_RESYNC_NOT_AUT | | |
| 1049 | + DA732X_PC_SAME; | |
| 1050 | + break; | |
| 1051 | + case DA732X_DAI_ID2: | |
| 1052 | + reg_aif1 = DA732X_REG_AIFB1; | |
| 1053 | + reg_aif3 = DA732X_REG_AIFB3; | |
| 1054 | + pc_count = DA732X_PC_PULSE_AIFB | DA732X_PC_RESYNC_NOT_AUT | | |
| 1055 | + DA732X_PC_SAME; | |
| 1056 | + break; | |
| 1057 | + default: | |
| 1058 | + return -EINVAL; | |
| 1059 | + } | |
| 1060 | + | |
| 1061 | + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | |
| 1062 | + case SND_SOC_DAIFMT_CBS_CFS: | |
| 1063 | + aif1 = DA732X_AIF_SLAVE; | |
| 1064 | + aif_mclk = DA732X_AIFM_FRAME_64 | DA732X_AIFM_SRC_SEL_AIFA; | |
| 1065 | + break; | |
| 1066 | + case SND_SOC_DAIFMT_CBM_CFM: | |
| 1067 | + aif1 = DA732X_AIF_CLK_FROM_SRC; | |
| 1068 | + aif_mclk = DA732X_CLK_GENERATION_AIF_A; | |
| 1069 | + break; | |
| 1070 | + default: | |
| 1071 | + return -EINVAL; | |
| 1072 | + } | |
| 1073 | + | |
| 1074 | + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | |
| 1075 | + case SND_SOC_DAIFMT_I2S: | |
| 1076 | + aif3 = DA732X_AIF_I2S_MODE; | |
| 1077 | + break; | |
| 1078 | + case SND_SOC_DAIFMT_RIGHT_J: | |
| 1079 | + aif3 = DA732X_AIF_RIGHT_J_MODE; | |
| 1080 | + break; | |
| 1081 | + case SND_SOC_DAIFMT_LEFT_J: | |
| 1082 | + aif3 = DA732X_AIF_LEFT_J_MODE; | |
| 1083 | + break; | |
| 1084 | + case SND_SOC_DAIFMT_DSP_B: | |
| 1085 | + aif3 = DA732X_AIF_DSP_MODE; | |
| 1086 | + break; | |
| 1087 | + default: | |
| 1088 | + return -EINVAL; | |
| 1089 | + } | |
| 1090 | + | |
| 1091 | + /* Clock inversion */ | |
| 1092 | + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | |
| 1093 | + case SND_SOC_DAIFMT_DSP_B: | |
| 1094 | + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | |
| 1095 | + case SND_SOC_DAIFMT_NB_NF: | |
| 1096 | + break; | |
| 1097 | + case SND_SOC_DAIFMT_IB_NF: | |
| 1098 | + aif3 |= DA732X_AIF_BCLK_INV; | |
| 1099 | + break; | |
| 1100 | + default: | |
| 1101 | + return -EINVAL; | |
| 1102 | + } | |
| 1103 | + break; | |
| 1104 | + case SND_SOC_DAIFMT_I2S: | |
| 1105 | + case SND_SOC_DAIFMT_RIGHT_J: | |
| 1106 | + case SND_SOC_DAIFMT_LEFT_J: | |
| 1107 | + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | |
| 1108 | + case SND_SOC_DAIFMT_NB_NF: | |
| 1109 | + break; | |
| 1110 | + case SND_SOC_DAIFMT_IB_IF: | |
| 1111 | + aif3 |= DA732X_AIF_BCLK_INV | DA732X_AIF_WCLK_INV; | |
| 1112 | + break; | |
| 1113 | + case SND_SOC_DAIFMT_IB_NF: | |
| 1114 | + aif3 |= DA732X_AIF_BCLK_INV; | |
| 1115 | + break; | |
| 1116 | + case SND_SOC_DAIFMT_NB_IF: | |
| 1117 | + aif3 |= DA732X_AIF_WCLK_INV; | |
| 1118 | + break; | |
| 1119 | + default: | |
| 1120 | + return -EINVAL; | |
| 1121 | + } | |
| 1122 | + break; | |
| 1123 | + default: | |
| 1124 | + return -EINVAL; | |
| 1125 | + } | |
| 1126 | + | |
| 1127 | + snd_soc_write(codec, DA732X_REG_AIF_MCLK, aif_mclk); | |
| 1128 | + snd_soc_update_bits(codec, reg_aif1, DA732X_AIF1_CLK_MASK, aif1); | |
| 1129 | + snd_soc_update_bits(codec, reg_aif3, DA732X_AIF_BCLK_INV | | |
| 1130 | + DA732X_AIF_WCLK_INV | DA732X_AIF_MODE_MASK, aif3); | |
| 1131 | + snd_soc_write(codec, DA732X_REG_PC_CTRL, pc_count); | |
| 1132 | + | |
| 1133 | + return 0; | |
| 1134 | +} | |
| 1135 | + | |
| 1136 | + | |
| 1137 | + | |
| 1138 | +static int da732x_set_dai_pll(struct snd_soc_codec *codec, int pll_id, | |
| 1139 | + int source, unsigned int freq_in, | |
| 1140 | + unsigned int freq_out) | |
| 1141 | +{ | |
| 1142 | + struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec); | |
| 1143 | + int fref, indiv; | |
| 1144 | + u8 div_lo, div_mid, div_hi; | |
| 1145 | + u64 frac_div; | |
| 1146 | + | |
| 1147 | + /* Disable PLL */ | |
| 1148 | + if (freq_out == 0) { | |
| 1149 | + snd_soc_update_bits(codec, DA732X_REG_PLL_CTRL, | |
| 1150 | + DA732X_PLL_EN, 0); | |
| 1151 | + da732x->pll_en = false; | |
| 1152 | + return 0; | |
| 1153 | + } | |
| 1154 | + | |
| 1155 | + if (da732x->pll_en) | |
| 1156 | + return -EBUSY; | |
| 1157 | + | |
| 1158 | + if (source == DA732X_SRCCLK_MCLK) { | |
| 1159 | + /* Validate Sysclk rate */ | |
| 1160 | + switch (da732x->sysclk) { | |
| 1161 | + case 11290000: | |
| 1162 | + case 12288000: | |
| 1163 | + case 22580000: | |
| 1164 | + case 24576000: | |
| 1165 | + case 45160000: | |
| 1166 | + case 49152000: | |
| 1167 | + snd_soc_write(codec, DA732X_REG_PLL_CTRL, | |
| 1168 | + DA732X_PLL_BYPASS); | |
| 1169 | + return 0; | |
| 1170 | + default: | |
| 1171 | + dev_err(codec->dev, | |
| 1172 | + "Cannot use PLL Bypass, invalid SYSCLK rate\n"); | |
| 1173 | + return -EINVAL; | |
| 1174 | + } | |
| 1175 | + } | |
| 1176 | + | |
| 1177 | + indiv = da732x_get_input_div(codec, da732x->sysclk); | |
| 1178 | + if (indiv < 0) | |
| 1179 | + return indiv; | |
| 1180 | + | |
| 1181 | + fref = (da732x->sysclk / indiv); | |
| 1182 | + div_hi = freq_out / fref; | |
| 1183 | + frac_div = (u64)(freq_out % fref) * 8192ULL; | |
| 1184 | + do_div(frac_div, fref); | |
| 1185 | + div_mid = (frac_div >> DA732X_1BYTE_SHIFT) & DA732X_U8_MASK; | |
| 1186 | + div_lo = (frac_div) & DA732X_U8_MASK; | |
| 1187 | + | |
| 1188 | + snd_soc_write(codec, DA732X_REG_PLL_DIV_LO, div_lo); | |
| 1189 | + snd_soc_write(codec, DA732X_REG_PLL_DIV_MID, div_mid); | |
| 1190 | + snd_soc_write(codec, DA732X_REG_PLL_DIV_HI, div_hi); | |
| 1191 | + | |
| 1192 | + snd_soc_update_bits(codec, DA732X_REG_PLL_CTRL, DA732X_PLL_EN, | |
| 1193 | + DA732X_PLL_EN); | |
| 1194 | + | |
| 1195 | + da732x->pll_en = true; | |
| 1196 | + | |
| 1197 | + return 0; | |
| 1198 | +} | |
| 1199 | + | |
| 1200 | +static int da732x_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, | |
| 1201 | + unsigned int freq, int dir) | |
| 1202 | +{ | |
| 1203 | + struct snd_soc_codec *codec = dai->codec; | |
| 1204 | + struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec); | |
| 1205 | + | |
| 1206 | + da732x->sysclk = freq; | |
| 1207 | + | |
| 1208 | + return 0; | |
| 1209 | +} | |
| 1210 | + | |
| 1211 | +#define DA732X_RATES SNDRV_PCM_RATE_8000_96000 | |
| 1212 | + | |
| 1213 | +#define DA732X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | |
| 1214 | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | |
| 1215 | + | |
| 1216 | +static struct snd_soc_dai_ops da732x_dai1_ops = { | |
| 1217 | + .hw_params = da732x_hw_params, | |
| 1218 | + .set_fmt = da732x_set_dai_fmt, | |
| 1219 | + .set_sysclk = da732x_set_dai_sysclk, | |
| 1220 | +}; | |
| 1221 | + | |
| 1222 | +static struct snd_soc_dai_ops da732x_dai2_ops = { | |
| 1223 | + .hw_params = da732x_hw_params, | |
| 1224 | + .set_fmt = da732x_set_dai_fmt, | |
| 1225 | + .set_sysclk = da732x_set_dai_sysclk, | |
| 1226 | +}; | |
| 1227 | + | |
| 1228 | +static struct snd_soc_dai_driver da732x_dai[] = { | |
| 1229 | + { | |
| 1230 | + .name = "DA732X_AIFA", | |
| 1231 | + .id = DA732X_DAI_ID1, | |
| 1232 | + .base = DA732X_REG_AIFA1, | |
| 1233 | + .playback = { | |
| 1234 | + .stream_name = "AIFA Playback", | |
| 1235 | + .channels_min = 1, | |
| 1236 | + .channels_max = 2, | |
| 1237 | + .rates = DA732X_RATES, | |
| 1238 | + .formats = DA732X_FORMATS, | |
| 1239 | + }, | |
| 1240 | + .capture = { | |
| 1241 | + .stream_name = "AIFA Capture", | |
| 1242 | + .channels_min = 1, | |
| 1243 | + .channels_max = 2, | |
| 1244 | + .rates = DA732X_RATES, | |
| 1245 | + .formats = DA732X_FORMATS, | |
| 1246 | + }, | |
| 1247 | + .ops = &da732x_dai1_ops, | |
| 1248 | + }, | |
| 1249 | + { | |
| 1250 | + .name = "DA732X_AIFB", | |
| 1251 | + .id = DA732X_DAI_ID2, | |
| 1252 | + .base = DA732X_REG_AIFB1, | |
| 1253 | + .playback = { | |
| 1254 | + .stream_name = "AIFB Playback", | |
| 1255 | + .channels_min = 1, | |
| 1256 | + .channels_max = 2, | |
| 1257 | + .rates = DA732X_RATES, | |
| 1258 | + .formats = DA732X_FORMATS, | |
| 1259 | + }, | |
| 1260 | + .capture = { | |
| 1261 | + .stream_name = "AIFB Capture", | |
| 1262 | + .channels_min = 1, | |
| 1263 | + .channels_max = 2, | |
| 1264 | + .rates = DA732X_RATES, | |
| 1265 | + .formats = DA732X_FORMATS, | |
| 1266 | + }, | |
| 1267 | + .ops = &da732x_dai2_ops, | |
| 1268 | + }, | |
| 1269 | +}; | |
| 1270 | + | |
| 1271 | +static const struct regmap_config da732x_regmap = { | |
| 1272 | + .reg_bits = 8, | |
| 1273 | + .val_bits = 8, | |
| 1274 | + | |
| 1275 | + .max_register = DA732X_MAX_REG, | |
| 1276 | + .reg_defaults = da732x_reg_cache, | |
| 1277 | + .num_reg_defaults = ARRAY_SIZE(da732x_reg_cache), | |
| 1278 | + .cache_type = REGCACHE_RBTREE, | |
| 1279 | +}; | |
| 1280 | + | |
| 1281 | + | |
| 1282 | +static void da732x_dac_offset_adjust(struct snd_soc_codec *codec) | |
| 1283 | +{ | |
| 1284 | + u8 offset[DA732X_HP_DACS]; | |
| 1285 | + u8 sign[DA732X_HP_DACS]; | |
| 1286 | + u8 step = DA732X_DAC_OFFSET_STEP; | |
| 1287 | + | |
| 1288 | + /* Initialize DAC offset calibration circuits and registers */ | |
| 1289 | + snd_soc_write(codec, DA732X_REG_HPL_DAC_OFFSET, | |
| 1290 | + DA732X_HP_DAC_OFFSET_TRIM_VAL); | |
| 1291 | + snd_soc_write(codec, DA732X_REG_HPR_DAC_OFFSET, | |
| 1292 | + DA732X_HP_DAC_OFFSET_TRIM_VAL); | |
| 1293 | + snd_soc_write(codec, DA732X_REG_HPL_DAC_OFF_CNTL, | |
| 1294 | + DA732X_HP_DAC_OFF_CALIBRATION | | |
| 1295 | + DA732X_HP_DAC_OFF_SCALE_STEPS); | |
| 1296 | + snd_soc_write(codec, DA732X_REG_HPR_DAC_OFF_CNTL, | |
| 1297 | + DA732X_HP_DAC_OFF_CALIBRATION | | |
| 1298 | + DA732X_HP_DAC_OFF_SCALE_STEPS); | |
| 1299 | + | |
| 1300 | + /* Wait for voltage stabilization */ | |
| 1301 | + msleep(DA732X_WAIT_FOR_STABILIZATION); | |
| 1302 | + | |
| 1303 | + /* Check DAC offset sign */ | |
| 1304 | + sign[DA732X_HPL_DAC] = (codec->hw_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) & | |
| 1305 | + DA732X_HP_DAC_OFF_CNTL_COMPO); | |
| 1306 | + sign[DA732X_HPR_DAC] = (codec->hw_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) & | |
| 1307 | + DA732X_HP_DAC_OFF_CNTL_COMPO); | |
| 1308 | + | |
| 1309 | + /* Binary search DAC offset values (both channels at once) */ | |
| 1310 | + offset[DA732X_HPL_DAC] = sign[DA732X_HPL_DAC] << DA732X_HP_DAC_COMPO_SHIFT; | |
| 1311 | + offset[DA732X_HPR_DAC] = sign[DA732X_HPR_DAC] << DA732X_HP_DAC_COMPO_SHIFT; | |
| 1312 | + | |
| 1313 | + do { | |
| 1314 | + offset[DA732X_HPL_DAC] |= step; | |
| 1315 | + offset[DA732X_HPR_DAC] |= step; | |
| 1316 | + snd_soc_write(codec, DA732X_REG_HPL_DAC_OFFSET, | |
| 1317 | + ~offset[DA732X_HPL_DAC] & DA732X_HP_DAC_OFF_MASK); | |
| 1318 | + snd_soc_write(codec, DA732X_REG_HPR_DAC_OFFSET, | |
| 1319 | + ~offset[DA732X_HPR_DAC] & DA732X_HP_DAC_OFF_MASK); | |
| 1320 | + | |
| 1321 | + msleep(DA732X_WAIT_FOR_STABILIZATION); | |
| 1322 | + | |
| 1323 | + if ((codec->hw_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) & | |
| 1324 | + DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPL_DAC]) | |
| 1325 | + offset[DA732X_HPL_DAC] &= ~step; | |
| 1326 | + if ((codec->hw_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) & | |
| 1327 | + DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPR_DAC]) | |
| 1328 | + offset[DA732X_HPR_DAC] &= ~step; | |
| 1329 | + | |
| 1330 | + step >>= 1; | |
| 1331 | + } while (step); | |
| 1332 | + | |
| 1333 | + /* Write final DAC offsets to registers */ | |
| 1334 | + snd_soc_write(codec, DA732X_REG_HPL_DAC_OFFSET, | |
| 1335 | + ~offset[DA732X_HPL_DAC] & DA732X_HP_DAC_OFF_MASK); | |
| 1336 | + snd_soc_write(codec, DA732X_REG_HPR_DAC_OFFSET, | |
| 1337 | + ~offset[DA732X_HPR_DAC] & DA732X_HP_DAC_OFF_MASK); | |
| 1338 | + | |
| 1339 | + /* End DAC calibration mode */ | |
| 1340 | + snd_soc_write(codec, DA732X_REG_HPL_DAC_OFF_CNTL, | |
| 1341 | + DA732X_HP_DAC_OFF_SCALE_STEPS); | |
| 1342 | + snd_soc_write(codec, DA732X_REG_HPR_DAC_OFF_CNTL, | |
| 1343 | + DA732X_HP_DAC_OFF_SCALE_STEPS); | |
| 1344 | +} | |
| 1345 | + | |
| 1346 | +static void da732x_output_offset_adjust(struct snd_soc_codec *codec) | |
| 1347 | +{ | |
| 1348 | + u8 offset[DA732X_HP_AMPS]; | |
| 1349 | + u8 sign[DA732X_HP_AMPS]; | |
| 1350 | + u8 step = DA732X_OUTPUT_OFFSET_STEP; | |
| 1351 | + | |
| 1352 | + offset[DA732X_HPL_AMP] = DA732X_HP_OUT_TRIM_VAL; | |
| 1353 | + offset[DA732X_HPR_AMP] = DA732X_HP_OUT_TRIM_VAL; | |
| 1354 | + | |
| 1355 | + /* Initialize output offset calibration circuits and registers */ | |
| 1356 | + snd_soc_write(codec, DA732X_REG_HPL_OUT_OFFSET, DA732X_HP_OUT_TRIM_VAL); | |
| 1357 | + snd_soc_write(codec, DA732X_REG_HPR_OUT_OFFSET, DA732X_HP_OUT_TRIM_VAL); | |
| 1358 | + snd_soc_write(codec, DA732X_REG_HPL, | |
| 1359 | + DA732X_HP_OUT_COMP | DA732X_HP_OUT_EN); | |
| 1360 | + snd_soc_write(codec, DA732X_REG_HPR, | |
| 1361 | + DA732X_HP_OUT_COMP | DA732X_HP_OUT_EN); | |
| 1362 | + | |
| 1363 | + /* Wait for voltage stabilization */ | |
| 1364 | + msleep(DA732X_WAIT_FOR_STABILIZATION); | |
| 1365 | + | |
| 1366 | + /* Check output offset sign */ | |
| 1367 | + sign[DA732X_HPL_AMP] = codec->hw_read(codec, DA732X_REG_HPL) & | |
| 1368 | + DA732X_HP_OUT_COMPO; | |
| 1369 | + sign[DA732X_HPR_AMP] = codec->hw_read(codec, DA732X_REG_HPR) & | |
| 1370 | + DA732X_HP_OUT_COMPO; | |
| 1371 | + | |
| 1372 | + snd_soc_write(codec, DA732X_REG_HPL, DA732X_HP_OUT_COMP | | |
| 1373 | + (sign[DA732X_HPL_AMP] >> DA732X_HP_OUT_COMPO_SHIFT) | | |
| 1374 | + DA732X_HP_OUT_EN); | |
| 1375 | + snd_soc_write(codec, DA732X_REG_HPR, DA732X_HP_OUT_COMP | | |
| 1376 | + (sign[DA732X_HPR_AMP] >> DA732X_HP_OUT_COMPO_SHIFT) | | |
| 1377 | + DA732X_HP_OUT_EN); | |
| 1378 | + | |
| 1379 | + /* Binary search output offset values (both channels at once) */ | |
| 1380 | + do { | |
| 1381 | + offset[DA732X_HPL_AMP] |= step; | |
| 1382 | + offset[DA732X_HPR_AMP] |= step; | |
| 1383 | + snd_soc_write(codec, DA732X_REG_HPL_OUT_OFFSET, | |
| 1384 | + offset[DA732X_HPL_AMP]); | |
| 1385 | + snd_soc_write(codec, DA732X_REG_HPR_OUT_OFFSET, | |
| 1386 | + offset[DA732X_HPR_AMP]); | |
| 1387 | + | |
| 1388 | + msleep(DA732X_WAIT_FOR_STABILIZATION); | |
| 1389 | + | |
| 1390 | + if ((codec->hw_read(codec, DA732X_REG_HPL) & | |
| 1391 | + DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPL_AMP]) | |
| 1392 | + offset[DA732X_HPL_AMP] &= ~step; | |
| 1393 | + if ((codec->hw_read(codec, DA732X_REG_HPR) & | |
| 1394 | + DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPR_AMP]) | |
| 1395 | + offset[DA732X_HPR_AMP] &= ~step; | |
| 1396 | + | |
| 1397 | + step >>= 1; | |
| 1398 | + } while (step); | |
| 1399 | + | |
| 1400 | + /* Write final DAC offsets to registers */ | |
| 1401 | + snd_soc_write(codec, DA732X_REG_HPL_OUT_OFFSET, offset[DA732X_HPL_AMP]); | |
| 1402 | + snd_soc_write(codec, DA732X_REG_HPR_OUT_OFFSET, offset[DA732X_HPR_AMP]); | |
| 1403 | +} | |
| 1404 | + | |
| 1405 | +static void da732x_hp_dc_offset_cancellation(struct snd_soc_codec *codec) | |
| 1406 | +{ | |
| 1407 | + /* Make sure that we have Soft Mute enabled */ | |
| 1408 | + snd_soc_write(codec, DA732X_REG_DAC1_SOFTMUTE, DA732X_SOFTMUTE_EN | | |
| 1409 | + DA732X_GAIN_RAMPED | DA732X_16_SAMPLES); | |
| 1410 | + snd_soc_write(codec, DA732X_REG_DAC1_SEL, DA732X_DACL_EN | | |
| 1411 | + DA732X_DACR_EN | DA732X_DACL_SDM | DA732X_DACR_SDM | | |
| 1412 | + DA732X_DACL_MUTE | DA732X_DACR_MUTE); | |
| 1413 | + snd_soc_write(codec, DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN | | |
| 1414 | + DA732X_HP_OUT_MUTE | DA732X_HP_OUT_EN); | |
| 1415 | + snd_soc_write(codec, DA732X_REG_HPR, DA732X_HP_OUT_EN | | |
| 1416 | + DA732X_HP_OUT_MUTE | DA732X_HP_OUT_DAC_EN); | |
| 1417 | + | |
| 1418 | + da732x_dac_offset_adjust(codec); | |
| 1419 | + da732x_output_offset_adjust(codec); | |
| 1420 | + | |
| 1421 | + snd_soc_write(codec, DA732X_REG_DAC1_SEL, DA732X_DACS_DIS); | |
| 1422 | + snd_soc_write(codec, DA732X_REG_HPL, DA732X_HP_DIS); | |
| 1423 | + snd_soc_write(codec, DA732X_REG_HPR, DA732X_HP_DIS); | |
| 1424 | +} | |
| 1425 | + | |
| 1426 | +static int da732x_set_bias_level(struct snd_soc_codec *codec, | |
| 1427 | + enum snd_soc_bias_level level) | |
| 1428 | +{ | |
| 1429 | + struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec); | |
| 1430 | + | |
| 1431 | + switch (level) { | |
| 1432 | + case SND_SOC_BIAS_ON: | |
| 1433 | + snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, | |
| 1434 | + DA732X_BIAS_BOOST_MASK, | |
| 1435 | + DA732X_BIAS_BOOST_100PC); | |
| 1436 | + break; | |
| 1437 | + case SND_SOC_BIAS_PREPARE: | |
| 1438 | + break; | |
| 1439 | + case SND_SOC_BIAS_STANDBY: | |
| 1440 | + if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | |
| 1441 | + /* Init Codec */ | |
| 1442 | + snd_soc_write(codec, DA732X_REG_REF1, | |
| 1443 | + DA732X_VMID_FASTCHG); | |
| 1444 | + snd_soc_write(codec, DA732X_REG_BIAS_EN, | |
| 1445 | + DA732X_BIAS_EN); | |
| 1446 | + | |
| 1447 | + mdelay(DA732X_STARTUP_DELAY); | |
| 1448 | + | |
| 1449 | + /* Disable Fast Charge and enable DAC ref voltage */ | |
| 1450 | + snd_soc_write(codec, DA732X_REG_REF1, | |
| 1451 | + DA732X_REFBUFX2_EN); | |
| 1452 | + | |
| 1453 | + /* Enable bypass DSP routing */ | |
| 1454 | + snd_soc_write(codec, DA732X_REG_DATA_ROUTE, | |
| 1455 | + DA732X_BYPASS_DSP); | |
| 1456 | + | |
| 1457 | + /* Enable Digital subsystem */ | |
| 1458 | + snd_soc_write(codec, DA732X_REG_DSP_CTRL, | |
| 1459 | + DA732X_DIGITAL_EN); | |
| 1460 | + | |
| 1461 | + snd_soc_write(codec, DA732X_REG_SPARE1_OUT, | |
| 1462 | + DA732X_HP_DRIVER_EN | | |
| 1463 | + DA732X_HP_GATE_LOW | | |
| 1464 | + DA732X_HP_LOOP_GAIN_CTRL); | |
| 1465 | + snd_soc_write(codec, DA732X_REG_HP_LIN1_GNDSEL, | |
| 1466 | + DA732X_HP_OUT_GNDSEL); | |
| 1467 | + | |
| 1468 | + da732x_set_charge_pump(codec, DA732X_ENABLE_CP); | |
| 1469 | + | |
| 1470 | + snd_soc_write(codec, DA732X_REG_CLK_EN1, | |
| 1471 | + DA732X_SYS3_CLK_EN | DA732X_PC_CLK_EN); | |
| 1472 | + | |
| 1473 | + /* Enable Zero Crossing */ | |
| 1474 | + snd_soc_write(codec, DA732X_REG_INP_ZC_EN, | |
| 1475 | + DA732X_MIC1_PRE_ZC_EN | | |
| 1476 | + DA732X_MIC1_ZC_EN | | |
| 1477 | + DA732X_MIC2_PRE_ZC_EN | | |
| 1478 | + DA732X_MIC2_ZC_EN | | |
| 1479 | + DA732X_AUXL_ZC_EN | | |
| 1480 | + DA732X_AUXR_ZC_EN | | |
| 1481 | + DA732X_MIC3_PRE_ZC_EN | | |
| 1482 | + DA732X_MIC3_ZC_EN); | |
| 1483 | + snd_soc_write(codec, DA732X_REG_OUT_ZC_EN, | |
| 1484 | + DA732X_HPL_ZC_EN | DA732X_HPR_ZC_EN | | |
| 1485 | + DA732X_LIN2_ZC_EN | DA732X_LIN3_ZC_EN | | |
| 1486 | + DA732X_LIN4_ZC_EN); | |
| 1487 | + | |
| 1488 | + da732x_hp_dc_offset_cancellation(codec); | |
| 1489 | + | |
| 1490 | + regcache_cache_only(codec->control_data, false); | |
| 1491 | + regcache_sync(codec->control_data); | |
| 1492 | + } else { | |
| 1493 | + snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, | |
| 1494 | + DA732X_BIAS_BOOST_MASK, | |
| 1495 | + DA732X_BIAS_BOOST_50PC); | |
| 1496 | + snd_soc_update_bits(codec, DA732X_REG_PLL_CTRL, | |
| 1497 | + DA732X_PLL_EN, 0); | |
| 1498 | + da732x->pll_en = false; | |
| 1499 | + } | |
| 1500 | + break; | |
| 1501 | + case SND_SOC_BIAS_OFF: | |
| 1502 | + regcache_cache_only(codec->control_data, true); | |
| 1503 | + da732x_set_charge_pump(codec, DA732X_DISABLE_CP); | |
| 1504 | + snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, DA732X_BIAS_EN, | |
| 1505 | + DA732X_BIAS_DIS); | |
| 1506 | + da732x->pll_en = false; | |
| 1507 | + break; | |
| 1508 | + } | |
| 1509 | + | |
| 1510 | + codec->dapm.bias_level = level; | |
| 1511 | + | |
| 1512 | + return 0; | |
| 1513 | +} | |
| 1514 | + | |
| 1515 | +static int da732x_probe(struct snd_soc_codec *codec) | |
| 1516 | +{ | |
| 1517 | + struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec); | |
| 1518 | + struct snd_soc_dapm_context *dapm = &codec->dapm; | |
| 1519 | + int ret = 0; | |
| 1520 | + | |
| 1521 | + da732x->codec = codec; | |
| 1522 | + | |
| 1523 | + dapm->idle_bias_off = false; | |
| 1524 | + | |
| 1525 | + codec->control_data = da732x->regmap; | |
| 1526 | + | |
| 1527 | + ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | |
| 1528 | + if (ret != 0) { | |
| 1529 | + dev_err(codec->dev, "Failed to register codec.\n"); | |
| 1530 | + goto err; | |
| 1531 | + } | |
| 1532 | + | |
| 1533 | + da732x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | |
| 1534 | +err: | |
| 1535 | + return ret; | |
| 1536 | +} | |
| 1537 | + | |
| 1538 | +static int da732x_remove(struct snd_soc_codec *codec) | |
| 1539 | +{ | |
| 1540 | + | |
| 1541 | + da732x_set_bias_level(codec, SND_SOC_BIAS_OFF); | |
| 1542 | + | |
| 1543 | + return 0; | |
| 1544 | +} | |
| 1545 | + | |
| 1546 | +static struct snd_soc_codec_driver soc_codec_dev_da732x = { | |
| 1547 | + .probe = da732x_probe, | |
| 1548 | + .remove = da732x_remove, | |
| 1549 | + .set_bias_level = da732x_set_bias_level, | |
| 1550 | + .controls = da732x_snd_controls, | |
| 1551 | + .num_controls = ARRAY_SIZE(da732x_snd_controls), | |
| 1552 | + .dapm_widgets = da732x_dapm_widgets, | |
| 1553 | + .num_dapm_widgets = ARRAY_SIZE(da732x_dapm_widgets), | |
| 1554 | + .dapm_routes = da732x_dapm_routes, | |
| 1555 | + .num_dapm_routes = ARRAY_SIZE(da732x_dapm_routes), | |
| 1556 | + .set_pll = da732x_set_dai_pll, | |
| 1557 | + .reg_cache_size = ARRAY_SIZE(da732x_reg_cache), | |
| 1558 | +}; | |
| 1559 | + | |
| 1560 | +static __devinit int da732x_i2c_probe(struct i2c_client *i2c, | |
| 1561 | + const struct i2c_device_id *id) | |
| 1562 | +{ | |
| 1563 | + struct da732x_priv *da732x; | |
| 1564 | + unsigned int reg; | |
| 1565 | + int ret; | |
| 1566 | + | |
| 1567 | + da732x = devm_kzalloc(&i2c->dev, sizeof(struct da732x_priv), | |
| 1568 | + GFP_KERNEL); | |
| 1569 | + if (!da732x) | |
| 1570 | + return -ENOMEM; | |
| 1571 | + | |
| 1572 | + i2c_set_clientdata(i2c, da732x); | |
| 1573 | + | |
| 1574 | + da732x->regmap = devm_regmap_init_i2c(i2c, &da732x_regmap); | |
| 1575 | + if (IS_ERR(da732x->regmap)) { | |
| 1576 | + ret = PTR_ERR(da732x->regmap); | |
| 1577 | + dev_err(&i2c->dev, "Failed to initialize regmap\n"); | |
| 1578 | + goto err; | |
| 1579 | + } | |
| 1580 | + | |
| 1581 | + ret = regmap_read(da732x->regmap, DA732X_REG_ID, ®); | |
| 1582 | + if (ret < 0) { | |
| 1583 | + dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret); | |
| 1584 | + goto err; | |
| 1585 | + } | |
| 1586 | + | |
| 1587 | + dev_info(&i2c->dev, "Revision: %d.%d\n", | |
| 1588 | + (reg & DA732X_ID_MAJOR_MASK), (reg & DA732X_ID_MINOR_MASK)); | |
| 1589 | + | |
| 1590 | + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_da732x, | |
| 1591 | + da732x_dai, ARRAY_SIZE(da732x_dai)); | |
| 1592 | + if (ret != 0) | |
| 1593 | + dev_err(&i2c->dev, "Failed to register codec.\n"); | |
| 1594 | + | |
| 1595 | +err: | |
| 1596 | + return ret; | |
| 1597 | +} | |
| 1598 | + | |
| 1599 | +static __devexit int da732x_i2c_remove(struct i2c_client *client) | |
| 1600 | +{ | |
| 1601 | + snd_soc_unregister_codec(&client->dev); | |
| 1602 | + | |
| 1603 | + return 0; | |
| 1604 | +} | |
| 1605 | + | |
| 1606 | +static const struct i2c_device_id da732x_i2c_id[] = { | |
| 1607 | + { "da7320", 0}, | |
| 1608 | + { } | |
| 1609 | +}; | |
| 1610 | +MODULE_DEVICE_TABLE(i2c, da732x_i2c_id); | |
| 1611 | + | |
| 1612 | +static struct i2c_driver da732x_i2c_driver = { | |
| 1613 | + .driver = { | |
| 1614 | + .name = "da7320", | |
| 1615 | + .owner = THIS_MODULE, | |
| 1616 | + }, | |
| 1617 | + .probe = da732x_i2c_probe, | |
| 1618 | + .remove = __devexit_p(da732x_i2c_remove), | |
| 1619 | + .id_table = da732x_i2c_id, | |
| 1620 | +}; | |
| 1621 | + | |
| 1622 | +module_i2c_driver(da732x_i2c_driver); | |
| 1623 | + | |
| 1624 | + | |
| 1625 | +MODULE_DESCRIPTION("ASoC DA732X driver"); | |
| 1626 | +MODULE_AUTHOR("Michal Hajduk <michal.hajduk@diasemi.com>"); | |
| 1627 | +MODULE_LICENSE("GPL"); | |
| @@ -0,0 +1,133 @@ | ||
| 1 | +/* | |
| 2 | + * da732x.h -- Dialog DA732X ALSA SoC Audio Driver Header File | |
| 3 | + * | |
| 4 | + * Copyright (C) 2012 Dialog Semiconductor GmbH | |
| 5 | + * | |
| 6 | + * Author: Michal Hajduk <Michal.Hajduk@diasemi.com> | |
| 7 | + * | |
| 8 | + * This program is free software; you can redistribute it and/or modify | |
| 9 | + * it under the terms of the GNU General Public License version 2 as | |
| 10 | + * published by the Free Software Foundation. | |
| 11 | + */ | |
| 12 | + | |
| 13 | +#ifndef __DA732X_H_ | |
| 14 | +#define __DA732X_H | |
| 15 | + | |
| 16 | +#include <sound/soc.h> | |
| 17 | + | |
| 18 | +/* General */ | |
| 19 | +#define DA732X_U8_MASK 0xFF | |
| 20 | +#define DA732X_4BYTES 4 | |
| 21 | +#define DA732X_3BYTES 3 | |
| 22 | +#define DA732X_2BYTES 2 | |
| 23 | +#define DA732X_1BYTE 1 | |
| 24 | +#define DA732X_1BYTE_SHIFT 8 | |
| 25 | +#define DA732X_2BYTES_SHIFT 16 | |
| 26 | +#define DA732X_3BYTES_SHIFT 24 | |
| 27 | +#define DA732X_4BYTES_SHIFT 32 | |
| 28 | + | |
| 29 | +#define DA732X_DACS_DIS 0x0 | |
| 30 | +#define DA732X_HP_DIS 0x0 | |
| 31 | +#define DA732X_CLEAR_REG 0x0 | |
| 32 | + | |
| 33 | +/* Calibration */ | |
| 34 | +#define DA732X_DAC_OFFSET_STEP 0x20 | |
| 35 | +#define DA732X_OUTPUT_OFFSET_STEP 0x80 | |
| 36 | +#define DA732X_HP_OUT_TRIM_VAL 0x0 | |
| 37 | +#define DA732X_WAIT_FOR_STABILIZATION 1 | |
| 38 | +#define DA732X_HPL_DAC 0 | |
| 39 | +#define DA732X_HPR_DAC 1 | |
| 40 | +#define DA732X_HP_DACS 2 | |
| 41 | +#define DA732X_HPL_AMP 0 | |
| 42 | +#define DA732X_HPR_AMP 1 | |
| 43 | +#define DA732X_HP_AMPS 2 | |
| 44 | + | |
| 45 | +/* Clock settings */ | |
| 46 | +#define DA732X_STARTUP_DELAY 100 | |
| 47 | +#define DA732X_PLL_OUT_196608 196608000 | |
| 48 | +#define DA732X_PLL_OUT_180634 180633600 | |
| 49 | +#define DA732X_PLL_OUT_SRM 188620800 | |
| 50 | +#define DA732X_MCLK_10MHZ 10000000 | |
| 51 | +#define DA732X_MCLK_20MHZ 20000000 | |
| 52 | +#define DA732X_MCLK_40MHZ 40000000 | |
| 53 | +#define DA732X_MCLK_54MHZ 54000000 | |
| 54 | +#define DA732X_MCLK_RET_0_10MHZ 0 | |
| 55 | +#define DA732X_MCLK_VAL_0_10MHZ 1 | |
| 56 | +#define DA732X_MCLK_RET_10_20MHZ 1 | |
| 57 | +#define DA732X_MCLK_VAL_10_20MHZ 2 | |
| 58 | +#define DA732X_MCLK_RET_20_40MHZ 2 | |
| 59 | +#define DA732X_MCLK_VAL_20_40MHZ 4 | |
| 60 | +#define DA732X_MCLK_RET_40_54MHZ 3 | |
| 61 | +#define DA732X_MCLK_VAL_40_54MHZ 8 | |
| 62 | +#define DA732X_DAI_ID1 0 | |
| 63 | +#define DA732X_DAI_ID2 1 | |
| 64 | +#define DA732X_SRCCLK_PLL 0 | |
| 65 | +#define DA732X_SRCCLK_MCLK 1 | |
| 66 | + | |
| 67 | +#define DA732X_LIN_LP_VOL 0x4F | |
| 68 | +#define DA732X_LP_VOL 0x40 | |
| 69 | + | |
| 70 | +/* Kcontrols */ | |
| 71 | +#define DA732X_DAC_EN_MAX 2 | |
| 72 | +#define DA732X_ADCL_MUX_MAX 2 | |
| 73 | +#define DA732X_ADCR_MUX_MAX 3 | |
| 74 | +#define DA732X_HPF_MODE_MAX 3 | |
| 75 | +#define DA732X_HPF_MODE_SHIFT 4 | |
| 76 | +#define DA732X_HPF_MUSIC_SHIFT 0 | |
| 77 | +#define DA732X_HPF_MUSIC_MAX 4 | |
| 78 | +#define DA732X_HPF_VOICE_SHIFT 4 | |
| 79 | +#define DA732X_HPF_VOICE_MAX 8 | |
| 80 | +#define DA732X_EQ_EN_MAX 1 | |
| 81 | +#define DA732X_HPF_VOICE 1 | |
| 82 | +#define DA732X_HPF_MUSIC 2 | |
| 83 | +#define DA732X_HPF_DISABLED 0 | |
| 84 | +#define DA732X_NO_INVERT 0 | |
| 85 | +#define DA732X_INVERT 1 | |
| 86 | +#define DA732X_SWITCH_MAX 1 | |
| 87 | +#define DA732X_ENABLE_CP 1 | |
| 88 | +#define DA732X_DISABLE_CP 0 | |
| 89 | +#define DA732X_DISABLE_ALL_CLKS 0 | |
| 90 | +#define DA732X_RESET_ADCS 0 | |
| 91 | + | |
| 92 | +/* dB values */ | |
| 93 | +#define DA732X_MIC_VOL_DB_MIN 0 | |
| 94 | +#define DA732X_MIC_VOL_DB_INC 50 | |
| 95 | +#define DA732X_MIC_PRE_VOL_DB_MIN 0 | |
| 96 | +#define DA732X_MIC_PRE_VOL_DB_INC 600 | |
| 97 | +#define DA732X_AUX_VOL_DB_MIN -6000 | |
| 98 | +#define DA732X_AUX_VOL_DB_INC 150 | |
| 99 | +#define DA732X_HP_VOL_DB_MIN -2250 | |
| 100 | +#define DA732X_HP_VOL_DB_INC 150 | |
| 101 | +#define DA732X_LIN2_VOL_DB_MIN -1650 | |
| 102 | +#define DA732X_LIN2_VOL_DB_INC 150 | |
| 103 | +#define DA732X_LIN3_VOL_DB_MIN -1650 | |
| 104 | +#define DA732X_LIN3_VOL_DB_INC 150 | |
| 105 | +#define DA732X_LIN4_VOL_DB_MIN -2250 | |
| 106 | +#define DA732X_LIN4_VOL_DB_INC 150 | |
| 107 | +#define DA732X_EQ_BAND_VOL_DB_MIN -1050 | |
| 108 | +#define DA732X_EQ_BAND_VOL_DB_INC 150 | |
| 109 | +#define DA732X_DAC_VOL_DB_MIN -7725 | |
| 110 | +#define DA732X_DAC_VOL_DB_INC 75 | |
| 111 | +#define DA732X_ADC_VOL_DB_MIN 0 | |
| 112 | +#define DA732X_ADC_VOL_DB_INC -1 | |
| 113 | +#define DA732X_EQ_OVERALL_VOL_DB_MIN -1800 | |
| 114 | +#define DA732X_EQ_OVERALL_VOL_DB_INC 600 | |
| 115 | + | |
| 116 | +#define DA732X_SOC_ENUM_DOUBLE_R(xreg, xrreg, xmax, xtext) \ | |
| 117 | + {.reg = xreg, .reg2 = xrreg, .max = xmax, .texts = xtext} | |
| 118 | + | |
| 119 | +enum da732x_sysctl { | |
| 120 | + DA732X_SR_8KHZ = 0x1, | |
| 121 | + DA732X_SR_11_025KHZ = 0x2, | |
| 122 | + DA732X_SR_12KHZ = 0x3, | |
| 123 | + DA732X_SR_16KHZ = 0x5, | |
| 124 | + DA732X_SR_22_05KHZ = 0x6, | |
| 125 | + DA732X_SR_24KHZ = 0x7, | |
| 126 | + DA732X_SR_32KHZ = 0x9, | |
| 127 | + DA732X_SR_44_1KHZ = 0xA, | |
| 128 | + DA732X_SR_48KHZ = 0xB, | |
| 129 | + DA732X_SR_88_1KHZ = 0xE, | |
| 130 | + DA732X_SR_96KHZ = 0xF, | |
| 131 | +}; | |
| 132 | + | |
| 133 | +#endif /* __DA732X_H_ */ | |
| @@ -0,0 +1,654 @@ | ||
| 1 | +/* | |
| 2 | + * da732x_reg.h --- Dialog DA732X ALSA SoC Audio Registers Header File | |
| 3 | + * | |
| 4 | + * Copyright (C) 2012 Dialog Semiconductor GmbH | |
| 5 | + * | |
| 6 | + * Author: Michal Hajduk <Michal.Hajduk@diasemi.com> | |
| 7 | + * | |
| 8 | + * This program is free software; you can redistribute it and/or modify | |
| 9 | + * it under the terms of the GNU General Public License version 2 as | |
| 10 | + * published by the Free Software Foundation. | |
| 11 | + */ | |
| 12 | + | |
| 13 | +#ifndef __DA732X_REG_H_ | |
| 14 | +#define __DA732X_REG_H_ | |
| 15 | + | |
| 16 | +/* DA732X registers */ | |
| 17 | +#define DA732X_REG_STATUS_EXT 0x00 | |
| 18 | +#define DA732X_REG_STATUS 0x01 | |
| 19 | +#define DA732X_REG_REF1 0x02 | |
| 20 | +#define DA732X_REG_BIAS_EN 0x03 | |
| 21 | +#define DA732X_REG_BIAS1 0x04 | |
| 22 | +#define DA732X_REG_BIAS2 0x05 | |
| 23 | +#define DA732X_REG_BIAS3 0x06 | |
| 24 | +#define DA732X_REG_BIAS4 0x07 | |
| 25 | +#define DA732X_REG_MICBIAS2 0x0F | |
| 26 | +#define DA732X_REG_MICBIAS1 0x10 | |
| 27 | +#define DA732X_REG_MICDET 0x11 | |
| 28 | +#define DA732X_REG_MIC1_PRE 0x12 | |
| 29 | +#define DA732X_REG_MIC1 0x13 | |
| 30 | +#define DA732X_REG_MIC2_PRE 0x14 | |
| 31 | +#define DA732X_REG_MIC2 0x15 | |
| 32 | +#define DA732X_REG_AUX1L 0x16 | |
| 33 | +#define DA732X_REG_AUX1R 0x17 | |
| 34 | +#define DA732X_REG_MIC3_PRE 0x18 | |
| 35 | +#define DA732X_REG_MIC3 0x19 | |
| 36 | +#define DA732X_REG_INP_PINBIAS 0x1A | |
| 37 | +#define DA732X_REG_INP_ZC_EN 0x1B | |
| 38 | +#define DA732X_REG_INP_MUX 0x1D | |
| 39 | +#define DA732X_REG_HP_DET 0x20 | |
| 40 | +#define DA732X_REG_HPL_DAC_OFFSET 0x21 | |
| 41 | +#define DA732X_REG_HPL_DAC_OFF_CNTL 0x22 | |
| 42 | +#define DA732X_REG_HPL_OUT_OFFSET 0x23 | |
| 43 | +#define DA732X_REG_HPL 0x24 | |
| 44 | +#define DA732X_REG_HPL_VOL 0x25 | |
| 45 | +#define DA732X_REG_HPR_DAC_OFFSET 0x26 | |
| 46 | +#define DA732X_REG_HPR_DAC_OFF_CNTL 0x27 | |
| 47 | +#define DA732X_REG_HPR_OUT_OFFSET 0x28 | |
| 48 | +#define DA732X_REG_HPR 0x29 | |
| 49 | +#define DA732X_REG_HPR_VOL 0x2A | |
| 50 | +#define DA732X_REG_LIN2 0x2B | |
| 51 | +#define DA732X_REG_LIN3 0x2C | |
| 52 | +#define DA732X_REG_LIN4 0x2D | |
| 53 | +#define DA732X_REG_OUT_ZC_EN 0x2E | |
| 54 | +#define DA732X_REG_HP_LIN1_GNDSEL 0x37 | |
| 55 | +#define DA732X_REG_CP_HP1 0x3A | |
| 56 | +#define DA732X_REG_CP_HP2 0x3B | |
| 57 | +#define DA732X_REG_CP_CTRL1 0x40 | |
| 58 | +#define DA732X_REG_CP_CTRL2 0x41 | |
| 59 | +#define DA732X_REG_CP_CTRL3 0x42 | |
| 60 | +#define DA732X_REG_CP_LEVEL_MASK 0x43 | |
| 61 | +#define DA732X_REG_CP_DET 0x44 | |
| 62 | +#define DA732X_REG_CP_STATUS 0x45 | |
| 63 | +#define DA732X_REG_CP_THRESH1 0x46 | |
| 64 | +#define DA732X_REG_CP_THRESH2 0x47 | |
| 65 | +#define DA732X_REG_CP_THRESH3 0x48 | |
| 66 | +#define DA732X_REG_CP_THRESH4 0x49 | |
| 67 | +#define DA732X_REG_CP_THRESH5 0x4A | |
| 68 | +#define DA732X_REG_CP_THRESH6 0x4B | |
| 69 | +#define DA732X_REG_CP_THRESH7 0x4C | |
| 70 | +#define DA732X_REG_CP_THRESH8 0x4D | |
| 71 | +#define DA732X_REG_PLL_DIV_LO 0x50 | |
| 72 | +#define DA732X_REG_PLL_DIV_MID 0x51 | |
| 73 | +#define DA732X_REG_PLL_DIV_HI 0x52 | |
| 74 | +#define DA732X_REG_PLL_CTRL 0x53 | |
| 75 | +#define DA732X_REG_CLK_CTRL 0x54 | |
| 76 | +#define DA732X_REG_CLK_DSP 0x5A | |
| 77 | +#define DA732X_REG_CLK_EN1 0x5B | |
| 78 | +#define DA732X_REG_CLK_EN2 0x5C | |
| 79 | +#define DA732X_REG_CLK_EN3 0x5D | |
| 80 | +#define DA732X_REG_CLK_EN4 0x5E | |
| 81 | +#define DA732X_REG_CLK_EN5 0x5F | |
| 82 | +#define DA732X_REG_AIF_MCLK 0x60 | |
| 83 | +#define DA732X_REG_AIFA1 0x61 | |
| 84 | +#define DA732X_REG_AIFA2 0x62 | |
| 85 | +#define DA732X_REG_AIFA3 0x63 | |
| 86 | +#define DA732X_REG_AIFB1 0x64 | |
| 87 | +#define DA732X_REG_AIFB2 0x65 | |
| 88 | +#define DA732X_REG_AIFB3 0x66 | |
| 89 | +#define DA732X_REG_PC_CTRL 0x6A | |
| 90 | +#define DA732X_REG_DATA_ROUTE 0x70 | |
| 91 | +#define DA732X_REG_DSP_CTRL 0x71 | |
| 92 | +#define DA732X_REG_CIF_CTRL2 0x74 | |
| 93 | +#define DA732X_REG_HANDSHAKE 0x75 | |
| 94 | +#define DA732X_REG_MBOX0 0x76 | |
| 95 | +#define DA732X_REG_MBOX1 0x77 | |
| 96 | +#define DA732X_REG_MBOX2 0x78 | |
| 97 | +#define DA732X_REG_MBOX_STATUS 0x79 | |
| 98 | +#define DA732X_REG_SPARE1_OUT 0x7D | |
| 99 | +#define DA732X_REG_SPARE2_OUT 0x7E | |
| 100 | +#define DA732X_REG_SPARE1_IN 0x7F | |
| 101 | +#define DA732X_REG_ID 0x81 | |
| 102 | +#define DA732X_REG_ADC1_PD 0x90 | |
| 103 | +#define DA732X_REG_ADC1_HPF 0x93 | |
| 104 | +#define DA732X_REG_ADC1_SEL 0x94 | |
| 105 | +#define DA732X_REG_ADC1_EQ12 0x95 | |
| 106 | +#define DA732X_REG_ADC1_EQ34 0x96 | |
| 107 | +#define DA732X_REG_ADC1_EQ5 0x97 | |
| 108 | +#define DA732X_REG_ADC2_PD 0x98 | |
| 109 | +#define DA732X_REG_ADC2_HPF 0x9B | |
| 110 | +#define DA732X_REG_ADC2_SEL 0x9C | |
| 111 | +#define DA732X_REG_ADC2_EQ12 0x9D | |
| 112 | +#define DA732X_REG_ADC2_EQ34 0x9E | |
| 113 | +#define DA732X_REG_ADC2_EQ5 0x9F | |
| 114 | +#define DA732X_REG_DAC1_HPF 0xA0 | |
| 115 | +#define DA732X_REG_DAC1_L_VOL 0xA1 | |
| 116 | +#define DA732X_REG_DAC1_R_VOL 0xA2 | |
| 117 | +#define DA732X_REG_DAC1_SEL 0xA3 | |
| 118 | +#define DA732X_REG_DAC1_SOFTMUTE 0xA4 | |
| 119 | +#define DA732X_REG_DAC1_EQ12 0xA5 | |
| 120 | +#define DA732X_REG_DAC1_EQ34 0xA6 | |
| 121 | +#define DA732X_REG_DAC1_EQ5 0xA7 | |
| 122 | +#define DA732X_REG_DAC2_HPF 0xB0 | |
| 123 | +#define DA732X_REG_DAC2_L_VOL 0xB1 | |
| 124 | +#define DA732X_REG_DAC2_R_VOL 0xB2 | |
| 125 | +#define DA732X_REG_DAC2_SEL 0xB3 | |
| 126 | +#define DA732X_REG_DAC2_SOFTMUTE 0xB4 | |
| 127 | +#define DA732X_REG_DAC2_EQ12 0xB5 | |
| 128 | +#define DA732X_REG_DAC2_EQ34 0xB6 | |
| 129 | +#define DA732X_REG_DAC2_EQ5 0xB7 | |
| 130 | +#define DA732X_REG_DAC3_HPF 0xC0 | |
| 131 | +#define DA732X_REG_DAC3_VOL 0xC1 | |
| 132 | +#define DA732X_REG_DAC3_SEL 0xC3 | |
| 133 | +#define DA732X_REG_DAC3_SOFTMUTE 0xC4 | |
| 134 | +#define DA732X_REG_DAC3_EQ12 0xC5 | |
| 135 | +#define DA732X_REG_DAC3_EQ34 0xC6 | |
| 136 | +#define DA732X_REG_DAC3_EQ5 0xC7 | |
| 137 | +#define DA732X_REG_BIQ_BYP 0xD2 | |
| 138 | +#define DA732X_REG_DMA_CMD 0xD3 | |
| 139 | +#define DA732X_REG_DMA_ADDR0 0xD4 | |
| 140 | +#define DA732X_REG_DMA_ADDR1 0xD5 | |
| 141 | +#define DA732X_REG_DMA_DATA0 0xD6 | |
| 142 | +#define DA732X_REG_DMA_DATA1 0xD7 | |
| 143 | +#define DA732X_REG_DMA_DATA2 0xD8 | |
| 144 | +#define DA732X_REG_DMA_DATA3 0xD9 | |
| 145 | +#define DA732X_REG_DMA_STATUS 0xDA | |
| 146 | +#define DA732X_REG_BROWNOUT 0xDF | |
| 147 | +#define DA732X_REG_UNLOCK 0xE0 | |
| 148 | + | |
| 149 | +#define DA732X_MAX_REG DA732X_REG_UNLOCK | |
| 150 | +/* | |
| 151 | + * Bits | |
| 152 | + */ | |
| 153 | + | |
| 154 | +/* DA732X_REG_STATUS_EXT (addr=0x00) */ | |
| 155 | +#define DA732X_STATUS_EXT_DSP (1 << 4) | |
| 156 | +#define DA732X_STATUS_EXT_CLEAR (0 << 0) | |
| 157 | + | |
| 158 | +/* DA732X_REG_STATUS (addr=0x01) */ | |
| 159 | +#define DA732X_STATUS_PLL_LOCK (1 << 0) | |
| 160 | +#define DA732X_STATUS_PLL_MCLK_DET (1 << 1) | |
| 161 | +#define DA732X_STATUS_HPDET_OUT (1 << 2) | |
| 162 | +#define DA732X_STATUS_INP_MIXDET_1 (1 << 3) | |
| 163 | +#define DA732X_STATUS_INP_MIXDET_2 (1 << 4) | |
| 164 | +#define DA732X_STATUS_BO_STATUS (1 << 5) | |
| 165 | + | |
| 166 | +/* DA732X_REG_REF1 (addr=0x02) */ | |
| 167 | +#define DA732X_VMID_FASTCHG (1 << 1) | |
| 168 | +#define DA732X_VMID_FASTDISCHG (1 << 2) | |
| 169 | +#define DA732X_REFBUFX2_EN (1 << 6) | |
| 170 | +#define DA732X_REFBUFX2_DIS (0 << 6) | |
| 171 | + | |
| 172 | +/* DA732X_REG_BIAS_EN (addr=0x03) */ | |
| 173 | +#define DA732X_BIAS_BOOST_MASK (3 << 0) | |
| 174 | +#define DA732X_BIAS_BOOST_100PC (0 << 0) | |
| 175 | +#define DA732X_BIAS_BOOST_133PC (1 << 0) | |
| 176 | +#define DA732X_BIAS_BOOST_88PC (2 << 0) | |
| 177 | +#define DA732X_BIAS_BOOST_50PC (3 << 0) | |
| 178 | +#define DA732X_BIAS_EN (1 << 7) | |
| 179 | +#define DA732X_BIAS_DIS (0 << 7) | |
| 180 | + | |
| 181 | +/* DA732X_REG_BIAS1 (addr=0x04) */ | |
| 182 | +#define DA732X_BIAS1_HP_DAC_BIAS_MASK (3 << 0) | |
| 183 | +#define DA732X_BIAS1_HP_DAC_BIAS_100PC (0 << 0) | |
| 184 | +#define DA732X_BIAS1_HP_DAC_BIAS_150PC (1 << 0) | |
| 185 | +#define DA732X_BIAS1_HP_DAC_BIAS_50PC (2 << 0) | |
| 186 | +#define DA732X_BIAS1_HP_DAC_BIAS_75PC (3 << 0) | |
| 187 | +#define DA732X_BIAS1_HP_OUT_BIAS_MASK (7 << 4) | |
| 188 | +#define DA732X_BIAS1_HP_OUT_BIAS_100PC (0 << 4) | |
| 189 | +#define DA732X_BIAS1_HP_OUT_BIAS_125PC (1 << 4) | |
| 190 | +#define DA732X_BIAS1_HP_OUT_BIAS_150PC (2 << 4) | |
| 191 | +#define DA732X_BIAS1_HP_OUT_BIAS_175PC (3 << 4) | |
| 192 | +#define DA732X_BIAS1_HP_OUT_BIAS_200PC (4 << 4) | |
| 193 | +#define DA732X_BIAS1_HP_OUT_BIAS_250PC (5 << 4) | |
| 194 | +#define DA732X_BIAS1_HP_OUT_BIAS_300PC (6 << 4) | |
| 195 | +#define DA732X_BIAS1_HP_OUT_BIAS_350PC (7 << 4) | |
| 196 | + | |
| 197 | +/* DA732X_REG_BIAS2 (addr=0x05) */ | |
| 198 | +#define DA732X_BIAS2_LINE2_DAC_BIAS_MASK (3 << 0) | |
| 199 | +#define DA732X_BIAS2_LINE2_DAC_BIAS_100PC (0 << 0) | |
| 200 | +#define DA732X_BIAS2_LINE2_DAC_BIAS_150PC (1 << 0) | |
| 201 | +#define DA732X_BIAS2_LINE2_DAC_BIAS_50PC (2 << 0) | |
| 202 | +#define DA732X_BIAS2_LINE2_DAC_BIAS_75PC (3 << 0) | |
| 203 | +#define DA732X_BIAS2_LINE2_OUT_BIAS_MASK (7 << 4) | |
| 204 | +#define DA732X_BIAS2_LINE2_OUT_BIAS_100PC (0 << 4) | |
| 205 | +#define DA732X_BIAS2_LINE2_OUT_BIAS_125PC (1 << 4) | |
| 206 | +#define DA732X_BIAS2_LINE2_OUT_BIAS_150PC (2 << 4) | |
| 207 | +#define DA732X_BIAS2_LINE2_OUT_BIAS_175PC (3 << 4) | |
| 208 | +#define DA732X_BIAS2_LINE2_OUT_BIAS_200PC (4 << 4) | |
| 209 | +#define DA732X_BIAS2_LINE2_OUT_BIAS_250PC (5 << 4) | |
| 210 | +#define DA732X_BIAS2_LINE2_OUT_BIAS_300PC (6 << 4) | |
| 211 | +#define DA732X_BIAS2_LINE2_OUT_BIAS_350PC (7 << 4) | |
| 212 | + | |
| 213 | +/* DA732X_REG_BIAS3 (addr=0x06) */ | |
| 214 | +#define DA732X_BIAS3_LINE3_DAC_BIAS_MASK (3 << 0) | |
| 215 | +#define DA732X_BIAS3_LINE3_DAC_BIAS_100PC (0 << 0) | |
| 216 | +#define DA732X_BIAS3_LINE3_DAC_BIAS_150PC (1 << 0) | |
| 217 | +#define DA732X_BIAS3_LINE3_DAC_BIAS_50PC (2 << 0) | |
| 218 | +#define DA732X_BIAS3_LINE3_DAC_BIAS_75PC (3 << 0) | |
| 219 | +#define DA732X_BIAS3_LINE3_OUT_BIAS_MASK (7 << 4) | |
| 220 | +#define DA732X_BIAS3_LINE3_OUT_BIAS_100PC (0 << 4) | |
| 221 | +#define DA732X_BIAS3_LINE3_OUT_BIAS_125PC (1 << 4) | |
| 222 | +#define DA732X_BIAS3_LINE3_OUT_BIAS_150PC (2 << 4) | |
| 223 | +#define DA732X_BIAS3_LINE3_OUT_BIAS_175PC (3 << 4) | |
| 224 | +#define DA732X_BIAS3_LINE3_OUT_BIAS_200PC (4 << 4) | |
| 225 | +#define DA732X_BIAS3_LINE3_OUT_BIAS_250PC (5 << 4) | |
| 226 | +#define DA732X_BIAS3_LINE3_OUT_BIAS_300PC (6 << 4) | |
| 227 | +#define DA732X_BIAS3_LINE3_OUT_BIAS_350PC (7 << 4) | |
| 228 | + | |
| 229 | +/* DA732X_REG_BIAS4 (addr=0x07) */ | |
| 230 | +#define DA732X_BIAS4_LINE4_DAC_BIAS_MASK (3 << 0) | |
| 231 | +#define DA732X_BIAS4_LINE4_DAC_BIAS_100PC (0 << 0) | |
| 232 | +#define DA732X_BIAS4_LINE4_DAC_BIAS_150PC (1 << 0) | |
| 233 | +#define DA732X_BIAS4_LINE4_DAC_BIAS_50PC (2 << 0) | |
| 234 | +#define DA732X_BIAS4_LINE4_DAC_BIAS_75PC (3 << 0) | |
| 235 | +#define DA732X_BIAS4_LINE4_OUT_BIAS_MASK (7 << 4) | |
| 236 | +#define DA732X_BIAS4_LINE4_OUT_BIAS_100PC (0 << 4) | |
| 237 | +#define DA732X_BIAS4_LINE4_OUT_BIAS_125PC (1 << 4) | |
| 238 | +#define DA732X_BIAS4_LINE4_OUT_BIAS_150PC (2 << 4) | |
| 239 | +#define DA732X_BIAS4_LINE4_OUT_BIAS_175PC (3 << 4) | |
| 240 | +#define DA732X_BIAS4_LINE4_OUT_BIAS_200PC (4 << 4) | |
| 241 | +#define DA732X_BIAS4_LINE4_OUT_BIAS_250PC (5 << 4) | |
| 242 | +#define DA732X_BIAS4_LINE4_OUT_BIAS_300PC (6 << 4) | |
| 243 | +#define DA732X_BIAS4_LINE4_OUT_BIAS_350PC (7 << 4) | |
| 244 | + | |
| 245 | +/* DA732X_REG_SIF_VDD_SEL (addr=0x08) */ | |
| 246 | +#define DA732X_SIF_VDD_SEL_AIFA_VDD2 (1 << 0) | |
| 247 | +#define DA732X_SIF_VDD_SEL_AIFB_VDD2 (1 << 1) | |
| 248 | +#define DA732X_SIF_VDD_SEL_CIFA_VDD2 (1 << 4) | |
| 249 | + | |
| 250 | +/* DA732X_REG_MICBIAS2/1 (addr=0x0F/0x10) */ | |
| 251 | +#define DA732X_MICBIAS_VOLTAGE_MASK (0x0F << 0) | |
| 252 | +#define DA732X_MICBIAS_VOLTAGE_2V (0x00 << 0) | |
| 253 | +#define DA732X_MICBIAS_VOLTAGE_2V05 (0x01 << 0) | |
| 254 | +#define DA732X_MICBIAS_VOLTAGE_2V1 (0x02 << 0) | |
| 255 | +#define DA732X_MICBIAS_VOLTAGE_2V15 (0x03 << 0) | |
| 256 | +#define DA732X_MICBIAS_VOLTAGE_2V2 (0x04 << 0) | |
| 257 | +#define DA732X_MICBIAS_VOLTAGE_2V25 (0x05 << 0) | |
| 258 | +#define DA732X_MICBIAS_VOLTAGE_2V3 (0x06 << 0) | |
| 259 | +#define DA732X_MICBIAS_VOLTAGE_2V35 (0x07 << 0) | |
| 260 | +#define DA732X_MICBIAS_VOLTAGE_2V4 (0x08 << 0) | |
| 261 | +#define DA732X_MICBIAS_VOLTAGE_2V45 (0x09 << 0) | |
| 262 | +#define DA732X_MICBIAS_VOLTAGE_2V5 (0x0A << 0) | |
| 263 | +#define DA732X_MICBIAS_EN (1 << 7) | |
| 264 | +#define DA732X_MICBIAS_EN_SHIFT 7 | |
| 265 | +#define DA732X_MICBIAS_VOLTAGE_SHIFT 0 | |
| 266 | +#define DA732X_MICBIAS_VOLTAGE_MAX 0x0B | |
| 267 | + | |
| 268 | +/* DA732X_REG_MICDET (addr=0x11) */ | |
| 269 | +#define DA732X_MICDET_INP_MICRES (1 << 0) | |
| 270 | +#define DA732X_MICDET_INP_MICHOOK (1 << 1) | |
| 271 | +#define DA732X_MICDET_INP_DEBOUNCE_PRD_8MS (0 << 0) | |
| 272 | +#define DA732X_MICDET_INP_DEBOUNCE_PRD_16MS (1 << 0) | |
| 273 | +#define DA732X_MICDET_INP_DEBOUNCE_PRD_32MS (2 << 0) | |
| 274 | +#define DA732X_MICDET_INP_DEBOUNCE_PRD_64MS (3 << 0) | |
| 275 | +#define DA732X_MICDET_INP_MICDET_EN (1 << 7) | |
| 276 | + | |
| 277 | +/* DA732X_REG_MIC1/2/3_PRE (addr=0x11/0x14/0x18) */ | |
| 278 | +#define DA732X_MICBOOST_MASK 0x7 | |
| 279 | +#define DA732X_MICBOOST_SHIFT 0 | |
| 280 | +#define DA732X_MICBOOST_MIN 0x1 | |
| 281 | +#define DA732X_MICBOOST_MAX DA732X_MICBOOST_MASK | |
| 282 | + | |
| 283 | +/* DA732X_REG_MIC1/2/3 (addr=0x13/0x15/0x19) */ | |
| 284 | +#define DA732X_MIC_VOL_SHIFT 0 | |
| 285 | +#define DA732X_MIC_VOL_VAL_MASK 0x1F | |
| 286 | +#define DA732X_MIC_MUTE_SHIFT 6 | |
| 287 | +#define DA732X_MIC_EN_SHIFT 7 | |
| 288 | +#define DA732X_MIC_VOL_VAL_MIN 0x7 | |
| 289 | +#define DA732X_MIC_VOL_VAL_MAX DA732X_MIC_VOL_VAL_MASK | |
| 290 | + | |
| 291 | +/* DA732X_REG_AUX1L/R (addr=0x16/0x17) */ | |
| 292 | +#define DA732X_AUX_VOL_SHIFT 0 | |
| 293 | +#define DA732X_AUX_VOL_MASK 0x7 | |
| 294 | +#define DA732X_AUX_MUTE_SHIFT 6 | |
| 295 | +#define DA732X_AUX_EN_SHIFT 7 | |
| 296 | +#define DA732X_AUX_VOL_VAL_MAX DA732X_AUX_VOL_MASK | |
| 297 | + | |
| 298 | +/* DA732X_REG_INP_PINBIAS (addr=0x1A) */ | |
| 299 | +#define DA732X_INP_MICL_PINBIAS_EN (1 << 0) | |
| 300 | +#define DA732X_INP_MICR_PINBIAS_EN (1 << 1) | |
| 301 | +#define DA732X_INP_AUX1L_PINBIAS_EN (1 << 2) | |
| 302 | +#define DA732X_INP_AUX1R_PINBIAS_EN (1 << 3) | |
| 303 | +#define DA732X_INP_AUX2_PINBIAS_EN (1 << 4) | |
| 304 | + | |
| 305 | +/* DA732X_REG_INP_ZC_EN (addr=0x1B) */ | |
| 306 | +#define DA732X_MIC1_PRE_ZC_EN (1 << 0) | |
| 307 | +#define DA732X_MIC1_ZC_EN (1 << 1) | |
| 308 | +#define DA732X_MIC2_PRE_ZC_EN (1 << 2) | |
| 309 | +#define DA732X_MIC2_ZC_EN (1 << 3) | |
| 310 | +#define DA732X_AUXL_ZC_EN (1 << 4) | |
| 311 | +#define DA732X_AUXR_ZC_EN (1 << 5) | |
| 312 | +#define DA732X_MIC3_PRE_ZC_EN (1 << 6) | |
| 313 | +#define DA732X_MIC3_ZC_EN (1 << 7) | |
| 314 | + | |
| 315 | +/* DA732X_REG_INP_MUX (addr=0x1D) */ | |
| 316 | +#define DA732X_INP_ADC1L_MUX_SEL_AUX1L (0 << 0) | |
| 317 | +#define DA732X_INP_ADC1L_MUX_SEL_MIC1 (1 << 0) | |
| 318 | +#define DA732X_INP_ADC1R_MUX_SEL_MASK (3 << 2) | |
| 319 | +#define DA732X_INP_ADC1R_MUX_SEL_AUX1R (0 << 2) | |
| 320 | +#define DA732X_INP_ADC1R_MUX_SEL_MIC2 (1 << 2) | |
| 321 | +#define DA732X_INP_ADC1R_MUX_SEL_MIC3 (2 << 2) | |
| 322 | +#define DA732X_INP_ADC2L_MUX_SEL_AUX1L (0 << 4) | |
| 323 | +#define DA732X_INP_ADC2L_MUX_SEL_MICL (1 << 4) | |
| 324 | +#define DA732X_INP_ADC2R_MUX_SEL_MASK (3 << 6) | |
| 325 | +#define DA732X_INP_ADC2R_MUX_SEL_AUX1R (0 << 6) | |
| 326 | +#define DA732X_INP_ADC2R_MUX_SEL_MICR (1 << 6) | |
| 327 | +#define DA732X_INP_ADC2R_MUX_SEL_AUX2 (2 << 6) | |
| 328 | +#define DA732X_ADC1L_MUX_SEL_SHIFT 0 | |
| 329 | +#define DA732X_ADC1R_MUX_SEL_SHIFT 2 | |
| 330 | +#define DA732X_ADC2L_MUX_SEL_SHIFT 4 | |
| 331 | +#define DA732X_ADC2R_MUX_SEL_SHIFT 6 | |
| 332 | + | |
| 333 | +/* DA732X_REG_HP_DET (addr=0x20) */ | |
| 334 | +#define DA732X_HP_DET_AZ (1 << 0) | |
| 335 | +#define DA732X_HP_DET_SEL1 (1 << 1) | |
| 336 | +#define DA732X_HP_DET_IS_MASK (3 << 2) | |
| 337 | +#define DA732X_HP_DET_IS_0_5UA (0 << 2) | |
| 338 | +#define DA732X_HP_DET_IS_1UA (1 << 2) | |
| 339 | +#define DA732X_HP_DET_IS_2UA (2 << 2) | |
| 340 | +#define DA732X_HP_DET_IS_4UA (3 << 2) | |
| 341 | +#define DA732X_HP_DET_RS_MASK (3 << 4) | |
| 342 | +#define DA732X_HP_DET_RS_INFINITE (0 << 4) | |
| 343 | +#define DA732X_HP_DET_RS_100KOHM (1 << 4) | |
| 344 | +#define DA732X_HP_DET_RS_10KOHM (2 << 4) | |
| 345 | +#define DA732X_HP_DET_RS_1KOHM (3 << 4) | |
| 346 | +#define DA732X_HP_DET_EN (1 << 7) | |
| 347 | + | |
| 348 | +/* DA732X_REG_HPL_DAC_OFFSET (addr=0x21/0x26) */ | |
| 349 | +#define DA732X_HP_DAC_OFFSET_TRIM_MASK (0x3F << 0) | |
| 350 | +#define DA732X_HP_DAC_OFFSET_DAC_SIGN (1 << 6) | |
| 351 | + | |
| 352 | +/* DA732X_REG_HPL_DAC_OFF_CNTL (addr=0x22/0x27) */ | |
| 353 | +#define DA732X_HP_DAC_OFF_CNTL_CONT_MASK (7 << 0) | |
| 354 | +#define DA732X_HP_DAC_OFF_CNTL_COMPO (1 << 3) | |
| 355 | +#define DA732X_HP_DAC_OFF_CALIBRATION (1 << 0) | |
| 356 | +#define DA732X_HP_DAC_OFF_SCALE_STEPS (1 << 1) | |
| 357 | +#define DA732X_HP_DAC_OFF_MASK 0x7F | |
| 358 | +#define DA732X_HP_DAC_COMPO_SHIFT 3 | |
| 359 | + | |
| 360 | +/* DA732X_REG_HPL_OUT_OFFSET (addr=0x23/0x28) */ | |
| 361 | +#define DA732X_HP_OUT_OFFSET_MASK (0xFF << 0) | |
| 362 | +#define DA732X_HP_DAC_OFFSET_TRIM_VAL 0x7F | |
| 363 | + | |
| 364 | +/* DA732X_REG_HPL/R (addr=0x24/0x29) */ | |
| 365 | +#define DA732X_HP_OUT_SIGN (1 << 0) | |
| 366 | +#define DA732X_HP_OUT_COMP (1 << 1) | |
| 367 | +#define DA732X_HP_OUT_RESERVED (1 << 2) | |
| 368 | +#define DA732X_HP_OUT_COMPO (1 << 3) | |
| 369 | +#define DA732X_HP_OUT_DAC_EN (1 << 4) | |
| 370 | +#define DA732X_HP_OUT_HIZ_EN (1 << 5) | |
| 371 | +#define DA732X_HP_OUT_HIZ_DIS (0 << 5) | |
| 372 | +#define DA732X_HP_OUT_MUTE (1 << 6) | |
| 373 | +#define DA732X_HP_OUT_EN (1 << 7) | |
| 374 | +#define DA732X_HP_OUT_COMPO_SHIFT 3 | |
| 375 | +#define DA732X_HP_OUT_DAC_EN_SHIFT 4 | |
| 376 | +#define DA732X_HP_HIZ_SHIFT 5 | |
| 377 | +#define DA732X_HP_MUTE_SHIFT 6 | |
| 378 | +#define DA732X_HP_OUT_EN_SHIFT 7 | |
| 379 | + | |
| 380 | +#define DA732X_OUT_HIZ_EN (1 << 5) | |
| 381 | +#define DA732X_OUT_HIZ_DIS (0 << 5) | |
| 382 | + | |
| 383 | +/* DA732X_REG_HPL/R_VOL (addr=0x25/0x2A) */ | |
| 384 | +#define DA732X_HP_VOL_VAL_MASK 0xF | |
| 385 | +#define DA732X_HP_VOL_SHIFT 0 | |
| 386 | +#define DA732X_HP_VOL_VAL_MAX DA732X_HP_VOL_VAL_MASK | |
| 387 | + | |
| 388 | +/* DA732X_REG_LIN2/3/4 (addr=0x2B/0x2C/0x2D) */ | |
| 389 | +#define DA732X_LOUT_VOL_SHIFT 0 | |
| 390 | +#define DA732X_LOUT_VOL_MASK 0x0F | |
| 391 | +#define DA732X_LOUT_DAC_OFF (0 << 4) | |
| 392 | +#define DA732X_LOUT_DAC_EN (1 << 4) | |
| 393 | +#define DA732X_LOUT_HIZ_N_DIS (0 << 5) | |
| 394 | +#define DA732X_LOUT_HIZ_N_EN (1 << 5) | |
| 395 | +#define DA732X_LOUT_UNMUTED (0 << 6) | |
| 396 | +#define DA732X_LOUT_MUTED (1 << 6) | |
| 397 | +#define DA732X_LOUT_EN (0 << 7) | |
| 398 | +#define DA732X_LOUT_DIS (1 << 7) | |
| 399 | +#define DA732X_LOUT_DAC_EN_SHIFT 4 | |
| 400 | +#define DA732X_LOUT_MUTE_SHIFT 6 | |
| 401 | +#define DA732X_LIN_OUT_EN_SHIFT 7 | |
| 402 | +#define DA732X_LOUT_VOL_VAL_MAX DA732X_LOUT_VOL_MASK | |
| 403 | + | |
| 404 | +/* DA732X_REG_OUT_ZC_EN (addr=0x2E) */ | |
| 405 | +#define DA732X_HPL_ZC_EN_SHIFT 0 | |
| 406 | +#define DA732X_HPR_ZC_EN_SHIFT 1 | |
| 407 | +#define DA732X_HPL_ZC_EN (1 << 0) | |
| 408 | +#define DA732X_HPL_ZC_DIS (0 << 0) | |
| 409 | +#define DA732X_HPR_ZC_EN (1 << 1) | |
| 410 | +#define DA732X_HPR_ZC_DIS (0 << 1) | |
| 411 | +#define DA732X_LIN2_ZC_EN (1 << 2) | |
| 412 | +#define DA732X_LIN2_ZC_DIS (0 << 2) | |
| 413 | +#define DA732X_LIN3_ZC_EN (1 << 3) | |
| 414 | +#define DA732X_LIN3_ZC_DIS (0 << 3) | |
| 415 | +#define DA732X_LIN4_ZC_EN (1 << 4) | |
| 416 | +#define DA732X_LIN4_ZC_DIS (0 << 4) | |
| 417 | + | |
| 418 | +/* DA732X_REG_HP_LIN1_GNDSEL (addr=0x37) */ | |
| 419 | +#define DA732X_HP_OUT_GNDSEL (1 << 0) | |
| 420 | + | |
| 421 | +/* DA732X_REG_CP_HP2 (addr=0x3a) */ | |
| 422 | +#define DA732X_HP_CP_PULSESKIP (1 << 0) | |
| 423 | +#define DA732X_HP_CP_REG (1 << 1) | |
| 424 | +#define DA732X_HP_CP_EN (1 << 3) | |
| 425 | +#define DA732X_HP_CP_DIS (0 << 3) | |
| 426 | + | |
| 427 | +/* DA732X_REG_CP_CTRL1 (addr=0x40) */ | |
| 428 | +#define DA732X_CP_MODE_MASK (7 << 1) | |
| 429 | +#define DA732X_CP_CTRL_STANDBY (0 << 1) | |
| 430 | +#define DA732X_CP_CTRL_CPVDD6 (2 << 1) | |
| 431 | +#define DA732X_CP_CTRL_CPVDD5 (3 << 1) | |
| 432 | +#define DA732X_CP_CTRL_CPVDD4 (4 << 1) | |
| 433 | +#define DA732X_CP_CTRL_CPVDD3 (5 << 1) | |
| 434 | +#define DA732X_CP_CTRL_CPVDD2 (6 << 1) | |
| 435 | +#define DA732X_CP_CTRL_CPVDD1 (7 << 1) | |
| 436 | +#define DA723X_CP_DIS (0 << 7) | |
| 437 | +#define DA732X_CP_EN (1 << 7) | |
| 438 | + | |
| 439 | +/* DA732X_REG_CP_CTRL2 (addr=0x41) */ | |
| 440 | +#define DA732X_CP_BOOST (1 << 0) | |
| 441 | +#define DA732X_CP_MANAGE_MAGNITUDE (2 << 2) | |
| 442 | + | |
| 443 | +/* DA732X_REG_CP_CTRL3 (addr=0x42) */ | |
| 444 | +#define DA732X_CP_1MHZ (0 << 0) | |
| 445 | +#define DA732X_CP_500KHZ (1 << 0) | |
| 446 | +#define DA732X_CP_250KHZ (2 << 0) | |
| 447 | +#define DA732X_CP_125KHZ (3 << 0) | |
| 448 | +#define DA732X_CP_63KHZ (4 << 0) | |
| 449 | +#define DA732X_CP_0KHZ (5 << 0) | |
| 450 | + | |
| 451 | +/* DA732X_REG_PLL_CTRL (addr=0x53) */ | |
| 452 | +#define DA732X_PLL_INDIV_MASK (3 << 0) | |
| 453 | +#define DA732X_PLL_SRM_EN (1 << 2) | |
| 454 | +#define DA732X_PLL_EN (1 << 7) | |
| 455 | +#define DA732X_PLL_BYPASS (0 << 0) | |
| 456 | + | |
| 457 | +/* DA732X_REG_CLK_CTRL (addr=0x54) */ | |
| 458 | +#define DA732X_SR1_MASK (0xF) | |
| 459 | +#define DA732X_SR2_MASK (0xF0) | |
| 460 | + | |
| 461 | +/* DA732X_REG_CLK_DSP (addr=0x5A) */ | |
| 462 | +#define DA732X_DSP_FREQ_MASK (7 << 0) | |
| 463 | +#define DA732X_DSP_FREQ_12MHZ (0 << 0) | |
| 464 | +#define DA732X_DSP_FREQ_24MHZ (1 << 0) | |
| 465 | +#define DA732X_DSP_FREQ_36MHZ (2 << 0) | |
| 466 | +#define DA732X_DSP_FREQ_48MHZ (3 << 0) | |
| 467 | +#define DA732X_DSP_FREQ_60MHZ (4 << 0) | |
| 468 | +#define DA732X_DSP_FREQ_72MHZ (5 << 0) | |
| 469 | +#define DA732X_DSP_FREQ_84MHZ (6 << 0) | |
| 470 | +#define DA732X_DSP_FREQ_96MHZ (7 << 0) | |
| 471 | + | |
| 472 | +/* DA732X_REG_CLK_EN1 (addr=0x5B) */ | |
| 473 | +#define DA732X_DSP_CLK_EN (1 << 0) | |
| 474 | +#define DA732X_SYS3_CLK_EN (1 << 1) | |
| 475 | +#define DA732X_DSP12_CLK_EN (1 << 2) | |
| 476 | +#define DA732X_PC_CLK_EN (1 << 3) | |
| 477 | +#define DA732X_MCLK_SQR_EN (1 << 7) | |
| 478 | + | |
| 479 | +/* DA732X_REG_CLK_EN2 (addr=0x5C) */ | |
| 480 | +#define DA732X_UART_CLK_EN (1 << 1) | |
| 481 | +#define DA732X_CP_CLK_EN (1 << 2) | |
| 482 | +#define DA732X_CP_CLK_DIS (0 << 2) | |
| 483 | + | |
| 484 | +/* DA732X_REG_CLK_EN3 (addr=0x5D) */ | |
| 485 | +#define DA732X_ADCA_BB_CLK_EN (1 << 0) | |
| 486 | +#define DA732X_ADCC_BB_CLK_EN (1 << 4) | |
| 487 | + | |
| 488 | +/* DA732X_REG_CLK_EN4 (addr=0x5E) */ | |
| 489 | +#define DA732X_DACA_BB_CLK_EN (1 << 0) | |
| 490 | +#define DA732X_DACC_BB_CLK_EN (1 << 4) | |
| 491 | +#define DA732X_DACA_BB_CLK_SHIFT 0 | |
| 492 | +#define DA732X_DACC_BB_CLK_SHIFT 4 | |
| 493 | + | |
| 494 | +/* DA732X_REG_CLK_EN5 (addr=0x5F) */ | |
| 495 | +#define DA732X_DACE_BB_CLK_EN (1 << 0) | |
| 496 | +#define DA732X_DACE_BB_CLK_SHIFT 0 | |
| 497 | + | |
| 498 | +/* DA732X_REG_AIF_MCLK (addr=0x60) */ | |
| 499 | +#define DA732X_AIFM_FRAME_64 (1 << 2) | |
| 500 | +#define DA732X_AIFM_SRC_SEL_AIFA (1 << 6) | |
| 501 | +#define DA732X_CLK_GENERATION_AIF_A (1 << 4) | |
| 502 | +#define DA732X_NO_CLK_GENERATION 0x0 | |
| 503 | + | |
| 504 | +/* DA732X_REG_AIFA1 (addr=0x61) */ | |
| 505 | +#define DA732X_AIF_WORD_MASK (0x3 << 0) | |
| 506 | +#define DA732X_AIF_WORD_16 (0 << 0) | |
| 507 | +#define DA732X_AIF_WORD_20 (1 << 0) | |
| 508 | +#define DA732X_AIF_WORD_24 (2 << 0) | |
| 509 | +#define DA732X_AIF_WORD_32 (3 << 0) | |
| 510 | +#define DA732X_AIF_TDM_MONO_SHIFT (1 << 6) | |
| 511 | +#define DA732X_AIF1_CLK_MASK (1 << 7) | |
| 512 | +#define DA732X_AIF_SLAVE (0 << 7) | |
| 513 | +#define DA732X_AIF_CLK_FROM_SRC (1 << 7) | |
| 514 | + | |
| 515 | +/* DA732X_REG_AIFA3 (addr=0x63) */ | |
| 516 | +#define DA732X_AIF_MODE_SHIFT 0 | |
| 517 | +#define DA732X_AIF_MODE_MASK 0x3 | |
| 518 | +#define DA732X_AIF_I2S_MODE (0 << 0) | |
| 519 | +#define DA732X_AIF_LEFT_J_MODE (1 << 0) | |
| 520 | +#define DA732X_AIF_RIGHT_J_MODE (2 << 0) | |
| 521 | +#define DA732X_AIF_DSP_MODE (3 << 0) | |
| 522 | +#define DA732X_AIF_WCLK_INV (1 << 4) | |
| 523 | +#define DA732X_AIF_BCLK_INV (1 << 5) | |
| 524 | +#define DA732X_AIF_EN (1 << 7) | |
| 525 | +#define DA732X_AIF_EN_SHIFT 7 | |
| 526 | + | |
| 527 | +/* DA732X_REG_PC_CTRL (addr=0x6a) */ | |
| 528 | +#define DA732X_PC_PULSE_AIFA (0 << 0) | |
| 529 | +#define DA732X_PC_PULSE_AIFB (1 << 0) | |
| 530 | +#define DA732X_PC_RESYNC_AUT (1 << 6) | |
| 531 | +#define DA732X_PC_RESYNC_NOT_AUT (0 << 6) | |
| 532 | +#define DA732X_PC_SAME (1 << 7) | |
| 533 | + | |
| 534 | +/* DA732X_REG_DATA_ROUTE (addr=0x70) */ | |
| 535 | +#define DA732X_ADC1_TO_AIFA (0 << 0) | |
| 536 | +#define DA732X_DSP_TO_AIFA (1 << 0) | |
| 537 | +#define DA732X_ADC2_TO_AIFB (0 << 1) | |
| 538 | +#define DA732X_DSP_TO_AIFB (1 << 1) | |
| 539 | +#define DA732X_AIFA_TO_DAC1L (0 << 2) | |
| 540 | +#define DA732X_DSP_TO_DAC1L (1 << 2) | |
| 541 | +#define DA732X_AIFA_TO_DAC1R (0 << 3) | |
| 542 | +#define DA732X_DSP_TO_DAC1R (1 << 3) | |
| 543 | +#define DA732X_AIFB_TO_DAC2L (0 << 4) | |
| 544 | +#define DA732X_DSP_TO_DAC2L (1 << 4) | |
| 545 | +#define DA732X_AIFB_TO_DAC2R (0 << 5) | |
| 546 | +#define DA732X_DSP_TO_DAC2R (1 << 5) | |
| 547 | +#define DA732X_AIFB_TO_DAC3 (0 << 6) | |
| 548 | +#define DA732X_DSP_TO_DAC3 (1 << 6) | |
| 549 | +#define DA732X_BYPASS_DSP (0 << 0) | |
| 550 | +#define DA732X_ALL_TO_DSP (0x7F << 0) | |
| 551 | + | |
| 552 | +/* DA732X_REG_DSP_CTRL (addr=0x71) */ | |
| 553 | +#define DA732X_DIGITAL_EN (1 << 0) | |
| 554 | +#define DA732X_DIGITAL_RESET (0 << 0) | |
| 555 | +#define DA732X_DSP_CORE_EN (1 << 1) | |
| 556 | +#define DA732X_DSP_CORE_RESET (0 << 1) | |
| 557 | + | |
| 558 | +/* DA732X_REG_SPARE1_OUT (addr=0x7D)*/ | |
| 559 | +#define DA732X_HP_DRIVER_EN (1 << 0) | |
| 560 | +#define DA732X_HP_GATE_LOW (1 << 2) | |
| 561 | +#define DA732X_HP_LOOP_GAIN_CTRL (1 << 3) | |
| 562 | + | |
| 563 | +/* DA732X_REG_ID (addr=0x81)*/ | |
| 564 | +#define DA732X_ID_MINOR_MASK (0xF << 0) | |
| 565 | +#define DA732X_ID_MAJOR_MASK (0xF << 4) | |
| 566 | + | |
| 567 | +/* DA732X_REG_ADC1/2_PD (addr=0x90/0x98) */ | |
| 568 | +#define DA732X_ADC_RST_MASK (0x3 << 0) | |
| 569 | +#define DA732X_ADC_PD_MASK (0x3 << 2) | |
| 570 | +#define DA732X_ADC_SET_ACT (0x3 << 0) | |
| 571 | +#define DA732X_ADC_SET_RST (0x0 << 0) | |
| 572 | +#define DA732X_ADC_ON (0x3 << 2) | |
| 573 | +#define DA732X_ADC_OFF (0x0 << 2) | |
| 574 | + | |
| 575 | +/* DA732X_REG_ADC1/2_SEL (addr=0x94/0x9C) */ | |
| 576 | +#define DA732X_ADC_VOL_VAL_MASK 0x7 | |
| 577 | +#define DA732X_ADCL_VOL_SHIFT 0 | |
| 578 | +#define DA732X_ADCR_VOL_SHIFT 4 | |
| 579 | +#define DA732X_ADCL_EN_SHIFT 2 | |
| 580 | +#define DA732X_ADCR_EN_SHIFT 3 | |
| 581 | +#define DA732X_ADCL_EN (1 << 2) | |
| 582 | +#define DA732X_ADCR_EN (1 << 3) | |
| 583 | +#define DA732X_ADC_VOL_VAL_MAX DA732X_ADC_VOL_VAL_MASK | |
| 584 | + | |
| 585 | +/* | |
| 586 | + * DA732X_REG_ADC1/2_HPF (addr=0x93/0x9b) | |
| 587 | + * DA732x_REG_DAC1/2/3_HPG (addr=0xA5/0xB5/0xC5) | |
| 588 | + */ | |
| 589 | +#define DA732X_HPF_MUSIC_EN (1 << 3) | |
| 590 | +#define DA732X_HPF_VOICE_EN ((1 << 3) | (1 << 7)) | |
| 591 | +#define DA732X_HPF_MASK ((1 << 3) | (1 << 7)) | |
| 592 | +#define DA732X_HPF_DIS ((0 << 3) | (0 << 7)) | |
| 593 | + | |
| 594 | +/* DA732X_REG_DAC1/2/3_VOL */ | |
| 595 | +#define DA732X_DAC_VOL_VAL_MASK 0x7F | |
| 596 | +#define DA732X_DAC_VOL_SHIFT 0 | |
| 597 | +#define DA732X_DAC_VOL_VAL_MAX DA732X_DAC_VOL_VAL_MASK | |
| 598 | + | |
| 599 | +/* DA732X_REG_DAC1/2/3_SEL (addr=0xA3/0xB3/0xC3) */ | |
| 600 | +#define DA732X_DACL_EN_SHIFT 3 | |
| 601 | +#define DA732X_DACR_EN_SHIFT 7 | |
| 602 | +#define DA732X_DACL_MUTE_SHIFT 2 | |
| 603 | +#define DA732X_DACR_MUTE_SHIFT 6 | |
| 604 | +#define DA732X_DACL_EN (1 << 3) | |
| 605 | +#define DA732X_DACR_EN (1 << 7) | |
| 606 | +#define DA732X_DACL_SDM (1 << 0) | |
| 607 | +#define DA732X_DACR_SDM (1 << 4) | |
| 608 | +#define DA732X_DACL_MUTE (1 << 2) | |
| 609 | +#define DA732X_DACR_MUTE (1 << 6) | |
| 610 | + | |
| 611 | +/* DA732X_REG_DAC_SOFTMUTE (addr=0xA4/0xB4/0xC4) */ | |
| 612 | +#define DA732X_SOFTMUTE_EN (1 << 7) | |
| 613 | +#define DA732X_GAIN_RAMPED (1 << 6) | |
| 614 | +#define DA732X_16_SAMPLES (4 << 0) | |
| 615 | +#define DA732X_SOFTMUTE_MASK (1 << 7) | |
| 616 | +#define DA732X_SOFTMUTE_SHIFT 7 | |
| 617 | + | |
| 618 | +/* | |
| 619 | + * DA732x_REG_ADC1/2_EQ12 (addr=0x95/0x9D) | |
| 620 | + * DA732x_REG_ADC1/2_EQ34 (addr=0x96/0x9E) | |
| 621 | + * DA732x_REG_ADC1/2_EQ5 (addr=0x97/0x9F) | |
| 622 | + * DA732x_REG_DAC1/2/3_EQ12 (addr=0xA5/0xB5/0xC5) | |
| 623 | + * DA732x_REG_DAC1/2/3_EQ34 (addr=0xA6/0xB6/0xC6) | |
| 624 | + * DA732x_REG_DAC1/2/3_EQ5 (addr=0xA7/0xB7/0xB7) | |
| 625 | + */ | |
| 626 | +#define DA732X_EQ_VOL_VAL_MASK 0xF | |
| 627 | +#define DA732X_EQ_BAND1_SHIFT 0 | |
| 628 | +#define DA732X_EQ_BAND2_SHIFT 4 | |
| 629 | +#define DA732X_EQ_BAND3_SHIFT 0 | |
| 630 | +#define DA732X_EQ_BAND4_SHIFT 4 | |
| 631 | +#define DA732X_EQ_BAND5_SHIFT 0 | |
| 632 | +#define DA732X_EQ_OVERALL_SHIFT 4 | |
| 633 | +#define DA732X_EQ_OVERALL_VOL_VAL_MASK 0x3 | |
| 634 | +#define DA732X_EQ_DIS (0 << 7) | |
| 635 | +#define DA732X_EQ_EN (1 << 7) | |
| 636 | +#define DA732X_EQ_EN_SHIFT 7 | |
| 637 | +#define DA732X_EQ_VOL_VAL_MAX DA732X_EQ_VOL_VAL_MASK | |
| 638 | +#define DA732X_EQ_OVERALL_VOL_VAL_MAX DA732X_EQ_OVERALL_VOL_VAL_MASK | |
| 639 | + | |
| 640 | +/* DA732X_REG_DMA_CMD (addr=0xD3) */ | |
| 641 | +#define DA732X_SEL_DSP_DMA_MASK (3 << 0) | |
| 642 | +#define DA732X_SEL_DSP_DMA_DIS (0 << 0) | |
| 643 | +#define DA732X_SEL_DSP_DMA_PMEM (1 << 0) | |
| 644 | +#define DA732X_SEL_DSP_DMA_XMEM (2 << 0) | |
| 645 | +#define DA732X_SEL_DSP_DMA_YMEM (3 << 0) | |
| 646 | +#define DA732X_DSP_RW_MASK (1 << 4) | |
| 647 | +#define DA732X_DSP_DMA_WRITE (0 << 4) | |
| 648 | +#define DA732X_DSP_DMA_READ (1 << 4) | |
| 649 | + | |
| 650 | +/* DA732X_REG_DMA_STATUS (addr=0xDA) */ | |
| 651 | +#define DA732X_DSP_DMA_FREE (0 << 0) | |
| 652 | +#define DA732X_DSP_DMA_BUSY (1 << 0) | |
| 653 | + | |
| 654 | +#endif /* __DA732X_REG_H_ */ | |
| @@ -0,0 +1,1176 @@ | ||
| 1 | +/* | |
| 2 | + * isabelle.c - Low power high fidelity audio codec driver | |
| 3 | + * | |
| 4 | + * Copyright (c) 2012 Texas Instruments, Inc | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation; version 2 of the License. | |
| 9 | + * | |
| 10 | + * | |
| 11 | + * Initially based on sound/soc/codecs/twl6040.c | |
| 12 | + * | |
| 13 | + */ | |
| 14 | +#include <linux/module.h> | |
| 15 | +#include <linux/moduleparam.h> | |
| 16 | +#include <linux/version.h> | |
| 17 | +#include <linux/kernel.h> | |
| 18 | +#include <linux/init.h> | |
| 19 | +#include <linux/delay.h> | |
| 20 | +#include <linux/pm.h> | |
| 21 | +#include <linux/regmap.h> | |
| 22 | +#include <linux/i2c.h> | |
| 23 | +#include <linux/slab.h> | |
| 24 | +#include <sound/core.h> | |
| 25 | +#include <sound/pcm.h> | |
| 26 | +#include <sound/pcm_params.h> | |
| 27 | +#include <sound/soc.h> | |
| 28 | +#include <sound/soc-dapm.h> | |
| 29 | +#include <sound/tlv.h> | |
| 30 | +#include <sound/jack.h> | |
| 31 | +#include <sound/initval.h> | |
| 32 | +#include <asm/div64.h> | |
| 33 | +#include "isabelle.h" | |
| 34 | + | |
| 35 | + | |
| 36 | +/* Register default values for ISABELLE driver. */ | |
| 37 | +static struct reg_default isabelle_reg_defs[] = { | |
| 38 | + { 0, 0x00 }, | |
| 39 | + { 1, 0x00 }, | |
| 40 | + { 2, 0x00 }, | |
| 41 | + { 3, 0x00 }, | |
| 42 | + { 4, 0x00 }, | |
| 43 | + { 5, 0x00 }, | |
| 44 | + { 6, 0x00 }, | |
| 45 | + { 7, 0x00 }, | |
| 46 | + { 8, 0x00 }, | |
| 47 | + { 9, 0x00 }, | |
| 48 | + { 10, 0x00 }, | |
| 49 | + { 11, 0x00 }, | |
| 50 | + { 12, 0x00 }, | |
| 51 | + { 13, 0x00 }, | |
| 52 | + { 14, 0x00 }, | |
| 53 | + { 15, 0x00 }, | |
| 54 | + { 16, 0x00 }, | |
| 55 | + { 17, 0x00 }, | |
| 56 | + { 18, 0x00 }, | |
| 57 | + { 19, 0x00 }, | |
| 58 | + { 20, 0x00 }, | |
| 59 | + { 21, 0x02 }, | |
| 60 | + { 22, 0x02 }, | |
| 61 | + { 23, 0x02 }, | |
| 62 | + { 24, 0x02 }, | |
| 63 | + { 25, 0x0F }, | |
| 64 | + { 26, 0x8F }, | |
| 65 | + { 27, 0x0F }, | |
| 66 | + { 28, 0x8F }, | |
| 67 | + { 29, 0x00 }, | |
| 68 | + { 30, 0x00 }, | |
| 69 | + { 31, 0x00 }, | |
| 70 | + { 32, 0x00 }, | |
| 71 | + { 33, 0x00 }, | |
| 72 | + { 34, 0x00 }, | |
| 73 | + { 35, 0x00 }, | |
| 74 | + { 36, 0x00 }, | |
| 75 | + { 37, 0x00 }, | |
| 76 | + { 38, 0x00 }, | |
| 77 | + { 39, 0x00 }, | |
| 78 | + { 40, 0x00 }, | |
| 79 | + { 41, 0x00 }, | |
| 80 | + { 42, 0x00 }, | |
| 81 | + { 43, 0x00 }, | |
| 82 | + { 44, 0x00 }, | |
| 83 | + { 45, 0x00 }, | |
| 84 | + { 46, 0x00 }, | |
| 85 | + { 47, 0x00 }, | |
| 86 | + { 48, 0x00 }, | |
| 87 | + { 49, 0x00 }, | |
| 88 | + { 50, 0x00 }, | |
| 89 | + { 51, 0x00 }, | |
| 90 | + { 52, 0x00 }, | |
| 91 | + { 53, 0x00 }, | |
| 92 | + { 54, 0x00 }, | |
| 93 | + { 55, 0x00 }, | |
| 94 | + { 56, 0x00 }, | |
| 95 | + { 57, 0x00 }, | |
| 96 | + { 58, 0x00 }, | |
| 97 | + { 59, 0x00 }, | |
| 98 | + { 60, 0x00 }, | |
| 99 | + { 61, 0x00 }, | |
| 100 | + { 62, 0x00 }, | |
| 101 | + { 63, 0x00 }, | |
| 102 | + { 64, 0x00 }, | |
| 103 | + { 65, 0x00 }, | |
| 104 | + { 66, 0x00 }, | |
| 105 | + { 67, 0x00 }, | |
| 106 | + { 68, 0x00 }, | |
| 107 | + { 69, 0x90 }, | |
| 108 | + { 70, 0x90 }, | |
| 109 | + { 71, 0x90 }, | |
| 110 | + { 72, 0x00 }, | |
| 111 | + { 73, 0x00 }, | |
| 112 | + { 74, 0x00 }, | |
| 113 | + { 75, 0x00 }, | |
| 114 | + { 76, 0x00 }, | |
| 115 | + { 77, 0x00 }, | |
| 116 | + { 78, 0x00 }, | |
| 117 | + { 79, 0x00 }, | |
| 118 | + { 80, 0x00 }, | |
| 119 | + { 81, 0x00 }, | |
| 120 | + { 82, 0x00 }, | |
| 121 | + { 83, 0x00 }, | |
| 122 | + { 84, 0x00 }, | |
| 123 | + { 85, 0x07 }, | |
| 124 | + { 86, 0x00 }, | |
| 125 | + { 87, 0x00 }, | |
| 126 | + { 88, 0x00 }, | |
| 127 | + { 89, 0x07 }, | |
| 128 | + { 90, 0x80 }, | |
| 129 | + { 91, 0x07 }, | |
| 130 | + { 92, 0x07 }, | |
| 131 | + { 93, 0x00 }, | |
| 132 | + { 94, 0x00 }, | |
| 133 | + { 95, 0x00 }, | |
| 134 | + { 96, 0x00 }, | |
| 135 | + { 97, 0x00 }, | |
| 136 | + { 98, 0x00 }, | |
| 137 | + { 99, 0x00 }, | |
| 138 | +}; | |
| 139 | + | |
| 140 | +static const char *isabelle_rx1_texts[] = {"VRX1", "ARX1"}; | |
| 141 | +static const char *isabelle_rx2_texts[] = {"VRX2", "ARX2"}; | |
| 142 | + | |
| 143 | +static const struct soc_enum isabelle_rx1_enum[] = { | |
| 144 | + SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 3, 1, isabelle_rx1_texts), | |
| 145 | + SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 5, 1, isabelle_rx1_texts), | |
| 146 | +}; | |
| 147 | + | |
| 148 | +static const struct soc_enum isabelle_rx2_enum[] = { | |
| 149 | + SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 2, 1, isabelle_rx2_texts), | |
| 150 | + SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 4, 1, isabelle_rx2_texts), | |
| 151 | +}; | |
| 152 | + | |
| 153 | +/* Headset DAC playback switches */ | |
| 154 | +static const struct snd_kcontrol_new rx1_mux_controls = | |
| 155 | + SOC_DAPM_ENUM("Route", isabelle_rx1_enum); | |
| 156 | + | |
| 157 | +static const struct snd_kcontrol_new rx2_mux_controls = | |
| 158 | + SOC_DAPM_ENUM("Route", isabelle_rx2_enum); | |
| 159 | + | |
| 160 | +/* TX input selection */ | |
| 161 | +static const char *isabelle_atx_texts[] = {"AMIC1", "DMIC"}; | |
| 162 | +static const char *isabelle_vtx_texts[] = {"AMIC2", "DMIC"}; | |
| 163 | + | |
| 164 | +static const struct soc_enum isabelle_atx_enum[] = { | |
| 165 | + SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 7, 1, isabelle_atx_texts), | |
| 166 | + SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, 1, isabelle_atx_texts), | |
| 167 | +}; | |
| 168 | + | |
| 169 | +static const struct soc_enum isabelle_vtx_enum[] = { | |
| 170 | + SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 6, 1, isabelle_vtx_texts), | |
| 171 | + SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, 1, isabelle_vtx_texts), | |
| 172 | +}; | |
| 173 | + | |
| 174 | +static const struct snd_kcontrol_new atx_mux_controls = | |
| 175 | + SOC_DAPM_ENUM("Route", isabelle_atx_enum); | |
| 176 | + | |
| 177 | +static const struct snd_kcontrol_new vtx_mux_controls = | |
| 178 | + SOC_DAPM_ENUM("Route", isabelle_vtx_enum); | |
| 179 | + | |
| 180 | +/* Left analog microphone selection */ | |
| 181 | +static const char *isabelle_amic1_texts[] = { | |
| 182 | + "Main Mic", "Headset Mic", "Aux/FM Left"}; | |
| 183 | + | |
| 184 | +/* Left analog microphone selection */ | |
| 185 | +static const char *isabelle_amic2_texts[] = {"Sub Mic", "Aux/FM Right"}; | |
| 186 | + | |
| 187 | +static const struct soc_enum isabelle_amic1_enum[] = { | |
| 188 | + SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 5, | |
| 189 | + ARRAY_SIZE(isabelle_amic1_texts), | |
| 190 | + isabelle_amic1_texts), | |
| 191 | +}; | |
| 192 | + | |
| 193 | +static const struct soc_enum isabelle_amic2_enum[] = { | |
| 194 | + SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 4, | |
| 195 | + ARRAY_SIZE(isabelle_amic2_texts), | |
| 196 | + isabelle_amic2_texts), | |
| 197 | +}; | |
| 198 | + | |
| 199 | +static const struct snd_kcontrol_new amic1_control = | |
| 200 | + SOC_DAPM_ENUM("Route", isabelle_amic1_enum); | |
| 201 | + | |
| 202 | +static const struct snd_kcontrol_new amic2_control = | |
| 203 | + SOC_DAPM_ENUM("Route", isabelle_amic2_enum); | |
| 204 | + | |
| 205 | +static const char *isabelle_st_audio_texts[] = {"ATX1", "ATX2"}; | |
| 206 | + | |
| 207 | +static const char *isabelle_st_voice_texts[] = {"VTX1", "VTX2"}; | |
| 208 | + | |
| 209 | +static const struct soc_enum isabelle_st_audio_enum[] = { | |
| 210 | + SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA1_CFG_REG, 7, 1, | |
| 211 | + isabelle_st_audio_texts), | |
| 212 | + SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA2_CFG_REG, 7, 1, | |
| 213 | + isabelle_st_audio_texts), | |
| 214 | +}; | |
| 215 | + | |
| 216 | +static const struct soc_enum isabelle_st_voice_enum[] = { | |
| 217 | + SOC_ENUM_SINGLE(ISABELLE_VTX_STPGA1_CFG_REG, 7, 1, | |
| 218 | + isabelle_st_voice_texts), | |
| 219 | + SOC_ENUM_SINGLE(ISABELLE_VTX2_STPGA2_CFG_REG, 7, 1, | |
| 220 | + isabelle_st_voice_texts), | |
| 221 | +}; | |
| 222 | + | |
| 223 | +static const struct snd_kcontrol_new st_audio_control = | |
| 224 | + SOC_DAPM_ENUM("Route", isabelle_st_audio_enum); | |
| 225 | + | |
| 226 | +static const struct snd_kcontrol_new st_voice_control = | |
| 227 | + SOC_DAPM_ENUM("Route", isabelle_st_voice_enum); | |
| 228 | + | |
| 229 | +/* Mixer controls */ | |
| 230 | +static const struct snd_kcontrol_new isabelle_hs_left_mixer_controls[] = { | |
| 231 | +SOC_DAPM_SINGLE("DAC1L Playback Switch", ISABELLE_HSDRV_CFG1_REG, 7, 1, 0), | |
| 232 | +SOC_DAPM_SINGLE("APGA1 Playback Switch", ISABELLE_HSDRV_CFG1_REG, 6, 1, 0), | |
| 233 | +}; | |
| 234 | + | |
| 235 | +static const struct snd_kcontrol_new isabelle_hs_right_mixer_controls[] = { | |
| 236 | +SOC_DAPM_SINGLE("DAC1R Playback Switch", ISABELLE_HSDRV_CFG1_REG, 5, 1, 0), | |
| 237 | +SOC_DAPM_SINGLE("APGA2 Playback Switch", ISABELLE_HSDRV_CFG1_REG, 4, 1, 0), | |
| 238 | +}; | |
| 239 | + | |
| 240 | +static const struct snd_kcontrol_new isabelle_hf_left_mixer_controls[] = { | |
| 241 | +SOC_DAPM_SINGLE("DAC2L Playback Switch", ISABELLE_HFLPGA_CFG_REG, 7, 1, 0), | |
| 242 | +SOC_DAPM_SINGLE("APGA1 Playback Switch", ISABELLE_HFLPGA_CFG_REG, 6, 1, 0), | |
| 243 | +}; | |
| 244 | + | |
| 245 | +static const struct snd_kcontrol_new isabelle_hf_right_mixer_controls[] = { | |
| 246 | +SOC_DAPM_SINGLE("DAC2R Playback Switch", ISABELLE_HFRPGA_CFG_REG, 7, 1, 0), | |
| 247 | +SOC_DAPM_SINGLE("APGA2 Playback Switch", ISABELLE_HFRPGA_CFG_REG, 6, 1, 0), | |
| 248 | +}; | |
| 249 | + | |
| 250 | +static const struct snd_kcontrol_new isabelle_ep_mixer_controls[] = { | |
| 251 | +SOC_DAPM_SINGLE("DAC2L Playback Switch", ISABELLE_EARDRV_CFG1_REG, 7, 1, 0), | |
| 252 | +SOC_DAPM_SINGLE("APGA1 Playback Switch", ISABELLE_EARDRV_CFG1_REG, 6, 1, 0), | |
| 253 | +}; | |
| 254 | + | |
| 255 | +static const struct snd_kcontrol_new isabelle_aux_left_mixer_controls[] = { | |
| 256 | +SOC_DAPM_SINGLE("DAC3L Playback Switch", ISABELLE_LINEAMP_CFG_REG, 7, 1, 0), | |
| 257 | +SOC_DAPM_SINGLE("APGA1 Playback Switch", ISABELLE_LINEAMP_CFG_REG, 6, 1, 0), | |
| 258 | +}; | |
| 259 | + | |
| 260 | +static const struct snd_kcontrol_new isabelle_aux_right_mixer_controls[] = { | |
| 261 | +SOC_DAPM_SINGLE("DAC3R Playback Switch", ISABELLE_LINEAMP_CFG_REG, 5, 1, 0), | |
| 262 | +SOC_DAPM_SINGLE("APGA2 Playback Switch", ISABELLE_LINEAMP_CFG_REG, 4, 1, 0), | |
| 263 | +}; | |
| 264 | + | |
| 265 | +static const struct snd_kcontrol_new isabelle_dpga1_left_mixer_controls[] = { | |
| 266 | +SOC_DAPM_SINGLE("RX1 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 7, 1, 0), | |
| 267 | +SOC_DAPM_SINGLE("RX3 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 6, 1, 0), | |
| 268 | +SOC_DAPM_SINGLE("RX5 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 5, 1, 0), | |
| 269 | +}; | |
| 270 | + | |
| 271 | +static const struct snd_kcontrol_new isabelle_dpga1_right_mixer_controls[] = { | |
| 272 | +SOC_DAPM_SINGLE("RX2 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 3, 1, 0), | |
| 273 | +SOC_DAPM_SINGLE("RX4 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 2, 1, 0), | |
| 274 | +SOC_DAPM_SINGLE("RX6 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 1, 1, 0), | |
| 275 | +}; | |
| 276 | + | |
| 277 | +static const struct snd_kcontrol_new isabelle_dpga2_left_mixer_controls[] = { | |
| 278 | +SOC_DAPM_SINGLE("RX1 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 7, 1, 0), | |
| 279 | +SOC_DAPM_SINGLE("RX2 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 6, 1, 0), | |
| 280 | +SOC_DAPM_SINGLE("RX3 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 5, 1, 0), | |
| 281 | +SOC_DAPM_SINGLE("RX4 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 4, 1, 0), | |
| 282 | +SOC_DAPM_SINGLE("RX5 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 3, 1, 0), | |
| 283 | +SOC_DAPM_SINGLE("RX6 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 2, 1, 0), | |
| 284 | +}; | |
| 285 | + | |
| 286 | +static const struct snd_kcontrol_new isabelle_dpga2_right_mixer_controls[] = { | |
| 287 | +SOC_DAPM_SINGLE("USNC Playback Switch", ISABELLE_DPGA2R_IN_SEL_REG, 7, 1, 0), | |
| 288 | +SOC_DAPM_SINGLE("RX2 Playback Switch", ISABELLE_DPGA2R_IN_SEL_REG, 3, 1, 0), | |
| 289 | +SOC_DAPM_SINGLE("RX4 Playback Switch", ISABELLE_DPGA2R_IN_SEL_REG, 2, 1, 0), | |
| 290 | +SOC_DAPM_SINGLE("RX6 Playback Switch", ISABELLE_DPGA2R_IN_SEL_REG, 1, 1, 0), | |
| 291 | +}; | |
| 292 | + | |
| 293 | +static const struct snd_kcontrol_new isabelle_dpga3_left_mixer_controls[] = { | |
| 294 | +SOC_DAPM_SINGLE("RX1 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 7, 1, 0), | |
| 295 | +SOC_DAPM_SINGLE("RX3 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 6, 1, 0), | |
| 296 | +SOC_DAPM_SINGLE("RX5 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 5, 1, 0), | |
| 297 | +}; | |
| 298 | + | |
| 299 | +static const struct snd_kcontrol_new isabelle_dpga3_right_mixer_controls[] = { | |
| 300 | +SOC_DAPM_SINGLE("RX2 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 3, 1, 0), | |
| 301 | +SOC_DAPM_SINGLE("RX4 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 2, 1, 0), | |
| 302 | +SOC_DAPM_SINGLE("RX6 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 1, 1, 0), | |
| 303 | +}; | |
| 304 | + | |
| 305 | +static const struct snd_kcontrol_new isabelle_rx1_mixer_controls[] = { | |
| 306 | +SOC_DAPM_SINGLE("ST1 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 7, 1, 0), | |
| 307 | +SOC_DAPM_SINGLE("DL1 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 6, 1, 0), | |
| 308 | +}; | |
| 309 | + | |
| 310 | +static const struct snd_kcontrol_new isabelle_rx2_mixer_controls[] = { | |
| 311 | +SOC_DAPM_SINGLE("ST2 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 5, 1, 0), | |
| 312 | +SOC_DAPM_SINGLE("DL2 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 4, 1, 0), | |
| 313 | +}; | |
| 314 | + | |
| 315 | +static const struct snd_kcontrol_new isabelle_rx3_mixer_controls[] = { | |
| 316 | +SOC_DAPM_SINGLE("ST1 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 3, 1, 0), | |
| 317 | +SOC_DAPM_SINGLE("DL3 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 2, 1, 0), | |
| 318 | +}; | |
| 319 | + | |
| 320 | +static const struct snd_kcontrol_new isabelle_rx4_mixer_controls[] = { | |
| 321 | +SOC_DAPM_SINGLE("ST2 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 1, 1, 0), | |
| 322 | +SOC_DAPM_SINGLE("DL4 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 0, 1, 0), | |
| 323 | +}; | |
| 324 | + | |
| 325 | +static const struct snd_kcontrol_new isabelle_rx5_mixer_controls[] = { | |
| 326 | +SOC_DAPM_SINGLE("ST1 Playback Switch", ISABELLE_RX_INPUT_CFG2_REG, 7, 1, 0), | |
| 327 | +SOC_DAPM_SINGLE("DL5 Playback Switch", ISABELLE_RX_INPUT_CFG2_REG, 6, 1, 0), | |
| 328 | +}; | |
| 329 | + | |
| 330 | +static const struct snd_kcontrol_new isabelle_rx6_mixer_controls[] = { | |
| 331 | +SOC_DAPM_SINGLE("ST2 Playback Switch", ISABELLE_RX_INPUT_CFG2_REG, 5, 1, 0), | |
| 332 | +SOC_DAPM_SINGLE("DL6 Playback Switch", ISABELLE_RX_INPUT_CFG2_REG, 4, 1, 0), | |
| 333 | +}; | |
| 334 | + | |
| 335 | +static const struct snd_kcontrol_new ep_path_enable_control = | |
| 336 | + SOC_DAPM_SINGLE("Switch", ISABELLE_EARDRV_CFG2_REG, 0, 1, 0); | |
| 337 | + | |
| 338 | +/* TLV Declarations */ | |
| 339 | +static const DECLARE_TLV_DB_SCALE(mic_amp_tlv, 0, 100, 0); | |
| 340 | +static const DECLARE_TLV_DB_SCALE(afm_amp_tlv, -3300, 300, 0); | |
| 341 | +static const DECLARE_TLV_DB_SCALE(dac_tlv, -1200, 200, 0); | |
| 342 | +static const DECLARE_TLV_DB_SCALE(hf_tlv, -5000, 200, 0); | |
| 343 | + | |
| 344 | +/* from -63 to 0 dB in 1 dB steps */ | |
| 345 | +static const DECLARE_TLV_DB_SCALE(dpga_tlv, -6300, 100, 1); | |
| 346 | + | |
| 347 | +/* from -63 to 9 dB in 1 dB steps */ | |
| 348 | +static const DECLARE_TLV_DB_SCALE(rx_tlv, -6300, 100, 1); | |
| 349 | + | |
| 350 | +static const DECLARE_TLV_DB_SCALE(st_tlv, -2700, 300, 1); | |
| 351 | +static const DECLARE_TLV_DB_SCALE(tx_tlv, -600, 100, 0); | |
| 352 | + | |
| 353 | +static const struct snd_kcontrol_new isabelle_snd_controls[] = { | |
| 354 | + SOC_DOUBLE_TLV("Headset Playback Volume", ISABELLE_HSDRV_GAIN_REG, | |
| 355 | + 4, 0, 0xF, 0, dac_tlv), | |
| 356 | + SOC_DOUBLE_R_TLV("Handsfree Playback Volume", | |
| 357 | + ISABELLE_HFLPGA_CFG_REG, ISABELLE_HFRPGA_CFG_REG, | |
| 358 | + 0, 0x1F, 0, hf_tlv), | |
| 359 | + SOC_DOUBLE_TLV("Aux Playback Volume", ISABELLE_LINEAMP_GAIN_REG, | |
| 360 | + 4, 0, 0xF, 0, dac_tlv), | |
| 361 | + SOC_SINGLE_TLV("Earpiece Playback Volume", ISABELLE_EARDRV_CFG1_REG, | |
| 362 | + 0, 0xF, 0, dac_tlv), | |
| 363 | + | |
| 364 | + SOC_DOUBLE_TLV("Aux FM Volume", ISABELLE_APGA_GAIN_REG, 4, 0, 0xF, 0, | |
| 365 | + afm_amp_tlv), | |
| 366 | + SOC_SINGLE_TLV("Mic1 Capture Volume", ISABELLE_MIC1_GAIN_REG, 3, 0x1F, | |
| 367 | + 0, mic_amp_tlv), | |
| 368 | + SOC_SINGLE_TLV("Mic2 Capture Volume", ISABELLE_MIC2_GAIN_REG, 3, 0x1F, | |
| 369 | + 0, mic_amp_tlv), | |
| 370 | + | |
| 371 | + SOC_DOUBLE_R_TLV("DPGA1 Volume", ISABELLE_DPGA1L_GAIN_REG, | |
| 372 | + ISABELLE_DPGA1R_GAIN_REG, 0, 0x3F, 0, dpga_tlv), | |
| 373 | + SOC_DOUBLE_R_TLV("DPGA2 Volume", ISABELLE_DPGA2L_GAIN_REG, | |
| 374 | + ISABELLE_DPGA2R_GAIN_REG, 0, 0x3F, 0, dpga_tlv), | |
| 375 | + SOC_DOUBLE_R_TLV("DPGA3 Volume", ISABELLE_DPGA3L_GAIN_REG, | |
| 376 | + ISABELLE_DPGA3R_GAIN_REG, 0, 0x3F, 0, dpga_tlv), | |
| 377 | + | |
| 378 | + SOC_SINGLE_TLV("Sidetone Audio TX1 Volume", | |
| 379 | + ISABELLE_ATX_STPGA1_CFG_REG, 0, 0xF, 0, st_tlv), | |
| 380 | + SOC_SINGLE_TLV("Sidetone Audio TX2 Volume", | |
| 381 | + ISABELLE_ATX_STPGA2_CFG_REG, 0, 0xF, 0, st_tlv), | |
| 382 | + SOC_SINGLE_TLV("Sidetone Voice TX1 Volume", | |
| 383 | + ISABELLE_VTX_STPGA1_CFG_REG, 0, 0xF, 0, st_tlv), | |
| 384 | + SOC_SINGLE_TLV("Sidetone Voice TX2 Volume", | |
| 385 | + ISABELLE_VTX2_STPGA2_CFG_REG, 0, 0xF, 0, st_tlv), | |
| 386 | + | |
| 387 | + SOC_SINGLE_TLV("Audio TX1 Volume", ISABELLE_ATX1_DPGA_REG, 4, 0xF, 0, | |
| 388 | + tx_tlv), | |
| 389 | + SOC_SINGLE_TLV("Audio TX2 Volume", ISABELLE_ATX2_DPGA_REG, 4, 0xF, 0, | |
| 390 | + tx_tlv), | |
| 391 | + SOC_SINGLE_TLV("Voice TX1 Volume", ISABELLE_VTX1_DPGA_REG, 4, 0xF, 0, | |
| 392 | + tx_tlv), | |
| 393 | + SOC_SINGLE_TLV("Voice TX2 Volume", ISABELLE_VTX2_DPGA_REG, 4, 0xF, 0, | |
| 394 | + tx_tlv), | |
| 395 | + | |
| 396 | + SOC_SINGLE_TLV("RX1 DPGA Volume", ISABELLE_RX1_DPGA_REG, 0, 0x3F, 0, | |
| 397 | + rx_tlv), | |
| 398 | + SOC_SINGLE_TLV("RX2 DPGA Volume", ISABELLE_RX2_DPGA_REG, 0, 0x3F, 0, | |
| 399 | + rx_tlv), | |
| 400 | + SOC_SINGLE_TLV("RX3 DPGA Volume", ISABELLE_RX3_DPGA_REG, 0, 0x3F, 0, | |
| 401 | + rx_tlv), | |
| 402 | + SOC_SINGLE_TLV("RX4 DPGA Volume", ISABELLE_RX4_DPGA_REG, 0, 0x3F, 0, | |
| 403 | + rx_tlv), | |
| 404 | + SOC_SINGLE_TLV("RX5 DPGA Volume", ISABELLE_RX5_DPGA_REG, 0, 0x3F, 0, | |
| 405 | + rx_tlv), | |
| 406 | + SOC_SINGLE_TLV("RX6 DPGA Volume", ISABELLE_RX6_DPGA_REG, 0, 0x3F, 0, | |
| 407 | + rx_tlv), | |
| 408 | + | |
| 409 | + SOC_SINGLE("Headset Noise Gate", ISABELLE_HS_NG_CFG1_REG, 7, 1, 0), | |
| 410 | + SOC_SINGLE("Handsfree Noise Gate", ISABELLE_HF_NG_CFG1_REG, 7, 1, 0), | |
| 411 | + | |
| 412 | + SOC_SINGLE("ATX1 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, | |
| 413 | + 7, 1, 0), | |
| 414 | + SOC_SINGLE("ATX2 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, | |
| 415 | + 6, 1, 0), | |
| 416 | + SOC_SINGLE("ARX1 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, | |
| 417 | + 5, 1, 0), | |
| 418 | + SOC_SINGLE("ARX2 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, | |
| 419 | + 4, 1, 0), | |
| 420 | + SOC_SINGLE("ARX3 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, | |
| 421 | + 3, 1, 0), | |
| 422 | + SOC_SINGLE("ARX4 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, | |
| 423 | + 2, 1, 0), | |
| 424 | + SOC_SINGLE("ARX5 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, | |
| 425 | + 1, 1, 0), | |
| 426 | + SOC_SINGLE("ARX6 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, | |
| 427 | + 0, 1, 0), | |
| 428 | + SOC_SINGLE("VRX1 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, | |
| 429 | + 3, 1, 0), | |
| 430 | + SOC_SINGLE("VRX2 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, | |
| 431 | + 2, 1, 0), | |
| 432 | + | |
| 433 | + SOC_SINGLE("ATX1 Filter Enable Switch", ISABELLE_ALU_TX_EN_REG, | |
| 434 | + 7, 1, 0), | |
| 435 | + SOC_SINGLE("ATX2 Filter Enable Switch", ISABELLE_ALU_TX_EN_REG, | |
| 436 | + 6, 1, 0), | |
| 437 | + SOC_SINGLE("VTX1 Filter Enable Switch", ISABELLE_ALU_TX_EN_REG, | |
| 438 | + 5, 1, 0), | |
| 439 | + SOC_SINGLE("VTX2 Filter Enable Switch", ISABELLE_ALU_TX_EN_REG, | |
| 440 | + 4, 1, 0), | |
| 441 | + SOC_SINGLE("RX1 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG, | |
| 442 | + 5, 1, 0), | |
| 443 | + SOC_SINGLE("RX2 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG, | |
| 444 | + 4, 1, 0), | |
| 445 | + SOC_SINGLE("RX3 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG, | |
| 446 | + 3, 1, 0), | |
| 447 | + SOC_SINGLE("RX4 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG, | |
| 448 | + 2, 1, 0), | |
| 449 | + SOC_SINGLE("RX5 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG, | |
| 450 | + 1, 1, 0), | |
| 451 | + SOC_SINGLE("RX6 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG, | |
| 452 | + 0, 1, 0), | |
| 453 | + | |
| 454 | + SOC_SINGLE("ULATX12 Capture Switch", ISABELLE_ULATX12_INTF_CFG_REG, | |
| 455 | + 7, 1, 0), | |
| 456 | + | |
| 457 | + SOC_SINGLE("DL12 Playback Switch", ISABELLE_DL12_INTF_CFG_REG, | |
| 458 | + 7, 1, 0), | |
| 459 | + SOC_SINGLE("DL34 Playback Switch", ISABELLE_DL34_INTF_CFG_REG, | |
| 460 | + 7, 1, 0), | |
| 461 | + SOC_SINGLE("DL56 Playback Switch", ISABELLE_DL56_INTF_CFG_REG, | |
| 462 | + 7, 1, 0), | |
| 463 | + | |
| 464 | + /* DMIC Switch */ | |
| 465 | + SOC_SINGLE("DMIC Switch", ISABELLE_DMIC_CFG_REG, 0, 1, 0), | |
| 466 | +}; | |
| 467 | + | |
| 468 | +static const struct snd_soc_dapm_widget isabelle_dapm_widgets[] = { | |
| 469 | + /* Inputs */ | |
| 470 | + SND_SOC_DAPM_INPUT("MAINMIC"), | |
| 471 | + SND_SOC_DAPM_INPUT("HSMIC"), | |
| 472 | + SND_SOC_DAPM_INPUT("SUBMIC"), | |
| 473 | + SND_SOC_DAPM_INPUT("LINEIN1"), | |
| 474 | + SND_SOC_DAPM_INPUT("LINEIN2"), | |
| 475 | + SND_SOC_DAPM_INPUT("DMICDAT"), | |
| 476 | + | |
| 477 | + /* Outputs */ | |
| 478 | + SND_SOC_DAPM_OUTPUT("HSOL"), | |
| 479 | + SND_SOC_DAPM_OUTPUT("HSOR"), | |
| 480 | + SND_SOC_DAPM_OUTPUT("HFL"), | |
| 481 | + SND_SOC_DAPM_OUTPUT("HFR"), | |
| 482 | + SND_SOC_DAPM_OUTPUT("EP"), | |
| 483 | + SND_SOC_DAPM_OUTPUT("LINEOUT1"), | |
| 484 | + SND_SOC_DAPM_OUTPUT("LINEOUT2"), | |
| 485 | + | |
| 486 | + SND_SOC_DAPM_PGA("DL1", SND_SOC_NOPM, 0, 0, NULL, 0), | |
| 487 | + SND_SOC_DAPM_PGA("DL2", SND_SOC_NOPM, 0, 0, NULL, 0), | |
| 488 | + SND_SOC_DAPM_PGA("DL3", SND_SOC_NOPM, 0, 0, NULL, 0), | |
| 489 | + SND_SOC_DAPM_PGA("DL4", SND_SOC_NOPM, 0, 0, NULL, 0), | |
| 490 | + SND_SOC_DAPM_PGA("DL5", SND_SOC_NOPM, 0, 0, NULL, 0), | |
| 491 | + SND_SOC_DAPM_PGA("DL6", SND_SOC_NOPM, 0, 0, NULL, 0), | |
| 492 | + | |
| 493 | + /* Analog input muxes for the capture amplifiers */ | |
| 494 | + SND_SOC_DAPM_MUX("Analog Left Capture Route", | |
| 495 | + SND_SOC_NOPM, 0, 0, &amic1_control), | |
| 496 | + SND_SOC_DAPM_MUX("Analog Right Capture Route", | |
| 497 | + SND_SOC_NOPM, 0, 0, &amic2_control), | |
| 498 | + | |
| 499 | + SND_SOC_DAPM_MUX("Sidetone Audio Playback", SND_SOC_NOPM, 0, 0, | |
| 500 | + &st_audio_control), | |
| 501 | + SND_SOC_DAPM_MUX("Sidetone Voice Playback", SND_SOC_NOPM, 0, 0, | |
| 502 | + &st_voice_control), | |
| 503 | + | |
| 504 | + /* AIF */ | |
| 505 | + SND_SOC_DAPM_AIF_IN("INTF1_SDI", NULL, 0, ISABELLE_INTF_EN_REG, 7, 0), | |
| 506 | + SND_SOC_DAPM_AIF_IN("INTF2_SDI", NULL, 0, ISABELLE_INTF_EN_REG, 6, 0), | |
| 507 | + | |
| 508 | + SND_SOC_DAPM_AIF_OUT("INTF1_SDO", NULL, 0, ISABELLE_INTF_EN_REG, 5, 0), | |
| 509 | + SND_SOC_DAPM_AIF_OUT("INTF2_SDO", NULL, 0, ISABELLE_INTF_EN_REG, 4, 0), | |
| 510 | + | |
| 511 | + SND_SOC_DAPM_OUT_DRV("ULATX1", SND_SOC_NOPM, 0, 0, NULL, 0), | |
| 512 | + SND_SOC_DAPM_OUT_DRV("ULATX2", SND_SOC_NOPM, 0, 0, NULL, 0), | |
| 513 | + SND_SOC_DAPM_OUT_DRV("ULVTX1", SND_SOC_NOPM, 0, 0, NULL, 0), | |
| 514 | + SND_SOC_DAPM_OUT_DRV("ULVTX2", SND_SOC_NOPM, 0, 0, NULL, 0), | |
| 515 | + | |
| 516 | + /* Analog Capture PGAs */ | |
| 517 | + SND_SOC_DAPM_PGA("MicAmp1", ISABELLE_AMIC_CFG_REG, 5, 0, NULL, 0), | |
| 518 | + SND_SOC_DAPM_PGA("MicAmp2", ISABELLE_AMIC_CFG_REG, 4, 0, NULL, 0), | |
| 519 | + | |
| 520 | + /* Auxiliary FM PGAs */ | |
| 521 | + SND_SOC_DAPM_PGA("APGA1", ISABELLE_APGA_CFG_REG, 7, 0, NULL, 0), | |
| 522 | + SND_SOC_DAPM_PGA("APGA2", ISABELLE_APGA_CFG_REG, 6, 0, NULL, 0), | |
| 523 | + | |
| 524 | + /* ADCs */ | |
| 525 | + SND_SOC_DAPM_ADC("ADC1", "Left Front Capture", | |
| 526 | + ISABELLE_AMIC_CFG_REG, 7, 0), | |
| 527 | + SND_SOC_DAPM_ADC("ADC2", "Right Front Capture", | |
| 528 | + ISABELLE_AMIC_CFG_REG, 6, 0), | |
| 529 | + | |
| 530 | + /* Microphone Bias */ | |
| 531 | + SND_SOC_DAPM_SUPPLY("Headset Mic Bias", ISABELLE_ABIAS_CFG_REG, | |
| 532 | + 3, 0, NULL, 0), | |
| 533 | + SND_SOC_DAPM_SUPPLY("Main Mic Bias", ISABELLE_ABIAS_CFG_REG, | |
| 534 | + 2, 0, NULL, 0), | |
| 535 | + SND_SOC_DAPM_SUPPLY("Digital Mic1 Bias", | |
| 536 | + ISABELLE_DBIAS_CFG_REG, 3, 0, NULL, 0), | |
| 537 | + SND_SOC_DAPM_SUPPLY("Digital Mic2 Bias", | |
| 538 | + ISABELLE_DBIAS_CFG_REG, 2, 0, NULL, 0), | |
| 539 | + | |
| 540 | + /* Mixers */ | |
| 541 | + SND_SOC_DAPM_MIXER("Headset Left Mixer", SND_SOC_NOPM, 0, 0, | |
| 542 | + isabelle_hs_left_mixer_controls, | |
| 543 | + ARRAY_SIZE(isabelle_hs_left_mixer_controls)), | |
| 544 | + SND_SOC_DAPM_MIXER("Headset Right Mixer", SND_SOC_NOPM, 0, 0, | |
| 545 | + isabelle_hs_right_mixer_controls, | |
| 546 | + ARRAY_SIZE(isabelle_hs_right_mixer_controls)), | |
| 547 | + SND_SOC_DAPM_MIXER("Handsfree Left Mixer", SND_SOC_NOPM, 0, 0, | |
| 548 | + isabelle_hf_left_mixer_controls, | |
| 549 | + ARRAY_SIZE(isabelle_hf_left_mixer_controls)), | |
| 550 | + SND_SOC_DAPM_MIXER("Handsfree Right Mixer", SND_SOC_NOPM, 0, 0, | |
| 551 | + isabelle_hf_right_mixer_controls, | |
| 552 | + ARRAY_SIZE(isabelle_hf_right_mixer_controls)), | |
| 553 | + SND_SOC_DAPM_MIXER("LINEOUT1 Mixer", SND_SOC_NOPM, 0, 0, | |
| 554 | + isabelle_aux_left_mixer_controls, | |
| 555 | + ARRAY_SIZE(isabelle_aux_left_mixer_controls)), | |
| 556 | + SND_SOC_DAPM_MIXER("LINEOUT2 Mixer", SND_SOC_NOPM, 0, 0, | |
| 557 | + isabelle_aux_right_mixer_controls, | |
| 558 | + ARRAY_SIZE(isabelle_aux_right_mixer_controls)), | |
| 559 | + SND_SOC_DAPM_MIXER("Earphone Mixer", SND_SOC_NOPM, 0, 0, | |
| 560 | + isabelle_ep_mixer_controls, | |
| 561 | + ARRAY_SIZE(isabelle_ep_mixer_controls)), | |
| 562 | + | |
| 563 | + SND_SOC_DAPM_MIXER("DPGA1L Mixer", SND_SOC_NOPM, 0, 0, | |
| 564 | + isabelle_dpga1_left_mixer_controls, | |
| 565 | + ARRAY_SIZE(isabelle_dpga1_left_mixer_controls)), | |
| 566 | + SND_SOC_DAPM_MIXER("DPGA1R Mixer", SND_SOC_NOPM, 0, 0, | |
| 567 | + isabelle_dpga1_right_mixer_controls, | |
| 568 | + ARRAY_SIZE(isabelle_dpga1_right_mixer_controls)), | |
| 569 | + SND_SOC_DAPM_MIXER("DPGA2L Mixer", SND_SOC_NOPM, 0, 0, | |
| 570 | + isabelle_dpga2_left_mixer_controls, | |
| 571 | + ARRAY_SIZE(isabelle_dpga2_left_mixer_controls)), | |
| 572 | + SND_SOC_DAPM_MIXER("DPGA2R Mixer", SND_SOC_NOPM, 0, 0, | |
| 573 | + isabelle_dpga2_right_mixer_controls, | |
| 574 | + ARRAY_SIZE(isabelle_dpga2_right_mixer_controls)), | |
| 575 | + SND_SOC_DAPM_MIXER("DPGA3L Mixer", SND_SOC_NOPM, 0, 0, | |
| 576 | + isabelle_dpga3_left_mixer_controls, | |
| 577 | + ARRAY_SIZE(isabelle_dpga3_left_mixer_controls)), | |
| 578 | + SND_SOC_DAPM_MIXER("DPGA3R Mixer", SND_SOC_NOPM, 0, 0, | |
| 579 | + isabelle_dpga3_right_mixer_controls, | |
| 580 | + ARRAY_SIZE(isabelle_dpga3_right_mixer_controls)), | |
| 581 | + | |
| 582 | + SND_SOC_DAPM_MIXER("RX1 Mixer", SND_SOC_NOPM, 0, 0, | |
| 583 | + isabelle_rx1_mixer_controls, | |
| 584 | + ARRAY_SIZE(isabelle_rx1_mixer_controls)), | |
| 585 | + SND_SOC_DAPM_MIXER("RX2 Mixer", SND_SOC_NOPM, 0, 0, | |
| 586 | + isabelle_rx2_mixer_controls, | |
| 587 | + ARRAY_SIZE(isabelle_rx2_mixer_controls)), | |
| 588 | + SND_SOC_DAPM_MIXER("RX3 Mixer", SND_SOC_NOPM, 0, 0, | |
| 589 | + isabelle_rx3_mixer_controls, | |
| 590 | + ARRAY_SIZE(isabelle_rx3_mixer_controls)), | |
| 591 | + SND_SOC_DAPM_MIXER("RX4 Mixer", SND_SOC_NOPM, 0, 0, | |
| 592 | + isabelle_rx4_mixer_controls, | |
| 593 | + ARRAY_SIZE(isabelle_rx4_mixer_controls)), | |
| 594 | + SND_SOC_DAPM_MIXER("RX5 Mixer", SND_SOC_NOPM, 0, 0, | |
| 595 | + isabelle_rx5_mixer_controls, | |
| 596 | + ARRAY_SIZE(isabelle_rx5_mixer_controls)), | |
| 597 | + SND_SOC_DAPM_MIXER("RX6 Mixer", SND_SOC_NOPM, 0, 0, | |
| 598 | + isabelle_rx6_mixer_controls, | |
| 599 | + ARRAY_SIZE(isabelle_rx6_mixer_controls)), | |
| 600 | + | |
| 601 | + /* DACs */ | |
| 602 | + SND_SOC_DAPM_DAC("DAC1L", "Headset Playback", ISABELLE_DAC_CFG_REG, | |
| 603 | + 5, 0), | |
| 604 | + SND_SOC_DAPM_DAC("DAC1R", "Headset Playback", ISABELLE_DAC_CFG_REG, | |
| 605 | + 4, 0), | |
| 606 | + SND_SOC_DAPM_DAC("DAC2L", "Handsfree Playback", ISABELLE_DAC_CFG_REG, | |
| 607 | + 3, 0), | |
| 608 | + SND_SOC_DAPM_DAC("DAC2R", "Handsfree Playback", ISABELLE_DAC_CFG_REG, | |
| 609 | + 2, 0), | |
| 610 | + SND_SOC_DAPM_DAC("DAC3L", "Lineout Playback", ISABELLE_DAC_CFG_REG, | |
| 611 | + 1, 0), | |
| 612 | + SND_SOC_DAPM_DAC("DAC3R", "Lineout Playback", ISABELLE_DAC_CFG_REG, | |
| 613 | + 0, 0), | |
| 614 | + | |
| 615 | + /* Analog Playback PGAs */ | |
| 616 | + SND_SOC_DAPM_PGA("Sidetone Audio PGA", SND_SOC_NOPM, 0, 0, NULL, 0), | |
| 617 | + SND_SOC_DAPM_PGA("Sidetone Voice PGA", SND_SOC_NOPM, 0, 0, NULL, 0), | |
| 618 | + SND_SOC_DAPM_PGA("HF Left PGA", SND_SOC_NOPM, 0, 0, NULL, 0), | |
| 619 | + SND_SOC_DAPM_PGA("HF Right PGA", SND_SOC_NOPM, 0, 0, NULL, 0), | |
| 620 | + SND_SOC_DAPM_PGA("DPGA1L", SND_SOC_NOPM, 0, 0, NULL, 0), | |
| 621 | + SND_SOC_DAPM_PGA("DPGA1R", SND_SOC_NOPM, 0, 0, NULL, 0), | |
| 622 | + SND_SOC_DAPM_PGA("DPGA2L", SND_SOC_NOPM, 0, 0, NULL, 0), | |
| 623 | + SND_SOC_DAPM_PGA("DPGA2R", SND_SOC_NOPM, 0, 0, NULL, 0), | |
| 624 | + SND_SOC_DAPM_PGA("DPGA3L", SND_SOC_NOPM, 0, 0, NULL, 0), | |
| 625 | + SND_SOC_DAPM_PGA("DPGA3R", SND_SOC_NOPM, 0, 0, NULL, 0), | |
| 626 | + | |
| 627 | + /* Analog Playback Mux */ | |
| 628 | + SND_SOC_DAPM_MUX("RX1 Playback", ISABELLE_ALU_RX_EN_REG, 5, 0, | |
| 629 | + &rx1_mux_controls), | |
| 630 | + SND_SOC_DAPM_MUX("RX2 Playback", ISABELLE_ALU_RX_EN_REG, 4, 0, | |
| 631 | + &rx2_mux_controls), | |
| 632 | + | |
| 633 | + /* TX Select */ | |
| 634 | + SND_SOC_DAPM_MUX("ATX Select", ISABELLE_TX_INPUT_CFG_REG, | |
| 635 | + 7, 0, &atx_mux_controls), | |
| 636 | + SND_SOC_DAPM_MUX("VTX Select", ISABELLE_TX_INPUT_CFG_REG, | |
| 637 | + 6, 0, &vtx_mux_controls), | |
| 638 | + | |
| 639 | + SND_SOC_DAPM_SWITCH("Earphone Playback", SND_SOC_NOPM, 0, 0, | |
| 640 | + &ep_path_enable_control), | |
| 641 | + | |
| 642 | + /* Output Drivers */ | |
| 643 | + SND_SOC_DAPM_OUT_DRV("HS Left Driver", ISABELLE_HSDRV_CFG2_REG, | |
| 644 | + 1, 0, NULL, 0), | |
| 645 | + SND_SOC_DAPM_OUT_DRV("HS Right Driver", ISABELLE_HSDRV_CFG2_REG, | |
| 646 | + 0, 0, NULL, 0), | |
| 647 | + SND_SOC_DAPM_OUT_DRV("LINEOUT1 Left Driver", ISABELLE_LINEAMP_CFG_REG, | |
| 648 | + 1, 0, NULL, 0), | |
| 649 | + SND_SOC_DAPM_OUT_DRV("LINEOUT2 Right Driver", ISABELLE_LINEAMP_CFG_REG, | |
| 650 | + 0, 0, NULL, 0), | |
| 651 | + SND_SOC_DAPM_OUT_DRV("Earphone Driver", ISABELLE_EARDRV_CFG2_REG, | |
| 652 | + 1, 0, NULL, 0), | |
| 653 | + | |
| 654 | + SND_SOC_DAPM_OUT_DRV("HF Left Driver", ISABELLE_HFDRV_CFG_REG, | |
| 655 | + 1, 0, NULL, 0), | |
| 656 | + SND_SOC_DAPM_OUT_DRV("HF Right Driver", ISABELLE_HFDRV_CFG_REG, | |
| 657 | + 0, 0, NULL, 0), | |
| 658 | +}; | |
| 659 | + | |
| 660 | +static const struct snd_soc_dapm_route isabelle_intercon[] = { | |
| 661 | + /* Interface mapping */ | |
| 662 | + { "DL1", "DL12 Playback Switch", "INTF1_SDI" }, | |
| 663 | + { "DL2", "DL12 Playback Switch", "INTF1_SDI" }, | |
| 664 | + { "DL3", "DL34 Playback Switch", "INTF1_SDI" }, | |
| 665 | + { "DL4", "DL34 Playback Switch", "INTF1_SDI" }, | |
| 666 | + { "DL5", "DL56 Playback Switch", "INTF1_SDI" }, | |
| 667 | + { "DL6", "DL56 Playback Switch", "INTF1_SDI" }, | |
| 668 | + | |
| 669 | + { "DL1", "DL12 Playback Switch", "INTF2_SDI" }, | |
| 670 | + { "DL2", "DL12 Playback Switch", "INTF2_SDI" }, | |
| 671 | + { "DL3", "DL34 Playback Switch", "INTF2_SDI" }, | |
| 672 | + { "DL4", "DL34 Playback Switch", "INTF2_SDI" }, | |
| 673 | + { "DL5", "DL56 Playback Switch", "INTF2_SDI" }, | |
| 674 | + { "DL6", "DL56 Playback Switch", "INTF2_SDI" }, | |
| 675 | + | |
| 676 | + /* Input side mapping */ | |
| 677 | + { "Sidetone Audio PGA", NULL, "Sidetone Audio Playback" }, | |
| 678 | + { "Sidetone Voice PGA", NULL, "Sidetone Voice Playback" }, | |
| 679 | + | |
| 680 | + { "RX1 Mixer", "ST1 Playback Switch", "Sidetone Audio PGA" }, | |
| 681 | + | |
| 682 | + { "RX1 Mixer", "ST1 Playback Switch", "Sidetone Voice PGA" }, | |
| 683 | + { "RX1 Mixer", "DL1 Playback Switch", "DL1" }, | |
| 684 | + | |
| 685 | + { "RX2 Mixer", "ST2 Playback Switch", "Sidetone Audio PGA" }, | |
| 686 | + | |
| 687 | + { "RX2 Mixer", "ST2 Playback Switch", "Sidetone Voice PGA" }, | |
| 688 | + { "RX2 Mixer", "DL2 Playback Switch", "DL2" }, | |
| 689 | + | |
| 690 | + { "RX3 Mixer", "ST1 Playback Switch", "Sidetone Voice PGA" }, | |
| 691 | + { "RX3 Mixer", "DL3 Playback Switch", "DL3" }, | |
| 692 | + | |
| 693 | + { "RX4 Mixer", "ST2 Playback Switch", "Sidetone Voice PGA" }, | |
| 694 | + { "RX4 Mixer", "DL4 Playback Switch", "DL4" }, | |
| 695 | + | |
| 696 | + { "RX5 Mixer", "ST1 Playback Switch", "Sidetone Voice PGA" }, | |
| 697 | + { "RX5 Mixer", "DL5 Playback Switch", "DL5" }, | |
| 698 | + | |
| 699 | + { "RX6 Mixer", "ST2 Playback Switch", "Sidetone Voice PGA" }, | |
| 700 | + { "RX6 Mixer", "DL6 Playback Switch", "DL6" }, | |
| 701 | + | |
| 702 | + /* Capture path */ | |
| 703 | + { "Analog Left Capture Route", "Headset Mic", "HSMIC" }, | |
| 704 | + { "Analog Left Capture Route", "Main Mic", "MAINMIC" }, | |
| 705 | + { "Analog Left Capture Route", "Aux/FM Left", "LINEIN1" }, | |
| 706 | + | |
| 707 | + { "Analog Right Capture Route", "Sub Mic", "SUBMIC" }, | |
| 708 | + { "Analog Right Capture Route", "Aux/FM Right", "LINEIN2" }, | |
| 709 | + | |
| 710 | + { "MicAmp1", NULL, "Analog Left Capture Route" }, | |
| 711 | + { "MicAmp2", NULL, "Analog Right Capture Route" }, | |
| 712 | + | |
| 713 | + { "ADC1", NULL, "MicAmp1" }, | |
| 714 | + { "ADC2", NULL, "MicAmp2" }, | |
| 715 | + | |
| 716 | + { "ATX Select", "AMIC1", "ADC1" }, | |
| 717 | + { "ATX Select", "DMIC", "DMICDAT" }, | |
| 718 | + { "ATX Select", "AMIC2", "ADC2" }, | |
| 719 | + | |
| 720 | + { "VTX Select", "AMIC1", "ADC1" }, | |
| 721 | + { "VTX Select", "DMIC", "DMICDAT" }, | |
| 722 | + { "VTX Select", "AMIC2", "ADC2" }, | |
| 723 | + | |
| 724 | + { "ULATX1", "ATX1 Filter Enable Switch", "ATX Select" }, | |
| 725 | + { "ULATX1", "ATX1 Filter Bypass Switch", "ATX Select" }, | |
| 726 | + { "ULATX2", "ATX2 Filter Enable Switch", "ATX Select" }, | |
| 727 | + { "ULATX2", "ATX2 Filter Bypass Switch", "ATX Select" }, | |
| 728 | + | |
| 729 | + { "ULVTX1", "VTX1 Filter Enable Switch", "VTX Select" }, | |
| 730 | + { "ULVTX1", "VTX1 Filter Bypass Switch", "VTX Select" }, | |
| 731 | + { "ULVTX2", "VTX2 Filter Enable Switch", "VTX Select" }, | |
| 732 | + { "ULVTX2", "VTX2 Filter Bypass Switch", "VTX Select" }, | |
| 733 | + | |
| 734 | + { "INTF1_SDO", "ULATX12 Capture Switch", "ULATX1" }, | |
| 735 | + { "INTF1_SDO", "ULATX12 Capture Switch", "ULATX2" }, | |
| 736 | + { "INTF2_SDO", "ULATX12 Capture Switch", "ULATX1" }, | |
| 737 | + { "INTF2_SDO", "ULATX12 Capture Switch", "ULATX2" }, | |
| 738 | + | |
| 739 | + { "INTF1_SDO", NULL, "ULVTX1" }, | |
| 740 | + { "INTF1_SDO", NULL, "ULVTX2" }, | |
| 741 | + { "INTF2_SDO", NULL, "ULVTX1" }, | |
| 742 | + { "INTF2_SDO", NULL, "ULVTX2" }, | |
| 743 | + | |
| 744 | + /* AFM Path */ | |
| 745 | + { "APGA1", NULL, "LINEIN1" }, | |
| 746 | + { "APGA2", NULL, "LINEIN2" }, | |
| 747 | + | |
| 748 | + { "RX1 Playback", "VRX1 Filter Bypass Switch", "RX1 Mixer" }, | |
| 749 | + { "RX1 Playback", "ARX1 Filter Bypass Switch", "RX1 Mixer" }, | |
| 750 | + { "RX1 Playback", "RX1 Filter Enable Switch", "RX1 Mixer" }, | |
| 751 | + | |
| 752 | + { "RX2 Playback", "VRX2 Filter Bypass Switch", "RX2 Mixer" }, | |
| 753 | + { "RX2 Playback", "ARX2 Filter Bypass Switch", "RX2 Mixer" }, | |
| 754 | + { "RX2 Playback", "RX2 Filter Enable Switch", "RX2 Mixer" }, | |
| 755 | + | |
| 756 | + { "RX3 Playback", "ARX3 Filter Bypass Switch", "RX3 Mixer" }, | |
| 757 | + { "RX3 Playback", "RX3 Filter Enable Switch", "RX3 Mixer" }, | |
| 758 | + | |
| 759 | + { "RX4 Playback", "ARX4 Filter Bypass Switch", "RX4 Mixer" }, | |
| 760 | + { "RX4 Playback", "RX4 Filter Enable Switch", "RX4 Mixer" }, | |
| 761 | + | |
| 762 | + { "RX5 Playback", "ARX5 Filter Bypass Switch", "RX5 Mixer" }, | |
| 763 | + { "RX5 Playback", "RX5 Filter Enable Switch", "RX5 Mixer" }, | |
| 764 | + | |
| 765 | + { "RX6 Playback", "ARX6 Filter Bypass Switch", "RX6 Mixer" }, | |
| 766 | + { "RX6 Playback", "RX6 Filter Enable Switch", "RX6 Mixer" }, | |
| 767 | + | |
| 768 | + { "DPGA1L Mixer", "RX1 Playback Switch", "RX1 Playback" }, | |
| 769 | + { "DPGA1L Mixer", "RX3 Playback Switch", "RX3 Playback" }, | |
| 770 | + { "DPGA1L Mixer", "RX5 Playback Switch", "RX5 Playback" }, | |
| 771 | + | |
| 772 | + { "DPGA1R Mixer", "RX2 Playback Switch", "RX2 Playback" }, | |
| 773 | + { "DPGA1R Mixer", "RX4 Playback Switch", "RX4 Playback" }, | |
| 774 | + { "DPGA1R Mixer", "RX6 Playback Switch", "RX6 Playback" }, | |
| 775 | + | |
| 776 | + { "DPGA1L", NULL, "DPGA1L Mixer" }, | |
| 777 | + { "DPGA1R", NULL, "DPGA1R Mixer" }, | |
| 778 | + | |
| 779 | + { "DAC1L", NULL, "DPGA1L" }, | |
| 780 | + { "DAC1R", NULL, "DPGA1R" }, | |
| 781 | + | |
| 782 | + { "DPGA2L Mixer", "RX1 Playback Switch", "RX1 Playback" }, | |
| 783 | + { "DPGA2L Mixer", "RX2 Playback Switch", "RX2 Playback" }, | |
| 784 | + { "DPGA2L Mixer", "RX3 Playback Switch", "RX3 Playback" }, | |
| 785 | + { "DPGA2L Mixer", "RX4 Playback Switch", "RX4 Playback" }, | |
| 786 | + { "DPGA2L Mixer", "RX5 Playback Switch", "RX5 Playback" }, | |
| 787 | + { "DPGA2L Mixer", "RX6 Playback Switch", "RX6 Playback" }, | |
| 788 | + | |
| 789 | + { "DPGA2R Mixer", "RX2 Playback Switch", "RX2 Playback" }, | |
| 790 | + { "DPGA2R Mixer", "RX4 Playback Switch", "RX4 Playback" }, | |
| 791 | + { "DPGA2R Mixer", "RX6 Playback Switch", "RX6 Playback" }, | |
| 792 | + | |
| 793 | + { "DPGA2L", NULL, "DPGA2L Mixer" }, | |
| 794 | + { "DPGA2R", NULL, "DPGA2R Mixer" }, | |
| 795 | + | |
| 796 | + { "DAC2L", NULL, "DPGA2L" }, | |
| 797 | + { "DAC2R", NULL, "DPGA2R" }, | |
| 798 | + | |
| 799 | + { "DPGA3L Mixer", "RX1 Playback Switch", "RX1 Playback" }, | |
| 800 | + { "DPGA3L Mixer", "RX3 Playback Switch", "RX3 Playback" }, | |
| 801 | + { "DPGA3L Mixer", "RX5 Playback Switch", "RX5 Playback" }, | |
| 802 | + | |
| 803 | + { "DPGA3R Mixer", "RX2 Playback Switch", "RX2 Playback" }, | |
| 804 | + { "DPGA3R Mixer", "RX4 Playback Switch", "RX4 Playback" }, | |
| 805 | + { "DPGA3R Mixer", "RX6 Playback Switch", "RX6 Playback" }, | |
| 806 | + | |
| 807 | + { "DPGA3L", NULL, "DPGA3L Mixer" }, | |
| 808 | + { "DPGA3R", NULL, "DPGA3R Mixer" }, | |
| 809 | + | |
| 810 | + { "DAC3L", NULL, "DPGA3L" }, | |
| 811 | + { "DAC3R", NULL, "DPGA3R" }, | |
| 812 | + | |
| 813 | + { "Headset Left Mixer", "DAC1L Playback Switch", "DAC1L" }, | |
| 814 | + { "Headset Left Mixer", "APGA1 Playback Switch", "APGA1" }, | |
| 815 | + | |
| 816 | + { "Headset Right Mixer", "DAC1R Playback Switch", "DAC1R" }, | |
| 817 | + { "Headset Right Mixer", "APGA2 Playback Switch", "APGA2" }, | |
| 818 | + | |
| 819 | + { "HS Left Driver", NULL, "Headset Left Mixer" }, | |
| 820 | + { "HS Right Driver", NULL, "Headset Right Mixer" }, | |
| 821 | + | |
| 822 | + { "HSOL", NULL, "HS Left Driver" }, | |
| 823 | + { "HSOR", NULL, "HS Right Driver" }, | |
| 824 | + | |
| 825 | + /* Earphone playback path */ | |
| 826 | + { "Earphone Mixer", "DAC2L Playback Switch", "DAC2L" }, | |
| 827 | + { "Earphone Mixer", "APGA1 Playback Switch", "APGA1" }, | |
| 828 | + | |
| 829 | + { "Earphone Playback", "Switch", "Earphone Mixer" }, | |
| 830 | + { "Earphone Driver", NULL, "Earphone Playback" }, | |
| 831 | + { "EP", NULL, "Earphone Driver" }, | |
| 832 | + | |
| 833 | + { "Handsfree Left Mixer", "DAC2L Playback Switch", "DAC2L" }, | |
| 834 | + { "Handsfree Left Mixer", "APGA1 Playback Switch", "APGA1" }, | |
| 835 | + | |
| 836 | + { "Handsfree Right Mixer", "DAC2R Playback Switch", "DAC2R" }, | |
| 837 | + { "Handsfree Right Mixer", "APGA2 Playback Switch", "APGA2" }, | |
| 838 | + | |
| 839 | + { "HF Left PGA", NULL, "Handsfree Left Mixer" }, | |
| 840 | + { "HF Right PGA", NULL, "Handsfree Right Mixer" }, | |
| 841 | + | |
| 842 | + { "HF Left Driver", NULL, "HF Left PGA" }, | |
| 843 | + { "HF Right Driver", NULL, "HF Right PGA" }, | |
| 844 | + | |
| 845 | + { "HFL", NULL, "HF Left Driver" }, | |
| 846 | + { "HFR", NULL, "HF Right Driver" }, | |
| 847 | + | |
| 848 | + { "LINEOUT1 Mixer", "DAC3L Playback Switch", "DAC3L" }, | |
| 849 | + { "LINEOUT1 Mixer", "APGA1 Playback Switch", "APGA1" }, | |
| 850 | + | |
| 851 | + { "LINEOUT2 Mixer", "DAC3R Playback Switch", "DAC3R" }, | |
| 852 | + { "LINEOUT2 Mixer", "APGA2 Playback Switch", "APGA2" }, | |
| 853 | + | |
| 854 | + { "LINEOUT1 Driver", NULL, "LINEOUT1 Mixer" }, | |
| 855 | + { "LINEOUT2 Driver", NULL, "LINEOUT2 Mixer" }, | |
| 856 | + | |
| 857 | + { "LINEOUT1", NULL, "LINEOUT1 Driver" }, | |
| 858 | + { "LINEOUT2", NULL, "LINEOUT2 Driver" }, | |
| 859 | +}; | |
| 860 | + | |
| 861 | +static int isabelle_hs_mute(struct snd_soc_dai *dai, int mute) | |
| 862 | +{ | |
| 863 | + snd_soc_update_bits(dai->codec, ISABELLE_DAC1_SOFTRAMP_REG, | |
| 864 | + BIT(4), (mute ? BIT(4) : 0)); | |
| 865 | + | |
| 866 | + return 0; | |
| 867 | +} | |
| 868 | + | |
| 869 | +static int isabelle_hf_mute(struct snd_soc_dai *dai, int mute) | |
| 870 | +{ | |
| 871 | + snd_soc_update_bits(dai->codec, ISABELLE_DAC2_SOFTRAMP_REG, | |
| 872 | + BIT(4), (mute ? BIT(4) : 0)); | |
| 873 | + | |
| 874 | + return 0; | |
| 875 | +} | |
| 876 | + | |
| 877 | +static int isabelle_line_mute(struct snd_soc_dai *dai, int mute) | |
| 878 | +{ | |
| 879 | + snd_soc_update_bits(dai->codec, ISABELLE_DAC3_SOFTRAMP_REG, | |
| 880 | + BIT(4), (mute ? BIT(4) : 0)); | |
| 881 | + | |
| 882 | + return 0; | |
| 883 | +} | |
| 884 | + | |
| 885 | +static int isabelle_set_bias_level(struct snd_soc_codec *codec, | |
| 886 | + enum snd_soc_bias_level level) | |
| 887 | +{ | |
| 888 | + switch (level) { | |
| 889 | + case SND_SOC_BIAS_ON: | |
| 890 | + break; | |
| 891 | + case SND_SOC_BIAS_PREPARE: | |
| 892 | + break; | |
| 893 | + | |
| 894 | + case SND_SOC_BIAS_STANDBY: | |
| 895 | + snd_soc_update_bits(codec, ISABELLE_PWR_EN_REG, | |
| 896 | + ISABELLE_CHIP_EN, BIT(0)); | |
| 897 | + break; | |
| 898 | + | |
| 899 | + case SND_SOC_BIAS_OFF: | |
| 900 | + snd_soc_update_bits(codec, ISABELLE_PWR_EN_REG, | |
| 901 | + ISABELLE_CHIP_EN, 0); | |
| 902 | + break; | |
| 903 | + } | |
| 904 | + | |
| 905 | + codec->dapm.bias_level = level; | |
| 906 | + | |
| 907 | + return 0; | |
| 908 | +} | |
| 909 | + | |
| 910 | +static int isabelle_hw_params(struct snd_pcm_substream *substream, | |
| 911 | + struct snd_pcm_hw_params *params, | |
| 912 | + struct snd_soc_dai *dai) | |
| 913 | +{ | |
| 914 | + struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
| 915 | + struct snd_soc_codec *codec = rtd->codec; | |
| 916 | + u16 aif = 0; | |
| 917 | + unsigned int fs_val = 0; | |
| 918 | + | |
| 919 | + switch (params_rate(params)) { | |
| 920 | + case 8000: | |
| 921 | + fs_val = ISABELLE_FS_RATE_8; | |
| 922 | + break; | |
| 923 | + case 11025: | |
| 924 | + fs_val = ISABELLE_FS_RATE_11; | |
| 925 | + break; | |
| 926 | + case 12000: | |
| 927 | + fs_val = ISABELLE_FS_RATE_12; | |
| 928 | + break; | |
| 929 | + case 16000: | |
| 930 | + fs_val = ISABELLE_FS_RATE_16; | |
| 931 | + break; | |
| 932 | + case 22050: | |
| 933 | + fs_val = ISABELLE_FS_RATE_22; | |
| 934 | + break; | |
| 935 | + case 24000: | |
| 936 | + fs_val = ISABELLE_FS_RATE_24; | |
| 937 | + break; | |
| 938 | + case 32000: | |
| 939 | + fs_val = ISABELLE_FS_RATE_32; | |
| 940 | + break; | |
| 941 | + case 44100: | |
| 942 | + fs_val = ISABELLE_FS_RATE_44; | |
| 943 | + break; | |
| 944 | + case 48000: | |
| 945 | + fs_val = ISABELLE_FS_RATE_48; | |
| 946 | + break; | |
| 947 | + default: | |
| 948 | + return -EINVAL; | |
| 949 | + } | |
| 950 | + | |
| 951 | + snd_soc_update_bits(codec, ISABELLE_FS_RATE_CFG_REG, | |
| 952 | + ISABELLE_FS_RATE_MASK, fs_val); | |
| 953 | + | |
| 954 | + /* bit size */ | |
| 955 | + switch (params_format(params)) { | |
| 956 | + case SNDRV_PCM_FORMAT_S20_3LE: | |
| 957 | + aif |= ISABELLE_AIF_LENGTH_20; | |
| 958 | + break; | |
| 959 | + case SNDRV_PCM_FORMAT_S32_LE: | |
| 960 | + aif |= ISABELLE_AIF_LENGTH_32; | |
| 961 | + break; | |
| 962 | + default: | |
| 963 | + return -EINVAL; | |
| 964 | + } | |
| 965 | + | |
| 966 | + snd_soc_update_bits(codec, ISABELLE_INTF_CFG_REG, | |
| 967 | + ISABELLE_AIF_LENGTH_MASK, aif); | |
| 968 | + | |
| 969 | + return 0; | |
| 970 | +} | |
| 971 | + | |
| 972 | +static int isabelle_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | |
| 973 | +{ | |
| 974 | + struct snd_soc_codec *codec = codec_dai->codec; | |
| 975 | + unsigned int aif_val = 0; | |
| 976 | + | |
| 977 | + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | |
| 978 | + case SND_SOC_DAIFMT_CBS_CFS: | |
| 979 | + aif_val &= ~ISABELLE_AIF_MS; | |
| 980 | + break; | |
| 981 | + case SND_SOC_DAIFMT_CBM_CFM: | |
| 982 | + aif_val |= ISABELLE_AIF_MS; | |
| 983 | + break; | |
| 984 | + default: | |
| 985 | + return -EINVAL; | |
| 986 | + } | |
| 987 | + | |
| 988 | + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | |
| 989 | + case SND_SOC_DAIFMT_I2S: | |
| 990 | + aif_val |= ISABELLE_I2S_MODE; | |
| 991 | + break; | |
| 992 | + case SND_SOC_DAIFMT_LEFT_J: | |
| 993 | + aif_val |= ISABELLE_LEFT_J_MODE; | |
| 994 | + break; | |
| 995 | + case SND_SOC_DAIFMT_PDM: | |
| 996 | + aif_val |= ISABELLE_PDM_MODE; | |
| 997 | + break; | |
| 998 | + default: | |
| 999 | + return -EINVAL; | |
| 1000 | + } | |
| 1001 | + | |
| 1002 | + snd_soc_update_bits(codec, ISABELLE_INTF_CFG_REG, | |
| 1003 | + (ISABELLE_AIF_MS | ISABELLE_AIF_FMT_MASK), aif_val); | |
| 1004 | + | |
| 1005 | + return 0; | |
| 1006 | +} | |
| 1007 | + | |
| 1008 | +/* Rates supported by Isabelle driver */ | |
| 1009 | +#define ISABELLE_RATES SNDRV_PCM_RATE_8000_48000 | |
| 1010 | + | |
| 1011 | +/* Formates supported by Isabelle driver. */ | |
| 1012 | +#define ISABELLE_FORMATS (SNDRV_PCM_FMTBIT_S20_3LE |\ | |
| 1013 | + SNDRV_PCM_FMTBIT_S32_LE) | |
| 1014 | + | |
| 1015 | +static struct snd_soc_dai_ops isabelle_hs_dai_ops = { | |
| 1016 | + .hw_params = isabelle_hw_params, | |
| 1017 | + .set_fmt = isabelle_set_dai_fmt, | |
| 1018 | + .digital_mute = isabelle_hs_mute, | |
| 1019 | +}; | |
| 1020 | + | |
| 1021 | +static struct snd_soc_dai_ops isabelle_hf_dai_ops = { | |
| 1022 | + .hw_params = isabelle_hw_params, | |
| 1023 | + .set_fmt = isabelle_set_dai_fmt, | |
| 1024 | + .digital_mute = isabelle_hf_mute, | |
| 1025 | +}; | |
| 1026 | + | |
| 1027 | +static struct snd_soc_dai_ops isabelle_line_dai_ops = { | |
| 1028 | + .hw_params = isabelle_hw_params, | |
| 1029 | + .set_fmt = isabelle_set_dai_fmt, | |
| 1030 | + .digital_mute = isabelle_line_mute, | |
| 1031 | +}; | |
| 1032 | + | |
| 1033 | +static struct snd_soc_dai_ops isabelle_ul_dai_ops = { | |
| 1034 | + .hw_params = isabelle_hw_params, | |
| 1035 | + .set_fmt = isabelle_set_dai_fmt, | |
| 1036 | +}; | |
| 1037 | + | |
| 1038 | +/* ISABELLE dai structure */ | |
| 1039 | +static struct snd_soc_dai_driver isabelle_dai[] = { | |
| 1040 | + { | |
| 1041 | + .name = "isabelle-dl1", | |
| 1042 | + .playback = { | |
| 1043 | + .stream_name = "Headset Playback", | |
| 1044 | + .channels_min = 1, | |
| 1045 | + .channels_max = 2, | |
| 1046 | + .rates = ISABELLE_RATES, | |
| 1047 | + .formats = ISABELLE_FORMATS, | |
| 1048 | + }, | |
| 1049 | + .ops = &isabelle_hs_dai_ops, | |
| 1050 | + }, | |
| 1051 | + { | |
| 1052 | + .name = "isabelle-dl2", | |
| 1053 | + .playback = { | |
| 1054 | + .stream_name = "Handsfree Playback", | |
| 1055 | + .channels_min = 1, | |
| 1056 | + .channels_max = 2, | |
| 1057 | + .rates = ISABELLE_RATES, | |
| 1058 | + .formats = ISABELLE_FORMATS, | |
| 1059 | + }, | |
| 1060 | + .ops = &isabelle_hf_dai_ops, | |
| 1061 | + }, | |
| 1062 | + { | |
| 1063 | + .name = "isabelle-lineout", | |
| 1064 | + .playback = { | |
| 1065 | + .stream_name = "Lineout Playback", | |
| 1066 | + .channels_min = 1, | |
| 1067 | + .channels_max = 2, | |
| 1068 | + .rates = ISABELLE_RATES, | |
| 1069 | + .formats = ISABELLE_FORMATS, | |
| 1070 | + }, | |
| 1071 | + .ops = &isabelle_line_dai_ops, | |
| 1072 | + }, | |
| 1073 | + { | |
| 1074 | + .name = "isabelle-ul", | |
| 1075 | + .capture = { | |
| 1076 | + .stream_name = "Capture", | |
| 1077 | + .channels_min = 1, | |
| 1078 | + .channels_max = 2, | |
| 1079 | + .rates = ISABELLE_RATES, | |
| 1080 | + .formats = ISABELLE_FORMATS, | |
| 1081 | + }, | |
| 1082 | + .ops = &isabelle_ul_dai_ops, | |
| 1083 | + }, | |
| 1084 | +}; | |
| 1085 | + | |
| 1086 | +static int isabelle_probe(struct snd_soc_codec *codec) | |
| 1087 | +{ | |
| 1088 | + int ret = 0; | |
| 1089 | + | |
| 1090 | + codec->control_data = dev_get_regmap(codec->dev, NULL); | |
| 1091 | + | |
| 1092 | + ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | |
| 1093 | + if (ret < 0) { | |
| 1094 | + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | |
| 1095 | + return ret; | |
| 1096 | + } | |
| 1097 | + | |
| 1098 | + return 0; | |
| 1099 | +} | |
| 1100 | + | |
| 1101 | +static struct snd_soc_codec_driver soc_codec_dev_isabelle = { | |
| 1102 | + .probe = isabelle_probe, | |
| 1103 | + .set_bias_level = isabelle_set_bias_level, | |
| 1104 | + .controls = isabelle_snd_controls, | |
| 1105 | + .num_controls = ARRAY_SIZE(isabelle_snd_controls), | |
| 1106 | + .dapm_widgets = isabelle_dapm_widgets, | |
| 1107 | + .num_dapm_widgets = ARRAY_SIZE(isabelle_dapm_widgets), | |
| 1108 | + .dapm_routes = isabelle_intercon, | |
| 1109 | + .num_dapm_routes = ARRAY_SIZE(isabelle_intercon), | |
| 1110 | + .idle_bias_off = true, | |
| 1111 | +}; | |
| 1112 | + | |
| 1113 | +static const struct regmap_config isabelle_regmap_config = { | |
| 1114 | + .reg_bits = 8, | |
| 1115 | + .val_bits = 8, | |
| 1116 | + | |
| 1117 | + .max_register = ISABELLE_MAX_REGISTER, | |
| 1118 | + .reg_defaults = isabelle_reg_defs, | |
| 1119 | + .num_reg_defaults = ARRAY_SIZE(isabelle_reg_defs), | |
| 1120 | + .cache_type = REGCACHE_RBTREE, | |
| 1121 | +}; | |
| 1122 | + | |
| 1123 | +static int __devinit isabelle_i2c_probe(struct i2c_client *i2c, | |
| 1124 | + const struct i2c_device_id *id) | |
| 1125 | +{ | |
| 1126 | + struct regmap *isabelle_regmap; | |
| 1127 | + int ret = 0; | |
| 1128 | + | |
| 1129 | + isabelle_regmap = devm_regmap_init_i2c(i2c, &isabelle_regmap_config); | |
| 1130 | + if (IS_ERR(isabelle_regmap)) { | |
| 1131 | + ret = PTR_ERR(isabelle_regmap); | |
| 1132 | + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | |
| 1133 | + ret); | |
| 1134 | + return ret; | |
| 1135 | + } | |
| 1136 | + i2c_set_clientdata(i2c, isabelle_regmap); | |
| 1137 | + | |
| 1138 | + ret = snd_soc_register_codec(&i2c->dev, | |
| 1139 | + &soc_codec_dev_isabelle, isabelle_dai, | |
| 1140 | + ARRAY_SIZE(isabelle_dai)); | |
| 1141 | + if (ret < 0) { | |
| 1142 | + dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); | |
| 1143 | + return ret; | |
| 1144 | + } | |
| 1145 | + | |
| 1146 | + return ret; | |
| 1147 | +} | |
| 1148 | + | |
| 1149 | +static int __devexit isabelle_i2c_remove(struct i2c_client *client) | |
| 1150 | +{ | |
| 1151 | + snd_soc_unregister_codec(&client->dev); | |
| 1152 | + return 0; | |
| 1153 | +} | |
| 1154 | + | |
| 1155 | +static const struct i2c_device_id isabelle_i2c_id[] = { | |
| 1156 | + { "isabelle", 0 }, | |
| 1157 | + { } | |
| 1158 | +}; | |
| 1159 | +MODULE_DEVICE_TABLE(i2c, isabelle_i2c_id); | |
| 1160 | + | |
| 1161 | +static struct i2c_driver isabelle_i2c_driver = { | |
| 1162 | + .driver = { | |
| 1163 | + .name = "isabelle", | |
| 1164 | + .owner = THIS_MODULE, | |
| 1165 | + }, | |
| 1166 | + .probe = isabelle_i2c_probe, | |
| 1167 | + .remove = __devexit_p(isabelle_i2c_remove), | |
| 1168 | + .id_table = isabelle_i2c_id, | |
| 1169 | +}; | |
| 1170 | + | |
| 1171 | +module_i2c_driver(isabelle_i2c_driver); | |
| 1172 | + | |
| 1173 | +MODULE_DESCRIPTION("ASoC ISABELLE driver"); | |
| 1174 | +MODULE_AUTHOR("Vishwas A Deshpande <vishwas.a.deshpande@ti.com>"); | |
| 1175 | +MODULE_AUTHOR("M R Swami Reddy <MR.Swami.Reddy@ti.com>"); | |
| 1176 | +MODULE_LICENSE("GPL v2"); | |
| @@ -0,0 +1,143 @@ | ||
| 1 | +/* | |
| 2 | + * isabelle.h - Low power high fidelity audio codec driver header file | |
| 3 | + * | |
| 4 | + * Copyright (c) 2012 Texas Instruments, Inc | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation; version 2 of the License. | |
| 9 | + * | |
| 10 | + */ | |
| 11 | + | |
| 12 | +#ifndef _ISABELLE_H | |
| 13 | +#define _ISABELLE_H | |
| 14 | + | |
| 15 | +#include <linux/bitops.h> | |
| 16 | + | |
| 17 | +/* ISABELLE REGISTERS */ | |
| 18 | + | |
| 19 | +#define ISABELLE_PWR_CFG_REG 0x01 | |
| 20 | +#define ISABELLE_PWR_EN_REG 0x02 | |
| 21 | +#define ISABELLE_PS_EN1_REG 0x03 | |
| 22 | +#define ISABELLE_INT1_STATUS_REG 0x04 | |
| 23 | +#define ISABELLE_INT1_MASK_REG 0x05 | |
| 24 | +#define ISABELLE_INT2_STATUS_REG 0x06 | |
| 25 | +#define ISABELLE_INT2_MASK_REG 0x07 | |
| 26 | +#define ISABELLE_HKCTL1_REG 0x08 | |
| 27 | +#define ISABELLE_HKCTL2_REG 0x09 | |
| 28 | +#define ISABELLE_HKCTL3_REG 0x0A | |
| 29 | +#define ISABELLE_ACCDET_STATUS_REG 0x0B | |
| 30 | +#define ISABELLE_BUTTON_ID_REG 0x0C | |
| 31 | +#define ISABELLE_PLL_CFG_REG 0x10 | |
| 32 | +#define ISABELLE_PLL_EN_REG 0x11 | |
| 33 | +#define ISABELLE_FS_RATE_CFG_REG 0x12 | |
| 34 | +#define ISABELLE_INTF_CFG_REG 0x13 | |
| 35 | +#define ISABELLE_INTF_EN_REG 0x14 | |
| 36 | +#define ISABELLE_ULATX12_INTF_CFG_REG 0x15 | |
| 37 | +#define ISABELLE_DL12_INTF_CFG_REG 0x16 | |
| 38 | +#define ISABELLE_DL34_INTF_CFG_REG 0x17 | |
| 39 | +#define ISABELLE_DL56_INTF_CFG_REG 0x18 | |
| 40 | +#define ISABELLE_ATX_STPGA1_CFG_REG 0x19 | |
| 41 | +#define ISABELLE_ATX_STPGA2_CFG_REG 0x1A | |
| 42 | +#define ISABELLE_VTX_STPGA1_CFG_REG 0x1B | |
| 43 | +#define ISABELLE_VTX2_STPGA2_CFG_REG 0x1C | |
| 44 | +#define ISABELLE_ATX1_DPGA_REG 0x1D | |
| 45 | +#define ISABELLE_ATX2_DPGA_REG 0x1E | |
| 46 | +#define ISABELLE_VTX1_DPGA_REG 0x1F | |
| 47 | +#define ISABELLE_VTX2_DPGA_REG 0x20 | |
| 48 | +#define ISABELLE_TX_INPUT_CFG_REG 0x21 | |
| 49 | +#define ISABELLE_RX_INPUT_CFG_REG 0x22 | |
| 50 | +#define ISABELLE_RX_INPUT_CFG2_REG 0x23 | |
| 51 | +#define ISABELLE_VOICE_HPF_CFG_REG 0x24 | |
| 52 | +#define ISABELLE_AUDIO_HPF_CFG_REG 0x25 | |
| 53 | +#define ISABELLE_RX1_DPGA_REG 0x26 | |
| 54 | +#define ISABELLE_RX2_DPGA_REG 0x27 | |
| 55 | +#define ISABELLE_RX3_DPGA_REG 0x28 | |
| 56 | +#define ISABELLE_RX4_DPGA_REG 0x29 | |
| 57 | +#define ISABELLE_RX5_DPGA_REG 0x2A | |
| 58 | +#define ISABELLE_RX6_DPGA_REG 0x2B | |
| 59 | +#define ISABELLE_ALU_TX_EN_REG 0x2C | |
| 60 | +#define ISABELLE_ALU_RX_EN_REG 0x2D | |
| 61 | +#define ISABELLE_IIR_RESYNC_REG 0x2E | |
| 62 | +#define ISABELLE_ABIAS_CFG_REG 0x30 | |
| 63 | +#define ISABELLE_DBIAS_CFG_REG 0x31 | |
| 64 | +#define ISABELLE_MIC1_GAIN_REG 0x32 | |
| 65 | +#define ISABELLE_MIC2_GAIN_REG 0x33 | |
| 66 | +#define ISABELLE_AMIC_CFG_REG 0x34 | |
| 67 | +#define ISABELLE_DMIC_CFG_REG 0x35 | |
| 68 | +#define ISABELLE_APGA_GAIN_REG 0x36 | |
| 69 | +#define ISABELLE_APGA_CFG_REG 0x37 | |
| 70 | +#define ISABELLE_TX_GAIN_DLY_REG 0x38 | |
| 71 | +#define ISABELLE_RX_GAIN_DLY_REG 0x39 | |
| 72 | +#define ISABELLE_RX_PWR_CTRL_REG 0x3A | |
| 73 | +#define ISABELLE_DPGA1LR_IN_SEL_REG 0x3B | |
| 74 | +#define ISABELLE_DPGA1L_GAIN_REG 0x3C | |
| 75 | +#define ISABELLE_DPGA1R_GAIN_REG 0x3D | |
| 76 | +#define ISABELLE_DPGA2L_IN_SEL_REG 0x3E | |
| 77 | +#define ISABELLE_DPGA2R_IN_SEL_REG 0x3F | |
| 78 | +#define ISABELLE_DPGA2L_GAIN_REG 0x40 | |
| 79 | +#define ISABELLE_DPGA2R_GAIN_REG 0x41 | |
| 80 | +#define ISABELLE_DPGA3LR_IN_SEL_REG 0x42 | |
| 81 | +#define ISABELLE_DPGA3L_GAIN_REG 0x43 | |
| 82 | +#define ISABELLE_DPGA3R_GAIN_REG 0x44 | |
| 83 | +#define ISABELLE_DAC1_SOFTRAMP_REG 0x45 | |
| 84 | +#define ISABELLE_DAC2_SOFTRAMP_REG 0x46 | |
| 85 | +#define ISABELLE_DAC3_SOFTRAMP_REG 0x47 | |
| 86 | +#define ISABELLE_DAC_CFG_REG 0x48 | |
| 87 | +#define ISABELLE_EARDRV_CFG1_REG 0x49 | |
| 88 | +#define ISABELLE_EARDRV_CFG2_REG 0x4A | |
| 89 | +#define ISABELLE_HSDRV_GAIN_REG 0x4B | |
| 90 | +#define ISABELLE_HSDRV_CFG1_REG 0x4C | |
| 91 | +#define ISABELLE_HSDRV_CFG2_REG 0x4D | |
| 92 | +#define ISABELLE_HS_NG_CFG1_REG 0x4E | |
| 93 | +#define ISABELLE_HS_NG_CFG2_REG 0x4F | |
| 94 | +#define ISABELLE_LINEAMP_GAIN_REG 0x50 | |
| 95 | +#define ISABELLE_LINEAMP_CFG_REG 0x51 | |
| 96 | +#define ISABELLE_HFL_VOL_CTRL_REG 0x52 | |
| 97 | +#define ISABELLE_HFL_SFTVOL_CTRL_REG 0x53 | |
| 98 | +#define ISABELLE_HFL_LIM_CTRL_1_REG 0x54 | |
| 99 | +#define ISABELLE_HFL_LIM_CTRL_2_REG 0x55 | |
| 100 | +#define ISABELLE_HFR_VOL_CTRL_REG 0x56 | |
| 101 | +#define ISABELLE_HFR_SFTVOL_CTRL_REG 0x57 | |
| 102 | +#define ISABELLE_HFR_LIM_CTRL_1_REG 0x58 | |
| 103 | +#define ISABELLE_HFR_LIM_CTRL_2_REG 0x59 | |
| 104 | +#define ISABELLE_HF_MODE_REG 0x5A | |
| 105 | +#define ISABELLE_HFLPGA_CFG_REG 0x5B | |
| 106 | +#define ISABELLE_HFRPGA_CFG_REG 0x5C | |
| 107 | +#define ISABELLE_HFDRV_CFG_REG 0x5D | |
| 108 | +#define ISABELLE_PDMOUT_CFG1_REG 0x5E | |
| 109 | +#define ISABELLE_PDMOUT_CFG2_REG 0x5F | |
| 110 | +#define ISABELLE_PDMOUT_L_WM_REG 0x60 | |
| 111 | +#define ISABELLE_PDMOUT_R_WM_REG 0x61 | |
| 112 | +#define ISABELLE_HF_NG_CFG1_REG 0x62 | |
| 113 | +#define ISABELLE_HF_NG_CFG2_REG 0x63 | |
| 114 | + | |
| 115 | +/* ISABELLE_PWR_EN_REG (0x02h) */ | |
| 116 | +#define ISABELLE_CHIP_EN BIT(0) | |
| 117 | + | |
| 118 | +/* ISABELLE DAI FORMATS */ | |
| 119 | +#define ISABELLE_AIF_FMT_MASK 0x70 | |
| 120 | +#define ISABELLE_I2S_MODE 0x0 | |
| 121 | +#define ISABELLE_LEFT_J_MODE 0x1 | |
| 122 | +#define ISABELLE_PDM_MODE 0x2 | |
| 123 | + | |
| 124 | +#define ISABELLE_AIF_LENGTH_MASK 0x30 | |
| 125 | +#define ISABELLE_AIF_LENGTH_20 0x00 | |
| 126 | +#define ISABELLE_AIF_LENGTH_32 0x10 | |
| 127 | + | |
| 128 | +#define ISABELLE_AIF_MS 0x80 | |
| 129 | + | |
| 130 | +#define ISABELLE_FS_RATE_MASK 0xF | |
| 131 | +#define ISABELLE_FS_RATE_8 0x0 | |
| 132 | +#define ISABELLE_FS_RATE_11 0x1 | |
| 133 | +#define ISABELLE_FS_RATE_12 0x2 | |
| 134 | +#define ISABELLE_FS_RATE_16 0x4 | |
| 135 | +#define ISABELLE_FS_RATE_22 0x5 | |
| 136 | +#define ISABELLE_FS_RATE_24 0x6 | |
| 137 | +#define ISABELLE_FS_RATE_32 0x8 | |
| 138 | +#define ISABELLE_FS_RATE_44 0x9 | |
| 139 | +#define ISABELLE_FS_RATE_48 0xA | |
| 140 | + | |
| 141 | +#define ISABELLE_MAX_REGISTER 0xFF | |
| 142 | + | |
| 143 | +#endif | |
| @@ -12,7 +12,6 @@ · 11 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | #include <linux/module.h> |
| 14 | 14 | #include <linux/moduleparam.h> |
| 15 | −#include <linux/version.h> | |
| 16 | 15 | #include <linux/kernel.h> |
| 17 | 16 | #include <linux/init.h> |
| 18 | 17 | #include <linux/delay.h> |
| @@ -1358,7 +1357,7 @@ static struct snd_soc_dai_ops lm49453_lineout_dai_ops = { · 1339 unmodified lines | ||
| 1358 | 1357 | }; |
| 1359 | 1358 | |
| 1360 | 1359 | /* LM49453 dai structure. */ |
| 1361 | −static const struct snd_soc_dai_driver lm49453_dai[] = { | |
| 1360 | +static struct snd_soc_dai_driver lm49453_dai[] = { | |
| 1362 | 1361 | { |
| 1363 | 1362 | .name = "LM49453 Headset", |
| 1364 | 1363 | .playback = { |
| @@ -2216,7 +2216,7 @@ static irqreturn_t max98095_report_jack(int irq, void *data) · 2215 unmodified lines | ||
| 2216 | 2216 | return IRQ_HANDLED; |
| 2217 | 2217 | } |
| 2218 | 2218 | |
| 2219 | −int max98095_jack_detect_enable(struct snd_soc_codec *codec) | |
| 2219 | +static int max98095_jack_detect_enable(struct snd_soc_codec *codec) | |
| 2220 | 2220 | { |
| 2221 | 2221 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); |
| 2222 | 2222 | int ret = 0; |
| @@ -2245,7 +2245,7 @@ int max98095_jack_detect_enable(struct snd_soc_codec *codec) · 22 unmodified lines | ||
| 2245 | 2245 | return ret; |
| 2246 | 2246 | } |
| 2247 | 2247 | |
| 2248 | −int max98095_jack_detect_disable(struct snd_soc_codec *codec) | |
| 2248 | +static int max98095_jack_detect_disable(struct snd_soc_codec *codec) | |
| 2249 | 2249 | { |
| 2250 | 2250 | int ret = 0; |
| 2251 | 2251 | |
| @@ -2286,6 +2286,7 @@ int max98095_jack_detect(struct snd_soc_codec *codec, · 34 unmodified lines | ||
| 2286 | 2286 | max98095_report_jack(client->irq, codec); |
| 2287 | 2287 | return 0; |
| 2288 | 2288 | } |
| 2289 | +EXPORT_SYMBOL_GPL(max98095_jack_detect); | |
| 2289 | 2290 | |
| 2290 | 2291 | #ifdef CONFIG_PM |
| 2291 | 2292 | static int max98095_suspend(struct snd_soc_codec *codec) |
| @@ -638,7 +638,7 @@ static __devinit int ml26124_i2c_probe(struct i2c_client *i2c, · 637 unmodified lines | ||
| 638 | 638 | |
| 639 | 639 | i2c_set_clientdata(i2c, priv); |
| 640 | 640 | |
| 641 | − priv->regmap = regmap_init_i2c(i2c, &ml26124_i2c_regmap); | |
| 641 | + priv->regmap = devm_regmap_init_i2c(i2c, &ml26124_i2c_regmap); | |
| 642 | 642 | if (IS_ERR(priv->regmap)) { |
| 643 | 643 | ret = PTR_ERR(priv->regmap); |
| 644 | 644 | dev_err(&i2c->dev, "regmap_init_i2c() failed: %d\n", ret); |
| @@ -651,10 +651,7 @@ static __devinit int ml26124_i2c_probe(struct i2c_client *i2c, · 6 unmodified lines | ||
| 651 | 651 | |
| 652 | 652 | static __devexit int ml26124_i2c_remove(struct i2c_client *client) |
| 653 | 653 | { |
| 654 | − struct ml26124_priv *priv = i2c_get_clientdata(client); | |
| 655 | − | |
| 656 | 654 | snd_soc_unregister_codec(&client->dev); |
| 657 | − regmap_exit(priv->regmap); | |
| 658 | 655 | return 0; |
| 659 | 656 | } |
| 660 | 657 | |
| @@ -0,0 +1,67 @@ | ||
| 1 | +/* | |
| 2 | + * ALSA SoC SPDIF DIR (Digital Interface Reciever) driver | |
| 3 | + * | |
| 4 | + * Based on ALSA SoC SPDIF DIT driver | |
| 5 | + * | |
| 6 | + * This driver is used by controllers which can operate in DIR (SPDI/F) where | |
| 7 | + * no codec is needed. This file provides stub codec that can be used | |
| 8 | + * in these configurations. SPEAr SPDIF IN Audio controller uses this driver. | |
| 9 | + * | |
| 10 | + * Author: Vipin Kumar, <vipin.kumar@st.com> | |
| 11 | + * Copyright: (C) 2012 ST Microelectronics | |
| 12 | + * | |
| 13 | + * This program is free software; you can redistribute it and/or modify | |
| 14 | + * it under the terms of the GNU General Public License version 2 as | |
| 15 | + * published by the Free Software Foundation. | |
| 16 | + */ | |
| 17 | + | |
| 18 | +#include <linux/module.h> | |
| 19 | +#include <linux/moduleparam.h> | |
| 20 | +#include <linux/slab.h> | |
| 21 | +#include <sound/soc.h> | |
| 22 | +#include <sound/pcm.h> | |
| 23 | +#include <sound/initval.h> | |
| 24 | + | |
| 25 | +#define STUB_RATES SNDRV_PCM_RATE_8000_192000 | |
| 26 | +#define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | |
| 27 | + SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE) | |
| 28 | + | |
| 29 | +static struct snd_soc_codec_driver soc_codec_spdif_dir; | |
| 30 | + | |
| 31 | +static struct snd_soc_dai_driver dir_stub_dai = { | |
| 32 | + .name = "dir-hifi", | |
| 33 | + .capture = { | |
| 34 | + .stream_name = "Capture", | |
| 35 | + .channels_min = 1, | |
| 36 | + .channels_max = 384, | |
| 37 | + .rates = STUB_RATES, | |
| 38 | + .formats = STUB_FORMATS, | |
| 39 | + }, | |
| 40 | +}; | |
| 41 | + | |
| 42 | +static int spdif_dir_probe(struct platform_device *pdev) | |
| 43 | +{ | |
| 44 | + return snd_soc_register_codec(&pdev->dev, &soc_codec_spdif_dir, | |
| 45 | + &dir_stub_dai, 1); | |
| 46 | +} | |
| 47 | + | |
| 48 | +static int spdif_dir_remove(struct platform_device *pdev) | |
| 49 | +{ | |
| 50 | + snd_soc_unregister_codec(&pdev->dev); | |
| 51 | + return 0; | |
| 52 | +} | |
| 53 | + | |
| 54 | +static struct platform_driver spdif_dir_driver = { | |
| 55 | + .probe = spdif_dir_probe, | |
| 56 | + .remove = spdif_dir_remove, | |
| 57 | + .driver = { | |
| 58 | + .name = "spdif-dir", | |
| 59 | + .owner = THIS_MODULE, | |
| 60 | + }, | |
| 61 | +}; | |
| 62 | + | |
| 63 | +module_platform_driver(spdif_dir_driver); | |
| 64 | + | |
| 65 | +MODULE_DESCRIPTION("ASoC SPDIF DIR driver"); | |
| 66 | +MODULE_AUTHOR("Vipin Kumar <vipin.kumar@st.com>"); | |
| 67 | +MODULE_LICENSE("GPL"); | |
| @@ -0,0 +1,442 @@ | ||
| 1 | +/* | |
| 2 | + * ASoC codec driver for spear platform | |
| 3 | + * | |
| 4 | + * sound/soc/codecs/sta529.c -- spear ALSA Soc codec driver | |
| 5 | + * | |
| 6 | + * Copyright (C) 2012 ST Microelectronics | |
| 7 | + * Rajeev Kumar <rajeev-dlh.kumar@st.com> | |
| 8 | + * | |
| 9 | + * This file is licensed under the terms of the GNU General Public | |
| 10 | + * License version 2. This program is licensed "as is" without any | |
| 11 | + * warranty of any kind, whether express or implied. | |
| 12 | + */ | |
| 13 | + | |
| 14 | +#include <linux/clk.h> | |
| 15 | +#include <linux/init.h> | |
| 16 | +#include <linux/i2c.h> | |
| 17 | +#include <linux/io.h> | |
| 18 | +#include <linux/module.h> | |
| 19 | +#include <linux/moduleparam.h> | |
| 20 | +#include <linux/pm.h> | |
| 21 | +#include <linux/regmap.h> | |
| 22 | +#include <linux/slab.h> | |
| 23 | + | |
| 24 | +#include <sound/core.h> | |
| 25 | +#include <sound/initval.h> | |
| 26 | +#include <sound/pcm.h> | |
| 27 | +#include <sound/pcm_params.h> | |
| 28 | +#include <sound/soc.h> | |
| 29 | +#include <sound/soc-dapm.h> | |
| 30 | +#include <sound/tlv.h> | |
| 31 | + | |
| 32 | +/* STA529 Register offsets */ | |
| 33 | +#define STA529_FFXCFG0 0x00 | |
| 34 | +#define STA529_FFXCFG1 0x01 | |
| 35 | +#define STA529_MVOL 0x02 | |
| 36 | +#define STA529_LVOL 0x03 | |
| 37 | +#define STA529_RVOL 0x04 | |
| 38 | +#define STA529_TTF0 0x05 | |
| 39 | +#define STA529_TTF1 0x06 | |
| 40 | +#define STA529_TTP0 0x07 | |
| 41 | +#define STA529_TTP1 0x08 | |
| 42 | +#define STA529_S2PCFG0 0x0A | |
| 43 | +#define STA529_S2PCFG1 0x0B | |
| 44 | +#define STA529_P2SCFG0 0x0C | |
| 45 | +#define STA529_P2SCFG1 0x0D | |
| 46 | +#define STA529_PLLCFG0 0x14 | |
| 47 | +#define STA529_PLLCFG1 0x15 | |
| 48 | +#define STA529_PLLCFG2 0x16 | |
| 49 | +#define STA529_PLLCFG3 0x17 | |
| 50 | +#define STA529_PLLPFE 0x18 | |
| 51 | +#define STA529_PLLST 0x19 | |
| 52 | +#define STA529_ADCCFG 0x1E /*mic_select*/ | |
| 53 | +#define STA529_CKOCFG 0x1F | |
| 54 | +#define STA529_MISC 0x20 | |
| 55 | +#define STA529_PADST0 0x21 | |
| 56 | +#define STA529_PADST1 0x22 | |
| 57 | +#define STA529_FFXST 0x23 | |
| 58 | +#define STA529_PWMIN1 0x2D | |
| 59 | +#define STA529_PWMIN2 0x2E | |
| 60 | +#define STA529_POWST 0x32 | |
| 61 | + | |
| 62 | +#define STA529_MAX_REGISTER 0x32 | |
| 63 | + | |
| 64 | +#define STA529_RATES (SNDRV_PCM_RATE_8000 | \ | |
| 65 | + SNDRV_PCM_RATE_11025 | \ | |
| 66 | + SNDRV_PCM_RATE_16000 | \ | |
| 67 | + SNDRV_PCM_RATE_22050 | \ | |
| 68 | + SNDRV_PCM_RATE_32000 | \ | |
| 69 | + SNDRV_PCM_RATE_44100 | \ | |
| 70 | + SNDRV_PCM_RATE_48000) | |
| 71 | + | |
| 72 | +#define STA529_FORMAT (SNDRV_PCM_FMTBIT_S16_LE | \ | |
| 73 | + SNDRV_PCM_FMTBIT_S24_LE | \ | |
| 74 | + SNDRV_PCM_FMTBIT_S32_LE) | |
| 75 | +#define S2PC_VALUE 0x98 | |
| 76 | +#define CLOCK_OUT 0x60 | |
| 77 | +#define LEFT_J_DATA_FORMAT 0x10 | |
| 78 | +#define I2S_DATA_FORMAT 0x12 | |
| 79 | +#define RIGHT_J_DATA_FORMAT 0x14 | |
| 80 | +#define CODEC_MUTE_VAL 0x80 | |
| 81 | + | |
| 82 | +#define POWER_CNTLMSAK 0x40 | |
| 83 | +#define POWER_STDBY 0x40 | |
| 84 | +#define FFX_MASK 0x80 | |
| 85 | +#define FFX_OFF 0x80 | |
| 86 | +#define POWER_UP 0x00 | |
| 87 | +#define FFX_CLK_ENB 0x01 | |
| 88 | +#define FFX_CLK_DIS 0x00 | |
| 89 | +#define FFX_CLK_MSK 0x01 | |
| 90 | +#define PLAY_FREQ_RANGE_MSK 0x70 | |
| 91 | +#define CAP_FREQ_RANGE_MSK 0x0C | |
| 92 | +#define PDATA_LEN_MSK 0xC0 | |
| 93 | +#define BCLK_TO_FS_MSK 0x30 | |
| 94 | +#define AUDIO_MUTE_MSK 0x80 | |
| 95 | + | |
| 96 | +static const struct reg_default sta529_reg_defaults[] = { | |
| 97 | + { 0, 0x35 }, /* R0 - FFX Configuration reg 0 */ | |
| 98 | + { 1, 0xc8 }, /* R1 - FFX Configuration reg 1 */ | |
| 99 | + { 2, 0x50 }, /* R2 - Master Volume */ | |
| 100 | + { 3, 0x00 }, /* R3 - Left Volume */ | |
| 101 | + { 4, 0x00 }, /* R4 - Right Volume */ | |
| 102 | + { 10, 0xb2 }, /* R10 - S2P Config Reg 0 */ | |
| 103 | + { 11, 0x41 }, /* R11 - S2P Config Reg 1 */ | |
| 104 | + { 12, 0x92 }, /* R12 - P2S Config Reg 0 */ | |
| 105 | + { 13, 0x41 }, /* R13 - P2S Config Reg 1 */ | |
| 106 | + { 30, 0xd2 }, /* R30 - ADC Config Reg */ | |
| 107 | + { 31, 0x40 }, /* R31 - clock Out Reg */ | |
| 108 | + { 32, 0x21 }, /* R32 - Misc Register */ | |
| 109 | +}; | |
| 110 | + | |
| 111 | +struct sta529 { | |
| 112 | + struct regmap *regmap; | |
| 113 | +}; | |
| 114 | + | |
| 115 | +static bool sta529_readable(struct device *dev, unsigned int reg) | |
| 116 | +{ | |
| 117 | + switch (reg) { | |
| 118 | + | |
| 119 | + case STA529_FFXCFG0: | |
| 120 | + case STA529_FFXCFG1: | |
| 121 | + case STA529_MVOL: | |
| 122 | + case STA529_LVOL: | |
| 123 | + case STA529_RVOL: | |
| 124 | + case STA529_S2PCFG0: | |
| 125 | + case STA529_S2PCFG1: | |
| 126 | + case STA529_P2SCFG0: | |
| 127 | + case STA529_P2SCFG1: | |
| 128 | + case STA529_ADCCFG: | |
| 129 | + case STA529_CKOCFG: | |
| 130 | + case STA529_MISC: | |
| 131 | + return true; | |
| 132 | + default: | |
| 133 | + return false; | |
| 134 | + } | |
| 135 | +} | |
| 136 | + | |
| 137 | + | |
| 138 | +static const char *pwm_mode_text[] = { "Binary", "Headphone", "Ternary", | |
| 139 | + "Phase-shift"}; | |
| 140 | + | |
| 141 | +static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -9150, 50, 0); | |
| 142 | +static const DECLARE_TLV_DB_SCALE(master_vol_tlv, -12750, 50, 0); | |
| 143 | +static const SOC_ENUM_SINGLE_DECL(pwm_src, STA529_FFXCFG1, 4, pwm_mode_text); | |
| 144 | + | |
| 145 | +static const struct snd_kcontrol_new sta529_snd_controls[] = { | |
| 146 | + SOC_DOUBLE_R_TLV("Digital Playback Volume", STA529_LVOL, STA529_RVOL, 0, | |
| 147 | + 127, 0, out_gain_tlv), | |
| 148 | + SOC_SINGLE_TLV("Master Playback Volume", STA529_MVOL, 0, 127, 1, | |
| 149 | + master_vol_tlv), | |
| 150 | + SOC_ENUM("PWM Select", pwm_src), | |
| 151 | +}; | |
| 152 | + | |
| 153 | +static int sta529_set_bias_level(struct snd_soc_codec *codec, enum | |
| 154 | + snd_soc_bias_level level) | |
| 155 | +{ | |
| 156 | + struct sta529 *sta529 = snd_soc_codec_get_drvdata(codec); | |
| 157 | + | |
| 158 | + switch (level) { | |
| 159 | + case SND_SOC_BIAS_ON: | |
| 160 | + case SND_SOC_BIAS_PREPARE: | |
| 161 | + snd_soc_update_bits(codec, STA529_FFXCFG0, POWER_CNTLMSAK, | |
| 162 | + POWER_UP); | |
| 163 | + snd_soc_update_bits(codec, STA529_MISC, FFX_CLK_MSK, | |
| 164 | + FFX_CLK_ENB); | |
| 165 | + break; | |
| 166 | + case SND_SOC_BIAS_STANDBY: | |
| 167 | + if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | |
| 168 | + regcache_sync(sta529->regmap); | |
| 169 | + snd_soc_update_bits(codec, STA529_FFXCFG0, | |
| 170 | + POWER_CNTLMSAK, POWER_STDBY); | |
| 171 | + /* Making FFX output to zero */ | |
| 172 | + snd_soc_update_bits(codec, STA529_FFXCFG0, FFX_MASK, | |
| 173 | + FFX_OFF); | |
| 174 | + snd_soc_update_bits(codec, STA529_MISC, FFX_CLK_MSK, | |
| 175 | + FFX_CLK_DIS); | |
| 176 | + break; | |
| 177 | + case SND_SOC_BIAS_OFF: | |
| 178 | + break; | |
| 179 | + } | |
| 180 | + | |
| 181 | + /* | |
| 182 | + * store the label for powers down audio subsystem for suspend.This is | |
| 183 | + * used by soc core layer | |
| 184 | + */ | |
| 185 | + codec->dapm.bias_level = level; | |
| 186 | + | |
| 187 | + return 0; | |
| 188 | + | |
| 189 | +} | |
| 190 | + | |
| 191 | +static int sta529_hw_params(struct snd_pcm_substream *substream, | |
| 192 | + struct snd_pcm_hw_params *params, | |
| 193 | + struct snd_soc_dai *dai) | |
| 194 | +{ | |
| 195 | + struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
| 196 | + struct snd_soc_codec *codec = rtd->codec; | |
| 197 | + int pdata, play_freq_val, record_freq_val; | |
| 198 | + int bclk_to_fs_ratio; | |
| 199 | + | |
| 200 | + switch (params_format(params)) { | |
| 201 | + case SNDRV_PCM_FORMAT_S16_LE: | |
| 202 | + pdata = 1; | |
| 203 | + bclk_to_fs_ratio = 0; | |
| 204 | + break; | |
| 205 | + case SNDRV_PCM_FORMAT_S24_LE: | |
| 206 | + pdata = 2; | |
| 207 | + bclk_to_fs_ratio = 1; | |
| 208 | + break; | |
| 209 | + case SNDRV_PCM_FORMAT_S32_LE: | |
| 210 | + pdata = 3; | |
| 211 | + bclk_to_fs_ratio = 2; | |
| 212 | + break; | |
| 213 | + default: | |
| 214 | + dev_err(codec->dev, "Unsupported format\n"); | |
| 215 | + return -EINVAL; | |
| 216 | + } | |
| 217 | + | |
| 218 | + switch (params_rate(params)) { | |
| 219 | + case 8000: | |
| 220 | + case 11025: | |
| 221 | + play_freq_val = 0; | |
| 222 | + record_freq_val = 2; | |
| 223 | + break; | |
| 224 | + case 16000: | |
| 225 | + case 22050: | |
| 226 | + play_freq_val = 1; | |
| 227 | + record_freq_val = 0; | |
| 228 | + break; | |
| 229 | + | |
| 230 | + case 32000: | |
| 231 | + case 44100: | |
| 232 | + case 48000: | |
| 233 | + play_freq_val = 2; | |
| 234 | + record_freq_val = 0; | |
| 235 | + break; | |
| 236 | + default: | |
| 237 | + dev_err(codec->dev, "Unsupported rate\n"); | |
| 238 | + return -EINVAL; | |
| 239 | + } | |
| 240 | + | |
| 241 | + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | |
| 242 | + snd_soc_update_bits(codec, STA529_S2PCFG1, PDATA_LEN_MSK, | |
| 243 | + pdata << 6); | |
| 244 | + snd_soc_update_bits(codec, STA529_S2PCFG1, BCLK_TO_FS_MSK, | |
| 245 | + bclk_to_fs_ratio << 4); | |
| 246 | + snd_soc_update_bits(codec, STA529_MISC, PLAY_FREQ_RANGE_MSK, | |
| 247 | + play_freq_val << 4); | |
| 248 | + } else { | |
| 249 | + snd_soc_update_bits(codec, STA529_P2SCFG1, PDATA_LEN_MSK, | |
| 250 | + pdata << 6); | |
| 251 | + snd_soc_update_bits(codec, STA529_P2SCFG1, BCLK_TO_FS_MSK, | |
| 252 | + bclk_to_fs_ratio << 4); | |
| 253 | + snd_soc_update_bits(codec, STA529_MISC, CAP_FREQ_RANGE_MSK, | |
| 254 | + record_freq_val << 2); | |
| 255 | + } | |
| 256 | + | |
| 257 | + return 0; | |
| 258 | +} | |
| 259 | + | |
| 260 | +static int sta529_mute(struct snd_soc_dai *dai, int mute) | |
| 261 | +{ | |
| 262 | + u8 val = 0; | |
| 263 | + | |
| 264 | + if (mute) | |
| 265 | + val |= CODEC_MUTE_VAL; | |
| 266 | + | |
| 267 | + snd_soc_update_bits(dai->codec, STA529_FFXCFG0, AUDIO_MUTE_MSK, val); | |
| 268 | + | |
| 269 | + return 0; | |
| 270 | +} | |
| 271 | + | |
| 272 | +static int sta529_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt) | |
| 273 | +{ | |
| 274 | + struct snd_soc_codec *codec = codec_dai->codec; | |
| 275 | + u8 mode = 0; | |
| 276 | + | |
| 277 | + /* interface format */ | |
| 278 | + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | |
| 279 | + case SND_SOC_DAIFMT_LEFT_J: | |
| 280 | + mode = LEFT_J_DATA_FORMAT; | |
| 281 | + break; | |
| 282 | + case SND_SOC_DAIFMT_I2S: | |
| 283 | + mode = I2S_DATA_FORMAT; | |
| 284 | + break; | |
| 285 | + case SND_SOC_DAIFMT_RIGHT_J: | |
| 286 | + mode = RIGHT_J_DATA_FORMAT; | |
| 287 | + break; | |
| 288 | + default: | |
| 289 | + return -EINVAL; | |
| 290 | + } | |
| 291 | + | |
| 292 | + snd_soc_update_bits(codec, STA529_S2PCFG0, 0x0D, mode); | |
| 293 | + | |
| 294 | + return 0; | |
| 295 | +} | |
| 296 | + | |
| 297 | +static const struct snd_soc_dai_ops sta529_dai_ops = { | |
| 298 | + .hw_params = sta529_hw_params, | |
| 299 | + .set_fmt = sta529_set_dai_fmt, | |
| 300 | + .digital_mute = sta529_mute, | |
| 301 | +}; | |
| 302 | + | |
| 303 | +static struct snd_soc_dai_driver sta529_dai = { | |
| 304 | + .name = "sta529-audio", | |
| 305 | + .playback = { | |
| 306 | + .stream_name = "Playback", | |
| 307 | + .channels_min = 2, | |
| 308 | + .channels_max = 2, | |
| 309 | + .rates = STA529_RATES, | |
| 310 | + .formats = STA529_FORMAT, | |
| 311 | + }, | |
| 312 | + .capture = { | |
| 313 | + .stream_name = "Capture", | |
| 314 | + .channels_min = 2, | |
| 315 | + .channels_max = 2, | |
| 316 | + .rates = STA529_RATES, | |
| 317 | + .formats = STA529_FORMAT, | |
| 318 | + }, | |
| 319 | + .ops = &sta529_dai_ops, | |
| 320 | +}; | |
| 321 | + | |
| 322 | +static int sta529_probe(struct snd_soc_codec *codec) | |
| 323 | +{ | |
| 324 | + struct sta529 *sta529 = snd_soc_codec_get_drvdata(codec); | |
| 325 | + int ret; | |
| 326 | + | |
| 327 | + codec->control_data = sta529->regmap; | |
| 328 | + ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | |
| 329 | + | |
| 330 | + if (ret < 0) { | |
| 331 | + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | |
| 332 | + return ret; | |
| 333 | + } | |
| 334 | + sta529_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | |
| 335 | + | |
| 336 | + return 0; | |
| 337 | +} | |
| 338 | + | |
| 339 | +/* power down chip */ | |
| 340 | +static int sta529_remove(struct snd_soc_codec *codec) | |
| 341 | +{ | |
| 342 | + sta529_set_bias_level(codec, SND_SOC_BIAS_OFF); | |
| 343 | + | |
| 344 | + return 0; | |
| 345 | +} | |
| 346 | + | |
| 347 | +static int sta529_suspend(struct snd_soc_codec *codec) | |
| 348 | +{ | |
| 349 | + sta529_set_bias_level(codec, SND_SOC_BIAS_OFF); | |
| 350 | + | |
| 351 | + return 0; | |
| 352 | +} | |
| 353 | + | |
| 354 | +static int sta529_resume(struct snd_soc_codec *codec) | |
| 355 | +{ | |
| 356 | + sta529_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | |
| 357 | + | |
| 358 | + return 0; | |
| 359 | +} | |
| 360 | + | |
| 361 | +struct snd_soc_codec_driver sta529_codec_driver = { | |
| 362 | + .probe = sta529_probe, | |
| 363 | + .remove = sta529_remove, | |
| 364 | + .set_bias_level = sta529_set_bias_level, | |
| 365 | + .suspend = sta529_suspend, | |
| 366 | + .resume = sta529_resume, | |
| 367 | + .controls = sta529_snd_controls, | |
| 368 | + .num_controls = ARRAY_SIZE(sta529_snd_controls), | |
| 369 | +}; | |
| 370 | + | |
| 371 | +static const struct regmap_config sta529_regmap = { | |
| 372 | + .reg_bits = 8, | |
| 373 | + .val_bits = 8, | |
| 374 | + | |
| 375 | + .max_register = STA529_MAX_REGISTER, | |
| 376 | + .readable_reg = sta529_readable, | |
| 377 | + | |
| 378 | + .cache_type = REGCACHE_RBTREE, | |
| 379 | + .reg_defaults = sta529_reg_defaults, | |
| 380 | + .num_reg_defaults = ARRAY_SIZE(sta529_reg_defaults), | |
| 381 | +}; | |
| 382 | + | |
| 383 | +static __devinit int sta529_i2c_probe(struct i2c_client *i2c, | |
| 384 | + const struct i2c_device_id *id) | |
| 385 | +{ | |
| 386 | + struct sta529 *sta529; | |
| 387 | + int ret; | |
| 388 | + | |
| 389 | + if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | |
| 390 | + return -EINVAL; | |
| 391 | + | |
| 392 | + sta529 = devm_kzalloc(&i2c->dev, sizeof(struct sta529), GFP_KERNEL); | |
| 393 | + if (sta529 == NULL) { | |
| 394 | + dev_err(&i2c->dev, "Can not allocate memory\n"); | |
| 395 | + return -ENOMEM; | |
| 396 | + } | |
| 397 | + | |
| 398 | + sta529->regmap = devm_regmap_init_i2c(i2c, &sta529_regmap); | |
| 399 | + if (IS_ERR(sta529->regmap)) { | |
| 400 | + ret = PTR_ERR(sta529->regmap); | |
| 401 | + dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); | |
| 402 | + return ret; | |
| 403 | + } | |
| 404 | + | |
| 405 | + i2c_set_clientdata(i2c, sta529); | |
| 406 | + | |
| 407 | + ret = snd_soc_register_codec(&i2c->dev, | |
| 408 | + &sta529_codec_driver, &sta529_dai, 1); | |
| 409 | + if (ret != 0) | |
| 410 | + dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); | |
| 411 | + | |
| 412 | + return ret; | |
| 413 | +} | |
| 414 | + | |
| 415 | +static int __devexit sta529_i2c_remove(struct i2c_client *client) | |
| 416 | +{ | |
| 417 | + snd_soc_unregister_codec(&client->dev); | |
| 418 | + | |
| 419 | + return 0; | |
| 420 | +} | |
| 421 | + | |
| 422 | +static const struct i2c_device_id sta529_i2c_id[] = { | |
| 423 | + { "sta529", 0 }, | |
| 424 | + { } | |
| 425 | +}; | |
| 426 | +MODULE_DEVICE_TABLE(i2c, sta529_i2c_id); | |
| 427 | + | |
| 428 | +static struct i2c_driver sta529_i2c_driver = { | |
| 429 | + .driver = { | |
| 430 | + .name = "sta529", | |
| 431 | + .owner = THIS_MODULE, | |
| 432 | + }, | |
| 433 | + .probe = sta529_i2c_probe, | |
| 434 | + .remove = __devexit_p(sta529_i2c_remove), | |
| 435 | + .id_table = sta529_i2c_id, | |
| 436 | +}; | |
| 437 | + | |
| 438 | +module_i2c_driver(sta529_i2c_driver); | |
| 439 | + | |
| 440 | +MODULE_DESCRIPTION("ASoC STA529 codec driver"); | |
| 441 | +MODULE_AUTHOR("Rajeev Kumar <rajeev-dlh.kumar@st.com>"); | |
| 442 | +MODULE_LICENSE("GPL"); | |
| @@ -118,7 +118,9 @@ static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = { · 117 unmodified lines | ||
| 118 | 118 | 0x00, 0x00, 0x00, 0x00, /* 88 */ |
| 119 | 119 | 0x00, 0x00, 0x00, 0x00, /* 92 */ |
| 120 | 120 | 0x00, 0x00, 0x00, 0x00, /* 96 */ |
| 121 | − 0x00, 0x00, 0x02, /* 100 */ | |
| 121 | + 0x00, 0x00, 0x02, 0x00, /* 100 */ | |
| 122 | + 0x00, 0x00, 0x00, 0x00, /* 104 */ | |
| 123 | + 0x00, 0x00, /* 108 */ | |
| 122 | 124 | }; |
| 123 | 125 | |
| 124 | 126 | #define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \ |
| @@ -229,6 +231,25 @@ static const struct soc_enum aic3x_enum[] = { · 104 unmodified lines | ||
| 229 | 231 | SOC_ENUM_DOUBLE(AIC3X_CODEC_DFILT_CTRL, 6, 4, 4, aic3x_adc_hpf), |
| 230 | 232 | }; |
| 231 | 233 | |
| 234 | +static const char *aic3x_agc_level[] = | |
| 235 | + { "-5.5dB", "-8dB", "-10dB", "-12dB", "-14dB", "-17dB", "-20dB", "-24dB" }; | |
| 236 | +static const struct soc_enum aic3x_agc_level_enum[] = { | |
| 237 | + SOC_ENUM_SINGLE(LAGC_CTRL_A, 4, 8, aic3x_agc_level), | |
| 238 | + SOC_ENUM_SINGLE(RAGC_CTRL_A, 4, 8, aic3x_agc_level), | |
| 239 | +}; | |
| 240 | + | |
| 241 | +static const char *aic3x_agc_attack[] = { "8ms", "11ms", "16ms", "20ms" }; | |
| 242 | +static const struct soc_enum aic3x_agc_attack_enum[] = { | |
| 243 | + SOC_ENUM_SINGLE(LAGC_CTRL_A, 2, 4, aic3x_agc_attack), | |
| 244 | + SOC_ENUM_SINGLE(RAGC_CTRL_A, 2, 4, aic3x_agc_attack), | |
| 245 | +}; | |
| 246 | + | |
| 247 | +static const char *aic3x_agc_decay[] = { "100ms", "200ms", "400ms", "500ms" }; | |
| 248 | +static const struct soc_enum aic3x_agc_decay_enum[] = { | |
| 249 | + SOC_ENUM_SINGLE(LAGC_CTRL_A, 0, 4, aic3x_agc_decay), | |
| 250 | + SOC_ENUM_SINGLE(RAGC_CTRL_A, 0, 4, aic3x_agc_decay), | |
| 251 | +}; | |
| 252 | + | |
| 232 | 253 | /* |
| 233 | 254 | * DAC digital volumes. From -63.5 to 0 dB in 0.5 dB steps |
| 234 | 255 | */ |
| @@ -353,6 +374,15 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { · 118 unmodified lines | ||
| 353 | 374 | * adjust PGA to max value when ADC is on and will never go back. |
| 354 | 375 | */ |
| 355 | 376 | SOC_DOUBLE_R("AGC Switch", LAGC_CTRL_A, RAGC_CTRL_A, 7, 0x01, 0), |
| 377 | + SOC_ENUM("Left AGC Target level", aic3x_agc_level_enum[0]), | |
| 378 | + SOC_ENUM("Right AGC Target level", aic3x_agc_level_enum[1]), | |
| 379 | + SOC_ENUM("Left AGC Attack time", aic3x_agc_attack_enum[0]), | |
| 380 | + SOC_ENUM("Right AGC Attack time", aic3x_agc_attack_enum[1]), | |
| 381 | + SOC_ENUM("Left AGC Decay time", aic3x_agc_decay_enum[0]), | |
| 382 | + SOC_ENUM("Right AGC Decay time", aic3x_agc_decay_enum[1]), | |
| 383 | + | |
| 384 | + /* De-emphasis */ | |
| 385 | + SOC_DOUBLE("De-emphasis Switch", AIC3X_CODEC_DFILT_CTRL, 2, 0, 0x01, 0), | |
| 356 | 386 | |
| 357 | 387 | /* Input */ |
| 358 | 388 | SOC_DOUBLE_R_TLV("PGA Capture Volume", LADC_VOL, RADC_VOL, |
| @@ -368,7 +398,7 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { · 9 unmodified lines | ||
| 368 | 398 | static DECLARE_TLV_DB_SCALE(classd_amp_tlv, 0, 600, 0); |
| 369 | 399 | |
| 370 | 400 | static const struct snd_kcontrol_new aic3x_classd_amp_gain_ctrl = |
| 371 | − SOC_DOUBLE_TLV("Class-D Amplifier Gain", CLASSD_CTRL, 6, 4, 3, 0, classd_amp_tlv); | |
| 401 | + SOC_DOUBLE_TLV("Class-D Playback Volume", CLASSD_CTRL, 6, 4, 3, 0, classd_amp_tlv); | |
| 372 | 402 | |
| 373 | 403 | /* Left DAC Mux */ |
| 374 | 404 | static const struct snd_kcontrol_new aic3x_left_dac_mux_controls = |
| @@ -970,6 +1000,12 @@ static int aic3x_set_dai_sysclk(struct snd_soc_dai *codec_dai, · 595 unmodified lines | ||
| 970 | 1000 | struct snd_soc_codec *codec = codec_dai->codec; |
| 971 | 1001 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); |
| 972 | 1002 | |
| 1003 | + /* set clock on MCLK or GPIO2 or BCLK */ | |
| 1004 | + snd_soc_update_bits(codec, AIC3X_CLKGEN_CTRL_REG, PLLCLK_IN_MASK, | |
| 1005 | + clk_id << PLLCLK_IN_SHIFT); | |
| 1006 | + snd_soc_update_bits(codec, AIC3X_CLKGEN_CTRL_REG, CLKDIV_IN_MASK, | |
| 1007 | + clk_id << CLKDIV_IN_SHIFT); | |
| 1008 | + | |
| 973 | 1009 | aic3x->sysclk = freq; |
| 974 | 1010 | return 0; |
| 975 | 1011 | } |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #define _AIC3X_H |
| 14 | 14 | |
| 15 | 15 | /* AIC3X register space */ |
| 16 | −#define AIC3X_CACHEREGNUM 103 | |
| 16 | +#define AIC3X_CACHEREGNUM 110 | |
| 17 | 17 | |
| 18 | 18 | /* Page select register */ |
| 19 | 19 | #define AIC3X_PAGE_SELECT 0 |
| @@ -74,6 +74,8 @@ · 54 unmodified lines | ||
| 74 | 74 | #define HPLCOM_CFG 37 |
| 75 | 75 | /* Right High Power Output control registers */ |
| 76 | 76 | #define HPRCOM_CFG 38 |
| 77 | +/* High Power Output Stage Control Register */ | |
| 78 | +#define HPOUT_SC 40 | |
| 77 | 79 | /* DAC Output Switching control registers */ |
| 78 | 80 | #define DAC_LINE_MUX 41 |
| 79 | 81 | /* High Power Output Driver Pop Reduction registers */ |
| @@ -148,6 +150,17 @@ · 68 unmodified lines | ||
| 148 | 150 | #define AIC3X_GPIOB_REG 101 |
| 149 | 151 | /* Clock generation control register */ |
| 150 | 152 | #define AIC3X_CLKGEN_CTRL_REG 102 |
| 153 | +/* New AGC registers */ | |
| 154 | +#define LAGCN_ATTACK 103 | |
| 155 | +#define LAGCN_DECAY 104 | |
| 156 | +#define RAGCN_ATTACK 105 | |
| 157 | +#define RAGCN_DECAY 106 | |
| 158 | +/* New Programmable ADC Digital Path and I2C Bus Condition Register */ | |
| 159 | +#define NEW_ADC_DIGITALPATH 107 | |
| 160 | +/* Passive Analog Signal Bypass Selection During Powerdown Register */ | |
| 161 | +#define PASSIVE_BYPASS 108 | |
| 162 | +/* DAC Quiescent Current Adjustment Register */ | |
| 163 | +#define DAC_ICC_ADJ 109 | |
| 151 | 164 | |
| 152 | 165 | /* Page select register bits */ |
| 153 | 166 | #define PAGE0_SELECT 0 |
| @@ -163,6 +176,10 @@ · 9 unmodified lines | ||
| 163 | 176 | #define DUAL_RATE_MODE ((1 << 5) | (1 << 6)) |
| 164 | 177 | #define LDAC2LCH (0x1 << 3) |
| 165 | 178 | #define RDAC2RCH (0x1 << 1) |
| 179 | +#define LDAC2RCH (0x2 << 3) | |
| 180 | +#define RDAC2LCH (0x2 << 1) | |
| 181 | +#define LDAC2MONOMIX (0x3 << 3) | |
| 182 | +#define RDAC2MONOMIX (0x3 << 1) | |
| 166 | 183 | |
| 167 | 184 | /* PLL registers bitfields */ |
| 168 | 185 | #define PLLP_SHIFT 0 |
| @@ -179,6 +196,14 @@ · 10 unmodified lines | ||
| 179 | 196 | #define PLL_CLKIN_SHIFT 4 |
| 180 | 197 | #define MCLK_SOURCE 0x0 |
| 181 | 198 | #define PLL_CLKDIV_SHIFT 0 |
| 199 | +#define PLLCLK_IN_MASK 0x30 | |
| 200 | +#define PLLCLK_IN_SHIFT 4 | |
| 201 | +#define CLKDIV_IN_MASK 0xc0 | |
| 202 | +#define CLKDIV_IN_SHIFT 6 | |
| 203 | +/* clock in source */ | |
| 204 | +#define CLKIN_MCLK 0 | |
| 205 | +#define CLKIN_GPIO2 1 | |
| 206 | +#define CLKIN_BCLK 2 | |
| 182 | 207 | |
| 183 | 208 | /* Software reset register bits */ |
| 184 | 209 | #define SOFT_RESET 0x80 |
| @@ -553,7 +553,7 @@ static const struct snd_kcontrol_new vibrar_mux_controls = · 552 unmodified lines | ||
| 553 | 553 | |
| 554 | 554 | /* Headset power mode */ |
| 555 | 555 | static const char *twl6040_power_mode_texts[] = { |
| 556 | − "Low-Power", "High-Perfomance", | |
| 556 | + "Low-Power", "High-Performance", | |
| 557 | 557 | }; |
| 558 | 558 | |
| 559 | 559 | static const struct soc_enum twl6040_power_mode_enum = |
| @@ -121,20 +121,23 @@ static const struct snd_soc_dai_ops wm1250_ev1_ops = { · 120 unmodified lines | ||
| 121 | 121 | .hw_params = wm1250_ev1_hw_params, |
| 122 | 122 | }; |
| 123 | 123 | |
| 124 | +#define WM1250_EV1_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ | |
| 125 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_64000) | |
| 126 | + | |
| 124 | 127 | static struct snd_soc_dai_driver wm1250_ev1_dai = { |
| 125 | 128 | .name = "wm1250-ev1", |
| 126 | 129 | .playback = { |
| 127 | 130 | .stream_name = "Playback", |
| 128 | 131 | .channels_min = 1, |
| 129 | 132 | .channels_max = 2, |
| 130 | − .rates = SNDRV_PCM_RATE_8000, | |
| 133 | + .rates = WM1250_EV1_RATES, | |
| 131 | 134 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
| 132 | 135 | }, |
| 133 | 136 | .capture = { |
| 134 | 137 | .stream_name = "Capture", |
| 135 | 138 | .channels_min = 1, |
| 136 | 139 | .channels_max = 2, |
| 137 | − .rates = SNDRV_PCM_RATE_8000, | |
| 140 | + .rates = WM1250_EV1_RATES, | |
| 138 | 141 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
| 139 | 142 | }, |
| 140 | 143 | .ops = &wm1250_ev1_ops, |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * wm2000.c -- WM2000 ALSA Soc Audio driver |
| 3 | 3 | * |
| 4 | − * Copyright 2008-2010 Wolfson Microelectronics PLC. | |
| 4 | + * Copyright 2008-2011 Wolfson Microelectronics PLC. | |
| 5 | 5 | * |
| 6 | 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
| 7 | 7 | * |
| @@ -674,9 +674,39 @@ static int wm2000_resume(struct snd_soc_codec *codec) · 666 unmodified lines | ||
| 674 | 674 | #define wm2000_resume NULL |
| 675 | 675 | #endif |
| 676 | 676 | |
| 677 | +static bool wm2000_readable_reg(struct device *dev, unsigned int reg) | |
| 678 | +{ | |
| 679 | + switch (reg) { | |
| 680 | + case WM2000_REG_SYS_START: | |
| 681 | + case WM2000_REG_SPEECH_CLARITY: | |
| 682 | + case WM2000_REG_SYS_WATCHDOG: | |
| 683 | + case WM2000_REG_ANA_VMID_PD_TIME: | |
| 684 | + case WM2000_REG_ANA_VMID_PU_TIME: | |
| 685 | + case WM2000_REG_CAT_FLTR_INDX: | |
| 686 | + case WM2000_REG_CAT_GAIN_0: | |
| 687 | + case WM2000_REG_SYS_STATUS: | |
| 688 | + case WM2000_REG_SYS_MODE_CNTRL: | |
| 689 | + case WM2000_REG_SYS_START0: | |
| 690 | + case WM2000_REG_SYS_START1: | |
| 691 | + case WM2000_REG_ID1: | |
| 692 | + case WM2000_REG_ID2: | |
| 693 | + case WM2000_REG_REVISON: | |
| 694 | + case WM2000_REG_SYS_CTL1: | |
| 695 | + case WM2000_REG_SYS_CTL2: | |
| 696 | + case WM2000_REG_ANC_STAT: | |
| 697 | + case WM2000_REG_IF_CTL: | |
| 698 | + return true; | |
| 699 | + default: | |
| 700 | + return false; | |
| 701 | + } | |
| 702 | +} | |
| 703 | + | |
| 677 | 704 | static const struct regmap_config wm2000_regmap = { |
| 678 | 705 | .reg_bits = 8, |
| 679 | 706 | .val_bits = 8, |
| 707 | + | |
| 708 | + .max_register = WM2000_REG_IF_CTL, | |
| 709 | + .readable_reg = wm2000_readable_reg, | |
| 680 | 710 | }; |
| 681 | 711 | |
| 682 | 712 | static int wm2000_probe(struct snd_soc_codec *codec) |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * wm5100-tables.c -- WM5100 ALSA SoC Audio driver data |
| 3 | 3 | * |
| 4 | − * Copyright 2011 Wolfson Microelectronics plc | |
| 4 | + * Copyright 2011-2 Wolfson Microelectronics plc | |
| 5 | 5 | * |
| 6 | 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
| 7 | 7 | * |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * wm5100.c -- WM5100 ALSA SoC Audio driver |
| 3 | 3 | * |
| 4 | − * Copyright 2011 Wolfson Microelectronics plc | |
| 4 | + * Copyright 2011-2 Wolfson Microelectronics plc | |
| 5 | 5 | * |
| 6 | 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
| 7 | 7 | * |
| @@ -2378,13 +2378,6 @@ static int wm5100_remove(struct snd_soc_codec *codec) · 2370 unmodified lines | ||
| 2378 | 2378 | return 0; |
| 2379 | 2379 | } |
| 2380 | 2380 | |
| 2381 | −static int wm5100_soc_volatile(struct snd_soc_codec *codec, | |
| 2382 | − unsigned int reg) | |
| 2383 | −{ | |
| 2384 | − return true; | |
| 2385 | −} | |
| 2386 | − | |
| 2387 | − | |
| 2388 | 2381 | static struct snd_soc_codec_driver soc_codec_dev_wm5100 = { |
| 2389 | 2382 | .probe = wm5100_probe, |
| 2390 | 2383 | .remove = wm5100_remove, |
| @@ -2392,8 +2385,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5100 = { · 1 unmodified line | ||
| 2392 | 2385 | .set_sysclk = wm5100_set_sysclk, |
| 2393 | 2386 | .set_pll = wm5100_set_fll, |
| 2394 | 2387 | .idle_bias_off = 1, |
| 2395 | − .reg_cache_size = WM5100_MAX_REGISTER, | |
| 2396 | − .volatile_register = wm5100_soc_volatile, | |
| 2397 | 2388 | |
| 2398 | 2389 | .seq_notifier = wm5100_seq_notifier, |
| 2399 | 2390 | .controls = wm5100_snd_controls, |
| @@ -0,0 +1,903 @@ | ||
| 1 | +/* | |
| 2 | + * wm5102.c -- WM5102 ALSA SoC Audio driver | |
| 3 | + * | |
| 4 | + * Copyright 2012 Wolfson Microelectronics plc | |
| 5 | + * | |
| 6 | + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | |
| 7 | + * | |
| 8 | + * This program is free software; you can redistribute it and/or modify | |
| 9 | + * it under the terms of the GNU General Public License version 2 as | |
| 10 | + * published by the Free Software Foundation. | |
| 11 | + */ | |
| 12 | + | |
| 13 | +#include <linux/module.h> | |
| 14 | +#include <linux/moduleparam.h> | |
| 15 | +#include <linux/init.h> | |
| 16 | +#include <linux/delay.h> | |
| 17 | +#include <linux/pm.h> | |
| 18 | +#include <linux/pm_runtime.h> | |
| 19 | +#include <linux/regmap.h> | |
| 20 | +#include <linux/slab.h> | |
| 21 | +#include <sound/core.h> | |
| 22 | +#include <sound/pcm.h> | |
| 23 | +#include <sound/pcm_params.h> | |
| 24 | +#include <sound/soc.h> | |
| 25 | +#include <sound/jack.h> | |
| 26 | +#include <sound/initval.h> | |
| 27 | +#include <sound/tlv.h> | |
| 28 | + | |
| 29 | +#include <linux/mfd/arizona/core.h> | |
| 30 | +#include <linux/mfd/arizona/registers.h> | |
| 31 | + | |
| 32 | +#include "arizona.h" | |
| 33 | +#include "wm5102.h" | |
| 34 | + | |
| 35 | +struct wm5102_priv { | |
| 36 | + struct arizona_priv core; | |
| 37 | + struct arizona_fll fll[2]; | |
| 38 | +}; | |
| 39 | + | |
| 40 | +static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); | |
| 41 | +static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | |
| 42 | +static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); | |
| 43 | +static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0); | |
| 44 | + | |
| 45 | +static const struct snd_kcontrol_new wm5102_snd_controls[] = { | |
| 46 | +SOC_SINGLE("IN1 High Performance Switch", ARIZONA_IN1L_CONTROL, | |
| 47 | + ARIZONA_IN1_OSR_SHIFT, 1, 0), | |
| 48 | +SOC_SINGLE("IN2 High Performance Switch", ARIZONA_IN2L_CONTROL, | |
| 49 | + ARIZONA_IN2_OSR_SHIFT, 1, 0), | |
| 50 | +SOC_SINGLE("IN3 High Performance Switch", ARIZONA_IN3L_CONTROL, | |
| 51 | + ARIZONA_IN3_OSR_SHIFT, 1, 0), | |
| 52 | + | |
| 53 | +SOC_DOUBLE_R_RANGE_TLV("IN1 Volume", ARIZONA_IN1L_CONTROL, | |
| 54 | + ARIZONA_IN1R_CONTROL, | |
| 55 | + ARIZONA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), | |
| 56 | +SOC_DOUBLE_R_RANGE_TLV("IN2 Volume", ARIZONA_IN2L_CONTROL, | |
| 57 | + ARIZONA_IN2R_CONTROL, | |
| 58 | + ARIZONA_IN2L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), | |
| 59 | +SOC_DOUBLE_R_RANGE_TLV("IN3 Volume", ARIZONA_IN3L_CONTROL, | |
| 60 | + ARIZONA_IN3R_CONTROL, | |
| 61 | + ARIZONA_IN3L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), | |
| 62 | + | |
| 63 | +SOC_DOUBLE_R("IN1 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_1L, | |
| 64 | + ARIZONA_ADC_DIGITAL_VOLUME_1R, ARIZONA_IN1L_MUTE_SHIFT, 1, 1), | |
| 65 | +SOC_DOUBLE_R("IN2 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_2L, | |
| 66 | + ARIZONA_ADC_DIGITAL_VOLUME_2R, ARIZONA_IN2L_MUTE_SHIFT, 1, 1), | |
| 67 | +SOC_DOUBLE_R("IN3 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_3L, | |
| 68 | + ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_MUTE_SHIFT, 1, 1), | |
| 69 | + | |
| 70 | +SOC_DOUBLE_R_TLV("IN1 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1L, | |
| 71 | + ARIZONA_ADC_DIGITAL_VOLUME_1R, ARIZONA_IN1L_DIG_VOL_SHIFT, | |
| 72 | + 0xbf, 0, digital_tlv), | |
| 73 | +SOC_DOUBLE_R_TLV("IN2 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_2L, | |
| 74 | + ARIZONA_ADC_DIGITAL_VOLUME_2R, ARIZONA_IN2L_DIG_VOL_SHIFT, | |
| 75 | + 0xbf, 0, digital_tlv), | |
| 76 | +SOC_DOUBLE_R_TLV("IN3 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_3L, | |
| 77 | + ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_DIG_VOL_SHIFT, | |
| 78 | + 0xbf, 0, digital_tlv), | |
| 79 | + | |
| 80 | +ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE), | |
| 81 | +ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), | |
| 82 | +ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), | |
| 83 | +ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), | |
| 84 | + | |
| 85 | +SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, | |
| 86 | + 24, 0, eq_tlv), | |
| 87 | +SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, | |
| 88 | + 24, 0, eq_tlv), | |
| 89 | +SOC_SINGLE_TLV("EQ1 B3 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B3_GAIN_SHIFT, | |
| 90 | + 24, 0, eq_tlv), | |
| 91 | +SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, | |
| 92 | + 24, 0, eq_tlv), | |
| 93 | +SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, | |
| 94 | + 24, 0, eq_tlv), | |
| 95 | + | |
| 96 | +SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, | |
| 97 | + 24, 0, eq_tlv), | |
| 98 | +SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, | |
| 99 | + 24, 0, eq_tlv), | |
| 100 | +SOC_SINGLE_TLV("EQ2 B3 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B3_GAIN_SHIFT, | |
| 101 | + 24, 0, eq_tlv), | |
| 102 | +SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, | |
| 103 | + 24, 0, eq_tlv), | |
| 104 | +SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, | |
| 105 | + 24, 0, eq_tlv), | |
| 106 | + | |
| 107 | +SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, | |
| 108 | + 24, 0, eq_tlv), | |
| 109 | +SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, | |
| 110 | + 24, 0, eq_tlv), | |
| 111 | +SOC_SINGLE_TLV("EQ3 B3 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B3_GAIN_SHIFT, | |
| 112 | + 24, 0, eq_tlv), | |
| 113 | +SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, | |
| 114 | + 24, 0, eq_tlv), | |
| 115 | +SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, | |
| 116 | + 24, 0, eq_tlv), | |
| 117 | + | |
| 118 | +SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, | |
| 119 | + 24, 0, eq_tlv), | |
| 120 | +SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, | |
| 121 | + 24, 0, eq_tlv), | |
| 122 | +SOC_SINGLE_TLV("EQ4 B3 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B3_GAIN_SHIFT, | |
| 123 | + 24, 0, eq_tlv), | |
| 124 | +SOC_SINGLE_TLV("EQ4 B4 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B4_GAIN_SHIFT, | |
| 125 | + 24, 0, eq_tlv), | |
| 126 | +SOC_SINGLE_TLV("EQ4 B5 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B5_GAIN_SHIFT, | |
| 127 | + 24, 0, eq_tlv), | |
| 128 | + | |
| 129 | +ARIZONA_MIXER_CONTROLS("DRC1L", ARIZONA_DRC1LMIX_INPUT_1_SOURCE), | |
| 130 | +ARIZONA_MIXER_CONTROLS("DRC1R", ARIZONA_DRC1RMIX_INPUT_1_SOURCE), | |
| 131 | +ARIZONA_MIXER_CONTROLS("DRC2L", ARIZONA_DRC2LMIX_INPUT_1_SOURCE), | |
| 132 | +ARIZONA_MIXER_CONTROLS("DRC2R", ARIZONA_DRC2RMIX_INPUT_1_SOURCE), | |
| 133 | + | |
| 134 | +SND_SOC_BYTES_MASK("DRC1", ARIZONA_DRC1_CTRL1, 5, | |
| 135 | + ARIZONA_DRC1R_ENA | ARIZONA_DRC1L_ENA), | |
| 136 | +SND_SOC_BYTES_MASK("DRC2", ARIZONA_DRC2_CTRL1, 5, | |
| 137 | + ARIZONA_DRC2R_ENA | ARIZONA_DRC2L_ENA), | |
| 138 | + | |
| 139 | +ARIZONA_MIXER_CONTROLS("LHPF1", ARIZONA_HPLP1MIX_INPUT_1_SOURCE), | |
| 140 | +ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE), | |
| 141 | +ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE), | |
| 142 | +ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE), | |
| 143 | + | |
| 144 | +SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode), | |
| 145 | +SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode), | |
| 146 | +SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode), | |
| 147 | +SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode), | |
| 148 | + | |
| 149 | +ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE), | |
| 150 | +ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE), | |
| 151 | + | |
| 152 | +SOC_SINGLE_TLV("Noise Generator Volume", ARIZONA_COMFORT_NOISE_GENERATOR, | |
| 153 | + ARIZONA_NOISE_GEN_GAIN_SHIFT, 0x16, 0, noise_tlv), | |
| 154 | + | |
| 155 | +ARIZONA_MIXER_CONTROLS("HPOUT1L", ARIZONA_OUT1LMIX_INPUT_1_SOURCE), | |
| 156 | +ARIZONA_MIXER_CONTROLS("HPOUT1R", ARIZONA_OUT1RMIX_INPUT_1_SOURCE), | |
| 157 | +ARIZONA_MIXER_CONTROLS("HPOUT2L", ARIZONA_OUT2LMIX_INPUT_1_SOURCE), | |
| 158 | +ARIZONA_MIXER_CONTROLS("HPOUT2R", ARIZONA_OUT2RMIX_INPUT_1_SOURCE), | |
| 159 | +ARIZONA_MIXER_CONTROLS("EPOUT", ARIZONA_OUT3LMIX_INPUT_1_SOURCE), | |
| 160 | +ARIZONA_MIXER_CONTROLS("SPKOUTL", ARIZONA_OUT4LMIX_INPUT_1_SOURCE), | |
| 161 | +ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE), | |
| 162 | +ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE), | |
| 163 | +ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE), | |
| 164 | + | |
| 165 | +SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L, | |
| 166 | + ARIZONA_OUT1_OSR_SHIFT, 1, 0), | |
| 167 | +SOC_SINGLE("OUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L, | |
| 168 | + ARIZONA_OUT2_OSR_SHIFT, 1, 0), | |
| 169 | +SOC_SINGLE("EPOUT High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L, | |
| 170 | + ARIZONA_OUT3_OSR_SHIFT, 1, 0), | |
| 171 | +SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L, | |
| 172 | + ARIZONA_OUT4_OSR_SHIFT, 1, 0), | |
| 173 | +SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L, | |
| 174 | + ARIZONA_OUT5_OSR_SHIFT, 1, 0), | |
| 175 | + | |
| 176 | +SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L, | |
| 177 | + ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1), | |
| 178 | +SOC_DOUBLE_R("OUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L, | |
| 179 | + ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_MUTE_SHIFT, 1, 1), | |
| 180 | +SOC_SINGLE("EPOUT Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_3L, | |
| 181 | + ARIZONA_OUT3L_MUTE_SHIFT, 1, 1), | |
| 182 | +SOC_DOUBLE_R("Speaker Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_4L, | |
| 183 | + ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_MUTE_SHIFT, 1, 1), | |
| 184 | +SOC_DOUBLE_R("SPKDAT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_5L, | |
| 185 | + ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_MUTE_SHIFT, 1, 1), | |
| 186 | + | |
| 187 | +SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_1L, | |
| 188 | + ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_VOL_SHIFT, | |
| 189 | + 0xbf, 0, digital_tlv), | |
| 190 | +SOC_DOUBLE_R_TLV("OUT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_2L, | |
| 191 | + ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_VOL_SHIFT, | |
| 192 | + 0xbf, 0, digital_tlv), | |
| 193 | +SOC_SINGLE_TLV("EPOUT Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_3L, | |
| 194 | + ARIZONA_OUT3L_VOL_SHIFT, 0xbf, 0, digital_tlv), | |
| 195 | +SOC_DOUBLE_R_TLV("Speaker Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_4L, | |
| 196 | + ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_VOL_SHIFT, | |
| 197 | + 0xbf, 0, digital_tlv), | |
| 198 | +SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L, | |
| 199 | + ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT, | |
| 200 | + 0xbf, 0, digital_tlv), | |
| 201 | + | |
| 202 | +SOC_DOUBLE_R_RANGE_TLV("HPOUT1 Volume", ARIZONA_OUTPUT_PATH_CONFIG_1L, | |
| 203 | + ARIZONA_OUTPUT_PATH_CONFIG_1R, | |
| 204 | + ARIZONA_OUT1L_PGA_VOL_SHIFT, | |
| 205 | + 0x34, 0x40, 0, ana_tlv), | |
| 206 | +SOC_DOUBLE_R_RANGE_TLV("OUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L, | |
| 207 | + ARIZONA_OUTPUT_PATH_CONFIG_2R, | |
| 208 | + ARIZONA_OUT2L_PGA_VOL_SHIFT, | |
| 209 | + 0x34, 0x40, 0, ana_tlv), | |
| 210 | +SOC_SINGLE_RANGE_TLV("EPOUT Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L, | |
| 211 | + ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv), | |
| 212 | + | |
| 213 | +SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT, | |
| 214 | + ARIZONA_SPK1R_MUTE_SHIFT, 1, 1), | |
| 215 | + | |
| 216 | +ARIZONA_MIXER_CONTROLS("AIF1TX1", ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE), | |
| 217 | +ARIZONA_MIXER_CONTROLS("AIF1TX2", ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE), | |
| 218 | +ARIZONA_MIXER_CONTROLS("AIF1TX3", ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE), | |
| 219 | +ARIZONA_MIXER_CONTROLS("AIF1TX4", ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE), | |
| 220 | +ARIZONA_MIXER_CONTROLS("AIF1TX5", ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE), | |
| 221 | +ARIZONA_MIXER_CONTROLS("AIF1TX6", ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE), | |
| 222 | +ARIZONA_MIXER_CONTROLS("AIF1TX7", ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE), | |
| 223 | +ARIZONA_MIXER_CONTROLS("AIF1TX8", ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE), | |
| 224 | + | |
| 225 | +ARIZONA_MIXER_CONTROLS("AIF2TX1", ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE), | |
| 226 | +ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE), | |
| 227 | + | |
| 228 | +ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), | |
| 229 | +ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), | |
| 230 | +}; | |
| 231 | + | |
| 232 | +ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); | |
| 233 | +ARIZONA_MIXER_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE); | |
| 234 | +ARIZONA_MIXER_ENUMS(EQ3, ARIZONA_EQ3MIX_INPUT_1_SOURCE); | |
| 235 | +ARIZONA_MIXER_ENUMS(EQ4, ARIZONA_EQ4MIX_INPUT_1_SOURCE); | |
| 236 | + | |
| 237 | +ARIZONA_MIXER_ENUMS(DRC1L, ARIZONA_DRC1LMIX_INPUT_1_SOURCE); | |
| 238 | +ARIZONA_MIXER_ENUMS(DRC1R, ARIZONA_DRC1RMIX_INPUT_1_SOURCE); | |
| 239 | +ARIZONA_MIXER_ENUMS(DRC2L, ARIZONA_DRC2LMIX_INPUT_1_SOURCE); | |
| 240 | +ARIZONA_MIXER_ENUMS(DRC2R, ARIZONA_DRC2RMIX_INPUT_1_SOURCE); | |
| 241 | + | |
| 242 | +ARIZONA_MIXER_ENUMS(LHPF1, ARIZONA_HPLP1MIX_INPUT_1_SOURCE); | |
| 243 | +ARIZONA_MIXER_ENUMS(LHPF2, ARIZONA_HPLP2MIX_INPUT_1_SOURCE); | |
| 244 | +ARIZONA_MIXER_ENUMS(LHPF3, ARIZONA_HPLP3MIX_INPUT_1_SOURCE); | |
| 245 | +ARIZONA_MIXER_ENUMS(LHPF4, ARIZONA_HPLP4MIX_INPUT_1_SOURCE); | |
| 246 | + | |
| 247 | +ARIZONA_MIXER_ENUMS(Mic, ARIZONA_MICMIX_INPUT_1_SOURCE); | |
| 248 | +ARIZONA_MIXER_ENUMS(Noise, ARIZONA_NOISEMIX_INPUT_1_SOURCE); | |
| 249 | + | |
| 250 | +ARIZONA_MIXER_ENUMS(PWM1, ARIZONA_PWM1MIX_INPUT_1_SOURCE); | |
| 251 | +ARIZONA_MIXER_ENUMS(PWM2, ARIZONA_PWM2MIX_INPUT_1_SOURCE); | |
| 252 | + | |
| 253 | +ARIZONA_MIXER_ENUMS(OUT1L, ARIZONA_OUT1LMIX_INPUT_1_SOURCE); | |
| 254 | +ARIZONA_MIXER_ENUMS(OUT1R, ARIZONA_OUT1RMIX_INPUT_1_SOURCE); | |
| 255 | +ARIZONA_MIXER_ENUMS(OUT2L, ARIZONA_OUT2LMIX_INPUT_1_SOURCE); | |
| 256 | +ARIZONA_MIXER_ENUMS(OUT2R, ARIZONA_OUT2RMIX_INPUT_1_SOURCE); | |
| 257 | +ARIZONA_MIXER_ENUMS(OUT3, ARIZONA_OUT3LMIX_INPUT_1_SOURCE); | |
| 258 | +ARIZONA_MIXER_ENUMS(SPKOUTL, ARIZONA_OUT4LMIX_INPUT_1_SOURCE); | |
| 259 | +ARIZONA_MIXER_ENUMS(SPKOUTR, ARIZONA_OUT4RMIX_INPUT_1_SOURCE); | |
| 260 | +ARIZONA_MIXER_ENUMS(SPKDAT1L, ARIZONA_OUT5LMIX_INPUT_1_SOURCE); | |
| 261 | +ARIZONA_MIXER_ENUMS(SPKDAT1R, ARIZONA_OUT5RMIX_INPUT_1_SOURCE); | |
| 262 | + | |
| 263 | +ARIZONA_MIXER_ENUMS(AIF1TX1, ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE); | |
| 264 | +ARIZONA_MIXER_ENUMS(AIF1TX2, ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE); | |
| 265 | +ARIZONA_MIXER_ENUMS(AIF1TX3, ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE); | |
| 266 | +ARIZONA_MIXER_ENUMS(AIF1TX4, ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE); | |
| 267 | +ARIZONA_MIXER_ENUMS(AIF1TX5, ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE); | |
| 268 | +ARIZONA_MIXER_ENUMS(AIF1TX6, ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE); | |
| 269 | +ARIZONA_MIXER_ENUMS(AIF1TX7, ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE); | |
| 270 | +ARIZONA_MIXER_ENUMS(AIF1TX8, ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE); | |
| 271 | + | |
| 272 | +ARIZONA_MIXER_ENUMS(AIF2TX1, ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE); | |
| 273 | +ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE); | |
| 274 | + | |
| 275 | +ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); | |
| 276 | +ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); | |
| 277 | + | |
| 278 | +ARIZONA_MIXER_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE); | |
| 279 | +ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); | |
| 280 | +ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); | |
| 281 | +ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); | |
| 282 | + | |
| 283 | +static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = { | |
| 284 | +SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, | |
| 285 | + 0, NULL, 0), | |
| 286 | +SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, | |
| 287 | + ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), | |
| 288 | + | |
| 289 | +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), | |
| 290 | +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), | |
| 291 | +SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), | |
| 292 | +SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0), | |
| 293 | +SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0), | |
| 294 | +SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0), | |
| 295 | + | |
| 296 | +SND_SOC_DAPM_SIGGEN("TONE"), | |
| 297 | +SND_SOC_DAPM_SIGGEN("NOISE"), | |
| 298 | + | |
| 299 | +SND_SOC_DAPM_INPUT("IN1L"), | |
| 300 | +SND_SOC_DAPM_INPUT("IN1R"), | |
| 301 | +SND_SOC_DAPM_INPUT("IN2L"), | |
| 302 | +SND_SOC_DAPM_INPUT("IN2R"), | |
| 303 | +SND_SOC_DAPM_INPUT("IN3L"), | |
| 304 | +SND_SOC_DAPM_INPUT("IN3R"), | |
| 305 | + | |
| 306 | +SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT, | |
| 307 | + 0, NULL, 0, arizona_in_ev, | |
| 308 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 309 | +SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT, | |
| 310 | + 0, NULL, 0, arizona_in_ev, | |
| 311 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 312 | +SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT, | |
| 313 | + 0, NULL, 0, arizona_in_ev, | |
| 314 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 315 | +SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT, | |
| 316 | + 0, NULL, 0, arizona_in_ev, | |
| 317 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 318 | +SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT, | |
| 319 | + 0, NULL, 0, arizona_in_ev, | |
| 320 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 321 | +SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT, | |
| 322 | + 0, NULL, 0, arizona_in_ev, | |
| 323 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 324 | + | |
| 325 | +SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1, | |
| 326 | + ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), | |
| 327 | +SND_SOC_DAPM_SUPPLY("MICBIAS2", ARIZONA_MIC_BIAS_CTRL_2, | |
| 328 | + ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), | |
| 329 | +SND_SOC_DAPM_SUPPLY("MICBIAS3", ARIZONA_MIC_BIAS_CTRL_3, | |
| 330 | + ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), | |
| 331 | + | |
| 332 | +SND_SOC_DAPM_PGA("Noise Generator", ARIZONA_COMFORT_NOISE_GENERATOR, | |
| 333 | + ARIZONA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0), | |
| 334 | + | |
| 335 | +SND_SOC_DAPM_PGA("Tone Generator 1", ARIZONA_TONE_GENERATOR_1, | |
| 336 | + ARIZONA_TONE1_ENA_SHIFT, 0, NULL, 0), | |
| 337 | +SND_SOC_DAPM_PGA("Tone Generator 2", ARIZONA_TONE_GENERATOR_1, | |
| 338 | + ARIZONA_TONE2_ENA_SHIFT, 0, NULL, 0), | |
| 339 | + | |
| 340 | +SND_SOC_DAPM_PGA("Mic Mute Mixer", ARIZONA_MIC_NOISE_MIX_CONTROL_1, | |
| 341 | + ARIZONA_MICMUTE_MIX_ENA_SHIFT, 0, NULL, 0), | |
| 342 | + | |
| 343 | +SND_SOC_DAPM_PGA("EQ1", ARIZONA_EQ1_1, ARIZONA_EQ1_ENA_SHIFT, 0, NULL, 0), | |
| 344 | +SND_SOC_DAPM_PGA("EQ2", ARIZONA_EQ2_1, ARIZONA_EQ2_ENA_SHIFT, 0, NULL, 0), | |
| 345 | +SND_SOC_DAPM_PGA("EQ3", ARIZONA_EQ3_1, ARIZONA_EQ3_ENA_SHIFT, 0, NULL, 0), | |
| 346 | +SND_SOC_DAPM_PGA("EQ4", ARIZONA_EQ4_1, ARIZONA_EQ4_ENA_SHIFT, 0, NULL, 0), | |
| 347 | + | |
| 348 | +SND_SOC_DAPM_PGA("DRC1L", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1L_ENA_SHIFT, 0, | |
| 349 | + NULL, 0), | |
| 350 | +SND_SOC_DAPM_PGA("DRC1R", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1R_ENA_SHIFT, 0, | |
| 351 | + NULL, 0), | |
| 352 | +SND_SOC_DAPM_PGA("DRC2L", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2L_ENA_SHIFT, 0, | |
| 353 | + NULL, 0), | |
| 354 | +SND_SOC_DAPM_PGA("DRC2R", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2R_ENA_SHIFT, 0, | |
| 355 | + NULL, 0), | |
| 356 | + | |
| 357 | +SND_SOC_DAPM_PGA("LHPF1", ARIZONA_HPLPF1_1, ARIZONA_LHPF1_ENA_SHIFT, 0, | |
| 358 | + NULL, 0), | |
| 359 | +SND_SOC_DAPM_PGA("LHPF2", ARIZONA_HPLPF2_1, ARIZONA_LHPF2_ENA_SHIFT, 0, | |
| 360 | + NULL, 0), | |
| 361 | +SND_SOC_DAPM_PGA("LHPF3", ARIZONA_HPLPF3_1, ARIZONA_LHPF3_ENA_SHIFT, 0, | |
| 362 | + NULL, 0), | |
| 363 | +SND_SOC_DAPM_PGA("LHPF4", ARIZONA_HPLPF4_1, ARIZONA_LHPF4_ENA_SHIFT, 0, | |
| 364 | + NULL, 0), | |
| 365 | + | |
| 366 | +SND_SOC_DAPM_PGA("PWM1 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM1_ENA_SHIFT, | |
| 367 | + 0, NULL, 0), | |
| 368 | +SND_SOC_DAPM_PGA("PWM2 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM2_ENA_SHIFT, | |
| 369 | + 0, NULL, 0), | |
| 370 | + | |
| 371 | +SND_SOC_DAPM_PGA("ASRC1L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC1L_ENA_SHIFT, 0, | |
| 372 | + NULL, 0), | |
| 373 | +SND_SOC_DAPM_PGA("ASRC1R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC1R_ENA_SHIFT, 0, | |
| 374 | + NULL, 0), | |
| 375 | +SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0, | |
| 376 | + NULL, 0), | |
| 377 | +SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0, | |
| 378 | + NULL, 0), | |
| 379 | + | |
| 380 | +SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, | |
| 381 | + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0), | |
| 382 | +SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, | |
| 383 | + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX2_ENA_SHIFT, 0), | |
| 384 | +SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, | |
| 385 | + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX3_ENA_SHIFT, 0), | |
| 386 | +SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, | |
| 387 | + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX4_ENA_SHIFT, 0), | |
| 388 | +SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, | |
| 389 | + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX5_ENA_SHIFT, 0), | |
| 390 | +SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, | |
| 391 | + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX6_ENA_SHIFT, 0), | |
| 392 | +SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0, | |
| 393 | + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX7_ENA_SHIFT, 0), | |
| 394 | +SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0, | |
| 395 | + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX8_ENA_SHIFT, 0), | |
| 396 | + | |
| 397 | +SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, | |
| 398 | + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX1_ENA_SHIFT, 0), | |
| 399 | +SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, | |
| 400 | + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX2_ENA_SHIFT, 0), | |
| 401 | +SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, | |
| 402 | + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX3_ENA_SHIFT, 0), | |
| 403 | +SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, | |
| 404 | + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX4_ENA_SHIFT, 0), | |
| 405 | +SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, | |
| 406 | + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX5_ENA_SHIFT, 0), | |
| 407 | +SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, | |
| 408 | + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX6_ENA_SHIFT, 0), | |
| 409 | +SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0, | |
| 410 | + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX7_ENA_SHIFT, 0), | |
| 411 | +SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0, | |
| 412 | + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX8_ENA_SHIFT, 0), | |
| 413 | + | |
| 414 | +SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, | |
| 415 | + ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX1_ENA_SHIFT, 0), | |
| 416 | +SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, | |
| 417 | + ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX2_ENA_SHIFT, 0), | |
| 418 | + | |
| 419 | +SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, | |
| 420 | + ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX1_ENA_SHIFT, 0), | |
| 421 | +SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, | |
| 422 | + ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0), | |
| 423 | + | |
| 424 | +SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, | |
| 425 | + ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX1_ENA_SHIFT, 0), | |
| 426 | +SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, | |
| 427 | + ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX2_ENA_SHIFT, 0), | |
| 428 | + | |
| 429 | +SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, | |
| 430 | + ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX1_ENA_SHIFT, 0), | |
| 431 | +SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, | |
| 432 | + ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0), | |
| 433 | + | |
| 434 | +SND_SOC_DAPM_PGA_E("OUT1L", ARIZONA_OUTPUT_ENABLES_1, | |
| 435 | + ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | |
| 436 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 437 | +SND_SOC_DAPM_PGA_E("OUT1R", ARIZONA_OUTPUT_ENABLES_1, | |
| 438 | + ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | |
| 439 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 440 | +SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1, | |
| 441 | + ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | |
| 442 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 443 | +SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1, | |
| 444 | + ARIZONA_OUT2R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | |
| 445 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 446 | +SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, | |
| 447 | + ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | |
| 448 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 449 | +SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1, | |
| 450 | + ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | |
| 451 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 452 | +SND_SOC_DAPM_PGA_E("OUT4R", ARIZONA_OUTPUT_ENABLES_1, | |
| 453 | + ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | |
| 454 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 455 | +SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1, | |
| 456 | + ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | |
| 457 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 458 | +SND_SOC_DAPM_PGA_E("OUT5R", ARIZONA_OUTPUT_ENABLES_1, | |
| 459 | + ARIZONA_OUT5R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | |
| 460 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 461 | + | |
| 462 | +ARIZONA_MIXER_WIDGETS(EQ1, "EQ1"), | |
| 463 | +ARIZONA_MIXER_WIDGETS(EQ2, "EQ2"), | |
| 464 | +ARIZONA_MIXER_WIDGETS(EQ3, "EQ3"), | |
| 465 | +ARIZONA_MIXER_WIDGETS(EQ4, "EQ4"), | |
| 466 | + | |
| 467 | +ARIZONA_MIXER_WIDGETS(DRC1L, "DRC1L"), | |
| 468 | +ARIZONA_MIXER_WIDGETS(DRC1R, "DRC1R"), | |
| 469 | +ARIZONA_MIXER_WIDGETS(DRC2L, "DRC2L"), | |
| 470 | +ARIZONA_MIXER_WIDGETS(DRC2R, "DRC2R"), | |
| 471 | + | |
| 472 | +ARIZONA_MIXER_WIDGETS(LHPF1, "LHPF1"), | |
| 473 | +ARIZONA_MIXER_WIDGETS(LHPF2, "LHPF2"), | |
| 474 | +ARIZONA_MIXER_WIDGETS(LHPF3, "LHPF3"), | |
| 475 | +ARIZONA_MIXER_WIDGETS(LHPF4, "LHPF4"), | |
| 476 | + | |
| 477 | +ARIZONA_MIXER_WIDGETS(Mic, "Mic"), | |
| 478 | +ARIZONA_MIXER_WIDGETS(Noise, "Noise"), | |
| 479 | + | |
| 480 | +ARIZONA_MIXER_WIDGETS(PWM1, "PWM1"), | |
| 481 | +ARIZONA_MIXER_WIDGETS(PWM2, "PWM2"), | |
| 482 | + | |
| 483 | +ARIZONA_MIXER_WIDGETS(OUT1L, "HPOUT1L"), | |
| 484 | +ARIZONA_MIXER_WIDGETS(OUT1R, "HPOUT1R"), | |
| 485 | +ARIZONA_MIXER_WIDGETS(OUT2L, "HPOUT2L"), | |
| 486 | +ARIZONA_MIXER_WIDGETS(OUT2R, "HPOUT2R"), | |
| 487 | +ARIZONA_MIXER_WIDGETS(OUT3, "EPOUT"), | |
| 488 | +ARIZONA_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"), | |
| 489 | +ARIZONA_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"), | |
| 490 | +ARIZONA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"), | |
| 491 | +ARIZONA_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"), | |
| 492 | + | |
| 493 | +ARIZONA_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"), | |
| 494 | +ARIZONA_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"), | |
| 495 | +ARIZONA_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"), | |
| 496 | +ARIZONA_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"), | |
| 497 | +ARIZONA_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"), | |
| 498 | +ARIZONA_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"), | |
| 499 | +ARIZONA_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"), | |
| 500 | +ARIZONA_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"), | |
| 501 | + | |
| 502 | +ARIZONA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"), | |
| 503 | +ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), | |
| 504 | + | |
| 505 | +ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), | |
| 506 | +ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), | |
| 507 | + | |
| 508 | +ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"), | |
| 509 | +ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"), | |
| 510 | +ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"), | |
| 511 | +ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"), | |
| 512 | + | |
| 513 | +SND_SOC_DAPM_OUTPUT("HPOUT1L"), | |
| 514 | +SND_SOC_DAPM_OUTPUT("HPOUT1R"), | |
| 515 | +SND_SOC_DAPM_OUTPUT("HPOUT2L"), | |
| 516 | +SND_SOC_DAPM_OUTPUT("HPOUT2R"), | |
| 517 | +SND_SOC_DAPM_OUTPUT("EPOUTN"), | |
| 518 | +SND_SOC_DAPM_OUTPUT("EPOUTP"), | |
| 519 | +SND_SOC_DAPM_OUTPUT("SPKOUTLN"), | |
| 520 | +SND_SOC_DAPM_OUTPUT("SPKOUTLP"), | |
| 521 | +SND_SOC_DAPM_OUTPUT("SPKOUTRN"), | |
| 522 | +SND_SOC_DAPM_OUTPUT("SPKOUTRP"), | |
| 523 | +SND_SOC_DAPM_OUTPUT("SPKDAT1L"), | |
| 524 | +SND_SOC_DAPM_OUTPUT("SPKDAT1R"), | |
| 525 | +}; | |
| 526 | + | |
| 527 | +#define ARIZONA_MIXER_INPUT_ROUTES(name) \ | |
| 528 | + { name, "Noise Generator", "Noise Generator" }, \ | |
| 529 | + { name, "Tone Generator 1", "Tone Generator 1" }, \ | |
| 530 | + { name, "Tone Generator 2", "Tone Generator 2" }, \ | |
| 531 | + { name, "IN1L", "IN1L PGA" }, \ | |
| 532 | + { name, "IN1R", "IN1R PGA" }, \ | |
| 533 | + { name, "IN2L", "IN2L PGA" }, \ | |
| 534 | + { name, "IN2R", "IN2R PGA" }, \ | |
| 535 | + { name, "IN3L", "IN3L PGA" }, \ | |
| 536 | + { name, "IN3R", "IN3R PGA" }, \ | |
| 537 | + { name, "Mic Mute Mixer", "Mic Mute Mixer" }, \ | |
| 538 | + { name, "AIF1RX1", "AIF1RX1" }, \ | |
| 539 | + { name, "AIF1RX2", "AIF1RX2" }, \ | |
| 540 | + { name, "AIF1RX3", "AIF1RX3" }, \ | |
| 541 | + { name, "AIF1RX4", "AIF1RX4" }, \ | |
| 542 | + { name, "AIF1RX5", "AIF1RX5" }, \ | |
| 543 | + { name, "AIF1RX6", "AIF1RX6" }, \ | |
| 544 | + { name, "AIF1RX7", "AIF1RX7" }, \ | |
| 545 | + { name, "AIF1RX8", "AIF1RX8" }, \ | |
| 546 | + { name, "AIF2RX1", "AIF2RX1" }, \ | |
| 547 | + { name, "AIF2RX2", "AIF2RX2" }, \ | |
| 548 | + { name, "AIF3RX1", "AIF3RX1" }, \ | |
| 549 | + { name, "AIF3RX2", "AIF3RX2" }, \ | |
| 550 | + { name, "EQ1", "EQ1" }, \ | |
| 551 | + { name, "EQ2", "EQ2" }, \ | |
| 552 | + { name, "EQ3", "EQ3" }, \ | |
| 553 | + { name, "EQ4", "EQ4" }, \ | |
| 554 | + { name, "DRC1L", "DRC1L" }, \ | |
| 555 | + { name, "DRC1R", "DRC1R" }, \ | |
| 556 | + { name, "DRC2L", "DRC2L" }, \ | |
| 557 | + { name, "DRC2R", "DRC2R" }, \ | |
| 558 | + { name, "LHPF1", "LHPF1" }, \ | |
| 559 | + { name, "LHPF2", "LHPF2" }, \ | |
| 560 | + { name, "LHPF3", "LHPF3" }, \ | |
| 561 | + { name, "LHPF4", "LHPF4" }, \ | |
| 562 | + { name, "ASRC1L", "ASRC1L" }, \ | |
| 563 | + { name, "ASRC1R", "ASRC1R" }, \ | |
| 564 | + { name, "ASRC2L", "ASRC2L" }, \ | |
| 565 | + { name, "ASRC2R", "ASRC2R" } | |
| 566 | + | |
| 567 | +static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { | |
| 568 | + { "AIF2 Capture", NULL, "DBVDD2" }, | |
| 569 | + { "AIF2 Playback", NULL, "DBVDD2" }, | |
| 570 | + | |
| 571 | + { "AIF3 Capture", NULL, "DBVDD3" }, | |
| 572 | + { "AIF3 Playback", NULL, "DBVDD3" }, | |
| 573 | + | |
| 574 | + { "OUT1L", NULL, "CPVDD" }, | |
| 575 | + { "OUT1R", NULL, "CPVDD" }, | |
| 576 | + { "OUT2L", NULL, "CPVDD" }, | |
| 577 | + { "OUT2R", NULL, "CPVDD" }, | |
| 578 | + { "OUT3L", NULL, "CPVDD" }, | |
| 579 | + | |
| 580 | + { "OUT4L", NULL, "SPKVDDL" }, | |
| 581 | + { "OUT4R", NULL, "SPKVDDR" }, | |
| 582 | + | |
| 583 | + { "OUT1L", NULL, "SYSCLK" }, | |
| 584 | + { "OUT1R", NULL, "SYSCLK" }, | |
| 585 | + { "OUT2L", NULL, "SYSCLK" }, | |
| 586 | + { "OUT2R", NULL, "SYSCLK" }, | |
| 587 | + { "OUT3L", NULL, "SYSCLK" }, | |
| 588 | + { "OUT4L", NULL, "SYSCLK" }, | |
| 589 | + { "OUT4R", NULL, "SYSCLK" }, | |
| 590 | + { "OUT5L", NULL, "SYSCLK" }, | |
| 591 | + { "OUT5R", NULL, "SYSCLK" }, | |
| 592 | + | |
| 593 | + { "MICBIAS1", NULL, "MICVDD" }, | |
| 594 | + { "MICBIAS2", NULL, "MICVDD" }, | |
| 595 | + { "MICBIAS3", NULL, "MICVDD" }, | |
| 596 | + | |
| 597 | + { "Noise Generator", NULL, "NOISE" }, | |
| 598 | + { "Tone Generator 1", NULL, "TONE" }, | |
| 599 | + { "Tone Generator 2", NULL, "TONE" }, | |
| 600 | + | |
| 601 | + { "Mic Mute Mixer", NULL, "Noise Mixer" }, | |
| 602 | + { "Mic Mute Mixer", NULL, "Mic Mixer" }, | |
| 603 | + | |
| 604 | + { "AIF1 Capture", NULL, "AIF1TX1" }, | |
| 605 | + { "AIF1 Capture", NULL, "AIF1TX2" }, | |
| 606 | + { "AIF1 Capture", NULL, "AIF1TX3" }, | |
| 607 | + { "AIF1 Capture", NULL, "AIF1TX4" }, | |
| 608 | + { "AIF1 Capture", NULL, "AIF1TX5" }, | |
| 609 | + { "AIF1 Capture", NULL, "AIF1TX6" }, | |
| 610 | + { "AIF1 Capture", NULL, "AIF1TX7" }, | |
| 611 | + { "AIF1 Capture", NULL, "AIF1TX8" }, | |
| 612 | + | |
| 613 | + { "AIF1RX1", NULL, "AIF1 Playback" }, | |
| 614 | + { "AIF1RX2", NULL, "AIF1 Playback" }, | |
| 615 | + { "AIF1RX3", NULL, "AIF1 Playback" }, | |
| 616 | + { "AIF1RX4", NULL, "AIF1 Playback" }, | |
| 617 | + { "AIF1RX5", NULL, "AIF1 Playback" }, | |
| 618 | + { "AIF1RX6", NULL, "AIF1 Playback" }, | |
| 619 | + { "AIF1RX7", NULL, "AIF1 Playback" }, | |
| 620 | + { "AIF1RX8", NULL, "AIF1 Playback" }, | |
| 621 | + | |
| 622 | + { "AIF2 Capture", NULL, "AIF2TX1" }, | |
| 623 | + { "AIF2 Capture", NULL, "AIF2TX2" }, | |
| 624 | + | |
| 625 | + { "AIF2RX1", NULL, "AIF2 Playback" }, | |
| 626 | + { "AIF2RX2", NULL, "AIF2 Playback" }, | |
| 627 | + | |
| 628 | + { "AIF3 Capture", NULL, "AIF3TX1" }, | |
| 629 | + { "AIF3 Capture", NULL, "AIF3TX2" }, | |
| 630 | + | |
| 631 | + { "AIF3RX1", NULL, "AIF3 Playback" }, | |
| 632 | + { "AIF3RX2", NULL, "AIF3 Playback" }, | |
| 633 | + | |
| 634 | + { "AIF1 Playback", NULL, "SYSCLK" }, | |
| 635 | + { "AIF2 Playback", NULL, "SYSCLK" }, | |
| 636 | + { "AIF3 Playback", NULL, "SYSCLK" }, | |
| 637 | + | |
| 638 | + { "AIF1 Capture", NULL, "SYSCLK" }, | |
| 639 | + { "AIF2 Capture", NULL, "SYSCLK" }, | |
| 640 | + { "AIF3 Capture", NULL, "SYSCLK" }, | |
| 641 | + | |
| 642 | + ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"), | |
| 643 | + ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"), | |
| 644 | + ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"), | |
| 645 | + ARIZONA_MIXER_ROUTES("OUT2R", "HPOUT2R"), | |
| 646 | + ARIZONA_MIXER_ROUTES("OUT3L", "EPOUT"), | |
| 647 | + | |
| 648 | + ARIZONA_MIXER_ROUTES("OUT4L", "SPKOUTL"), | |
| 649 | + ARIZONA_MIXER_ROUTES("OUT4R", "SPKOUTR"), | |
| 650 | + ARIZONA_MIXER_ROUTES("OUT5L", "SPKDAT1L"), | |
| 651 | + ARIZONA_MIXER_ROUTES("OUT5R", "SPKDAT1R"), | |
| 652 | + | |
| 653 | + ARIZONA_MIXER_ROUTES("PWM1 Driver", "PWM1"), | |
| 654 | + ARIZONA_MIXER_ROUTES("PWM2 Driver", "PWM2"), | |
| 655 | + | |
| 656 | + ARIZONA_MIXER_ROUTES("AIF1TX1", "AIF1TX1"), | |
| 657 | + ARIZONA_MIXER_ROUTES("AIF1TX2", "AIF1TX2"), | |
| 658 | + ARIZONA_MIXER_ROUTES("AIF1TX3", "AIF1TX3"), | |
| 659 | + ARIZONA_MIXER_ROUTES("AIF1TX4", "AIF1TX4"), | |
| 660 | + ARIZONA_MIXER_ROUTES("AIF1TX5", "AIF1TX5"), | |
| 661 | + ARIZONA_MIXER_ROUTES("AIF1TX6", "AIF1TX6"), | |
| 662 | + ARIZONA_MIXER_ROUTES("AIF1TX7", "AIF1TX7"), | |
| 663 | + ARIZONA_MIXER_ROUTES("AIF1TX8", "AIF1TX8"), | |
| 664 | + | |
| 665 | + ARIZONA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"), | |
| 666 | + ARIZONA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"), | |
| 667 | + | |
| 668 | + ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), | |
| 669 | + ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), | |
| 670 | + | |
| 671 | + ARIZONA_MIXER_ROUTES("EQ1", "EQ1"), | |
| 672 | + ARIZONA_MIXER_ROUTES("EQ2", "EQ2"), | |
| 673 | + ARIZONA_MIXER_ROUTES("EQ3", "EQ3"), | |
| 674 | + ARIZONA_MIXER_ROUTES("EQ4", "EQ4"), | |
| 675 | + | |
| 676 | + ARIZONA_MIXER_ROUTES("DRC1L", "DRC1L"), | |
| 677 | + ARIZONA_MIXER_ROUTES("DRC1R", "DRC1R"), | |
| 678 | + ARIZONA_MIXER_ROUTES("DRC2L", "DRC2L"), | |
| 679 | + ARIZONA_MIXER_ROUTES("DRC2R", "DRC2R"), | |
| 680 | + | |
| 681 | + ARIZONA_MIXER_ROUTES("LHPF1", "LHPF1"), | |
| 682 | + ARIZONA_MIXER_ROUTES("LHPF2", "LHPF2"), | |
| 683 | + ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"), | |
| 684 | + ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"), | |
| 685 | + | |
| 686 | + ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"), | |
| 687 | + ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"), | |
| 688 | + ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"), | |
| 689 | + ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"), | |
| 690 | + | |
| 691 | + { "HPOUT1L", NULL, "OUT1L" }, | |
| 692 | + { "HPOUT1R", NULL, "OUT1R" }, | |
| 693 | + | |
| 694 | + { "HPOUT2L", NULL, "OUT2L" }, | |
| 695 | + { "HPOUT2R", NULL, "OUT2R" }, | |
| 696 | + | |
| 697 | + { "EPOUTN", NULL, "OUT3L" }, | |
| 698 | + { "EPOUTP", NULL, "OUT3L" }, | |
| 699 | + | |
| 700 | + { "SPKOUTLN", NULL, "OUT4L" }, | |
| 701 | + { "SPKOUTLP", NULL, "OUT4L" }, | |
| 702 | + | |
| 703 | + { "SPKOUTRN", NULL, "OUT4R" }, | |
| 704 | + { "SPKOUTRP", NULL, "OUT4R" }, | |
| 705 | + | |
| 706 | + { "SPKDAT1L", NULL, "OUT5L" }, | |
| 707 | + { "SPKDAT1R", NULL, "OUT5R" }, | |
| 708 | +}; | |
| 709 | + | |
| 710 | +static int wm5102_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |
| 711 | + unsigned int Fref, unsigned int Fout) | |
| 712 | +{ | |
| 713 | + struct wm5102_priv *wm5102 = snd_soc_codec_get_drvdata(codec); | |
| 714 | + | |
| 715 | + switch (fll_id) { | |
| 716 | + case WM5102_FLL1: | |
| 717 | + return arizona_set_fll(&wm5102->fll[0], source, Fref, Fout); | |
| 718 | + case WM5102_FLL2: | |
| 719 | + return arizona_set_fll(&wm5102->fll[1], source, Fref, Fout); | |
| 720 | + default: | |
| 721 | + return -EINVAL; | |
| 722 | + } | |
| 723 | +} | |
| 724 | + | |
| 725 | +#define WM5102_RATES SNDRV_PCM_RATE_8000_192000 | |
| 726 | + | |
| 727 | +#define WM5102_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | |
| 728 | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | |
| 729 | + | |
| 730 | +static struct snd_soc_dai_driver wm5102_dai[] = { | |
| 731 | + { | |
| 732 | + .name = "wm5102-aif1", | |
| 733 | + .id = 1, | |
| 734 | + .base = ARIZONA_AIF1_BCLK_CTRL, | |
| 735 | + .playback = { | |
| 736 | + .stream_name = "AIF1 Playback", | |
| 737 | + .channels_min = 1, | |
| 738 | + .channels_max = 8, | |
| 739 | + .rates = WM5102_RATES, | |
| 740 | + .formats = WM5102_FORMATS, | |
| 741 | + }, | |
| 742 | + .capture = { | |
| 743 | + .stream_name = "AIF1 Capture", | |
| 744 | + .channels_min = 1, | |
| 745 | + .channels_max = 8, | |
| 746 | + .rates = WM5102_RATES, | |
| 747 | + .formats = WM5102_FORMATS, | |
| 748 | + }, | |
| 749 | + .ops = &arizona_dai_ops, | |
| 750 | + .symmetric_rates = 1, | |
| 751 | + }, | |
| 752 | + { | |
| 753 | + .name = "wm5102-aif2", | |
| 754 | + .id = 2, | |
| 755 | + .base = ARIZONA_AIF2_BCLK_CTRL, | |
| 756 | + .playback = { | |
| 757 | + .stream_name = "AIF2 Playback", | |
| 758 | + .channels_min = 1, | |
| 759 | + .channels_max = 2, | |
| 760 | + .rates = WM5102_RATES, | |
| 761 | + .formats = WM5102_FORMATS, | |
| 762 | + }, | |
| 763 | + .capture = { | |
| 764 | + .stream_name = "AIF2 Capture", | |
| 765 | + .channels_min = 1, | |
| 766 | + .channels_max = 2, | |
| 767 | + .rates = WM5102_RATES, | |
| 768 | + .formats = WM5102_FORMATS, | |
| 769 | + }, | |
| 770 | + .ops = &arizona_dai_ops, | |
| 771 | + .symmetric_rates = 1, | |
| 772 | + }, | |
| 773 | + { | |
| 774 | + .name = "wm5102-aif3", | |
| 775 | + .id = 3, | |
| 776 | + .base = ARIZONA_AIF3_BCLK_CTRL, | |
| 777 | + .playback = { | |
| 778 | + .stream_name = "AIF3 Playback", | |
| 779 | + .channels_min = 1, | |
| 780 | + .channels_max = 2, | |
| 781 | + .rates = WM5102_RATES, | |
| 782 | + .formats = WM5102_FORMATS, | |
| 783 | + }, | |
| 784 | + .capture = { | |
| 785 | + .stream_name = "AIF3 Capture", | |
| 786 | + .channels_min = 1, | |
| 787 | + .channels_max = 2, | |
| 788 | + .rates = WM5102_RATES, | |
| 789 | + .formats = WM5102_FORMATS, | |
| 790 | + }, | |
| 791 | + .ops = &arizona_dai_ops, | |
| 792 | + .symmetric_rates = 1, | |
| 793 | + }, | |
| 794 | +}; | |
| 795 | + | |
| 796 | +static int wm5102_codec_probe(struct snd_soc_codec *codec) | |
| 797 | +{ | |
| 798 | + struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec); | |
| 799 | + | |
| 800 | + codec->control_data = priv->core.arizona->regmap; | |
| 801 | + return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP); | |
| 802 | +} | |
| 803 | + | |
| 804 | +#define WM5102_DIG_VU 0x0200 | |
| 805 | + | |
| 806 | +static unsigned int wm5102_digital_vu[] = { | |
| 807 | + ARIZONA_ADC_DIGITAL_VOLUME_1L, | |
| 808 | + ARIZONA_ADC_DIGITAL_VOLUME_1R, | |
| 809 | + ARIZONA_ADC_DIGITAL_VOLUME_2L, | |
| 810 | + ARIZONA_ADC_DIGITAL_VOLUME_2R, | |
| 811 | + ARIZONA_ADC_DIGITAL_VOLUME_3L, | |
| 812 | + ARIZONA_ADC_DIGITAL_VOLUME_3R, | |
| 813 | + | |
| 814 | + ARIZONA_DAC_DIGITAL_VOLUME_1L, | |
| 815 | + ARIZONA_DAC_DIGITAL_VOLUME_1R, | |
| 816 | + ARIZONA_DAC_DIGITAL_VOLUME_2L, | |
| 817 | + ARIZONA_DAC_DIGITAL_VOLUME_2R, | |
| 818 | + ARIZONA_DAC_DIGITAL_VOLUME_3L, | |
| 819 | + ARIZONA_DAC_DIGITAL_VOLUME_3R, | |
| 820 | + ARIZONA_DAC_DIGITAL_VOLUME_4L, | |
| 821 | + ARIZONA_DAC_DIGITAL_VOLUME_4R, | |
| 822 | + ARIZONA_DAC_DIGITAL_VOLUME_5L, | |
| 823 | + ARIZONA_DAC_DIGITAL_VOLUME_5R, | |
| 824 | +}; | |
| 825 | + | |
| 826 | +static struct snd_soc_codec_driver soc_codec_dev_wm5102 = { | |
| 827 | + .probe = wm5102_codec_probe, | |
| 828 | + | |
| 829 | + .idle_bias_off = true, | |
| 830 | + | |
| 831 | + .set_sysclk = arizona_set_sysclk, | |
| 832 | + .set_pll = wm5102_set_fll, | |
| 833 | + | |
| 834 | + .controls = wm5102_snd_controls, | |
| 835 | + .num_controls = ARRAY_SIZE(wm5102_snd_controls), | |
| 836 | + .dapm_widgets = wm5102_dapm_widgets, | |
| 837 | + .num_dapm_widgets = ARRAY_SIZE(wm5102_dapm_widgets), | |
| 838 | + .dapm_routes = wm5102_dapm_routes, | |
| 839 | + .num_dapm_routes = ARRAY_SIZE(wm5102_dapm_routes), | |
| 840 | +}; | |
| 841 | + | |
| 842 | +static int __devinit wm5102_probe(struct platform_device *pdev) | |
| 843 | +{ | |
| 844 | + struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); | |
| 845 | + struct wm5102_priv *wm5102; | |
| 846 | + int i; | |
| 847 | + | |
| 848 | + wm5102 = devm_kzalloc(&pdev->dev, sizeof(struct wm5102_priv), | |
| 849 | + GFP_KERNEL); | |
| 850 | + if (wm5102 == NULL) | |
| 851 | + return -ENOMEM; | |
| 852 | + platform_set_drvdata(pdev, wm5102); | |
| 853 | + | |
| 854 | + wm5102->core.arizona = arizona; | |
| 855 | + | |
| 856 | + for (i = 0; i < ARRAY_SIZE(wm5102->fll); i++) | |
| 857 | + wm5102->fll[i].vco_mult = 1; | |
| 858 | + | |
| 859 | + arizona_init_fll(arizona, 1, ARIZONA_FLL1_CONTROL_1 - 1, | |
| 860 | + ARIZONA_IRQ_FLL1_LOCK, ARIZONA_IRQ_FLL1_CLOCK_OK, | |
| 861 | + &wm5102->fll[0]); | |
| 862 | + arizona_init_fll(arizona, 2, ARIZONA_FLL2_CONTROL_1 - 1, | |
| 863 | + ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK, | |
| 864 | + &wm5102->fll[1]); | |
| 865 | + | |
| 866 | + for (i = 0; i < ARRAY_SIZE(wm5102_dai); i++) | |
| 867 | + arizona_init_dai(&wm5102->core, i); | |
| 868 | + | |
| 869 | + /* Latch volume update bits */ | |
| 870 | + for (i = 0; i < ARRAY_SIZE(wm5102_digital_vu); i++) | |
| 871 | + regmap_update_bits(arizona->regmap, wm5102_digital_vu[i], | |
| 872 | + WM5102_DIG_VU, WM5102_DIG_VU); | |
| 873 | + | |
| 874 | + pm_runtime_enable(&pdev->dev); | |
| 875 | + pm_runtime_idle(&pdev->dev); | |
| 876 | + | |
| 877 | + return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5102, | |
| 878 | + wm5102_dai, ARRAY_SIZE(wm5102_dai)); | |
| 879 | +} | |
| 880 | + | |
| 881 | +static int __devexit wm5102_remove(struct platform_device *pdev) | |
| 882 | +{ | |
| 883 | + snd_soc_unregister_codec(&pdev->dev); | |
| 884 | + pm_runtime_disable(&pdev->dev); | |
| 885 | + | |
| 886 | + return 0; | |
| 887 | +} | |
| 888 | + | |
| 889 | +static struct platform_driver wm5102_codec_driver = { | |
| 890 | + .driver = { | |
| 891 | + .name = "wm5102-codec", | |
| 892 | + .owner = THIS_MODULE, | |
| 893 | + }, | |
| 894 | + .probe = wm5102_probe, | |
| 895 | + .remove = __devexit_p(wm5102_remove), | |
| 896 | +}; | |
| 897 | + | |
| 898 | +module_platform_driver(wm5102_codec_driver); | |
| 899 | + | |
| 900 | +MODULE_DESCRIPTION("ASoC WM5102 driver"); | |
| 901 | +MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | |
| 902 | +MODULE_LICENSE("GPL"); | |
| 903 | +MODULE_ALIAS("platform:wm5102-codec"); | |
| @@ -0,0 +1,21 @@ | ||
| 1 | +/* | |
| 2 | + * wm5102.h -- WM5102 ALSA SoC Audio driver | |
| 3 | + * | |
| 4 | + * Copyright 2012 Wolfson Microelectronics plc | |
| 5 | + * | |
| 6 | + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | |
| 7 | + * | |
| 8 | + * This program is free software; you can redistribute it and/or modify | |
| 9 | + * it under the terms of the GNU General Public License version 2 as | |
| 10 | + * published by the Free Software Foundation. | |
| 11 | + */ | |
| 12 | + | |
| 13 | +#ifndef _WM5102_H | |
| 14 | +#define _WM5102_H | |
| 15 | + | |
| 16 | +#include "arizona.h" | |
| 17 | + | |
| 18 | +#define WM5102_FLL1 1 | |
| 19 | +#define WM5102_FLL2 2 | |
| 20 | + | |
| 21 | +#endif | |
| @@ -0,0 +1,950 @@ | ||
| 1 | +/* | |
| 2 | + * wm5110.c -- WM5110 ALSA SoC Audio driver | |
| 3 | + * | |
| 4 | + * Copyright 2012 Wolfson Microelectronics plc | |
| 5 | + * | |
| 6 | + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | |
| 7 | + * | |
| 8 | + * This program is free software; you can redistribute it and/or modify | |
| 9 | + * it under the terms of the GNU General Public License version 2 as | |
| 10 | + * published by the Free Software Foundation. | |
| 11 | + */ | |
| 12 | + | |
| 13 | +#include <linux/module.h> | |
| 14 | +#include <linux/moduleparam.h> | |
| 15 | +#include <linux/init.h> | |
| 16 | +#include <linux/delay.h> | |
| 17 | +#include <linux/pm.h> | |
| 18 | +#include <linux/pm_runtime.h> | |
| 19 | +#include <linux/regmap.h> | |
| 20 | +#include <linux/slab.h> | |
| 21 | +#include <sound/core.h> | |
| 22 | +#include <sound/pcm.h> | |
| 23 | +#include <sound/pcm_params.h> | |
| 24 | +#include <sound/soc.h> | |
| 25 | +#include <sound/jack.h> | |
| 26 | +#include <sound/initval.h> | |
| 27 | +#include <sound/tlv.h> | |
| 28 | + | |
| 29 | +#include <linux/mfd/arizona/core.h> | |
| 30 | +#include <linux/mfd/arizona/registers.h> | |
| 31 | + | |
| 32 | +#include "arizona.h" | |
| 33 | +#include "wm5110.h" | |
| 34 | + | |
| 35 | +struct wm5110_priv { | |
| 36 | + struct arizona_priv core; | |
| 37 | + struct arizona_fll fll[2]; | |
| 38 | +}; | |
| 39 | + | |
| 40 | +static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); | |
| 41 | +static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | |
| 42 | +static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); | |
| 43 | +static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0); | |
| 44 | + | |
| 45 | +static const struct snd_kcontrol_new wm5110_snd_controls[] = { | |
| 46 | +SOC_SINGLE("IN1 High Performance Switch", ARIZONA_IN1L_CONTROL, | |
| 47 | + ARIZONA_IN1_OSR_SHIFT, 1, 0), | |
| 48 | +SOC_SINGLE("IN2 High Performance Switch", ARIZONA_IN2L_CONTROL, | |
| 49 | + ARIZONA_IN2_OSR_SHIFT, 1, 0), | |
| 50 | +SOC_SINGLE("IN3 High Performance Switch", ARIZONA_IN3L_CONTROL, | |
| 51 | + ARIZONA_IN3_OSR_SHIFT, 1, 0), | |
| 52 | +SOC_SINGLE("IN4 High Performance Switch", ARIZONA_IN4L_CONTROL, | |
| 53 | + ARIZONA_IN4_OSR_SHIFT, 1, 0), | |
| 54 | + | |
| 55 | +SOC_DOUBLE_R_RANGE_TLV("IN1 Volume", ARIZONA_IN1L_CONTROL, | |
| 56 | + ARIZONA_IN1R_CONTROL, | |
| 57 | + ARIZONA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), | |
| 58 | +SOC_DOUBLE_R_RANGE_TLV("IN2 Volume", ARIZONA_IN2L_CONTROL, | |
| 59 | + ARIZONA_IN2R_CONTROL, | |
| 60 | + ARIZONA_IN2L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), | |
| 61 | +SOC_DOUBLE_R_RANGE_TLV("IN3 Volume", ARIZONA_IN3L_CONTROL, | |
| 62 | + ARIZONA_IN3R_CONTROL, | |
| 63 | + ARIZONA_IN3L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), | |
| 64 | + | |
| 65 | +SOC_DOUBLE_R("IN1 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_1L, | |
| 66 | + ARIZONA_ADC_DIGITAL_VOLUME_1R, ARIZONA_IN1L_MUTE_SHIFT, 1, 1), | |
| 67 | +SOC_DOUBLE_R("IN2 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_2L, | |
| 68 | + ARIZONA_ADC_DIGITAL_VOLUME_2R, ARIZONA_IN2L_MUTE_SHIFT, 1, 1), | |
| 69 | +SOC_DOUBLE_R("IN3 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_3L, | |
| 70 | + ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_MUTE_SHIFT, 1, 1), | |
| 71 | +SOC_DOUBLE_R("IN4 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_4L, | |
| 72 | + ARIZONA_ADC_DIGITAL_VOLUME_4R, ARIZONA_IN4L_MUTE_SHIFT, 1, 1), | |
| 73 | + | |
| 74 | +SOC_DOUBLE_R_TLV("IN1 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1L, | |
| 75 | + ARIZONA_ADC_DIGITAL_VOLUME_1R, ARIZONA_IN1L_DIG_VOL_SHIFT, | |
| 76 | + 0xbf, 0, digital_tlv), | |
| 77 | +SOC_DOUBLE_R_TLV("IN2 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_2L, | |
| 78 | + ARIZONA_ADC_DIGITAL_VOLUME_2R, ARIZONA_IN2L_DIG_VOL_SHIFT, | |
| 79 | + 0xbf, 0, digital_tlv), | |
| 80 | +SOC_DOUBLE_R_TLV("IN3 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_3L, | |
| 81 | + ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_DIG_VOL_SHIFT, | |
| 82 | + 0xbf, 0, digital_tlv), | |
| 83 | +SOC_DOUBLE_R_TLV("IN4 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_4L, | |
| 84 | + ARIZONA_ADC_DIGITAL_VOLUME_4R, ARIZONA_IN4L_DIG_VOL_SHIFT, | |
| 85 | + 0xbf, 0, digital_tlv), | |
| 86 | + | |
| 87 | +ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE), | |
| 88 | +ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), | |
| 89 | +ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), | |
| 90 | +ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), | |
| 91 | + | |
| 92 | +SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, | |
| 93 | + 24, 0, eq_tlv), | |
| 94 | +SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, | |
| 95 | + 24, 0, eq_tlv), | |
| 96 | +SOC_SINGLE_TLV("EQ1 B3 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B3_GAIN_SHIFT, | |
| 97 | + 24, 0, eq_tlv), | |
| 98 | +SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, | |
| 99 | + 24, 0, eq_tlv), | |
| 100 | +SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, | |
| 101 | + 24, 0, eq_tlv), | |
| 102 | + | |
| 103 | +SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, | |
| 104 | + 24, 0, eq_tlv), | |
| 105 | +SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, | |
| 106 | + 24, 0, eq_tlv), | |
| 107 | +SOC_SINGLE_TLV("EQ2 B3 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B3_GAIN_SHIFT, | |
| 108 | + 24, 0, eq_tlv), | |
| 109 | +SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, | |
| 110 | + 24, 0, eq_tlv), | |
| 111 | +SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, | |
| 112 | + 24, 0, eq_tlv), | |
| 113 | + | |
| 114 | +SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, | |
| 115 | + 24, 0, eq_tlv), | |
| 116 | +SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, | |
| 117 | + 24, 0, eq_tlv), | |
| 118 | +SOC_SINGLE_TLV("EQ3 B3 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B3_GAIN_SHIFT, | |
| 119 | + 24, 0, eq_tlv), | |
| 120 | +SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, | |
| 121 | + 24, 0, eq_tlv), | |
| 122 | +SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, | |
| 123 | + 24, 0, eq_tlv), | |
| 124 | + | |
| 125 | +SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, | |
| 126 | + 24, 0, eq_tlv), | |
| 127 | +SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, | |
| 128 | + 24, 0, eq_tlv), | |
| 129 | +SOC_SINGLE_TLV("EQ4 B3 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B3_GAIN_SHIFT, | |
| 130 | + 24, 0, eq_tlv), | |
| 131 | +SOC_SINGLE_TLV("EQ4 B4 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B4_GAIN_SHIFT, | |
| 132 | + 24, 0, eq_tlv), | |
| 133 | +SOC_SINGLE_TLV("EQ4 B5 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B5_GAIN_SHIFT, | |
| 134 | + 24, 0, eq_tlv), | |
| 135 | + | |
| 136 | +ARIZONA_MIXER_CONTROLS("DRC1L", ARIZONA_DRC1LMIX_INPUT_1_SOURCE), | |
| 137 | +ARIZONA_MIXER_CONTROLS("DRC1R", ARIZONA_DRC1RMIX_INPUT_1_SOURCE), | |
| 138 | +ARIZONA_MIXER_CONTROLS("DRC2L", ARIZONA_DRC2LMIX_INPUT_1_SOURCE), | |
| 139 | +ARIZONA_MIXER_CONTROLS("DRC2R", ARIZONA_DRC2RMIX_INPUT_1_SOURCE), | |
| 140 | + | |
| 141 | +SND_SOC_BYTES_MASK("DRC1", ARIZONA_DRC1_CTRL1, 5, | |
| 142 | + ARIZONA_DRC1R_ENA | ARIZONA_DRC1L_ENA), | |
| 143 | +SND_SOC_BYTES_MASK("DRC2", ARIZONA_DRC2_CTRL1, 5, | |
| 144 | + ARIZONA_DRC2R_ENA | ARIZONA_DRC2L_ENA), | |
| 145 | + | |
| 146 | +ARIZONA_MIXER_CONTROLS("LHPF1", ARIZONA_HPLP1MIX_INPUT_1_SOURCE), | |
| 147 | +ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE), | |
| 148 | +ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE), | |
| 149 | +ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE), | |
| 150 | + | |
| 151 | +SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode), | |
| 152 | +SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode), | |
| 153 | +SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode), | |
| 154 | +SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode), | |
| 155 | + | |
| 156 | +ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE), | |
| 157 | +ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE), | |
| 158 | + | |
| 159 | +SOC_SINGLE_TLV("Noise Generator Volume", ARIZONA_COMFORT_NOISE_GENERATOR, | |
| 160 | + ARIZONA_NOISE_GEN_GAIN_SHIFT, 0x16, 0, noise_tlv), | |
| 161 | + | |
| 162 | +ARIZONA_MIXER_CONTROLS("HPOUT1L", ARIZONA_OUT1LMIX_INPUT_1_SOURCE), | |
| 163 | +ARIZONA_MIXER_CONTROLS("HPOUT1R", ARIZONA_OUT1RMIX_INPUT_1_SOURCE), | |
| 164 | +ARIZONA_MIXER_CONTROLS("HPOUT2L", ARIZONA_OUT2LMIX_INPUT_1_SOURCE), | |
| 165 | +ARIZONA_MIXER_CONTROLS("HPOUT2R", ARIZONA_OUT2RMIX_INPUT_1_SOURCE), | |
| 166 | +ARIZONA_MIXER_CONTROLS("EPOUT", ARIZONA_OUT3LMIX_INPUT_1_SOURCE), | |
| 167 | +ARIZONA_MIXER_CONTROLS("SPKOUTL", ARIZONA_OUT4LMIX_INPUT_1_SOURCE), | |
| 168 | +ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE), | |
| 169 | +ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE), | |
| 170 | +ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE), | |
| 171 | +ARIZONA_MIXER_CONTROLS("SPKDAT2L", ARIZONA_OUT6LMIX_INPUT_1_SOURCE), | |
| 172 | +ARIZONA_MIXER_CONTROLS("SPKDAT2R", ARIZONA_OUT6RMIX_INPUT_1_SOURCE), | |
| 173 | + | |
| 174 | +SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L, | |
| 175 | + ARIZONA_OUT1_OSR_SHIFT, 1, 0), | |
| 176 | +SOC_SINGLE("OUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L, | |
| 177 | + ARIZONA_OUT2_OSR_SHIFT, 1, 0), | |
| 178 | +SOC_SINGLE("EPOUT High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L, | |
| 179 | + ARIZONA_OUT3_OSR_SHIFT, 1, 0), | |
| 180 | +SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L, | |
| 181 | + ARIZONA_OUT4_OSR_SHIFT, 1, 0), | |
| 182 | +SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L, | |
| 183 | + ARIZONA_OUT5_OSR_SHIFT, 1, 0), | |
| 184 | +SOC_SINGLE("SPKDAT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_6L, | |
| 185 | + ARIZONA_OUT6_OSR_SHIFT, 1, 0), | |
| 186 | + | |
| 187 | +SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L, | |
| 188 | + ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1), | |
| 189 | +SOC_DOUBLE_R("OUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L, | |
| 190 | + ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_MUTE_SHIFT, 1, 1), | |
| 191 | +SOC_SINGLE("EPOUT Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_3L, | |
| 192 | + ARIZONA_OUT3L_MUTE_SHIFT, 1, 1), | |
| 193 | +SOC_DOUBLE_R("Speaker Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_4L, | |
| 194 | + ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_MUTE_SHIFT, 1, 1), | |
| 195 | +SOC_DOUBLE_R("SPKDAT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_5L, | |
| 196 | + ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_MUTE_SHIFT, 1, 1), | |
| 197 | +SOC_DOUBLE_R("SPKDAT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_6L, | |
| 198 | + ARIZONA_DAC_DIGITAL_VOLUME_6R, ARIZONA_OUT6L_MUTE_SHIFT, 1, 1), | |
| 199 | + | |
| 200 | +SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_1L, | |
| 201 | + ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_VOL_SHIFT, | |
| 202 | + 0xbf, 0, digital_tlv), | |
| 203 | +SOC_DOUBLE_R_TLV("OUT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_2L, | |
| 204 | + ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_VOL_SHIFT, | |
| 205 | + 0xbf, 0, digital_tlv), | |
| 206 | +SOC_SINGLE_TLV("EPOUT Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_3L, | |
| 207 | + ARIZONA_OUT3L_VOL_SHIFT, 0xbf, 0, digital_tlv), | |
| 208 | +SOC_DOUBLE_R_TLV("Speaker Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_4L, | |
| 209 | + ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_VOL_SHIFT, | |
| 210 | + 0xbf, 0, digital_tlv), | |
| 211 | +SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L, | |
| 212 | + ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT, | |
| 213 | + 0xbf, 0, digital_tlv), | |
| 214 | +SOC_DOUBLE_R_TLV("SPKDAT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_6L, | |
| 215 | + ARIZONA_DAC_DIGITAL_VOLUME_6R, ARIZONA_OUT6L_VOL_SHIFT, | |
| 216 | + 0xbf, 0, digital_tlv), | |
| 217 | + | |
| 218 | +SOC_DOUBLE_R_RANGE_TLV("HPOUT1 Volume", ARIZONA_OUTPUT_PATH_CONFIG_1L, | |
| 219 | + ARIZONA_OUTPUT_PATH_CONFIG_1R, | |
| 220 | + ARIZONA_OUT1L_PGA_VOL_SHIFT, | |
| 221 | + 0x34, 0x40, 0, ana_tlv), | |
| 222 | +SOC_DOUBLE_R_RANGE_TLV("OUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L, | |
| 223 | + ARIZONA_OUTPUT_PATH_CONFIG_2R, | |
| 224 | + ARIZONA_OUT2L_PGA_VOL_SHIFT, | |
| 225 | + 0x34, 0x40, 0, ana_tlv), | |
| 226 | +SOC_SINGLE_RANGE_TLV("EPOUT Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L, | |
| 227 | + ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv), | |
| 228 | + | |
| 229 | +SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT, | |
| 230 | + ARIZONA_SPK1R_MUTE_SHIFT, 1, 1), | |
| 231 | +SOC_DOUBLE("SPKDAT2 Switch", ARIZONA_PDM_SPK2_CTRL_1, ARIZONA_SPK2L_MUTE_SHIFT, | |
| 232 | + ARIZONA_SPK2R_MUTE_SHIFT, 1, 1), | |
| 233 | + | |
| 234 | +ARIZONA_MIXER_CONTROLS("AIF1TX1", ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE), | |
| 235 | +ARIZONA_MIXER_CONTROLS("AIF1TX2", ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE), | |
| 236 | +ARIZONA_MIXER_CONTROLS("AIF1TX3", ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE), | |
| 237 | +ARIZONA_MIXER_CONTROLS("AIF1TX4", ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE), | |
| 238 | +ARIZONA_MIXER_CONTROLS("AIF1TX5", ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE), | |
| 239 | +ARIZONA_MIXER_CONTROLS("AIF1TX6", ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE), | |
| 240 | +ARIZONA_MIXER_CONTROLS("AIF1TX7", ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE), | |
| 241 | +ARIZONA_MIXER_CONTROLS("AIF1TX8", ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE), | |
| 242 | + | |
| 243 | +ARIZONA_MIXER_CONTROLS("AIF2TX1", ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE), | |
| 244 | +ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE), | |
| 245 | + | |
| 246 | +ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), | |
| 247 | +ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), | |
| 248 | +}; | |
| 249 | + | |
| 250 | +ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); | |
| 251 | +ARIZONA_MIXER_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE); | |
| 252 | +ARIZONA_MIXER_ENUMS(EQ3, ARIZONA_EQ3MIX_INPUT_1_SOURCE); | |
| 253 | +ARIZONA_MIXER_ENUMS(EQ4, ARIZONA_EQ4MIX_INPUT_1_SOURCE); | |
| 254 | + | |
| 255 | +ARIZONA_MIXER_ENUMS(DRC1L, ARIZONA_DRC1LMIX_INPUT_1_SOURCE); | |
| 256 | +ARIZONA_MIXER_ENUMS(DRC1R, ARIZONA_DRC1RMIX_INPUT_1_SOURCE); | |
| 257 | +ARIZONA_MIXER_ENUMS(DRC2L, ARIZONA_DRC2LMIX_INPUT_1_SOURCE); | |
| 258 | +ARIZONA_MIXER_ENUMS(DRC2R, ARIZONA_DRC2RMIX_INPUT_1_SOURCE); | |
| 259 | + | |
| 260 | +ARIZONA_MIXER_ENUMS(LHPF1, ARIZONA_HPLP1MIX_INPUT_1_SOURCE); | |
| 261 | +ARIZONA_MIXER_ENUMS(LHPF2, ARIZONA_HPLP2MIX_INPUT_1_SOURCE); | |
| 262 | +ARIZONA_MIXER_ENUMS(LHPF3, ARIZONA_HPLP3MIX_INPUT_1_SOURCE); | |
| 263 | +ARIZONA_MIXER_ENUMS(LHPF4, ARIZONA_HPLP4MIX_INPUT_1_SOURCE); | |
| 264 | + | |
| 265 | +ARIZONA_MIXER_ENUMS(Mic, ARIZONA_MICMIX_INPUT_1_SOURCE); | |
| 266 | +ARIZONA_MIXER_ENUMS(Noise, ARIZONA_NOISEMIX_INPUT_1_SOURCE); | |
| 267 | + | |
| 268 | +ARIZONA_MIXER_ENUMS(PWM1, ARIZONA_PWM1MIX_INPUT_1_SOURCE); | |
| 269 | +ARIZONA_MIXER_ENUMS(PWM2, ARIZONA_PWM2MIX_INPUT_1_SOURCE); | |
| 270 | + | |
| 271 | +ARIZONA_MIXER_ENUMS(OUT1L, ARIZONA_OUT1LMIX_INPUT_1_SOURCE); | |
| 272 | +ARIZONA_MIXER_ENUMS(OUT1R, ARIZONA_OUT1RMIX_INPUT_1_SOURCE); | |
| 273 | +ARIZONA_MIXER_ENUMS(OUT2L, ARIZONA_OUT2LMIX_INPUT_1_SOURCE); | |
| 274 | +ARIZONA_MIXER_ENUMS(OUT2R, ARIZONA_OUT2RMIX_INPUT_1_SOURCE); | |
| 275 | +ARIZONA_MIXER_ENUMS(OUT3, ARIZONA_OUT3LMIX_INPUT_1_SOURCE); | |
| 276 | +ARIZONA_MIXER_ENUMS(SPKOUTL, ARIZONA_OUT4LMIX_INPUT_1_SOURCE); | |
| 277 | +ARIZONA_MIXER_ENUMS(SPKOUTR, ARIZONA_OUT4RMIX_INPUT_1_SOURCE); | |
| 278 | +ARIZONA_MIXER_ENUMS(SPKDAT1L, ARIZONA_OUT5LMIX_INPUT_1_SOURCE); | |
| 279 | +ARIZONA_MIXER_ENUMS(SPKDAT1R, ARIZONA_OUT5RMIX_INPUT_1_SOURCE); | |
| 280 | +ARIZONA_MIXER_ENUMS(SPKDAT2L, ARIZONA_OUT6LMIX_INPUT_1_SOURCE); | |
| 281 | +ARIZONA_MIXER_ENUMS(SPKDAT2R, ARIZONA_OUT6RMIX_INPUT_1_SOURCE); | |
| 282 | + | |
| 283 | +ARIZONA_MIXER_ENUMS(AIF1TX1, ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE); | |
| 284 | +ARIZONA_MIXER_ENUMS(AIF1TX2, ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE); | |
| 285 | +ARIZONA_MIXER_ENUMS(AIF1TX3, ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE); | |
| 286 | +ARIZONA_MIXER_ENUMS(AIF1TX4, ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE); | |
| 287 | +ARIZONA_MIXER_ENUMS(AIF1TX5, ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE); | |
| 288 | +ARIZONA_MIXER_ENUMS(AIF1TX6, ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE); | |
| 289 | +ARIZONA_MIXER_ENUMS(AIF1TX7, ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE); | |
| 290 | +ARIZONA_MIXER_ENUMS(AIF1TX8, ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE); | |
| 291 | + | |
| 292 | +ARIZONA_MIXER_ENUMS(AIF2TX1, ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE); | |
| 293 | +ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE); | |
| 294 | + | |
| 295 | +ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); | |
| 296 | +ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); | |
| 297 | + | |
| 298 | +ARIZONA_MIXER_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE); | |
| 299 | +ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); | |
| 300 | +ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); | |
| 301 | +ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); | |
| 302 | + | |
| 303 | +static const struct snd_soc_dapm_widget wm5110_dapm_widgets[] = { | |
| 304 | +SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, | |
| 305 | + 0, NULL, 0), | |
| 306 | +SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, | |
| 307 | + ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), | |
| 308 | + | |
| 309 | +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), | |
| 310 | +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), | |
| 311 | +SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), | |
| 312 | +SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0), | |
| 313 | +SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0), | |
| 314 | +SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0), | |
| 315 | + | |
| 316 | +SND_SOC_DAPM_SIGGEN("TONE"), | |
| 317 | +SND_SOC_DAPM_SIGGEN("NOISE"), | |
| 318 | + | |
| 319 | +SND_SOC_DAPM_INPUT("IN1L"), | |
| 320 | +SND_SOC_DAPM_INPUT("IN1R"), | |
| 321 | +SND_SOC_DAPM_INPUT("IN2L"), | |
| 322 | +SND_SOC_DAPM_INPUT("IN2R"), | |
| 323 | +SND_SOC_DAPM_INPUT("IN3L"), | |
| 324 | +SND_SOC_DAPM_INPUT("IN3R"), | |
| 325 | +SND_SOC_DAPM_INPUT("IN4L"), | |
| 326 | +SND_SOC_DAPM_INPUT("IN4R"), | |
| 327 | + | |
| 328 | +SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT, | |
| 329 | + 0, NULL, 0, arizona_in_ev, | |
| 330 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 331 | +SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT, | |
| 332 | + 0, NULL, 0, arizona_in_ev, | |
| 333 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 334 | +SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT, | |
| 335 | + 0, NULL, 0, arizona_in_ev, | |
| 336 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 337 | +SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT, | |
| 338 | + 0, NULL, 0, arizona_in_ev, | |
| 339 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 340 | +SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT, | |
| 341 | + 0, NULL, 0, arizona_in_ev, | |
| 342 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 343 | +SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT, | |
| 344 | + 0, NULL, 0, arizona_in_ev, | |
| 345 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 346 | +SND_SOC_DAPM_PGA_E("IN4L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4L_ENA_SHIFT, | |
| 347 | + 0, NULL, 0, arizona_in_ev, | |
| 348 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 349 | +SND_SOC_DAPM_PGA_E("IN4R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4R_ENA_SHIFT, | |
| 350 | + 0, NULL, 0, arizona_in_ev, | |
| 351 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 352 | + | |
| 353 | +SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1, | |
| 354 | + ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), | |
| 355 | +SND_SOC_DAPM_SUPPLY("MICBIAS2", ARIZONA_MIC_BIAS_CTRL_2, | |
| 356 | + ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), | |
| 357 | +SND_SOC_DAPM_SUPPLY("MICBIAS3", ARIZONA_MIC_BIAS_CTRL_3, | |
| 358 | + ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), | |
| 359 | + | |
| 360 | +SND_SOC_DAPM_PGA("Noise Generator", ARIZONA_COMFORT_NOISE_GENERATOR, | |
| 361 | + ARIZONA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0), | |
| 362 | + | |
| 363 | +SND_SOC_DAPM_PGA("Tone Generator 1", ARIZONA_TONE_GENERATOR_1, | |
| 364 | + ARIZONA_TONE1_ENA_SHIFT, 0, NULL, 0), | |
| 365 | +SND_SOC_DAPM_PGA("Tone Generator 2", ARIZONA_TONE_GENERATOR_1, | |
| 366 | + ARIZONA_TONE2_ENA_SHIFT, 0, NULL, 0), | |
| 367 | + | |
| 368 | +SND_SOC_DAPM_PGA("Mic Mute Mixer", ARIZONA_MIC_NOISE_MIX_CONTROL_1, | |
| 369 | + ARIZONA_MICMUTE_MIX_ENA_SHIFT, 0, NULL, 0), | |
| 370 | + | |
| 371 | +SND_SOC_DAPM_PGA("EQ1", ARIZONA_EQ1_1, ARIZONA_EQ1_ENA_SHIFT, 0, NULL, 0), | |
| 372 | +SND_SOC_DAPM_PGA("EQ2", ARIZONA_EQ2_1, ARIZONA_EQ2_ENA_SHIFT, 0, NULL, 0), | |
| 373 | +SND_SOC_DAPM_PGA("EQ3", ARIZONA_EQ3_1, ARIZONA_EQ3_ENA_SHIFT, 0, NULL, 0), | |
| 374 | +SND_SOC_DAPM_PGA("EQ4", ARIZONA_EQ4_1, ARIZONA_EQ4_ENA_SHIFT, 0, NULL, 0), | |
| 375 | + | |
| 376 | +SND_SOC_DAPM_PGA("DRC1L", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1L_ENA_SHIFT, 0, | |
| 377 | + NULL, 0), | |
| 378 | +SND_SOC_DAPM_PGA("DRC1R", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1R_ENA_SHIFT, 0, | |
| 379 | + NULL, 0), | |
| 380 | +SND_SOC_DAPM_PGA("DRC2L", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2L_ENA_SHIFT, 0, | |
| 381 | + NULL, 0), | |
| 382 | +SND_SOC_DAPM_PGA("DRC2R", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2R_ENA_SHIFT, 0, | |
| 383 | + NULL, 0), | |
| 384 | + | |
| 385 | +SND_SOC_DAPM_PGA("LHPF1", ARIZONA_HPLPF1_1, ARIZONA_LHPF1_ENA_SHIFT, 0, | |
| 386 | + NULL, 0), | |
| 387 | +SND_SOC_DAPM_PGA("LHPF2", ARIZONA_HPLPF2_1, ARIZONA_LHPF2_ENA_SHIFT, 0, | |
| 388 | + NULL, 0), | |
| 389 | +SND_SOC_DAPM_PGA("LHPF3", ARIZONA_HPLPF3_1, ARIZONA_LHPF3_ENA_SHIFT, 0, | |
| 390 | + NULL, 0), | |
| 391 | +SND_SOC_DAPM_PGA("LHPF4", ARIZONA_HPLPF4_1, ARIZONA_LHPF4_ENA_SHIFT, 0, | |
| 392 | + NULL, 0), | |
| 393 | + | |
| 394 | +SND_SOC_DAPM_PGA("PWM1 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM1_ENA_SHIFT, | |
| 395 | + 0, NULL, 0), | |
| 396 | +SND_SOC_DAPM_PGA("PWM2 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM2_ENA_SHIFT, | |
| 397 | + 0, NULL, 0), | |
| 398 | + | |
| 399 | +SND_SOC_DAPM_PGA("ASRC1L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC1L_ENA_SHIFT, 0, | |
| 400 | + NULL, 0), | |
| 401 | +SND_SOC_DAPM_PGA("ASRC1R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC1R_ENA_SHIFT, 0, | |
| 402 | + NULL, 0), | |
| 403 | +SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0, | |
| 404 | + NULL, 0), | |
| 405 | +SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0, | |
| 406 | + NULL, 0), | |
| 407 | + | |
| 408 | +SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, | |
| 409 | + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0), | |
| 410 | +SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, | |
| 411 | + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX2_ENA_SHIFT, 0), | |
| 412 | +SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, | |
| 413 | + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX3_ENA_SHIFT, 0), | |
| 414 | +SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, | |
| 415 | + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX4_ENA_SHIFT, 0), | |
| 416 | +SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, | |
| 417 | + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX5_ENA_SHIFT, 0), | |
| 418 | +SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, | |
| 419 | + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX6_ENA_SHIFT, 0), | |
| 420 | +SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0, | |
| 421 | + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX7_ENA_SHIFT, 0), | |
| 422 | +SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0, | |
| 423 | + ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX8_ENA_SHIFT, 0), | |
| 424 | + | |
| 425 | +SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, | |
| 426 | + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX1_ENA_SHIFT, 0), | |
| 427 | +SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, | |
| 428 | + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX2_ENA_SHIFT, 0), | |
| 429 | +SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, | |
| 430 | + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX3_ENA_SHIFT, 0), | |
| 431 | +SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, | |
| 432 | + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX4_ENA_SHIFT, 0), | |
| 433 | +SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, | |
| 434 | + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX5_ENA_SHIFT, 0), | |
| 435 | +SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, | |
| 436 | + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX6_ENA_SHIFT, 0), | |
| 437 | +SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0, | |
| 438 | + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX7_ENA_SHIFT, 0), | |
| 439 | +SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0, | |
| 440 | + ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX8_ENA_SHIFT, 0), | |
| 441 | + | |
| 442 | +SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, | |
| 443 | + ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX1_ENA_SHIFT, 0), | |
| 444 | +SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, | |
| 445 | + ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX2_ENA_SHIFT, 0), | |
| 446 | + | |
| 447 | +SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, | |
| 448 | + ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX1_ENA_SHIFT, 0), | |
| 449 | +SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, | |
| 450 | + ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0), | |
| 451 | + | |
| 452 | +SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, | |
| 453 | + ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX1_ENA_SHIFT, 0), | |
| 454 | +SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, | |
| 455 | + ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX2_ENA_SHIFT, 0), | |
| 456 | + | |
| 457 | +SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, | |
| 458 | + ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX1_ENA_SHIFT, 0), | |
| 459 | +SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, | |
| 460 | + ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0), | |
| 461 | + | |
| 462 | +SND_SOC_DAPM_PGA_E("OUT1L", ARIZONA_OUTPUT_ENABLES_1, | |
| 463 | + ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | |
| 464 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 465 | +SND_SOC_DAPM_PGA_E("OUT1R", ARIZONA_OUTPUT_ENABLES_1, | |
| 466 | + ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | |
| 467 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 468 | +SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1, | |
| 469 | + ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | |
| 470 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 471 | +SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1, | |
| 472 | + ARIZONA_OUT2R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | |
| 473 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 474 | +SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, | |
| 475 | + ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | |
| 476 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 477 | +SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1, | |
| 478 | + ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | |
| 479 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 480 | +SND_SOC_DAPM_PGA_E("OUT4R", ARIZONA_OUTPUT_ENABLES_1, | |
| 481 | + ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | |
| 482 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 483 | +SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1, | |
| 484 | + ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | |
| 485 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 486 | +SND_SOC_DAPM_PGA_E("OUT5R", ARIZONA_OUTPUT_ENABLES_1, | |
| 487 | + ARIZONA_OUT5R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | |
| 488 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 489 | +SND_SOC_DAPM_PGA_E("OUT6L", ARIZONA_OUTPUT_ENABLES_1, | |
| 490 | + ARIZONA_OUT6L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | |
| 491 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 492 | +SND_SOC_DAPM_PGA_E("OUT6R", ARIZONA_OUTPUT_ENABLES_1, | |
| 493 | + ARIZONA_OUT6R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | |
| 494 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
| 495 | + | |
| 496 | +ARIZONA_MIXER_WIDGETS(EQ1, "EQ1"), | |
| 497 | +ARIZONA_MIXER_WIDGETS(EQ2, "EQ2"), | |
| 498 | +ARIZONA_MIXER_WIDGETS(EQ3, "EQ3"), | |
| 499 | +ARIZONA_MIXER_WIDGETS(EQ4, "EQ4"), | |
| 500 | + | |
| 501 | +ARIZONA_MIXER_WIDGETS(DRC1L, "DRC1L"), | |
| 502 | +ARIZONA_MIXER_WIDGETS(DRC1R, "DRC1R"), | |
| 503 | +ARIZONA_MIXER_WIDGETS(DRC2L, "DRC2L"), | |
| 504 | +ARIZONA_MIXER_WIDGETS(DRC2R, "DRC2R"), | |
| 505 | + | |
| 506 | +ARIZONA_MIXER_WIDGETS(LHPF1, "LHPF1"), | |
| 507 | +ARIZONA_MIXER_WIDGETS(LHPF2, "LHPF2"), | |
| 508 | +ARIZONA_MIXER_WIDGETS(LHPF3, "LHPF3"), | |
| 509 | +ARIZONA_MIXER_WIDGETS(LHPF4, "LHPF4"), | |
| 510 | + | |
| 511 | +ARIZONA_MIXER_WIDGETS(Mic, "Mic"), | |
| 512 | +ARIZONA_MIXER_WIDGETS(Noise, "Noise"), | |
| 513 | + | |
| 514 | +ARIZONA_MIXER_WIDGETS(PWM1, "PWM1"), | |
| 515 | +ARIZONA_MIXER_WIDGETS(PWM2, "PWM2"), | |
| 516 | + | |
| 517 | +ARIZONA_MIXER_WIDGETS(OUT1L, "HPOUT1L"), | |
| 518 | +ARIZONA_MIXER_WIDGETS(OUT1R, "HPOUT1R"), | |
| 519 | +ARIZONA_MIXER_WIDGETS(OUT2L, "HPOUT2L"), | |
| 520 | +ARIZONA_MIXER_WIDGETS(OUT2R, "HPOUT2R"), | |
| 521 | +ARIZONA_MIXER_WIDGETS(OUT3, "EPOUT"), | |
| 522 | +ARIZONA_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"), | |
| 523 | +ARIZONA_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"), | |
| 524 | +ARIZONA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"), | |
| 525 | +ARIZONA_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"), | |
| 526 | +ARIZONA_MIXER_WIDGETS(SPKDAT2L, "SPKDAT2L"), | |
| 527 | +ARIZONA_MIXER_WIDGETS(SPKDAT2R, "SPKDAT2R"), | |
| 528 | + | |
| 529 | +ARIZONA_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"), | |
| 530 | +ARIZONA_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"), | |
| 531 | +ARIZONA_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"), | |
| 532 | +ARIZONA_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"), | |
| 533 | +ARIZONA_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"), | |
| 534 | +ARIZONA_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"), | |
| 535 | +ARIZONA_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"), | |
| 536 | +ARIZONA_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"), | |
| 537 | + | |
| 538 | +ARIZONA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"), | |
| 539 | +ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), | |
| 540 | + | |
| 541 | +ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), | |
| 542 | +ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), | |
| 543 | + | |
| 544 | +ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"), | |
| 545 | +ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"), | |
| 546 | +ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"), | |
| 547 | +ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"), | |
| 548 | + | |
| 549 | +SND_SOC_DAPM_OUTPUT("HPOUT1L"), | |
| 550 | +SND_SOC_DAPM_OUTPUT("HPOUT1R"), | |
| 551 | +SND_SOC_DAPM_OUTPUT("HPOUT2L"), | |
| 552 | +SND_SOC_DAPM_OUTPUT("HPOUT2R"), | |
| 553 | +SND_SOC_DAPM_OUTPUT("EPOUTN"), | |
| 554 | +SND_SOC_DAPM_OUTPUT("EPOUTP"), | |
| 555 | +SND_SOC_DAPM_OUTPUT("SPKOUTLN"), | |
| 556 | +SND_SOC_DAPM_OUTPUT("SPKOUTLP"), | |
| 557 | +SND_SOC_DAPM_OUTPUT("SPKOUTRN"), | |
| 558 | +SND_SOC_DAPM_OUTPUT("SPKOUTRP"), | |
| 559 | +SND_SOC_DAPM_OUTPUT("SPKDAT1L"), | |
| 560 | +SND_SOC_DAPM_OUTPUT("SPKDAT1R"), | |
| 561 | +SND_SOC_DAPM_OUTPUT("SPKDAT2L"), | |
| 562 | +SND_SOC_DAPM_OUTPUT("SPKDAT2R"), | |
| 563 | +}; | |
| 564 | + | |
| 565 | +#define ARIZONA_MIXER_INPUT_ROUTES(name) \ | |
| 566 | + { name, "Noise Generator", "Noise Generator" }, \ | |
| 567 | + { name, "Tone Generator 1", "Tone Generator 1" }, \ | |
| 568 | + { name, "Tone Generator 2", "Tone Generator 2" }, \ | |
| 569 | + { name, "IN1L", "IN1L PGA" }, \ | |
| 570 | + { name, "IN1R", "IN1R PGA" }, \ | |
| 571 | + { name, "IN2L", "IN2L PGA" }, \ | |
| 572 | + { name, "IN2R", "IN2R PGA" }, \ | |
| 573 | + { name, "IN3L", "IN3L PGA" }, \ | |
| 574 | + { name, "IN3R", "IN3R PGA" }, \ | |
| 575 | + { name, "IN4L", "IN4L PGA" }, \ | |
| 576 | + { name, "IN4R", "IN4R PGA" }, \ | |
| 577 | + { name, "Mic Mute Mixer", "Mic Mute Mixer" }, \ | |
| 578 | + { name, "AIF1RX1", "AIF1RX1" }, \ | |
| 579 | + { name, "AIF1RX2", "AIF1RX2" }, \ | |
| 580 | + { name, "AIF1RX3", "AIF1RX3" }, \ | |
| 581 | + { name, "AIF1RX4", "AIF1RX4" }, \ | |
| 582 | + { name, "AIF1RX5", "AIF1RX5" }, \ | |
| 583 | + { name, "AIF1RX6", "AIF1RX6" }, \ | |
| 584 | + { name, "AIF1RX7", "AIF1RX7" }, \ | |
| 585 | + { name, "AIF1RX8", "AIF1RX8" }, \ | |
| 586 | + { name, "AIF2RX1", "AIF2RX1" }, \ | |
| 587 | + { name, "AIF2RX2", "AIF2RX2" }, \ | |
| 588 | + { name, "AIF3RX1", "AIF3RX1" }, \ | |
| 589 | + { name, "AIF3RX2", "AIF3RX2" }, \ | |
| 590 | + { name, "EQ1", "EQ1" }, \ | |
| 591 | + { name, "EQ2", "EQ2" }, \ | |
| 592 | + { name, "EQ3", "EQ3" }, \ | |
| 593 | + { name, "EQ4", "EQ4" }, \ | |
| 594 | + { name, "DRC1L", "DRC1L" }, \ | |
| 595 | + { name, "DRC1R", "DRC1R" }, \ | |
| 596 | + { name, "DRC2L", "DRC2L" }, \ | |
| 597 | + { name, "DRC2R", "DRC2R" }, \ | |
| 598 | + { name, "LHPF1", "LHPF1" }, \ | |
| 599 | + { name, "LHPF2", "LHPF2" }, \ | |
| 600 | + { name, "LHPF3", "LHPF3" }, \ | |
| 601 | + { name, "LHPF4", "LHPF4" }, \ | |
| 602 | + { name, "ASRC1L", "ASRC1L" }, \ | |
| 603 | + { name, "ASRC1R", "ASRC1R" }, \ | |
| 604 | + { name, "ASRC2L", "ASRC2L" }, \ | |
| 605 | + { name, "ASRC2R", "ASRC2R" } | |
| 606 | + | |
| 607 | +static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | |
| 608 | + { "AIF2 Capture", NULL, "DBVDD2" }, | |
| 609 | + { "AIF2 Playback", NULL, "DBVDD2" }, | |
| 610 | + | |
| 611 | + { "AIF3 Capture", NULL, "DBVDD3" }, | |
| 612 | + { "AIF3 Playback", NULL, "DBVDD3" }, | |
| 613 | + | |
| 614 | + { "OUT1L", NULL, "CPVDD" }, | |
| 615 | + { "OUT1R", NULL, "CPVDD" }, | |
| 616 | + { "OUT2L", NULL, "CPVDD" }, | |
| 617 | + { "OUT2R", NULL, "CPVDD" }, | |
| 618 | + { "OUT3L", NULL, "CPVDD" }, | |
| 619 | + | |
| 620 | + { "OUT4L", NULL, "SPKVDDL" }, | |
| 621 | + { "OUT4R", NULL, "SPKVDDR" }, | |
| 622 | + | |
| 623 | + { "OUT1L", NULL, "SYSCLK" }, | |
| 624 | + { "OUT1R", NULL, "SYSCLK" }, | |
| 625 | + { "OUT2L", NULL, "SYSCLK" }, | |
| 626 | + { "OUT2R", NULL, "SYSCLK" }, | |
| 627 | + { "OUT3L", NULL, "SYSCLK" }, | |
| 628 | + { "OUT4L", NULL, "SYSCLK" }, | |
| 629 | + { "OUT4R", NULL, "SYSCLK" }, | |
| 630 | + { "OUT5L", NULL, "SYSCLK" }, | |
| 631 | + { "OUT5R", NULL, "SYSCLK" }, | |
| 632 | + { "OUT6L", NULL, "SYSCLK" }, | |
| 633 | + { "OUT6R", NULL, "SYSCLK" }, | |
| 634 | + | |
| 635 | + { "MICBIAS1", NULL, "MICVDD" }, | |
| 636 | + { "MICBIAS2", NULL, "MICVDD" }, | |
| 637 | + { "MICBIAS3", NULL, "MICVDD" }, | |
| 638 | + | |
| 639 | + { "Noise Generator", NULL, "NOISE" }, | |
| 640 | + { "Tone Generator 1", NULL, "TONE" }, | |
| 641 | + { "Tone Generator 2", NULL, "TONE" }, | |
| 642 | + | |
| 643 | + { "Mic Mute Mixer", NULL, "Noise Mixer" }, | |
| 644 | + { "Mic Mute Mixer", NULL, "Mic Mixer" }, | |
| 645 | + | |
| 646 | + { "AIF1 Capture", NULL, "AIF1TX1" }, | |
| 647 | + { "AIF1 Capture", NULL, "AIF1TX2" }, | |
| 648 | + { "AIF1 Capture", NULL, "AIF1TX3" }, | |
| 649 | + { "AIF1 Capture", NULL, "AIF1TX4" }, | |
| 650 | + { "AIF1 Capture", NULL, "AIF1TX5" }, | |
| 651 | + { "AIF1 Capture", NULL, "AIF1TX6" }, | |
| 652 | + { "AIF1 Capture", NULL, "AIF1TX7" }, | |
| 653 | + { "AIF1 Capture", NULL, "AIF1TX8" }, | |
| 654 | + | |
| 655 | + { "AIF1RX1", NULL, "AIF1 Playback" }, | |
| 656 | + { "AIF1RX2", NULL, "AIF1 Playback" }, | |
| 657 | + { "AIF1RX3", NULL, "AIF1 Playback" }, | |
| 658 | + { "AIF1RX4", NULL, "AIF1 Playback" }, | |
| 659 | + { "AIF1RX5", NULL, "AIF1 Playback" }, | |
| 660 | + { "AIF1RX6", NULL, "AIF1 Playback" }, | |
| 661 | + { "AIF1RX7", NULL, "AIF1 Playback" }, | |
| 662 | + { "AIF1RX8", NULL, "AIF1 Playback" }, | |
| 663 | + | |
| 664 | + { "AIF2 Capture", NULL, "AIF2TX1" }, | |
| 665 | + { "AIF2 Capture", NULL, "AIF2TX2" }, | |
| 666 | + | |
| 667 | + { "AIF2RX1", NULL, "AIF2 Playback" }, | |
| 668 | + { "AIF2RX2", NULL, "AIF2 Playback" }, | |
| 669 | + | |
| 670 | + { "AIF3 Capture", NULL, "AIF3TX1" }, | |
| 671 | + { "AIF3 Capture", NULL, "AIF3TX2" }, | |
| 672 | + | |
| 673 | + { "AIF3RX1", NULL, "AIF3 Playback" }, | |
| 674 | + { "AIF3RX2", NULL, "AIF3 Playback" }, | |
| 675 | + | |
| 676 | + { "AIF1 Playback", NULL, "SYSCLK" }, | |
| 677 | + { "AIF2 Playback", NULL, "SYSCLK" }, | |
| 678 | + { "AIF3 Playback", NULL, "SYSCLK" }, | |
| 679 | + | |
| 680 | + { "AIF1 Capture", NULL, "SYSCLK" }, | |
| 681 | + { "AIF2 Capture", NULL, "SYSCLK" }, | |
| 682 | + { "AIF3 Capture", NULL, "SYSCLK" }, | |
| 683 | + | |
| 684 | + ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"), | |
| 685 | + ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"), | |
| 686 | + ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"), | |
| 687 | + ARIZONA_MIXER_ROUTES("OUT2R", "HPOUT2R"), | |
| 688 | + ARIZONA_MIXER_ROUTES("OUT3L", "EPOUT"), | |
| 689 | + | |
| 690 | + ARIZONA_MIXER_ROUTES("OUT4L", "SPKOUTL"), | |
| 691 | + ARIZONA_MIXER_ROUTES("OUT4R", "SPKOUTR"), | |
| 692 | + ARIZONA_MIXER_ROUTES("OUT5L", "SPKDAT1L"), | |
| 693 | + ARIZONA_MIXER_ROUTES("OUT5R", "SPKDAT1R"), | |
| 694 | + ARIZONA_MIXER_ROUTES("OUT6L", "SPKDAT2L"), | |
| 695 | + ARIZONA_MIXER_ROUTES("OUT6R", "SPKDAT2R"), | |
| 696 | + | |
| 697 | + ARIZONA_MIXER_ROUTES("PWM1 Driver", "PWM1"), | |
| 698 | + ARIZONA_MIXER_ROUTES("PWM2 Driver", "PWM2"), | |
| 699 | + | |
| 700 | + ARIZONA_MIXER_ROUTES("AIF1TX1", "AIF1TX1"), | |
| 701 | + ARIZONA_MIXER_ROUTES("AIF1TX2", "AIF1TX2"), | |
| 702 | + ARIZONA_MIXER_ROUTES("AIF1TX3", "AIF1TX3"), | |
| 703 | + ARIZONA_MIXER_ROUTES("AIF1TX4", "AIF1TX4"), | |
| 704 | + ARIZONA_MIXER_ROUTES("AIF1TX5", "AIF1TX5"), | |
| 705 | + ARIZONA_MIXER_ROUTES("AIF1TX6", "AIF1TX6"), | |
| 706 | + ARIZONA_MIXER_ROUTES("AIF1TX7", "AIF1TX7"), | |
| 707 | + ARIZONA_MIXER_ROUTES("AIF1TX8", "AIF1TX8"), | |
| 708 | + | |
| 709 | + ARIZONA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"), | |
| 710 | + ARIZONA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"), | |
| 711 | + | |
| 712 | + ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), | |
| 713 | + ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), | |
| 714 | + | |
| 715 | + ARIZONA_MIXER_ROUTES("EQ1", "EQ1"), | |
| 716 | + ARIZONA_MIXER_ROUTES("EQ2", "EQ2"), | |
| 717 | + ARIZONA_MIXER_ROUTES("EQ3", "EQ3"), | |
| 718 | + ARIZONA_MIXER_ROUTES("EQ4", "EQ4"), | |
| 719 | + | |
| 720 | + ARIZONA_MIXER_ROUTES("DRC1L", "DRC1L"), | |
| 721 | + ARIZONA_MIXER_ROUTES("DRC1R", "DRC1R"), | |
| 722 | + ARIZONA_MIXER_ROUTES("DRC2L", "DRC2L"), | |
| 723 | + ARIZONA_MIXER_ROUTES("DRC2R", "DRC2R"), | |
| 724 | + | |
| 725 | + ARIZONA_MIXER_ROUTES("LHPF1", "LHPF1"), | |
| 726 | + ARIZONA_MIXER_ROUTES("LHPF2", "LHPF2"), | |
| 727 | + ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"), | |
| 728 | + ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"), | |
| 729 | + | |
| 730 | + ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"), | |
| 731 | + ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"), | |
| 732 | + ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"), | |
| 733 | + ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"), | |
| 734 | + | |
| 735 | + { "HPOUT1L", NULL, "OUT1L" }, | |
| 736 | + { "HPOUT1R", NULL, "OUT1R" }, | |
| 737 | + | |
| 738 | + { "HPOUT2L", NULL, "OUT2L" }, | |
| 739 | + { "HPOUT2R", NULL, "OUT2R" }, | |
| 740 | + | |
| 741 | + { "EPOUTN", NULL, "OUT3L" }, | |
| 742 | + { "EPOUTP", NULL, "OUT3L" }, | |
| 743 | + | |
| 744 | + { "SPKOUTLN", NULL, "OUT4L" }, | |
| 745 | + { "SPKOUTLP", NULL, "OUT4L" }, | |
| 746 | + | |
| 747 | + { "SPKOUTRN", NULL, "OUT4R" }, | |
| 748 | + { "SPKOUTRP", NULL, "OUT4R" }, | |
| 749 | + | |
| 750 | + { "SPKDAT1L", NULL, "OUT5L" }, | |
| 751 | + { "SPKDAT1R", NULL, "OUT5R" }, | |
| 752 | + | |
| 753 | + { "SPKDAT2L", NULL, "OUT6L" }, | |
| 754 | + { "SPKDAT2R", NULL, "OUT6R" }, | |
| 755 | +}; | |
| 756 | + | |
| 757 | +static int wm5110_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |
| 758 | + unsigned int Fref, unsigned int Fout) | |
| 759 | +{ | |
| 760 | + struct wm5110_priv *wm5110 = snd_soc_codec_get_drvdata(codec); | |
| 761 | + | |
| 762 | + switch (fll_id) { | |
| 763 | + case WM5110_FLL1: | |
| 764 | + return arizona_set_fll(&wm5110->fll[0], source, Fref, Fout); | |
| 765 | + case WM5110_FLL2: | |
| 766 | + return arizona_set_fll(&wm5110->fll[1], source, Fref, Fout); | |
| 767 | + default: | |
| 768 | + return -EINVAL; | |
| 769 | + } | |
| 770 | +} | |
| 771 | + | |
| 772 | +#define WM5110_RATES SNDRV_PCM_RATE_8000_192000 | |
| 773 | + | |
| 774 | +#define WM5110_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | |
| 775 | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | |
| 776 | + | |
| 777 | +static struct snd_soc_dai_driver wm5110_dai[] = { | |
| 778 | + { | |
| 779 | + .name = "wm5110-aif1", | |
| 780 | + .id = 1, | |
| 781 | + .base = ARIZONA_AIF1_BCLK_CTRL, | |
| 782 | + .playback = { | |
| 783 | + .stream_name = "AIF1 Playback", | |
| 784 | + .channels_min = 1, | |
| 785 | + .channels_max = 8, | |
| 786 | + .rates = WM5110_RATES, | |
| 787 | + .formats = WM5110_FORMATS, | |
| 788 | + }, | |
| 789 | + .capture = { | |
| 790 | + .stream_name = "AIF1 Capture", | |
| 791 | + .channels_min = 1, | |
| 792 | + .channels_max = 8, | |
| 793 | + .rates = WM5110_RATES, | |
| 794 | + .formats = WM5110_FORMATS, | |
| 795 | + }, | |
| 796 | + .ops = &arizona_dai_ops, | |
| 797 | + .symmetric_rates = 1, | |
| 798 | + }, | |
| 799 | + { | |
| 800 | + .name = "wm5110-aif2", | |
| 801 | + .id = 2, | |
| 802 | + .base = ARIZONA_AIF2_BCLK_CTRL, | |
| 803 | + .playback = { | |
| 804 | + .stream_name = "AIF2 Playback", | |
| 805 | + .channels_min = 1, | |
| 806 | + .channels_max = 2, | |
| 807 | + .rates = WM5110_RATES, | |
| 808 | + .formats = WM5110_FORMATS, | |
| 809 | + }, | |
| 810 | + .capture = { | |
| 811 | + .stream_name = "AIF2 Capture", | |
| 812 | + .channels_min = 1, | |
| 813 | + .channels_max = 2, | |
| 814 | + .rates = WM5110_RATES, | |
| 815 | + .formats = WM5110_FORMATS, | |
| 816 | + }, | |
| 817 | + .ops = &arizona_dai_ops, | |
| 818 | + .symmetric_rates = 1, | |
| 819 | + }, | |
| 820 | + { | |
| 821 | + .name = "wm5110-aif3", | |
| 822 | + .id = 3, | |
| 823 | + .base = ARIZONA_AIF3_BCLK_CTRL, | |
| 824 | + .playback = { | |
| 825 | + .stream_name = "AIF3 Playback", | |
| 826 | + .channels_min = 1, | |
| 827 | + .channels_max = 2, | |
| 828 | + .rates = WM5110_RATES, | |
| 829 | + .formats = WM5110_FORMATS, | |
| 830 | + }, | |
| 831 | + .capture = { | |
| 832 | + .stream_name = "AIF3 Capture", | |
| 833 | + .channels_min = 1, | |
| 834 | + .channels_max = 2, | |
| 835 | + .rates = WM5110_RATES, | |
| 836 | + .formats = WM5110_FORMATS, | |
| 837 | + }, | |
| 838 | + .ops = &arizona_dai_ops, | |
| 839 | + .symmetric_rates = 1, | |
| 840 | + }, | |
| 841 | +}; | |
| 842 | + | |
| 843 | +static int wm5110_codec_probe(struct snd_soc_codec *codec) | |
| 844 | +{ | |
| 845 | + struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec); | |
| 846 | + | |
| 847 | + codec->control_data = priv->core.arizona->regmap; | |
| 848 | + return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP); | |
| 849 | +} | |
| 850 | + | |
| 851 | +#define WM5110_DIG_VU 0x0200 | |
| 852 | + | |
| 853 | +static unsigned int wm5110_digital_vu[] = { | |
| 854 | + ARIZONA_ADC_DIGITAL_VOLUME_1L, | |
| 855 | + ARIZONA_ADC_DIGITAL_VOLUME_1R, | |
| 856 | + ARIZONA_ADC_DIGITAL_VOLUME_2L, | |
| 857 | + ARIZONA_ADC_DIGITAL_VOLUME_2R, | |
| 858 | + ARIZONA_ADC_DIGITAL_VOLUME_3L, | |
| 859 | + ARIZONA_ADC_DIGITAL_VOLUME_3R, | |
| 860 | + | |
| 861 | + ARIZONA_DAC_DIGITAL_VOLUME_1L, | |
| 862 | + ARIZONA_DAC_DIGITAL_VOLUME_1R, | |
| 863 | + ARIZONA_DAC_DIGITAL_VOLUME_2L, | |
| 864 | + ARIZONA_DAC_DIGITAL_VOLUME_2R, | |
| 865 | + ARIZONA_DAC_DIGITAL_VOLUME_3L, | |
| 866 | + ARIZONA_DAC_DIGITAL_VOLUME_3R, | |
| 867 | + ARIZONA_DAC_DIGITAL_VOLUME_4L, | |
| 868 | + ARIZONA_DAC_DIGITAL_VOLUME_4R, | |
| 869 | + ARIZONA_DAC_DIGITAL_VOLUME_5L, | |
| 870 | + ARIZONA_DAC_DIGITAL_VOLUME_5R, | |
| 871 | +}; | |
| 872 | + | |
| 873 | +static struct snd_soc_codec_driver soc_codec_dev_wm5110 = { | |
| 874 | + .probe = wm5110_codec_probe, | |
| 875 | + | |
| 876 | + .idle_bias_off = true, | |
| 877 | + | |
| 878 | + .set_sysclk = arizona_set_sysclk, | |
| 879 | + .set_pll = wm5110_set_fll, | |
| 880 | + | |
| 881 | + .controls = wm5110_snd_controls, | |
| 882 | + .num_controls = ARRAY_SIZE(wm5110_snd_controls), | |
| 883 | + .dapm_widgets = wm5110_dapm_widgets, | |
| 884 | + .num_dapm_widgets = ARRAY_SIZE(wm5110_dapm_widgets), | |
| 885 | + .dapm_routes = wm5110_dapm_routes, | |
| 886 | + .num_dapm_routes = ARRAY_SIZE(wm5110_dapm_routes), | |
| 887 | +}; | |
| 888 | + | |
| 889 | +static int __devinit wm5110_probe(struct platform_device *pdev) | |
| 890 | +{ | |
| 891 | + struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); | |
| 892 | + struct wm5110_priv *wm5110; | |
| 893 | + int i; | |
| 894 | + | |
| 895 | + wm5110 = devm_kzalloc(&pdev->dev, sizeof(struct wm5110_priv), | |
| 896 | + GFP_KERNEL); | |
| 897 | + if (wm5110 == NULL) | |
| 898 | + return -ENOMEM; | |
| 899 | + platform_set_drvdata(pdev, wm5110); | |
| 900 | + | |
| 901 | + wm5110->core.arizona = arizona; | |
| 902 | + | |
| 903 | + for (i = 0; i < ARRAY_SIZE(wm5110->fll); i++) | |
| 904 | + wm5110->fll[i].vco_mult = 3; | |
| 905 | + | |
| 906 | + arizona_init_fll(arizona, 1, ARIZONA_FLL1_CONTROL_1 - 1, | |
| 907 | + ARIZONA_IRQ_FLL1_LOCK, ARIZONA_IRQ_FLL1_CLOCK_OK, | |
| 908 | + &wm5110->fll[0]); | |
| 909 | + arizona_init_fll(arizona, 2, ARIZONA_FLL2_CONTROL_1 - 1, | |
| 910 | + ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK, | |
| 911 | + &wm5110->fll[1]); | |
| 912 | + | |
| 913 | + for (i = 0; i < ARRAY_SIZE(wm5110_dai); i++) | |
| 914 | + arizona_init_dai(&wm5110->core, i); | |
| 915 | + | |
| 916 | + /* Latch volume update bits */ | |
| 917 | + for (i = 0; i < ARRAY_SIZE(wm5110_digital_vu); i++) | |
| 918 | + regmap_update_bits(arizona->regmap, wm5110_digital_vu[i], | |
| 919 | + WM5110_DIG_VU, WM5110_DIG_VU); | |
| 920 | + | |
| 921 | + pm_runtime_enable(&pdev->dev); | |
| 922 | + pm_runtime_idle(&pdev->dev); | |
| 923 | + | |
| 924 | + return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5110, | |
| 925 | + wm5110_dai, ARRAY_SIZE(wm5110_dai)); | |
| 926 | +} | |
| 927 | + | |
| 928 | +static int __devexit wm5110_remove(struct platform_device *pdev) | |
| 929 | +{ | |
| 930 | + snd_soc_unregister_codec(&pdev->dev); | |
| 931 | + pm_runtime_disable(&pdev->dev); | |
| 932 | + | |
| 933 | + return 0; | |
| 934 | +} | |
| 935 | + | |
| 936 | +static struct platform_driver wm5110_codec_driver = { | |
| 937 | + .driver = { | |
| 938 | + .name = "wm5110-codec", | |
| 939 | + .owner = THIS_MODULE, | |
| 940 | + }, | |
| 941 | + .probe = wm5110_probe, | |
| 942 | + .remove = __devexit_p(wm5110_remove), | |
| 943 | +}; | |
| 944 | + | |
| 945 | +module_platform_driver(wm5110_codec_driver); | |
| 946 | + | |
| 947 | +MODULE_DESCRIPTION("ASoC WM5110 driver"); | |
| 948 | +MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | |
| 949 | +MODULE_LICENSE("GPL"); | |
| 950 | +MODULE_ALIAS("platform:wm5110-codec"); | |
| @@ -0,0 +1,21 @@ | ||
| 1 | +/* | |
| 2 | + * wm5110.h -- WM5110 ALSA SoC Audio driver | |
| 3 | + * | |
| 4 | + * Copyright 2012 Wolfson Microelectronics plc | |
| 5 | + * | |
| 6 | + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | |
| 7 | + * | |
| 8 | + * This program is free software; you can redistribute it and/or modify | |
| 9 | + * it under the terms of the GNU General Public License version 2 as | |
| 10 | + * published by the Free Software Foundation. | |
| 11 | + */ | |
| 12 | + | |
| 13 | +#ifndef _WM5110_H | |
| 14 | +#define _WM5110_H | |
| 15 | + | |
| 16 | +#include "arizona.h" | |
| 17 | + | |
| 18 | +#define WM5110_FLL1 1 | |
| 19 | +#define WM5110_FLL2 2 | |
| 20 | + | |
| 21 | +#endif | |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * wm8350.c -- WM8350 ALSA SoC audio driver |
| 3 | 3 | * |
| 4 | − * Copyright (C) 2007, 2008 Wolfson Microelectronics PLC. | |
| 4 | + * Copyright (C) 2007-12 Wolfson Microelectronics PLC. | |
| 5 | 5 | * |
| 6 | 6 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
| 7 | 7 | * |
| @@ -71,20 +71,6 @@ struct wm8350_data { · 63 unmodified lines | ||
| 71 | 71 | int fll_freq_in; |
| 72 | 72 | }; |
| 73 | 73 | |
| 74 | −static unsigned int wm8350_codec_read(struct snd_soc_codec *codec, | |
| 75 | − unsigned int reg) | |
| 76 | −{ | |
| 77 | − struct wm8350 *wm8350 = codec->control_data; | |
| 78 | − return wm8350_reg_read(wm8350, reg); | |
| 79 | −} | |
| 80 | − | |
| 81 | −static int wm8350_codec_write(struct snd_soc_codec *codec, unsigned int reg, | |
| 82 | − unsigned int value) | |
| 83 | −{ | |
| 84 | − struct wm8350 *wm8350 = codec->control_data; | |
| 85 | − return wm8350_reg_write(wm8350, reg, value); | |
| 86 | −} | |
| 87 | − | |
| 88 | 74 | /* |
| 89 | 75 | * Ramp OUT1 PGA volume to minimise pops at stream startup and shutdown. |
| 90 | 76 | */ |
| @@ -1519,7 +1505,9 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec) · 1428 unmodified lines | ||
| 1519 | 1505 | if (ret != 0) |
| 1520 | 1506 | return ret; |
| 1521 | 1507 | |
| 1522 | − codec->control_data = wm8350; | |
| 1508 | + codec->control_data = wm8350->regmap; | |
| 1509 | + | |
| 1510 | + snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); | |
| 1523 | 1511 | |
| 1524 | 1512 | /* Put the codec into reset if it wasn't already */ |
| 1525 | 1513 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); |
| @@ -1629,8 +1617,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8350 = { · 103 unmodified lines | ||
| 1629 | 1617 | .remove = wm8350_codec_remove, |
| 1630 | 1618 | .suspend = wm8350_suspend, |
| 1631 | 1619 | .resume = wm8350_resume, |
| 1632 | − .read = wm8350_codec_read, | |
| 1633 | − .write = wm8350_codec_write, | |
| 1634 | 1620 | .set_bias_level = wm8350_set_bias_level, |
| 1635 | 1621 | |
| 1636 | 1622 | .controls = wm8350_snd_controls, |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * wm8400.c -- WM8400 ALSA Soc Audio driver |
| 3 | 3 | * |
| 4 | − * Copyright 2008, 2009 Wolfson Microelectronics PLC. | |
| 4 | + * Copyright 2008-11 Wolfson Microelectronics PLC. | |
| 5 | 5 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
| 6 | 6 | * |
| 7 | 7 | * This program is free software; you can redistribute it and/or modify it |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * wm8580.c -- WM8580 ALSA Soc Audio driver |
| 3 | 3 | * |
| 4 | − * Copyright 2008, 2009 Wolfson Microelectronics PLC. | |
| 4 | + * Copyright 2008-11 Wolfson Microelectronics PLC. | |
| 5 | 5 | * |
| 6 | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | 7 | * under the terms of the GNU General Public License as published by the |
| @@ -2,6 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | * wm8731.c -- WM8731 ALSA SoC Audio driver |
| 3 | 3 | * |
| 4 | 4 | * Copyright 2005 Openedhand Ltd. |
| 5 | + * Copyright 2006-12 Wolfson Microelectronics, plc | |
| 5 | 6 | * |
| 6 | 7 | * Author: Richard Purdie <richard@openedhand.com> |
| 7 | 8 | * |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * wm8741.c -- WM8741 ALSA SoC Audio driver |
| 3 | 3 | * |
| 4 | − * Copyright 2010 Wolfson Microelectronics plc | |
| 4 | + * Copyright 2010-1 Wolfson Microelectronics plc | |
| 5 | 5 | * |
| 6 | 6 | * Author: Ian Lartey <ian@opensource.wolfsonmicro.com> |
| 7 | 7 | * |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * wm8753.c -- WM8753 ALSA Soc Audio driver |
| 3 | 3 | * |
| 4 | − * Copyright 2003 Wolfson Microelectronics PLC. | |
| 4 | + * Copyright 2003-11 Wolfson Microelectronics PLC. | |
| 5 | 5 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
| 6 | 6 | * |
| 7 | 7 | * This program is free software; you can redistribute it and/or modify it |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * wm8776.c -- WM8776 ALSA SoC Audio driver |
| 3 | 3 | * |
| 4 | − * Copyright 2009 Wolfson Microelectronics plc | |
| 4 | + * Copyright 2009-12 Wolfson Microelectronics plc | |
| 5 | 5 | * |
| 6 | 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
| 7 | 7 | * |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * wm8804.c -- WM8804 S/PDIF transceiver driver |
| 3 | 3 | * |
| 4 | − * Copyright 2010 Wolfson Microelectronics plc | |
| 4 | + * Copyright 2010-11 Wolfson Microelectronics plc | |
| 5 | 5 | * |
| 6 | 6 | * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com> |
| 7 | 7 | * |
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * wm8903.c -- WM8903 ALSA SoC Audio driver |
| 3 | 3 | * |
| 4 | − * Copyright 2008 Wolfson Microelectronics | |
| 5 | − * Copyright 2011 NVIDIA, Inc. | |
| 4 | + * Copyright 2008-12 Wolfson Microelectronics | |
| 5 | + * Copyright 2011-2012 NVIDIA, Inc. | |
| 6 | 6 | * |
| 7 | 7 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
| 8 | 8 | * |
| @@ -116,6 +116,7 @@ static const struct reg_default wm8903_reg_defaults[] = { · 107 unmodified lines | ||
| 116 | 116 | |
| 117 | 117 | struct wm8903_priv { |
| 118 | 118 | struct wm8903_platform_data *pdata; |
| 119 | + struct device *dev; | |
| 119 | 120 | struct snd_soc_codec *codec; |
| 120 | 121 | struct regmap *regmap; |
| 121 | 122 | |
| @@ -1635,17 +1636,27 @@ EXPORT_SYMBOL_GPL(wm8903_mic_detect); · 1513 unmodified lines | ||
| 1635 | 1636 | |
| 1636 | 1637 | static irqreturn_t wm8903_irq(int irq, void *data) |
| 1637 | 1638 | { |
| 1638 | − struct snd_soc_codec *codec = data; | |
| 1639 | − struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | |
| 1640 | − int mic_report; | |
| 1641 | − int int_pol; | |
| 1642 | − int int_val = 0; | |
| 1643 | − int mask = ~snd_soc_read(codec, WM8903_INTERRUPT_STATUS_1_MASK); | |
| 1639 | + struct wm8903_priv *wm8903 = data; | |
| 1640 | + int mic_report, ret; | |
| 1641 | + unsigned int int_val, mask, int_pol; | |
| 1644 | 1642 | |
| 1645 | − int_val = snd_soc_read(codec, WM8903_INTERRUPT_STATUS_1) & mask; | |
| 1643 | + ret = regmap_read(wm8903->regmap, WM8903_INTERRUPT_STATUS_1_MASK, | |
| 1644 | + &mask); | |
| 1645 | + if (ret != 0) { | |
| 1646 | + dev_err(wm8903->dev, "Failed to read IRQ mask: %d\n", ret); | |
| 1647 | + return IRQ_NONE; | |
| 1648 | + } | |
| 1649 | + | |
| 1650 | + ret = regmap_read(wm8903->regmap, WM8903_INTERRUPT_STATUS_1, &int_val); | |
| 1651 | + if (ret != 0) { | |
| 1652 | + dev_err(wm8903->dev, "Failed to read IRQ status: %d\n", ret); | |
| 1653 | + return IRQ_NONE; | |
| 1654 | + } | |
| 1655 | + | |
| 1656 | + int_val &= ~mask; | |
| 1646 | 1657 | |
| 1647 | 1658 | if (int_val & WM8903_WSEQ_BUSY_EINT) { |
| 1648 | − dev_warn(codec->dev, "Write sequencer done\n"); | |
| 1659 | + dev_warn(wm8903->dev, "Write sequencer done\n"); | |
| 1649 | 1660 | } |
| 1650 | 1661 | |
| 1651 | 1662 | /* |
| @@ -1656,22 +1667,28 @@ static irqreturn_t wm8903_irq(int irq, void *data) · 4 unmodified lines | ||
| 1656 | 1667 | * the polarity register. |
| 1657 | 1668 | */ |
| 1658 | 1669 | mic_report = wm8903->mic_last_report; |
| 1659 | − int_pol = snd_soc_read(codec, WM8903_INTERRUPT_POLARITY_1); | |
| 1670 | + ret = regmap_read(wm8903->regmap, WM8903_INTERRUPT_POLARITY_1, | |
| 1671 | + &int_pol); | |
| 1672 | + if (ret != 0) { | |
| 1673 | + dev_err(wm8903->dev, "Failed to read interrupt polarity: %d\n", | |
| 1674 | + ret); | |
| 1675 | + return IRQ_HANDLED; | |
| 1676 | + } | |
| 1660 | 1677 | |
| 1661 | 1678 | #ifndef CONFIG_SND_SOC_WM8903_MODULE |
| 1662 | 1679 | if (int_val & (WM8903_MICSHRT_EINT | WM8903_MICDET_EINT)) |
| 1663 | − trace_snd_soc_jack_irq(dev_name(codec->dev)); | |
| 1680 | + trace_snd_soc_jack_irq(dev_name(wm8903->dev)); | |
| 1664 | 1681 | #endif |
| 1665 | 1682 | |
| 1666 | 1683 | if (int_val & WM8903_MICSHRT_EINT) { |
| 1667 | − dev_dbg(codec->dev, "Microphone short (pol=%x)\n", int_pol); | |
| 1684 | + dev_dbg(wm8903->dev, "Microphone short (pol=%x)\n", int_pol); | |
| 1668 | 1685 | |
| 1669 | 1686 | mic_report ^= wm8903->mic_short; |
| 1670 | 1687 | int_pol ^= WM8903_MICSHRT_INV; |
| 1671 | 1688 | } |
| 1672 | 1689 | |
| 1673 | 1690 | if (int_val & WM8903_MICDET_EINT) { |
| 1674 | − dev_dbg(codec->dev, "Microphone detect (pol=%x)\n", int_pol); | |
| 1691 | + dev_dbg(wm8903->dev, "Microphone detect (pol=%x)\n", int_pol); | |
| 1675 | 1692 | |
| 1676 | 1693 | mic_report ^= wm8903->mic_det; |
| 1677 | 1694 | int_pol ^= WM8903_MICDET_INV; |
| @@ -1679,8 +1696,8 @@ static irqreturn_t wm8903_irq(int irq, void *data) · 1 unmodified line | ||
| 1679 | 1696 | msleep(wm8903->mic_delay); |
| 1680 | 1697 | } |
| 1681 | 1698 | |
| 1682 | − snd_soc_update_bits(codec, WM8903_INTERRUPT_POLARITY_1, | |
| 1683 | − WM8903_MICSHRT_INV | WM8903_MICDET_INV, int_pol); | |
| 1699 | + regmap_update_bits(wm8903->regmap, WM8903_INTERRUPT_POLARITY_1, | |
| 1700 | + WM8903_MICSHRT_INV | WM8903_MICDET_INV, int_pol); | |
| 1684 | 1701 | |
| 1685 | 1702 | snd_soc_jack_report(wm8903->mic_jack, mic_report, |
| 1686 | 1703 | wm8903->mic_short | wm8903->mic_det); |
| @@ -1774,7 +1791,6 @@ static int wm8903_gpio_request(struct gpio_chip *chip, unsigned offset) · 87 unmodified lines | ||
| 1774 | 1791 | static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset) |
| 1775 | 1792 | { |
| 1776 | 1793 | struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); |
| 1777 | − struct snd_soc_codec *codec = wm8903->codec; | |
| 1778 | 1794 | unsigned int mask, val; |
| 1779 | 1795 | int ret; |
| 1780 | 1796 | |
| @@ -1782,8 +1798,8 @@ static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset) · 1 unmodified line | ||
| 1782 | 1798 | val = (WM8903_GPn_FN_GPIO_INPUT << WM8903_GP1_FN_SHIFT) | |
| 1783 | 1799 | WM8903_GP1_DIR; |
| 1784 | 1800 | |
| 1785 | − ret = snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset, | |
| 1786 | − mask, val); | |
| 1801 | + ret = regmap_update_bits(wm8903->regmap, | |
| 1802 | + WM8903_GPIO_CONTROL_1 + offset, mask, val); | |
| 1787 | 1803 | if (ret < 0) |
| 1788 | 1804 | return ret; |
| 1789 | 1805 | |
| @@ -1793,10 +1809,9 @@ static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset) · 3 unmodified lines | ||
| 1793 | 1809 | static int wm8903_gpio_get(struct gpio_chip *chip, unsigned offset) |
| 1794 | 1810 | { |
| 1795 | 1811 | struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); |
| 1796 | − struct snd_soc_codec *codec = wm8903->codec; | |
| 1797 | − int reg; | |
| 1812 | + unsigned int reg; | |
| 1798 | 1813 | |
| 1799 | − reg = snd_soc_read(codec, WM8903_GPIO_CONTROL_1 + offset); | |
| 1814 | + regmap_read(wm8903->regmap, WM8903_GPIO_CONTROL_1 + offset, ®); | |
| 1800 | 1815 | |
| 1801 | 1816 | return (reg & WM8903_GP1_LVL_MASK) >> WM8903_GP1_LVL_SHIFT; |
| 1802 | 1817 | } |
| @@ -1805,7 +1820,6 @@ static int wm8903_gpio_direction_out(struct gpio_chip *chip, · 2 unmodified lines | ||
| 1805 | 1820 | unsigned offset, int value) |
| 1806 | 1821 | { |
| 1807 | 1822 | struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); |
| 1808 | − struct snd_soc_codec *codec = wm8903->codec; | |
| 1809 | 1823 | unsigned int mask, val; |
| 1810 | 1824 | int ret; |
| 1811 | 1825 | |
| @@ -1813,8 +1827,8 @@ static int wm8903_gpio_direction_out(struct gpio_chip *chip, · 1 unmodified line | ||
| 1813 | 1827 | val = (WM8903_GPn_FN_GPIO_OUTPUT << WM8903_GP1_FN_SHIFT) | |
| 1814 | 1828 | (value << WM8903_GP2_LVL_SHIFT); |
| 1815 | 1829 | |
| 1816 | − ret = snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset, | |
| 1817 | − mask, val); | |
| 1830 | + ret = regmap_update_bits(wm8903->regmap, | |
| 1831 | + WM8903_GPIO_CONTROL_1 + offset, mask, val); | |
| 1818 | 1832 | if (ret < 0) |
| 1819 | 1833 | return ret; |
| 1820 | 1834 | |
| @@ -1824,11 +1838,10 @@ static int wm8903_gpio_direction_out(struct gpio_chip *chip, · 3 unmodified lines | ||
| 1824 | 1838 | static void wm8903_gpio_set(struct gpio_chip *chip, unsigned offset, int value) |
| 1825 | 1839 | { |
| 1826 | 1840 | struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); |
| 1827 | − struct snd_soc_codec *codec = wm8903->codec; | |
| 1828 | 1841 | |
| 1829 | − snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset, | |
| 1830 | − WM8903_GP1_LVL_MASK, | |
| 1831 | − !!value << WM8903_GP1_LVL_SHIFT); | |
| 1842 | + regmap_update_bits(wm8903->regmap, WM8903_GPIO_CONTROL_1 + offset, | |
| 1843 | + WM8903_GP1_LVL_MASK, | |
| 1844 | + !!value << WM8903_GP1_LVL_SHIFT); | |
| 1832 | 1845 | } |
| 1833 | 1846 | |
| 1834 | 1847 | static struct gpio_chip wm8903_template_chip = { |
| @@ -1842,15 +1855,14 @@ static struct gpio_chip wm8903_template_chip = { · 7 unmodified lines | ||
| 1842 | 1855 | .can_sleep = 1, |
| 1843 | 1856 | }; |
| 1844 | 1857 | |
| 1845 | −static void wm8903_init_gpio(struct snd_soc_codec *codec) | |
| 1858 | +static void wm8903_init_gpio(struct wm8903_priv *wm8903) | |
| 1846 | 1859 | { |
| 1847 | − struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | |
| 1848 | 1860 | struct wm8903_platform_data *pdata = wm8903->pdata; |
| 1849 | 1861 | int ret; |
| 1850 | 1862 | |
| 1851 | 1863 | wm8903->gpio_chip = wm8903_template_chip; |
| 1852 | 1864 | wm8903->gpio_chip.ngpio = WM8903_NUM_GPIO; |
| 1853 | − wm8903->gpio_chip.dev = codec->dev; | |
| 1865 | + wm8903->gpio_chip.dev = wm8903->dev; | |
| 1854 | 1866 | |
| 1855 | 1867 | if (pdata->gpio_base) |
| 1856 | 1868 | wm8903->gpio_chip.base = pdata->gpio_base; |
| @@ -1859,24 +1871,23 @@ static void wm8903_init_gpio(struct snd_soc_codec *codec) · 2 unmodified lines | ||
| 1859 | 1871 | |
| 1860 | 1872 | ret = gpiochip_add(&wm8903->gpio_chip); |
| 1861 | 1873 | if (ret != 0) |
| 1862 | − dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret); | |
| 1874 | + dev_err(wm8903->dev, "Failed to add GPIOs: %d\n", ret); | |
| 1863 | 1875 | } |
| 1864 | 1876 | |
| 1865 | −static void wm8903_free_gpio(struct snd_soc_codec *codec) | |
| 1877 | +static void wm8903_free_gpio(struct wm8903_priv *wm8903) | |
| 1866 | 1878 | { |
| 1867 | − struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | |
| 1868 | 1879 | int ret; |
| 1869 | 1880 | |
| 1870 | 1881 | ret = gpiochip_remove(&wm8903->gpio_chip); |
| 1871 | 1882 | if (ret != 0) |
| 1872 | − dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret); | |
| 1883 | + dev_err(wm8903->dev, "Failed to remove GPIOs: %d\n", ret); | |
| 1873 | 1884 | } |
| 1874 | 1885 | #else |
| 1875 | −static void wm8903_init_gpio(struct snd_soc_codec *codec) | |
| 1886 | +static void wm8903_init_gpio(struct wm8903_priv *wm8903) | |
| 1876 | 1887 | { |
| 1877 | 1888 | } |
| 1878 | 1889 | |
| 1879 | −static void wm8903_free_gpio(struct snd_soc_codec *codec) | |
| 1890 | +static void wm8903_free_gpio(struct wm8903_priv *wm8903) | |
| 1880 | 1891 | { |
| 1881 | 1892 | } |
| 1882 | 1893 | #endif |
| @@ -1884,11 +1895,7 @@ static void wm8903_free_gpio(struct snd_soc_codec *codec) · 1 unmodified line | ||
| 1884 | 1895 | static int wm8903_probe(struct snd_soc_codec *codec) |
| 1885 | 1896 | { |
| 1886 | 1897 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
| 1887 | − struct wm8903_platform_data *pdata = wm8903->pdata; | |
| 1888 | − int ret, i; | |
| 1889 | − int trigger, irq_pol; | |
| 1890 | − u16 val; | |
| 1891 | − bool mic_gpio = false; | |
| 1898 | + int ret; | |
| 1892 | 1899 | |
| 1893 | 1900 | wm8903->codec = codec; |
| 1894 | 1901 | codec->control_data = wm8903->regmap; |
| @@ -1899,121 +1906,16 @@ static int wm8903_probe(struct snd_soc_codec *codec) · 4 unmodified lines | ||
| 1899 | 1906 | return ret; |
| 1900 | 1907 | } |
| 1901 | 1908 | |
| 1902 | − /* Set up GPIOs, detect if any are MIC detect outputs */ | |
| 1903 | − for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) { | |
| 1904 | − if ((!pdata->gpio_cfg[i]) || | |
| 1905 | − (pdata->gpio_cfg[i] > WM8903_GPIO_CONFIG_ZERO)) | |
| 1906 | − continue; | |
| 1907 | − | |
| 1908 | − snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i, | |
| 1909 | − pdata->gpio_cfg[i] & 0x7fff); | |
| 1910 | − | |
| 1911 | − val = (pdata->gpio_cfg[i] & WM8903_GP1_FN_MASK) | |
| 1912 | − >> WM8903_GP1_FN_SHIFT; | |
| 1913 | − | |
| 1914 | − switch (val) { | |
| 1915 | − case WM8903_GPn_FN_MICBIAS_CURRENT_DETECT: | |
| 1916 | − case WM8903_GPn_FN_MICBIAS_SHORT_DETECT: | |
| 1917 | − mic_gpio = true; | |
| 1918 | − break; | |
| 1919 | − default: | |
| 1920 | − break; | |
| 1921 | − } | |
| 1922 | − } | |
| 1923 | − | |
| 1924 | − /* Set up microphone detection */ | |
| 1925 | − snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0, | |
| 1926 | − pdata->micdet_cfg); | |
| 1927 | − | |
| 1928 | − /* Microphone detection needs the WSEQ clock */ | |
| 1929 | − if (pdata->micdet_cfg) | |
| 1930 | − snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0, | |
| 1931 | − WM8903_WSEQ_ENA, WM8903_WSEQ_ENA); | |
| 1932 | − | |
| 1933 | − /* If microphone detection is enabled by pdata but | |
| 1934 | − * detected via IRQ then interrupts can be lost before | |
| 1935 | − * the machine driver has set up microphone detection | |
| 1936 | − * IRQs as the IRQs are clear on read. The detection | |
| 1937 | − * will be enabled when the machine driver configures. | |
| 1938 | − */ | |
| 1939 | − WARN_ON(!mic_gpio && (pdata->micdet_cfg & WM8903_MICDET_ENA)); | |
| 1940 | − | |
| 1941 | − wm8903->mic_delay = pdata->micdet_delay; | |
| 1942 | − | |
| 1943 | − if (wm8903->irq) { | |
| 1944 | − if (pdata->irq_active_low) { | |
| 1945 | − trigger = IRQF_TRIGGER_LOW; | |
| 1946 | − irq_pol = WM8903_IRQ_POL; | |
| 1947 | − } else { | |
| 1948 | − trigger = IRQF_TRIGGER_HIGH; | |
| 1949 | − irq_pol = 0; | |
| 1950 | − } | |
| 1951 | − | |
| 1952 | − snd_soc_update_bits(codec, WM8903_INTERRUPT_CONTROL, | |
| 1953 | − WM8903_IRQ_POL, irq_pol); | |
| 1954 | − | |
| 1955 | − ret = request_threaded_irq(wm8903->irq, NULL, wm8903_irq, | |
| 1956 | − trigger | IRQF_ONESHOT, | |
| 1957 | − "wm8903", codec); | |
| 1958 | − if (ret != 0) { | |
| 1959 | − dev_err(codec->dev, "Failed to request IRQ: %d\n", | |
| 1960 | − ret); | |
| 1961 | − return ret; | |
| 1962 | − } | |
| 1963 | − | |
| 1964 | − /* Enable write sequencer interrupts */ | |
| 1965 | − snd_soc_update_bits(codec, WM8903_INTERRUPT_STATUS_1_MASK, | |
| 1966 | − WM8903_IM_WSEQ_BUSY_EINT, 0); | |
| 1967 | − } | |
| 1968 | − | |
| 1969 | 1909 | /* power on device */ |
| 1970 | 1910 | wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
| 1971 | 1911 | |
| 1972 | − /* Latch volume update bits */ | |
| 1973 | − val = snd_soc_read(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT); | |
| 1974 | − val |= WM8903_ADCVU; | |
| 1975 | − snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT, val); | |
| 1976 | − snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_RIGHT, val); | |
| 1977 | − | |
| 1978 | − val = snd_soc_read(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT); | |
| 1979 | − val |= WM8903_DACVU; | |
| 1980 | − snd_soc_write(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT, val); | |
| 1981 | − snd_soc_write(codec, WM8903_DAC_DIGITAL_VOLUME_RIGHT, val); | |
| 1982 | − | |
| 1983 | − val = snd_soc_read(codec, WM8903_ANALOGUE_OUT1_LEFT); | |
| 1984 | − val |= WM8903_HPOUTVU; | |
| 1985 | − snd_soc_write(codec, WM8903_ANALOGUE_OUT1_LEFT, val); | |
| 1986 | − snd_soc_write(codec, WM8903_ANALOGUE_OUT1_RIGHT, val); | |
| 1987 | − | |
| 1988 | − val = snd_soc_read(codec, WM8903_ANALOGUE_OUT2_LEFT); | |
| 1989 | − val |= WM8903_LINEOUTVU; | |
| 1990 | − snd_soc_write(codec, WM8903_ANALOGUE_OUT2_LEFT, val); | |
| 1991 | − snd_soc_write(codec, WM8903_ANALOGUE_OUT2_RIGHT, val); | |
| 1992 | − | |
| 1993 | − val = snd_soc_read(codec, WM8903_ANALOGUE_OUT3_LEFT); | |
| 1994 | − val |= WM8903_SPKVU; | |
| 1995 | − snd_soc_write(codec, WM8903_ANALOGUE_OUT3_LEFT, val); | |
| 1996 | − snd_soc_write(codec, WM8903_ANALOGUE_OUT3_RIGHT, val); | |
| 1997 | − | |
| 1998 | − /* Enable DAC soft mute by default */ | |
| 1999 | − snd_soc_update_bits(codec, WM8903_DAC_DIGITAL_1, | |
| 2000 | − WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE, | |
| 2001 | − WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE); | |
| 2002 | − | |
| 2003 | − wm8903_init_gpio(codec); | |
| 2004 | − | |
| 2005 | 1912 | return ret; |
| 2006 | 1913 | } |
| 2007 | 1914 | |
| 2008 | 1915 | /* power down chip */ |
| 2009 | 1916 | static int wm8903_remove(struct snd_soc_codec *codec) |
| 2010 | 1917 | { |
| 2011 | − struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | |
| 2012 | − | |
| 2013 | − wm8903_free_gpio(codec); | |
| 2014 | 1918 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); |
| 2015 | − if (wm8903->irq) | |
| 2016 | − free_irq(wm8903->irq, codec); | |
| 2017 | 1919 | |
| 2018 | 1920 | return 0; |
| 2019 | 1921 | } |
| @@ -2123,15 +2025,18 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, · 103 unmodified lines | ||
| 2123 | 2025 | { |
| 2124 | 2026 | struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev); |
| 2125 | 2027 | struct wm8903_priv *wm8903; |
| 2126 | − unsigned int val; | |
| 2127 | − int ret; | |
| 2028 | + int trigger; | |
| 2029 | + bool mic_gpio = false; | |
| 2030 | + unsigned int val, irq_pol; | |
| 2031 | + int ret, i; | |
| 2128 | 2032 | |
| 2129 | 2033 | wm8903 = devm_kzalloc(&i2c->dev, sizeof(struct wm8903_priv), |
| 2130 | 2034 | GFP_KERNEL); |
| 2131 | 2035 | if (wm8903 == NULL) |
| 2132 | 2036 | return -ENOMEM; |
| 2037 | + wm8903->dev = &i2c->dev; | |
| 2133 | 2038 | |
| 2134 | − wm8903->regmap = regmap_init_i2c(i2c, &wm8903_regmap); | |
| 2039 | + wm8903->regmap = devm_regmap_init_i2c(i2c, &wm8903_regmap); | |
| 2135 | 2040 | if (IS_ERR(wm8903->regmap)) { |
| 2136 | 2041 | ret = PTR_ERR(wm8903->regmap); |
| 2137 | 2042 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", |
| @@ -2140,7 +2045,6 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, · 2 unmodified lines | ||
| 2140 | 2045 | } |
| 2141 | 2046 | |
| 2142 | 2047 | i2c_set_clientdata(i2c, wm8903); |
| 2143 | − wm8903->irq = i2c->irq; | |
| 2144 | 2048 | |
| 2145 | 2049 | /* If no platform data was supplied, create storage for defaults */ |
| 2146 | 2050 | if (pdata) { |
| @@ -2167,6 +2071,8 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, · 20 unmodified lines | ||
| 2167 | 2071 | } |
| 2168 | 2072 | } |
| 2169 | 2073 | |
| 2074 | + pdata = wm8903->pdata; | |
| 2075 | + | |
| 2170 | 2076 | ret = regmap_read(wm8903->regmap, WM8903_SW_RESET_AND_ID, &val); |
| 2171 | 2077 | if (ret != 0) { |
| 2172 | 2078 | dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret); |
| @@ -2189,6 +2095,107 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, · 16 unmodified lines | ||
| 2189 | 2095 | /* Reset the device */ |
| 2190 | 2096 | regmap_write(wm8903->regmap, WM8903_SW_RESET_AND_ID, 0x8903); |
| 2191 | 2097 | |
| 2098 | + wm8903_init_gpio(wm8903); | |
| 2099 | + | |
| 2100 | + /* Set up GPIO pin state, detect if any are MIC detect outputs */ | |
| 2101 | + for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) { | |
| 2102 | + if ((!pdata->gpio_cfg[i]) || | |
| 2103 | + (pdata->gpio_cfg[i] > WM8903_GPIO_CONFIG_ZERO)) | |
| 2104 | + continue; | |
| 2105 | + | |
| 2106 | + regmap_write(wm8903->regmap, WM8903_GPIO_CONTROL_1 + i, | |
| 2107 | + pdata->gpio_cfg[i] & 0x7fff); | |
| 2108 | + | |
| 2109 | + val = (pdata->gpio_cfg[i] & WM8903_GP1_FN_MASK) | |
| 2110 | + >> WM8903_GP1_FN_SHIFT; | |
| 2111 | + | |
| 2112 | + switch (val) { | |
| 2113 | + case WM8903_GPn_FN_MICBIAS_CURRENT_DETECT: | |
| 2114 | + case WM8903_GPn_FN_MICBIAS_SHORT_DETECT: | |
| 2115 | + mic_gpio = true; | |
| 2116 | + break; | |
| 2117 | + default: | |
| 2118 | + break; | |
| 2119 | + } | |
| 2120 | + } | |
| 2121 | + | |
| 2122 | + /* Set up microphone detection */ | |
| 2123 | + regmap_write(wm8903->regmap, WM8903_MIC_BIAS_CONTROL_0, | |
| 2124 | + pdata->micdet_cfg); | |
| 2125 | + | |
| 2126 | + /* Microphone detection needs the WSEQ clock */ | |
| 2127 | + if (pdata->micdet_cfg) | |
| 2128 | + regmap_update_bits(wm8903->regmap, WM8903_WRITE_SEQUENCER_0, | |
| 2129 | + WM8903_WSEQ_ENA, WM8903_WSEQ_ENA); | |
| 2130 | + | |
| 2131 | + /* If microphone detection is enabled by pdata but | |
| 2132 | + * detected via IRQ then interrupts can be lost before | |
| 2133 | + * the machine driver has set up microphone detection | |
| 2134 | + * IRQs as the IRQs are clear on read. The detection | |
| 2135 | + * will be enabled when the machine driver configures. | |
| 2136 | + */ | |
| 2137 | + WARN_ON(!mic_gpio && (pdata->micdet_cfg & WM8903_MICDET_ENA)); | |
| 2138 | + | |
| 2139 | + wm8903->mic_delay = pdata->micdet_delay; | |
| 2140 | + | |
| 2141 | + if (i2c->irq) { | |
| 2142 | + if (pdata->irq_active_low) { | |
| 2143 | + trigger = IRQF_TRIGGER_LOW; | |
| 2144 | + irq_pol = WM8903_IRQ_POL; | |
| 2145 | + } else { | |
| 2146 | + trigger = IRQF_TRIGGER_HIGH; | |
| 2147 | + irq_pol = 0; | |
| 2148 | + } | |
| 2149 | + | |
| 2150 | + regmap_update_bits(wm8903->regmap, WM8903_INTERRUPT_CONTROL, | |
| 2151 | + WM8903_IRQ_POL, irq_pol); | |
| 2152 | + | |
| 2153 | + ret = request_threaded_irq(i2c->irq, NULL, wm8903_irq, | |
| 2154 | + trigger | IRQF_ONESHOT, | |
| 2155 | + "wm8903", wm8903); | |
| 2156 | + if (ret != 0) { | |
| 2157 | + dev_err(wm8903->dev, "Failed to request IRQ: %d\n", | |
| 2158 | + ret); | |
| 2159 | + return ret; | |
| 2160 | + } | |
| 2161 | + | |
| 2162 | + /* Enable write sequencer interrupts */ | |
| 2163 | + regmap_update_bits(wm8903->regmap, | |
| 2164 | + WM8903_INTERRUPT_STATUS_1_MASK, | |
| 2165 | + WM8903_IM_WSEQ_BUSY_EINT, 0); | |
| 2166 | + } | |
| 2167 | + | |
| 2168 | + /* Latch volume update bits */ | |
| 2169 | + regmap_update_bits(wm8903->regmap, WM8903_ADC_DIGITAL_VOLUME_LEFT, | |
| 2170 | + WM8903_ADCVU, WM8903_ADCVU); | |
| 2171 | + regmap_update_bits(wm8903->regmap, WM8903_ADC_DIGITAL_VOLUME_RIGHT, | |
| 2172 | + WM8903_ADCVU, WM8903_ADCVU); | |
| 2173 | + | |
| 2174 | + regmap_update_bits(wm8903->regmap, WM8903_DAC_DIGITAL_VOLUME_LEFT, | |
| 2175 | + WM8903_DACVU, WM8903_DACVU); | |
| 2176 | + regmap_update_bits(wm8903->regmap, WM8903_DAC_DIGITAL_VOLUME_RIGHT, | |
| 2177 | + WM8903_DACVU, WM8903_DACVU); | |
| 2178 | + | |
| 2179 | + regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT1_LEFT, | |
| 2180 | + WM8903_HPOUTVU, WM8903_HPOUTVU); | |
| 2181 | + regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT1_RIGHT, | |
| 2182 | + WM8903_HPOUTVU, WM8903_HPOUTVU); | |
| 2183 | + | |
| 2184 | + regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT2_LEFT, | |
| 2185 | + WM8903_LINEOUTVU, WM8903_LINEOUTVU); | |
| 2186 | + regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT2_RIGHT, | |
| 2187 | + WM8903_LINEOUTVU, WM8903_LINEOUTVU); | |
| 2188 | + | |
| 2189 | + regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT3_LEFT, | |
| 2190 | + WM8903_SPKVU, WM8903_SPKVU); | |
| 2191 | + regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT3_RIGHT, | |
| 2192 | + WM8903_SPKVU, WM8903_SPKVU); | |
| 2193 | + | |
| 2194 | + /* Enable DAC soft mute by default */ | |
| 2195 | + regmap_update_bits(wm8903->regmap, WM8903_DAC_DIGITAL_1, | |
| 2196 | + WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE, | |
| 2197 | + WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE); | |
| 2198 | + | |
| 2192 | 2199 | ret = snd_soc_register_codec(&i2c->dev, |
| 2193 | 2200 | &soc_codec_dev_wm8903, &wm8903_dai, 1); |
| 2194 | 2201 | if (ret != 0) |
| @@ -2196,7 +2203,6 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, · 1 unmodified line | ||
| 2196 | 2203 | |
| 2197 | 2204 | return 0; |
| 2198 | 2205 | err: |
| 2199 | − regmap_exit(wm8903->regmap); | |
| 2200 | 2206 | return ret; |
| 2201 | 2207 | } |
| 2202 | 2208 | |
| @@ -2204,7 +2210,9 @@ static __devexit int wm8903_i2c_remove(struct i2c_client *client) · 1 unmodified line | ||
| 2204 | 2210 | { |
| 2205 | 2211 | struct wm8903_priv *wm8903 = i2c_get_clientdata(client); |
| 2206 | 2212 | |
| 2207 | − regmap_exit(wm8903->regmap); | |
| 2213 | + if (client->irq) | |
| 2214 | + free_irq(client->irq, wm8903); | |
| 2215 | + wm8903_free_gpio(wm8903); | |
| 2208 | 2216 | snd_soc_unregister_codec(&client->dev); |
| 2209 | 2217 | |
| 2210 | 2218 | return 0; |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * wm8904.c -- WM8904 ALSA SoC Audio driver |
| 3 | 3 | * |
| 4 | − * Copyright 2009 Wolfson Microelectronics plc | |
| 4 | + * Copyright 2009-12 Wolfson Microelectronics plc | |
| 5 | 5 | * |
| 6 | 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
| 7 | 7 | * |
| @@ -314,11 +314,6 @@ static bool wm8904_readable_register(struct device *dev, unsigned int reg) · 306 unmodified lines | ||
| 314 | 314 | } |
| 315 | 315 | } |
| 316 | 316 | |
| 317 | −static int wm8904_reset(struct snd_soc_codec *codec) | |
| 318 | −{ | |
| 319 | − return snd_soc_write(codec, WM8904_SW_RESET_AND_ID, 0); | |
| 320 | −} | |
| 321 | − | |
| 322 | 317 | static int wm8904_configure_clocking(struct snd_soc_codec *codec) |
| 323 | 318 | { |
| 324 | 319 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); |
| @@ -1945,25 +1940,6 @@ static struct snd_soc_dai_driver wm8904_dai = { · 1620 unmodified lines | ||
| 1945 | 1940 | .symmetric_rates = 1, |
| 1946 | 1941 | }; |
| 1947 | 1942 | |
| 1948 | −#ifdef CONFIG_PM | |
| 1949 | −static int wm8904_suspend(struct snd_soc_codec *codec) | |
| 1950 | −{ | |
| 1951 | − wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF); | |
| 1952 | − | |
| 1953 | − return 0; | |
| 1954 | −} | |
| 1955 | − | |
| 1956 | −static int wm8904_resume(struct snd_soc_codec *codec) | |
| 1957 | −{ | |
| 1958 | − wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | |
| 1959 | − | |
| 1960 | − return 0; | |
| 1961 | −} | |
| 1962 | −#else | |
| 1963 | −#define wm8904_suspend NULL | |
| 1964 | −#define wm8904_resume NULL | |
| 1965 | −#endif | |
| 1966 | − | |
| 1967 | 1943 | static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec) |
| 1968 | 1944 | { |
| 1969 | 1945 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); |
| @@ -2078,8 +2054,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec) · 108 unmodified lines | ||
| 2078 | 2054 | static int wm8904_probe(struct snd_soc_codec *codec) |
| 2079 | 2055 | { |
| 2080 | 2056 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); |
| 2081 | − struct wm8904_pdata *pdata = wm8904->pdata; | |
| 2082 | − int ret, i; | |
| 2057 | + int ret; | |
| 2083 | 2058 | |
| 2084 | 2059 | codec->control_data = wm8904->regmap; |
| 2085 | 2060 | |
| @@ -2101,127 +2076,17 @@ static int wm8904_probe(struct snd_soc_codec *codec) · 15 unmodified lines | ||
| 2101 | 2076 | return ret; |
| 2102 | 2077 | } |
| 2103 | 2078 | |
| 2104 | − for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++) | |
| 2105 | − wm8904->supplies[i].supply = wm8904_supply_names[i]; | |
| 2106 | − | |
| 2107 | − ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8904->supplies), | |
| 2108 | − wm8904->supplies); | |
| 2109 | − if (ret != 0) { | |
| 2110 | − dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | |
| 2111 | − return ret; | |
| 2112 | − } | |
| 2113 | − | |
| 2114 | − ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies), | |
| 2115 | − wm8904->supplies); | |
| 2116 | − if (ret != 0) { | |
| 2117 | − dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | |
| 2118 | − goto err_get; | |
| 2119 | − } | |
| 2120 | − | |
| 2121 | − ret = snd_soc_read(codec, WM8904_SW_RESET_AND_ID); | |
| 2122 | − if (ret < 0) { | |
| 2123 | − dev_err(codec->dev, "Failed to read ID register\n"); | |
| 2124 | − goto err_enable; | |
| 2125 | − } | |
| 2126 | − if (ret != 0x8904) { | |
| 2127 | − dev_err(codec->dev, "Device is not a WM8904, ID is %x\n", ret); | |
| 2128 | − ret = -EINVAL; | |
| 2129 | − goto err_enable; | |
| 2130 | − } | |
| 2131 | − | |
| 2132 | − ret = snd_soc_read(codec, WM8904_REVISION); | |
| 2133 | − if (ret < 0) { | |
| 2134 | − dev_err(codec->dev, "Failed to read device revision: %d\n", | |
| 2135 | − ret); | |
| 2136 | − goto err_enable; | |
| 2137 | − } | |
| 2138 | − dev_info(codec->dev, "revision %c\n", ret + 'A'); | |
| 2139 | − | |
| 2140 | − ret = wm8904_reset(codec); | |
| 2141 | − if (ret < 0) { | |
| 2142 | − dev_err(codec->dev, "Failed to issue reset\n"); | |
| 2143 | − goto err_enable; | |
| 2144 | − } | |
| 2145 | − | |
| 2146 | − regcache_cache_only(wm8904->regmap, true); | |
| 2147 | − /* Change some default settings - latch VU and enable ZC */ | |
| 2148 | − snd_soc_update_bits(codec, WM8904_ADC_DIGITAL_VOLUME_LEFT, | |
| 2149 | − WM8904_ADC_VU, WM8904_ADC_VU); | |
| 2150 | − snd_soc_update_bits(codec, WM8904_ADC_DIGITAL_VOLUME_RIGHT, | |
| 2151 | − WM8904_ADC_VU, WM8904_ADC_VU); | |
| 2152 | − snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_VOLUME_LEFT, | |
| 2153 | − WM8904_DAC_VU, WM8904_DAC_VU); | |
| 2154 | − snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_VOLUME_RIGHT, | |
| 2155 | − WM8904_DAC_VU, WM8904_DAC_VU); | |
| 2156 | − snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT1_LEFT, | |
| 2157 | − WM8904_HPOUT_VU | WM8904_HPOUTLZC, | |
| 2158 | − WM8904_HPOUT_VU | WM8904_HPOUTLZC); | |
| 2159 | − snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT1_RIGHT, | |
| 2160 | − WM8904_HPOUT_VU | WM8904_HPOUTRZC, | |
| 2161 | − WM8904_HPOUT_VU | WM8904_HPOUTRZC); | |
| 2162 | − snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT2_LEFT, | |
| 2163 | − WM8904_LINEOUT_VU | WM8904_LINEOUTLZC, | |
| 2164 | − WM8904_LINEOUT_VU | WM8904_LINEOUTLZC); | |
| 2165 | − snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT2_RIGHT, | |
| 2166 | − WM8904_LINEOUT_VU | WM8904_LINEOUTRZC, | |
| 2167 | − WM8904_LINEOUT_VU | WM8904_LINEOUTRZC); | |
| 2168 | − snd_soc_update_bits(codec, WM8904_CLOCK_RATES_0, | |
| 2169 | − WM8904_SR_MODE, 0); | |
| 2170 | − | |
| 2171 | − /* Apply configuration from the platform data. */ | |
| 2172 | − if (wm8904->pdata) { | |
| 2173 | − for (i = 0; i < WM8904_GPIO_REGS; i++) { | |
| 2174 | − if (!pdata->gpio_cfg[i]) | |
| 2175 | − continue; | |
| 2176 | − | |
| 2177 | − regmap_update_bits(wm8904->regmap, | |
| 2178 | − WM8904_GPIO_CONTROL_1 + i, | |
| 2179 | − 0xffff, | |
| 2180 | − pdata->gpio_cfg[i]); | |
| 2181 | − } | |
| 2182 | − | |
| 2183 | − /* Zero is the default value for these anyway */ | |
| 2184 | − for (i = 0; i < WM8904_MIC_REGS; i++) | |
| 2185 | − regmap_update_bits(wm8904->regmap, | |
| 2186 | − WM8904_MIC_BIAS_CONTROL_0 + i, | |
| 2187 | − 0xffff, | |
| 2188 | − pdata->mic_cfg[i]); | |
| 2189 | − } | |
| 2190 | − | |
| 2191 | − /* Set Class W by default - this will be managed by the Class | |
| 2192 | − * G widget at runtime where bypass paths are available. | |
| 2193 | − */ | |
| 2194 | − snd_soc_update_bits(codec, WM8904_CLASS_W_0, | |
| 2195 | − WM8904_CP_DYN_PWR, WM8904_CP_DYN_PWR); | |
| 2196 | − | |
| 2197 | − /* Use normal bias source */ | |
| 2198 | − snd_soc_update_bits(codec, WM8904_BIAS_CONTROL_0, | |
| 2199 | − WM8904_POBCTRL, 0); | |
| 2200 | − | |
| 2201 | − wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | |
| 2202 | − | |
| 2203 | − /* Bias level configuration will have done an extra enable */ | |
| 2204 | − regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); | |
| 2205 | − | |
| 2206 | 2079 | wm8904_handle_pdata(codec); |
| 2207 | 2080 | |
| 2208 | 2081 | wm8904_add_widgets(codec); |
| 2209 | 2082 | |
| 2210 | 2083 | return 0; |
| 2211 | − | |
| 2212 | −err_enable: | |
| 2213 | − regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); | |
| 2214 | −err_get: | |
| 2215 | − regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); | |
| 2216 | − return ret; | |
| 2217 | 2084 | } |
| 2218 | 2085 | |
| 2219 | 2086 | static int wm8904_remove(struct snd_soc_codec *codec) |
| 2220 | 2087 | { |
| 2221 | 2088 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); |
| 2222 | 2089 | |
| 2223 | − wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF); | |
| 2224 | − regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); | |
| 2225 | 2090 | kfree(wm8904->retune_mobile_texts); |
| 2226 | 2091 | kfree(wm8904->drc_texts); |
| 2227 | 2092 | |
| @@ -2231,8 +2096,6 @@ static int wm8904_remove(struct snd_soc_codec *codec) · 3 unmodified lines | ||
| 2231 | 2096 | static struct snd_soc_codec_driver soc_codec_dev_wm8904 = { |
| 2232 | 2097 | .probe = wm8904_probe, |
| 2233 | 2098 | .remove = wm8904_remove, |
| 2234 | − .suspend = wm8904_suspend, | |
| 2235 | − .resume = wm8904_resume, | |
| 2236 | 2099 | .set_bias_level = wm8904_set_bias_level, |
| 2237 | 2100 | .idle_bias_off = true, |
| 2238 | 2101 | }; |
| @@ -2254,14 +2117,15 @@ static __devinit int wm8904_i2c_probe(struct i2c_client *i2c, · 15 unmodified lines | ||
| 2254 | 2117 | const struct i2c_device_id *id) |
| 2255 | 2118 | { |
| 2256 | 2119 | struct wm8904_priv *wm8904; |
| 2257 | − int ret; | |
| 2120 | + unsigned int val; | |
| 2121 | + int ret, i; | |
| 2258 | 2122 | |
| 2259 | 2123 | wm8904 = devm_kzalloc(&i2c->dev, sizeof(struct wm8904_priv), |
| 2260 | 2124 | GFP_KERNEL); |
| 2261 | 2125 | if (wm8904 == NULL) |
| 2262 | 2126 | return -ENOMEM; |
| 2263 | 2127 | |
| 2264 | − wm8904->regmap = regmap_init_i2c(i2c, &wm8904_regmap); | |
| 2128 | + wm8904->regmap = devm_regmap_init_i2c(i2c, &wm8904_regmap); | |
| 2265 | 2129 | if (IS_ERR(wm8904->regmap)) { |
| 2266 | 2130 | ret = PTR_ERR(wm8904->regmap); |
| 2267 | 2131 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", |
| @@ -2273,23 +2137,121 @@ static __devinit int wm8904_i2c_probe(struct i2c_client *i2c, · 5 unmodified lines | ||
| 2273 | 2137 | i2c_set_clientdata(i2c, wm8904); |
| 2274 | 2138 | wm8904->pdata = i2c->dev.platform_data; |
| 2275 | 2139 | |
| 2140 | + for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++) | |
| 2141 | + wm8904->supplies[i].supply = wm8904_supply_names[i]; | |
| 2142 | + | |
| 2143 | + ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8904->supplies), | |
| 2144 | + wm8904->supplies); | |
| 2145 | + if (ret != 0) { | |
| 2146 | + dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); | |
| 2147 | + return ret; | |
| 2148 | + } | |
| 2149 | + | |
| 2150 | + ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies), | |
| 2151 | + wm8904->supplies); | |
| 2152 | + if (ret != 0) { | |
| 2153 | + dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); | |
| 2154 | + return ret; | |
| 2155 | + } | |
| 2156 | + | |
| 2157 | + ret = regmap_read(wm8904->regmap, WM8904_SW_RESET_AND_ID, &val); | |
| 2158 | + if (ret < 0) { | |
| 2159 | + dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret); | |
| 2160 | + goto err_enable; | |
| 2161 | + } | |
| 2162 | + if (val != 0x8904) { | |
| 2163 | + dev_err(&i2c->dev, "Device is not a WM8904, ID is %x\n", val); | |
| 2164 | + ret = -EINVAL; | |
| 2165 | + goto err_enable; | |
| 2166 | + } | |
| 2167 | + | |
| 2168 | + ret = regmap_read(wm8904->regmap, WM8904_REVISION, &val); | |
| 2169 | + if (ret < 0) { | |
| 2170 | + dev_err(&i2c->dev, "Failed to read device revision: %d\n", | |
| 2171 | + ret); | |
| 2172 | + goto err_enable; | |
| 2173 | + } | |
| 2174 | + dev_info(&i2c->dev, "revision %c\n", val + 'A'); | |
| 2175 | + | |
| 2176 | + ret = regmap_write(wm8904->regmap, WM8904_SW_RESET_AND_ID, 0); | |
| 2177 | + if (ret < 0) { | |
| 2178 | + dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret); | |
| 2179 | + goto err_enable; | |
| 2180 | + } | |
| 2181 | + | |
| 2182 | + /* Change some default settings - latch VU and enable ZC */ | |
| 2183 | + regmap_update_bits(wm8904->regmap, WM8904_ADC_DIGITAL_VOLUME_LEFT, | |
| 2184 | + WM8904_ADC_VU, WM8904_ADC_VU); | |
| 2185 | + regmap_update_bits(wm8904->regmap, WM8904_ADC_DIGITAL_VOLUME_RIGHT, | |
| 2186 | + WM8904_ADC_VU, WM8904_ADC_VU); | |
| 2187 | + regmap_update_bits(wm8904->regmap, WM8904_DAC_DIGITAL_VOLUME_LEFT, | |
| 2188 | + WM8904_DAC_VU, WM8904_DAC_VU); | |
| 2189 | + regmap_update_bits(wm8904->regmap, WM8904_DAC_DIGITAL_VOLUME_RIGHT, | |
| 2190 | + WM8904_DAC_VU, WM8904_DAC_VU); | |
| 2191 | + regmap_update_bits(wm8904->regmap, WM8904_ANALOGUE_OUT1_LEFT, | |
| 2192 | + WM8904_HPOUT_VU | WM8904_HPOUTLZC, | |
| 2193 | + WM8904_HPOUT_VU | WM8904_HPOUTLZC); | |
| 2194 | + regmap_update_bits(wm8904->regmap, WM8904_ANALOGUE_OUT1_RIGHT, | |
| 2195 | + WM8904_HPOUT_VU | WM8904_HPOUTRZC, | |
| 2196 | + WM8904_HPOUT_VU | WM8904_HPOUTRZC); | |
| 2197 | + regmap_update_bits(wm8904->regmap, WM8904_ANALOGUE_OUT2_LEFT, | |
| 2198 | + WM8904_LINEOUT_VU | WM8904_LINEOUTLZC, | |
| 2199 | + WM8904_LINEOUT_VU | WM8904_LINEOUTLZC); | |
| 2200 | + regmap_update_bits(wm8904->regmap, WM8904_ANALOGUE_OUT2_RIGHT, | |
| 2201 | + WM8904_LINEOUT_VU | WM8904_LINEOUTRZC, | |
| 2202 | + WM8904_LINEOUT_VU | WM8904_LINEOUTRZC); | |
| 2203 | + regmap_update_bits(wm8904->regmap, WM8904_CLOCK_RATES_0, | |
| 2204 | + WM8904_SR_MODE, 0); | |
| 2205 | + | |
| 2206 | + /* Apply configuration from the platform data. */ | |
| 2207 | + if (wm8904->pdata) { | |
| 2208 | + for (i = 0; i < WM8904_GPIO_REGS; i++) { | |
| 2209 | + if (!wm8904->pdata->gpio_cfg[i]) | |
| 2210 | + continue; | |
| 2211 | + | |
| 2212 | + regmap_update_bits(wm8904->regmap, | |
| 2213 | + WM8904_GPIO_CONTROL_1 + i, | |
| 2214 | + 0xffff, | |
| 2215 | + wm8904->pdata->gpio_cfg[i]); | |
| 2216 | + } | |
| 2217 | + | |
| 2218 | + /* Zero is the default value for these anyway */ | |
| 2219 | + for (i = 0; i < WM8904_MIC_REGS; i++) | |
| 2220 | + regmap_update_bits(wm8904->regmap, | |
| 2221 | + WM8904_MIC_BIAS_CONTROL_0 + i, | |
| 2222 | + 0xffff, | |
| 2223 | + wm8904->pdata->mic_cfg[i]); | |
| 2224 | + } | |
| 2225 | + | |
| 2226 | + /* Set Class W by default - this will be managed by the Class | |
| 2227 | + * G widget at runtime where bypass paths are available. | |
| 2228 | + */ | |
| 2229 | + regmap_update_bits(wm8904->regmap, WM8904_CLASS_W_0, | |
| 2230 | + WM8904_CP_DYN_PWR, WM8904_CP_DYN_PWR); | |
| 2231 | + | |
| 2232 | + /* Use normal bias source */ | |
| 2233 | + regmap_update_bits(wm8904->regmap, WM8904_BIAS_CONTROL_0, | |
| 2234 | + WM8904_POBCTRL, 0); | |
| 2235 | + | |
| 2236 | + /* Can leave the device powered off until we need it */ | |
| 2237 | + regcache_cache_only(wm8904->regmap, true); | |
| 2238 | + regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); | |
| 2239 | + | |
| 2276 | 2240 | ret = snd_soc_register_codec(&i2c->dev, |
| 2277 | 2241 | &soc_codec_dev_wm8904, &wm8904_dai, 1); |
| 2278 | 2242 | if (ret != 0) |
| 2279 | − goto err; | |
| 2243 | + return ret; | |
| 2280 | 2244 | |
| 2281 | 2245 | return 0; |
| 2282 | 2246 | |
| 2283 | −err: | |
| 2284 | − regmap_exit(wm8904->regmap); | |
| 2247 | +err_enable: | |
| 2248 | + regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); | |
| 2285 | 2249 | return ret; |
| 2286 | 2250 | } |
| 2287 | 2251 | |
| 2288 | 2252 | static __devexit int wm8904_i2c_remove(struct i2c_client *client) |
| 2289 | 2253 | { |
| 2290 | − struct wm8904_priv *wm8904 = i2c_get_clientdata(client); | |
| 2291 | 2254 | snd_soc_unregister_codec(&client->dev); |
| 2292 | − regmap_exit(wm8904->regmap); | |
| 2293 | 2255 | return 0; |
| 2294 | 2256 | } |
| 2295 | 2257 | |
| @@ -2311,23 +2273,7 @@ static struct i2c_driver wm8904_i2c_driver = { · 15 unmodified lines | ||
| 2311 | 2273 | .id_table = wm8904_i2c_id, |
| 2312 | 2274 | }; |
| 2313 | 2275 | |
| 2314 | −static int __init wm8904_modinit(void) | |
| 2315 | −{ | |
| 2316 | − int ret = 0; | |
| 2317 | − ret = i2c_add_driver(&wm8904_i2c_driver); | |
| 2318 | − if (ret != 0) { | |
| 2319 | − printk(KERN_ERR "Failed to register wm8904 I2C driver: %d\n", | |
| 2320 | − ret); | |
| 2321 | − } | |
| 2322 | − return ret; | |
| 2323 | −} | |
| 2324 | −module_init(wm8904_modinit); | |
| 2325 | − | |
| 2326 | −static void __exit wm8904_exit(void) | |
| 2327 | −{ | |
| 2328 | − i2c_del_driver(&wm8904_i2c_driver); | |
| 2329 | −} | |
| 2330 | −module_exit(wm8904_exit); | |
| 2276 | +module_i2c_driver(wm8904_i2c_driver); | |
| 2331 | 2277 | |
| 2332 | 2278 | MODULE_DESCRIPTION("ASoC WM8904 driver"); |
| 2333 | 2279 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
| @@ -1,6 +1,8 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * wm8960.c -- WM8960 ALSA SoC Audio driver |
| 3 | 3 | * |
| 4 | + * Copyright 2007-11 Wolfson Microelectronics, plc | |
| 5 | + * | |
| 4 | 6 | * Author: Liam Girdwood |
| 5 | 7 | * |
| 6 | 8 | * This program is free software; you can redistribute it and/or modify |
| @@ -1,6 +1,8 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * wm8961.c -- WM8961 ALSA SoC Audio driver |
| 3 | 3 | * |
| 4 | + * Copyright 2009-10 Wolfson Microelectronics, plc | |
| 5 | + * | |
| 4 | 6 | * Author: Mark Brown |
| 5 | 7 | * |
| 6 | 8 | * This program is free software; you can redistribute it and/or modify |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * wm8962.c -- WM8962 ALSA SoC Audio driver |
| 3 | 3 | * |
| 4 | − * Copyright 2010 Wolfson Microelectronics plc | |
| 4 | + * Copyright 2010-2 Wolfson Microelectronics plc | |
| 5 | 5 | * |
| 6 | 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
| 7 | 7 | * |
| @@ -2580,6 +2580,9 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream, · 2572 unmodified lines | ||
| 2580 | 2580 | WM8962_SAMPLE_RATE_INT_MODE | |
| 2581 | 2581 | WM8962_SAMPLE_RATE_MASK, adctl3); |
| 2582 | 2582 | |
| 2583 | + dev_dbg(codec->dev, "hw_params set BCLK %dHz LRCLK %dHz\n", | |
| 2584 | + wm8962->bclk, wm8962->lrclk); | |
| 2585 | + | |
| 2583 | 2586 | if (codec->dapm.bias_level == SND_SOC_BIAS_ON) |
| 2584 | 2587 | wm8962_configure_bclk(codec); |
| 2585 | 2588 | |
| @@ -3722,6 +3725,9 @@ static int wm8962_runtime_resume(struct device *dev) · 1136 unmodified lines | ||
| 3722 | 3725 | } |
| 3723 | 3726 | |
| 3724 | 3727 | regcache_cache_only(wm8962->regmap, false); |
| 3728 | + | |
| 3729 | + wm8962_reset(wm8962); | |
| 3730 | + | |
| 3725 | 3731 | regcache_sync(wm8962->regmap); |
| 3726 | 3732 | |
| 3727 | 3733 | regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP, |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * wm8993.c -- WM8993 ALSA SoC audio driver |
| 3 | 3 | * |
| 4 | − * Copyright 2009, 2010 Wolfson Microelectronics plc | |
| 4 | + * Copyright 2009-12 Wolfson Microelectronics plc | |
| 5 | 5 | * |
| 6 | 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
| 7 | 7 | * |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * wm8994.c -- WM8994 ALSA SoC Audio driver |
| 3 | 3 | * |
| 4 | − * Copyright 2009 Wolfson Microelectronics plc | |
| 4 | + * Copyright 2009-12 Wolfson Microelectronics plc | |
| 5 | 5 | * |
| 6 | 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
| 7 | 7 | * |
| @@ -2967,23 +2967,8 @@ static struct snd_soc_dai_driver wm8994_dai[] = { · 2959 unmodified lines | ||
| 2967 | 2967 | static int wm8994_codec_suspend(struct snd_soc_codec *codec) |
| 2968 | 2968 | { |
| 2969 | 2969 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
| 2970 | − struct wm8994 *control = wm8994->wm8994; | |
| 2971 | 2970 | int i, ret; |
| 2972 | 2971 | |
| 2973 | − switch (control->type) { | |
| 2974 | − case WM8994: | |
| 2975 | − snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, 0); | |
| 2976 | − break; | |
| 2977 | − case WM1811: | |
| 2978 | − snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | |
| 2979 | − WM1811_JACKDET_MODE_MASK, 0); | |
| 2980 | − /* Fall through */ | |
| 2981 | − case WM8958: | |
| 2982 | − snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, | |
| 2983 | − WM8958_MICD_ENA, 0); | |
| 2984 | − break; | |
| 2985 | − } | |
| 2986 | − | |
| 2987 | 2972 | for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { |
| 2988 | 2973 | memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i], |
| 2989 | 2974 | sizeof(struct wm8994_fll_config)); |
| @@ -3033,28 +3018,6 @@ static int wm8994_codec_resume(struct snd_soc_codec *codec) · 43 unmodified lines | ||
| 3033 | 3018 | i + 1, ret); |
| 3034 | 3019 | } |
| 3035 | 3020 | |
| 3036 | − switch (control->type) { | |
| 3037 | − case WM8994: | |
| 3038 | − if (wm8994->micdet[0].jack || wm8994->micdet[1].jack) | |
| 3039 | − snd_soc_update_bits(codec, WM8994_MICBIAS, | |
| 3040 | − WM8994_MICD_ENA, WM8994_MICD_ENA); | |
| 3041 | − break; | |
| 3042 | − case WM1811: | |
| 3043 | − if (wm8994->jackdet && wm8994->jack_cb) { | |
| 3044 | − /* Restart from idle */ | |
| 3045 | − snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | |
| 3046 | − WM1811_JACKDET_MODE_MASK, | |
| 3047 | − WM1811_JACKDET_MODE_JACK); | |
| 3048 | − break; | |
| 3049 | − } | |
| 3050 | − break; | |
| 3051 | − case WM8958: | |
| 3052 | − if (wm8994->jack_cb) | |
| 3053 | − snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, | |
| 3054 | − WM8958_MICD_ENA, WM8958_MICD_ENA); | |
| 3055 | − break; | |
| 3056 | − } | |
| 3057 | − | |
| 3058 | 3021 | return 0; |
| 3059 | 3022 | } |
| 3060 | 3023 | #else |
| @@ -3729,9 +3692,6 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) · 668 unmodified lines | ||
| 3729 | 3692 | |
| 3730 | 3693 | if (wm8994->pdata && wm8994->pdata->micdet_irq) |
| 3731 | 3694 | wm8994->micdet_irq = wm8994->pdata->micdet_irq; |
| 3732 | − else if (wm8994->pdata && wm8994->pdata->irq_base) | |
| 3733 | − wm8994->micdet_irq = wm8994->pdata->irq_base + | |
| 3734 | − WM8994_IRQ_MIC1_DET; | |
| 3735 | 3695 | |
| 3736 | 3696 | pm_runtime_enable(codec->dev); |
| 3737 | 3697 | pm_runtime_idle(codec->dev); |
| @@ -3870,6 +3830,10 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) · 132 unmodified lines | ||
| 3870 | 3830 | dev_warn(codec->dev, |
| 3871 | 3831 | "Failed to request Mic detect IRQ: %d\n", |
| 3872 | 3832 | ret); |
| 3833 | + } else { | |
| 3834 | + wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_MIC1_DET, | |
| 3835 | + wm8958_mic_irq, "Mic detect", | |
| 3836 | + wm8994); | |
| 3873 | 3837 | } |
| 3874 | 3838 | } |
| 3875 | 3839 | |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * wm8996.c - WM8996 audio codec interface |
| 3 | 3 | * |
| 4 | − * Copyright 2011 Wolfson Microelectronics PLC. | |
| 4 | + * Copyright 2011-2 Wolfson Microelectronics PLC. | |
| 5 | 5 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
| 6 | 6 | * |
| 7 | 7 | * This program is free software; you can redistribute it and/or modify it |
| @@ -296,184 +296,6 @@ static struct reg_default wm8996_reg[] = { · 288 unmodified lines | ||
| 296 | 296 | { WM8996_RIGHT_PDM_SPEAKER, 0x1 }, |
| 297 | 297 | { WM8996_PDM_SPEAKER_MUTE_SEQUENCE, 0x69 }, |
| 298 | 298 | { WM8996_PDM_SPEAKER_VOLUME, 0x66 }, |
| 299 | − { WM8996_WRITE_SEQUENCER_0, 0x1 }, | |
| 300 | − { WM8996_WRITE_SEQUENCER_1, 0x1 }, | |
| 301 | − { WM8996_WRITE_SEQUENCER_3, 0x6 }, | |
| 302 | − { WM8996_WRITE_SEQUENCER_4, 0x40 }, | |
| 303 | − { WM8996_WRITE_SEQUENCER_5, 0x1 }, | |
| 304 | − { WM8996_WRITE_SEQUENCER_6, 0xf }, | |
| 305 | − { WM8996_WRITE_SEQUENCER_7, 0x6 }, | |
| 306 | − { WM8996_WRITE_SEQUENCER_8, 0x1 }, | |
| 307 | − { WM8996_WRITE_SEQUENCER_9, 0x3 }, | |
| 308 | − { WM8996_WRITE_SEQUENCER_10, 0x104 }, | |
| 309 | − { WM8996_WRITE_SEQUENCER_12, 0x60 }, | |
| 310 | − { WM8996_WRITE_SEQUENCER_13, 0x11 }, | |
| 311 | − { WM8996_WRITE_SEQUENCER_14, 0x401 }, | |
| 312 | − { WM8996_WRITE_SEQUENCER_16, 0x50 }, | |
| 313 | − { WM8996_WRITE_SEQUENCER_17, 0x3 }, | |
| 314 | − { WM8996_WRITE_SEQUENCER_18, 0x100 }, | |
| 315 | − { WM8996_WRITE_SEQUENCER_20, 0x51 }, | |
| 316 | − { WM8996_WRITE_SEQUENCER_21, 0x3 }, | |
| 317 | − { WM8996_WRITE_SEQUENCER_22, 0x104 }, | |
| 318 | − { WM8996_WRITE_SEQUENCER_23, 0xa }, | |
| 319 | − { WM8996_WRITE_SEQUENCER_24, 0x60 }, | |
| 320 | − { WM8996_WRITE_SEQUENCER_25, 0x3b }, | |
| 321 | − { WM8996_WRITE_SEQUENCER_26, 0x502 }, | |
| 322 | − { WM8996_WRITE_SEQUENCER_27, 0x100 }, | |
| 323 | − { WM8996_WRITE_SEQUENCER_28, 0x2fff }, | |
| 324 | − { WM8996_WRITE_SEQUENCER_32, 0x2fff }, | |
| 325 | − { WM8996_WRITE_SEQUENCER_36, 0x2fff }, | |
| 326 | − { WM8996_WRITE_SEQUENCER_40, 0x2fff }, | |
| 327 | − { WM8996_WRITE_SEQUENCER_44, 0x2fff }, | |
| 328 | − { WM8996_WRITE_SEQUENCER_48, 0x2fff }, | |
| 329 | − { WM8996_WRITE_SEQUENCER_52, 0x2fff }, | |
| 330 | − { WM8996_WRITE_SEQUENCER_56, 0x2fff }, | |
| 331 | − { WM8996_WRITE_SEQUENCER_60, 0x2fff }, | |
| 332 | − { WM8996_WRITE_SEQUENCER_64, 0x1 }, | |
| 333 | − { WM8996_WRITE_SEQUENCER_65, 0x1 }, | |
| 334 | − { WM8996_WRITE_SEQUENCER_67, 0x6 }, | |
| 335 | − { WM8996_WRITE_SEQUENCER_68, 0x40 }, | |
| 336 | − { WM8996_WRITE_SEQUENCER_69, 0x1 }, | |
| 337 | − { WM8996_WRITE_SEQUENCER_70, 0xf }, | |
| 338 | − { WM8996_WRITE_SEQUENCER_71, 0x6 }, | |
| 339 | − { WM8996_WRITE_SEQUENCER_72, 0x1 }, | |
| 340 | − { WM8996_WRITE_SEQUENCER_73, 0x3 }, | |
| 341 | − { WM8996_WRITE_SEQUENCER_74, 0x104 }, | |
| 342 | − { WM8996_WRITE_SEQUENCER_76, 0x60 }, | |
| 343 | − { WM8996_WRITE_SEQUENCER_77, 0x11 }, | |
| 344 | − { WM8996_WRITE_SEQUENCER_78, 0x401 }, | |
| 345 | − { WM8996_WRITE_SEQUENCER_80, 0x50 }, | |
| 346 | − { WM8996_WRITE_SEQUENCER_81, 0x3 }, | |
| 347 | − { WM8996_WRITE_SEQUENCER_82, 0x100 }, | |
| 348 | − { WM8996_WRITE_SEQUENCER_84, 0x60 }, | |
| 349 | − { WM8996_WRITE_SEQUENCER_85, 0x3b }, | |
| 350 | − { WM8996_WRITE_SEQUENCER_86, 0x502 }, | |
| 351 | − { WM8996_WRITE_SEQUENCER_87, 0x100 }, | |
| 352 | − { WM8996_WRITE_SEQUENCER_88, 0x2fff }, | |
| 353 | − { WM8996_WRITE_SEQUENCER_92, 0x2fff }, | |
| 354 | − { WM8996_WRITE_SEQUENCER_96, 0x2fff }, | |
| 355 | − { WM8996_WRITE_SEQUENCER_100, 0x2fff }, | |
| 356 | − { WM8996_WRITE_SEQUENCER_104, 0x2fff }, | |
| 357 | − { WM8996_WRITE_SEQUENCER_108, 0x2fff }, | |
| 358 | − { WM8996_WRITE_SEQUENCER_112, 0x2fff }, | |
| 359 | − { WM8996_WRITE_SEQUENCER_116, 0x2fff }, | |
| 360 | − { WM8996_WRITE_SEQUENCER_120, 0x2fff }, | |
| 361 | − { WM8996_WRITE_SEQUENCER_124, 0x2fff }, | |
| 362 | − { WM8996_WRITE_SEQUENCER_128, 0x1 }, | |
| 363 | − { WM8996_WRITE_SEQUENCER_129, 0x1 }, | |
| 364 | − { WM8996_WRITE_SEQUENCER_131, 0x6 }, | |
| 365 | − { WM8996_WRITE_SEQUENCER_132, 0x40 }, | |
| 366 | − { WM8996_WRITE_SEQUENCER_133, 0x1 }, | |
| 367 | − { WM8996_WRITE_SEQUENCER_134, 0xf }, | |
| 368 | − { WM8996_WRITE_SEQUENCER_135, 0x6 }, | |
| 369 | − { WM8996_WRITE_SEQUENCER_136, 0x1 }, | |
| 370 | − { WM8996_WRITE_SEQUENCER_137, 0x3 }, | |
| 371 | − { WM8996_WRITE_SEQUENCER_138, 0x106 }, | |
| 372 | − { WM8996_WRITE_SEQUENCER_140, 0x61 }, | |
| 373 | − { WM8996_WRITE_SEQUENCER_141, 0x11 }, | |
| 374 | − { WM8996_WRITE_SEQUENCER_142, 0x401 }, | |
| 375 | − { WM8996_WRITE_SEQUENCER_144, 0x50 }, | |
| 376 | − { WM8996_WRITE_SEQUENCER_145, 0x3 }, | |
| 377 | − { WM8996_WRITE_SEQUENCER_146, 0x102 }, | |
| 378 | − { WM8996_WRITE_SEQUENCER_148, 0x51 }, | |
| 379 | − { WM8996_WRITE_SEQUENCER_149, 0x3 }, | |
| 380 | − { WM8996_WRITE_SEQUENCER_150, 0x106 }, | |
| 381 | − { WM8996_WRITE_SEQUENCER_151, 0xa }, | |
| 382 | − { WM8996_WRITE_SEQUENCER_152, 0x61 }, | |
| 383 | − { WM8996_WRITE_SEQUENCER_153, 0x3b }, | |
| 384 | − { WM8996_WRITE_SEQUENCER_154, 0x502 }, | |
| 385 | − { WM8996_WRITE_SEQUENCER_155, 0x100 }, | |
| 386 | − { WM8996_WRITE_SEQUENCER_156, 0x2fff }, | |
| 387 | − { WM8996_WRITE_SEQUENCER_160, 0x2fff }, | |
| 388 | − { WM8996_WRITE_SEQUENCER_164, 0x2fff }, | |
| 389 | − { WM8996_WRITE_SEQUENCER_168, 0x2fff }, | |
| 390 | − { WM8996_WRITE_SEQUENCER_172, 0x2fff }, | |
| 391 | − { WM8996_WRITE_SEQUENCER_176, 0x2fff }, | |
| 392 | − { WM8996_WRITE_SEQUENCER_180, 0x2fff }, | |
| 393 | − { WM8996_WRITE_SEQUENCER_184, 0x2fff }, | |
| 394 | − { WM8996_WRITE_SEQUENCER_188, 0x2fff }, | |
| 395 | − { WM8996_WRITE_SEQUENCER_192, 0x1 }, | |
| 396 | − { WM8996_WRITE_SEQUENCER_193, 0x1 }, | |
| 397 | − { WM8996_WRITE_SEQUENCER_195, 0x6 }, | |
| 398 | − { WM8996_WRITE_SEQUENCER_196, 0x40 }, | |
| 399 | − { WM8996_WRITE_SEQUENCER_197, 0x1 }, | |
| 400 | − { WM8996_WRITE_SEQUENCER_198, 0xf }, | |
| 401 | − { WM8996_WRITE_SEQUENCER_199, 0x6 }, | |
| 402 | − { WM8996_WRITE_SEQUENCER_200, 0x1 }, | |
| 403 | − { WM8996_WRITE_SEQUENCER_201, 0x3 }, | |
| 404 | − { WM8996_WRITE_SEQUENCER_202, 0x106 }, | |
| 405 | − { WM8996_WRITE_SEQUENCER_204, 0x61 }, | |
| 406 | − { WM8996_WRITE_SEQUENCER_205, 0x11 }, | |
| 407 | − { WM8996_WRITE_SEQUENCER_206, 0x401 }, | |
| 408 | − { WM8996_WRITE_SEQUENCER_208, 0x50 }, | |
| 409 | − { WM8996_WRITE_SEQUENCER_209, 0x3 }, | |
| 410 | − { WM8996_WRITE_SEQUENCER_210, 0x102 }, | |
| 411 | − { WM8996_WRITE_SEQUENCER_212, 0x61 }, | |
| 412 | − { WM8996_WRITE_SEQUENCER_213, 0x3b }, | |
| 413 | − { WM8996_WRITE_SEQUENCER_214, 0x502 }, | |
| 414 | − { WM8996_WRITE_SEQUENCER_215, 0x100 }, | |
| 415 | − { WM8996_WRITE_SEQUENCER_216, 0x2fff }, | |
| 416 | − { WM8996_WRITE_SEQUENCER_220, 0x2fff }, | |
| 417 | − { WM8996_WRITE_SEQUENCER_224, 0x2fff }, | |
| 418 | − { WM8996_WRITE_SEQUENCER_228, 0x2fff }, | |
| 419 | − { WM8996_WRITE_SEQUENCER_232, 0x2fff }, | |
| 420 | − { WM8996_WRITE_SEQUENCER_236, 0x2fff }, | |
| 421 | − { WM8996_WRITE_SEQUENCER_240, 0x2fff }, | |
| 422 | − { WM8996_WRITE_SEQUENCER_244, 0x2fff }, | |
| 423 | − { WM8996_WRITE_SEQUENCER_248, 0x2fff }, | |
| 424 | − { WM8996_WRITE_SEQUENCER_252, 0x2fff }, | |
| 425 | − { WM8996_WRITE_SEQUENCER_256, 0x60 }, | |
| 426 | − { WM8996_WRITE_SEQUENCER_258, 0x601 }, | |
| 427 | − { WM8996_WRITE_SEQUENCER_260, 0x50 }, | |
| 428 | − { WM8996_WRITE_SEQUENCER_262, 0x100 }, | |
| 429 | − { WM8996_WRITE_SEQUENCER_264, 0x1 }, | |
| 430 | − { WM8996_WRITE_SEQUENCER_266, 0x104 }, | |
| 431 | − { WM8996_WRITE_SEQUENCER_267, 0x100 }, | |
| 432 | − { WM8996_WRITE_SEQUENCER_268, 0x2fff }, | |
| 433 | − { WM8996_WRITE_SEQUENCER_272, 0x2fff }, | |
| 434 | − { WM8996_WRITE_SEQUENCER_276, 0x2fff }, | |
| 435 | − { WM8996_WRITE_SEQUENCER_280, 0x2fff }, | |
| 436 | − { WM8996_WRITE_SEQUENCER_284, 0x2fff }, | |
| 437 | − { WM8996_WRITE_SEQUENCER_288, 0x2fff }, | |
| 438 | − { WM8996_WRITE_SEQUENCER_292, 0x2fff }, | |
| 439 | − { WM8996_WRITE_SEQUENCER_296, 0x2fff }, | |
| 440 | − { WM8996_WRITE_SEQUENCER_300, 0x2fff }, | |
| 441 | − { WM8996_WRITE_SEQUENCER_304, 0x2fff }, | |
| 442 | − { WM8996_WRITE_SEQUENCER_308, 0x2fff }, | |
| 443 | − { WM8996_WRITE_SEQUENCER_312, 0x2fff }, | |
| 444 | − { WM8996_WRITE_SEQUENCER_316, 0x2fff }, | |
| 445 | − { WM8996_WRITE_SEQUENCER_320, 0x61 }, | |
| 446 | − { WM8996_WRITE_SEQUENCER_322, 0x601 }, | |
| 447 | − { WM8996_WRITE_SEQUENCER_324, 0x50 }, | |
| 448 | − { WM8996_WRITE_SEQUENCER_326, 0x102 }, | |
| 449 | − { WM8996_WRITE_SEQUENCER_328, 0x1 }, | |
| 450 | − { WM8996_WRITE_SEQUENCER_330, 0x106 }, | |
| 451 | − { WM8996_WRITE_SEQUENCER_331, 0x100 }, | |
| 452 | − { WM8996_WRITE_SEQUENCER_332, 0x2fff }, | |
| 453 | − { WM8996_WRITE_SEQUENCER_336, 0x2fff }, | |
| 454 | − { WM8996_WRITE_SEQUENCER_340, 0x2fff }, | |
| 455 | − { WM8996_WRITE_SEQUENCER_344, 0x2fff }, | |
| 456 | − { WM8996_WRITE_SEQUENCER_348, 0x2fff }, | |
| 457 | − { WM8996_WRITE_SEQUENCER_352, 0x2fff }, | |
| 458 | − { WM8996_WRITE_SEQUENCER_356, 0x2fff }, | |
| 459 | − { WM8996_WRITE_SEQUENCER_360, 0x2fff }, | |
| 460 | − { WM8996_WRITE_SEQUENCER_364, 0x2fff }, | |
| 461 | − { WM8996_WRITE_SEQUENCER_368, 0x2fff }, | |
| 462 | − { WM8996_WRITE_SEQUENCER_372, 0x2fff }, | |
| 463 | − { WM8996_WRITE_SEQUENCER_376, 0x2fff }, | |
| 464 | − { WM8996_WRITE_SEQUENCER_380, 0x2fff }, | |
| 465 | − { WM8996_WRITE_SEQUENCER_384, 0x60 }, | |
| 466 | − { WM8996_WRITE_SEQUENCER_386, 0x601 }, | |
| 467 | − { WM8996_WRITE_SEQUENCER_388, 0x61 }, | |
| 468 | − { WM8996_WRITE_SEQUENCER_390, 0x601 }, | |
| 469 | − { WM8996_WRITE_SEQUENCER_392, 0x50 }, | |
| 470 | − { WM8996_WRITE_SEQUENCER_394, 0x300 }, | |
| 471 | − { WM8996_WRITE_SEQUENCER_396, 0x1 }, | |
| 472 | − { WM8996_WRITE_SEQUENCER_398, 0x304 }, | |
| 473 | − { WM8996_WRITE_SEQUENCER_400, 0x40 }, | |
| 474 | − { WM8996_WRITE_SEQUENCER_402, 0xf }, | |
| 475 | − { WM8996_WRITE_SEQUENCER_404, 0x1 }, | |
| 476 | − { WM8996_WRITE_SEQUENCER_407, 0x100 }, | |
| 477 | 299 | }; |
| 478 | 300 | |
| 479 | 301 | static const DECLARE_TLV_DB_SCALE(inpga_tlv, 0, 100, 0); |
| @@ -1706,18 +1528,6 @@ static bool wm8996_volatile_register(struct device *dev, unsigned int reg) · 1226 unmodified lines | ||
| 1706 | 1528 | } |
| 1707 | 1529 | } |
| 1708 | 1530 | |
| 1709 | −static int wm8996_reset(struct wm8996_priv *wm8996) | |
| 1710 | −{ | |
| 1711 | − if (wm8996->pdata.ldo_ena > 0) { | |
| 1712 | − gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); | |
| 1713 | − gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 1); | |
| 1714 | − return 0; | |
| 1715 | − } else { | |
| 1716 | − return regmap_write(wm8996->regmap, WM8996_SOFTWARE_RESET, | |
| 1717 | − 0x8915); | |
| 1718 | − } | |
| 1719 | −} | |
| 1720 | − | |
| 1721 | 1531 | static const int bclk_divs[] = { |
| 1722 | 1532 | 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96 |
| 1723 | 1533 | }; |
| @@ -1809,8 +1619,10 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec, · 85 unmodified lines | ||
| 1809 | 1619 | |
| 1810 | 1620 | case SND_SOC_BIAS_OFF: |
| 1811 | 1621 | regcache_cache_only(codec->control_data, true); |
| 1812 | − if (wm8996->pdata.ldo_ena >= 0) | |
| 1622 | + if (wm8996->pdata.ldo_ena >= 0) { | |
| 1813 | 1623 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); |
| 1624 | + regcache_cache_only(codec->control_data, true); | |
| 1625 | + } | |
| 1814 | 1626 | regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), |
| 1815 | 1627 | wm8996->supplies); |
| 1816 | 1628 | break; |
| @@ -2807,7 +2619,7 @@ static int wm8996_probe(struct snd_soc_codec *codec) · 990 unmodified lines | ||
| 2807 | 2619 | int ret; |
| 2808 | 2620 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); |
| 2809 | 2621 | struct i2c_client *i2c = to_i2c_client(codec->dev); |
| 2810 | − int i, irq_flags; | |
| 2622 | + int irq_flags; | |
| 2811 | 2623 | |
| 2812 | 2624 | wm8996->codec = codec; |
| 2813 | 2625 | |
| @@ -2822,177 +2634,12 @@ static int wm8996_probe(struct snd_soc_codec *codec) · 8 unmodified lines | ||
| 2822 | 2634 | goto err; |
| 2823 | 2635 | } |
| 2824 | 2636 | |
| 2825 | − wm8996->disable_nb[0].notifier_call = wm8996_regulator_event_0; | |
| 2826 | − wm8996->disable_nb[1].notifier_call = wm8996_regulator_event_1; | |
| 2827 | − wm8996->disable_nb[2].notifier_call = wm8996_regulator_event_2; | |
| 2828 | − | |
| 2829 | − /* This should really be moved into the regulator core */ | |
| 2830 | − for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) { | |
| 2831 | − ret = regulator_register_notifier(wm8996->supplies[i].consumer, | |
| 2832 | − &wm8996->disable_nb[i]); | |
| 2833 | − if (ret != 0) { | |
| 2834 | − dev_err(codec->dev, | |
| 2835 | − "Failed to register regulator notifier: %d\n", | |
| 2836 | − ret); | |
| 2837 | − } | |
| 2838 | − } | |
| 2839 | − | |
| 2840 | − /* Apply platform data settings */ | |
| 2841 | − snd_soc_update_bits(codec, WM8996_LINE_INPUT_CONTROL, | |
| 2842 | − WM8996_INL_MODE_MASK | WM8996_INR_MODE_MASK, | |
| 2843 | − wm8996->pdata.inl_mode << WM8996_INL_MODE_SHIFT | | |
| 2844 | − wm8996->pdata.inr_mode); | |
| 2845 | − | |
| 2846 | − for (i = 0; i < ARRAY_SIZE(wm8996->pdata.gpio_default); i++) { | |
| 2847 | − if (!wm8996->pdata.gpio_default[i]) | |
| 2848 | − continue; | |
| 2849 | − | |
| 2850 | − snd_soc_write(codec, WM8996_GPIO_1 + i, | |
| 2851 | − wm8996->pdata.gpio_default[i] & 0xffff); | |
| 2852 | − } | |
| 2853 | − | |
| 2854 | − if (wm8996->pdata.spkmute_seq) | |
| 2855 | − snd_soc_update_bits(codec, WM8996_PDM_SPEAKER_MUTE_SEQUENCE, | |
| 2856 | − WM8996_SPK_MUTE_ENDIAN | | |
| 2857 | − WM8996_SPK_MUTE_SEQ1_MASK, | |
| 2858 | − wm8996->pdata.spkmute_seq); | |
| 2859 | − | |
| 2860 | − snd_soc_update_bits(codec, WM8996_ACCESSORY_DETECT_MODE_2, | |
| 2861 | − WM8996_MICD_BIAS_SRC | WM8996_HPOUT1FB_SRC | | |
| 2862 | − WM8996_MICD_SRC, wm8996->pdata.micdet_def); | |
| 2863 | − | |
| 2864 | − /* Latch volume update bits */ | |
| 2865 | − snd_soc_update_bits(codec, WM8996_LEFT_LINE_INPUT_VOLUME, | |
| 2866 | − WM8996_IN1_VU, WM8996_IN1_VU); | |
| 2867 | − snd_soc_update_bits(codec, WM8996_RIGHT_LINE_INPUT_VOLUME, | |
| 2868 | − WM8996_IN1_VU, WM8996_IN1_VU); | |
| 2869 | − | |
| 2870 | − snd_soc_update_bits(codec, WM8996_DAC1_LEFT_VOLUME, | |
| 2871 | − WM8996_DAC1_VU, WM8996_DAC1_VU); | |
| 2872 | − snd_soc_update_bits(codec, WM8996_DAC1_RIGHT_VOLUME, | |
| 2873 | − WM8996_DAC1_VU, WM8996_DAC1_VU); | |
| 2874 | − snd_soc_update_bits(codec, WM8996_DAC2_LEFT_VOLUME, | |
| 2875 | − WM8996_DAC2_VU, WM8996_DAC2_VU); | |
| 2876 | − snd_soc_update_bits(codec, WM8996_DAC2_RIGHT_VOLUME, | |
| 2877 | − WM8996_DAC2_VU, WM8996_DAC2_VU); | |
| 2878 | − | |
| 2879 | − snd_soc_update_bits(codec, WM8996_OUTPUT1_LEFT_VOLUME, | |
| 2880 | − WM8996_DAC1_VU, WM8996_DAC1_VU); | |
| 2881 | − snd_soc_update_bits(codec, WM8996_OUTPUT1_RIGHT_VOLUME, | |
| 2882 | − WM8996_DAC1_VU, WM8996_DAC1_VU); | |
| 2883 | − snd_soc_update_bits(codec, WM8996_OUTPUT2_LEFT_VOLUME, | |
| 2884 | − WM8996_DAC2_VU, WM8996_DAC2_VU); | |
| 2885 | − snd_soc_update_bits(codec, WM8996_OUTPUT2_RIGHT_VOLUME, | |
| 2886 | − WM8996_DAC2_VU, WM8996_DAC2_VU); | |
| 2887 | − | |
| 2888 | − snd_soc_update_bits(codec, WM8996_DSP1_TX_LEFT_VOLUME, | |
| 2889 | − WM8996_DSP1TX_VU, WM8996_DSP1TX_VU); | |
| 2890 | − snd_soc_update_bits(codec, WM8996_DSP1_TX_RIGHT_VOLUME, | |
| 2891 | − WM8996_DSP1TX_VU, WM8996_DSP1TX_VU); | |
| 2892 | − snd_soc_update_bits(codec, WM8996_DSP2_TX_LEFT_VOLUME, | |
| 2893 | − WM8996_DSP2TX_VU, WM8996_DSP2TX_VU); | |
| 2894 | − snd_soc_update_bits(codec, WM8996_DSP2_TX_RIGHT_VOLUME, | |
| 2895 | − WM8996_DSP2TX_VU, WM8996_DSP2TX_VU); | |
| 2896 | − | |
| 2897 | − snd_soc_update_bits(codec, WM8996_DSP1_RX_LEFT_VOLUME, | |
| 2898 | − WM8996_DSP1RX_VU, WM8996_DSP1RX_VU); | |
| 2899 | − snd_soc_update_bits(codec, WM8996_DSP1_RX_RIGHT_VOLUME, | |
| 2900 | − WM8996_DSP1RX_VU, WM8996_DSP1RX_VU); | |
| 2901 | − snd_soc_update_bits(codec, WM8996_DSP2_RX_LEFT_VOLUME, | |
| 2902 | − WM8996_DSP2RX_VU, WM8996_DSP2RX_VU); | |
| 2903 | − snd_soc_update_bits(codec, WM8996_DSP2_RX_RIGHT_VOLUME, | |
| 2904 | − WM8996_DSP2RX_VU, WM8996_DSP2RX_VU); | |
| 2905 | − | |
| 2906 | − /* No support currently for the underclocked TDM modes and | |
| 2907 | − * pick a default TDM layout with each channel pair working with | |
| 2908 | − * slots 0 and 1. */ | |
| 2909 | − snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_0_CONFIGURATION, | |
| 2910 | − WM8996_AIF1RX_CHAN0_SLOTS_MASK | | |
| 2911 | − WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | |
| 2912 | − 1 << WM8996_AIF1RX_CHAN0_SLOTS_SHIFT | 0); | |
| 2913 | − snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_1_CONFIGURATION, | |
| 2914 | − WM8996_AIF1RX_CHAN1_SLOTS_MASK | | |
| 2915 | − WM8996_AIF1RX_CHAN1_START_SLOT_MASK, | |
| 2916 | − 1 << WM8996_AIF1RX_CHAN1_SLOTS_SHIFT | 1); | |
| 2917 | − snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_2_CONFIGURATION, | |
| 2918 | − WM8996_AIF1RX_CHAN2_SLOTS_MASK | | |
| 2919 | − WM8996_AIF1RX_CHAN2_START_SLOT_MASK, | |
| 2920 | − 1 << WM8996_AIF1RX_CHAN2_SLOTS_SHIFT | 0); | |
| 2921 | − snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_3_CONFIGURATION, | |
| 2922 | − WM8996_AIF1RX_CHAN3_SLOTS_MASK | | |
| 2923 | − WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | |
| 2924 | − 1 << WM8996_AIF1RX_CHAN3_SLOTS_SHIFT | 1); | |
| 2925 | − snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_4_CONFIGURATION, | |
| 2926 | − WM8996_AIF1RX_CHAN4_SLOTS_MASK | | |
| 2927 | − WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | |
| 2928 | − 1 << WM8996_AIF1RX_CHAN4_SLOTS_SHIFT | 0); | |
| 2929 | − snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_5_CONFIGURATION, | |
| 2930 | − WM8996_AIF1RX_CHAN5_SLOTS_MASK | | |
| 2931 | − WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | |
| 2932 | − 1 << WM8996_AIF1RX_CHAN5_SLOTS_SHIFT | 1); | |
| 2933 | − | |
| 2934 | − snd_soc_update_bits(codec, WM8996_AIF2RX_CHANNEL_0_CONFIGURATION, | |
| 2935 | − WM8996_AIF2RX_CHAN0_SLOTS_MASK | | |
| 2936 | − WM8996_AIF2RX_CHAN0_START_SLOT_MASK, | |
| 2937 | − 1 << WM8996_AIF2RX_CHAN0_SLOTS_SHIFT | 0); | |
| 2938 | − snd_soc_update_bits(codec, WM8996_AIF2RX_CHANNEL_1_CONFIGURATION, | |
| 2939 | − WM8996_AIF2RX_CHAN1_SLOTS_MASK | | |
| 2940 | − WM8996_AIF2RX_CHAN1_START_SLOT_MASK, | |
| 2941 | − 1 << WM8996_AIF2RX_CHAN1_SLOTS_SHIFT | 1); | |
| 2942 | − | |
| 2943 | − snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_0_CONFIGURATION, | |
| 2944 | − WM8996_AIF1TX_CHAN0_SLOTS_MASK | | |
| 2945 | − WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | |
| 2946 | − 1 << WM8996_AIF1TX_CHAN0_SLOTS_SHIFT | 0); | |
| 2947 | − snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_1_CONFIGURATION, | |
| 2948 | − WM8996_AIF1TX_CHAN1_SLOTS_MASK | | |
| 2949 | − WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | |
| 2950 | − 1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1); | |
| 2951 | − snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_2_CONFIGURATION, | |
| 2952 | − WM8996_AIF1TX_CHAN2_SLOTS_MASK | | |
| 2953 | − WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | |
| 2954 | − 1 << WM8996_AIF1TX_CHAN2_SLOTS_SHIFT | 0); | |
| 2955 | − snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_3_CONFIGURATION, | |
| 2956 | − WM8996_AIF1TX_CHAN3_SLOTS_MASK | | |
| 2957 | − WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | |
| 2958 | − 1 << WM8996_AIF1TX_CHAN3_SLOTS_SHIFT | 1); | |
| 2959 | − snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_4_CONFIGURATION, | |
| 2960 | − WM8996_AIF1TX_CHAN4_SLOTS_MASK | | |
| 2961 | − WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | |
| 2962 | − 1 << WM8996_AIF1TX_CHAN4_SLOTS_SHIFT | 0); | |
| 2963 | − snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_5_CONFIGURATION, | |
| 2964 | − WM8996_AIF1TX_CHAN5_SLOTS_MASK | | |
| 2965 | − WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | |
| 2966 | − 1 << WM8996_AIF1TX_CHAN5_SLOTS_SHIFT | 1); | |
| 2967 | − | |
| 2968 | − snd_soc_update_bits(codec, WM8996_AIF2TX_CHANNEL_0_CONFIGURATION, | |
| 2969 | − WM8996_AIF2TX_CHAN0_SLOTS_MASK | | |
| 2970 | − WM8996_AIF2TX_CHAN0_START_SLOT_MASK, | |
| 2971 | − 1 << WM8996_AIF2TX_CHAN0_SLOTS_SHIFT | 0); | |
| 2972 | − snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_1_CONFIGURATION, | |
| 2973 | − WM8996_AIF2TX_CHAN1_SLOTS_MASK | | |
| 2974 | − WM8996_AIF2TX_CHAN1_START_SLOT_MASK, | |
| 2975 | − 1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1); | |
| 2976 | − | |
| 2977 | 2637 | if (wm8996->pdata.num_retune_mobile_cfgs) |
| 2978 | 2638 | wm8996_retune_mobile_pdata(codec); |
| 2979 | 2639 | else |
| 2980 | 2640 | snd_soc_add_codec_controls(codec, wm8996_eq_controls, |
| 2981 | 2641 | ARRAY_SIZE(wm8996_eq_controls)); |
| 2982 | 2642 | |
| 2983 | − /* If the TX LRCLK pins are not in LRCLK mode configure the | |
| 2984 | − * AIFs to source their clocks from the RX LRCLKs. | |
| 2985 | − */ | |
| 2986 | − if ((snd_soc_read(codec, WM8996_GPIO_1))) | |
| 2987 | − snd_soc_update_bits(codec, WM8996_AIF1_TX_LRCLK_2, | |
| 2988 | − WM8996_AIF1TX_LRCLK_MODE, | |
| 2989 | − WM8996_AIF1TX_LRCLK_MODE); | |
| 2990 | − | |
| 2991 | − if ((snd_soc_read(codec, WM8996_GPIO_2))) | |
| 2992 | − snd_soc_update_bits(codec, WM8996_AIF2_TX_LRCLK_2, | |
| 2993 | − WM8996_AIF2TX_LRCLK_MODE, | |
| 2994 | − WM8996_AIF2TX_LRCLK_MODE); | |
| 2995 | − | |
| 2996 | 2643 | if (i2c->irq) { |
| 2997 | 2644 | if (wm8996->pdata.irq_flags) |
| 2998 | 2645 | irq_flags = wm8996->pdata.irq_flags; |
| @@ -3036,9 +2683,7 @@ err: · 37 unmodified lines | ||
| 3036 | 2683 | |
| 3037 | 2684 | static int wm8996_remove(struct snd_soc_codec *codec) |
| 3038 | 2685 | { |
| 3039 | − struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | |
| 3040 | 2686 | struct i2c_client *i2c = to_i2c_client(codec->dev); |
| 3041 | − int i; | |
| 3042 | 2687 | |
| 3043 | 2688 | snd_soc_update_bits(codec, WM8996_INTERRUPT_CONTROL, |
| 3044 | 2689 | WM8996_IM_IRQ, WM8996_IM_IRQ); |
| @@ -3046,10 +2691,6 @@ static int wm8996_remove(struct snd_soc_codec *codec) · 1 unmodified line | ||
| 3046 | 2691 | if (i2c->irq) |
| 3047 | 2692 | free_irq(i2c->irq, codec); |
| 3048 | 2693 | |
| 3049 | − for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) | |
| 3050 | − regulator_unregister_notifier(wm8996->supplies[i].consumer, | |
| 3051 | − &wm8996->disable_nb[i]); | |
| 3052 | − | |
| 3053 | 2694 | return 0; |
| 3054 | 2695 | } |
| 3055 | 2696 | |
| @@ -3163,6 +2804,21 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c, · 107 unmodified lines | ||
| 3163 | 2804 | goto err_gpio; |
| 3164 | 2805 | } |
| 3165 | 2806 | |
| 2807 | + wm8996->disable_nb[0].notifier_call = wm8996_regulator_event_0; | |
| 2808 | + wm8996->disable_nb[1].notifier_call = wm8996_regulator_event_1; | |
| 2809 | + wm8996->disable_nb[2].notifier_call = wm8996_regulator_event_2; | |
| 2810 | + | |
| 2811 | + /* This should really be moved into the regulator core */ | |
| 2812 | + for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) { | |
| 2813 | + ret = regulator_register_notifier(wm8996->supplies[i].consumer, | |
| 2814 | + &wm8996->disable_nb[i]); | |
| 2815 | + if (ret != 0) { | |
| 2816 | + dev_err(&i2c->dev, | |
| 2817 | + "Failed to register regulator notifier: %d\n", | |
| 2818 | + ret); | |
| 2819 | + } | |
| 2820 | + } | |
| 2821 | + | |
| 3166 | 2822 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies), |
| 3167 | 2823 | wm8996->supplies); |
| 3168 | 2824 | if (ret != 0) { |
| @@ -3175,7 +2831,7 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c, · 6 unmodified lines | ||
| 3175 | 2831 | msleep(5); |
| 3176 | 2832 | } |
| 3177 | 2833 | |
| 3178 | − wm8996->regmap = regmap_init_i2c(i2c, &wm8996_regmap); | |
| 2834 | + wm8996->regmap = devm_regmap_init_i2c(i2c, &wm8996_regmap); | |
| 3179 | 2835 | if (IS_ERR(wm8996->regmap)) { |
| 3180 | 2836 | ret = PTR_ERR(wm8996->regmap); |
| 3181 | 2837 | dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret); |
| @@ -3203,15 +2859,199 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c, · 21 unmodified lines | ||
| 3203 | 2859 | dev_info(&i2c->dev, "revision %c\n", |
| 3204 | 2860 | (reg & WM8996_CHIP_REV_MASK) + 'A'); |
| 3205 | 2861 | |
| 3206 | − ret = wm8996_reset(wm8996); | |
| 3207 | − if (ret < 0) { | |
| 3208 | − dev_err(&i2c->dev, "Failed to issue reset\n"); | |
| 3209 | − goto err_regmap; | |
| 2862 | + if (wm8996->pdata.ldo_ena > 0) { | |
| 2863 | + gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); | |
| 2864 | + regcache_cache_only(wm8996->regmap, true); | |
| 2865 | + } else { | |
| 2866 | + ret = regmap_write(wm8996->regmap, WM8996_SOFTWARE_RESET, | |
| 2867 | + 0x8915); | |
| 2868 | + if (ret != 0) { | |
| 2869 | + dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret); | |
| 2870 | + goto err_regmap; | |
| 2871 | + } | |
| 3210 | 2872 | } |
| 3211 | 2873 | |
| 3212 | − regcache_cache_only(wm8996->regmap, true); | |
| 3213 | 2874 | regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); |
| 3214 | 2875 | |
| 2876 | + /* Apply platform data settings */ | |
| 2877 | + regmap_update_bits(wm8996->regmap, WM8996_LINE_INPUT_CONTROL, | |
| 2878 | + WM8996_INL_MODE_MASK | WM8996_INR_MODE_MASK, | |
| 2879 | + wm8996->pdata.inl_mode << WM8996_INL_MODE_SHIFT | | |
| 2880 | + wm8996->pdata.inr_mode); | |
| 2881 | + | |
| 2882 | + for (i = 0; i < ARRAY_SIZE(wm8996->pdata.gpio_default); i++) { | |
| 2883 | + if (!wm8996->pdata.gpio_default[i]) | |
| 2884 | + continue; | |
| 2885 | + | |
| 2886 | + regmap_write(wm8996->regmap, WM8996_GPIO_1 + i, | |
| 2887 | + wm8996->pdata.gpio_default[i] & 0xffff); | |
| 2888 | + } | |
| 2889 | + | |
| 2890 | + if (wm8996->pdata.spkmute_seq) | |
| 2891 | + regmap_update_bits(wm8996->regmap, | |
| 2892 | + WM8996_PDM_SPEAKER_MUTE_SEQUENCE, | |
| 2893 | + WM8996_SPK_MUTE_ENDIAN | | |
| 2894 | + WM8996_SPK_MUTE_SEQ1_MASK, | |
| 2895 | + wm8996->pdata.spkmute_seq); | |
| 2896 | + | |
| 2897 | + regmap_update_bits(wm8996->regmap, WM8996_ACCESSORY_DETECT_MODE_2, | |
| 2898 | + WM8996_MICD_BIAS_SRC | WM8996_HPOUT1FB_SRC | | |
| 2899 | + WM8996_MICD_SRC, wm8996->pdata.micdet_def); | |
| 2900 | + | |
| 2901 | + /* Latch volume update bits */ | |
| 2902 | + regmap_update_bits(wm8996->regmap, WM8996_LEFT_LINE_INPUT_VOLUME, | |
| 2903 | + WM8996_IN1_VU, WM8996_IN1_VU); | |
| 2904 | + regmap_update_bits(wm8996->regmap, WM8996_RIGHT_LINE_INPUT_VOLUME, | |
| 2905 | + WM8996_IN1_VU, WM8996_IN1_VU); | |
| 2906 | + | |
| 2907 | + regmap_update_bits(wm8996->regmap, WM8996_DAC1_LEFT_VOLUME, | |
| 2908 | + WM8996_DAC1_VU, WM8996_DAC1_VU); | |
| 2909 | + regmap_update_bits(wm8996->regmap, WM8996_DAC1_RIGHT_VOLUME, | |
| 2910 | + WM8996_DAC1_VU, WM8996_DAC1_VU); | |
| 2911 | + regmap_update_bits(wm8996->regmap, WM8996_DAC2_LEFT_VOLUME, | |
| 2912 | + WM8996_DAC2_VU, WM8996_DAC2_VU); | |
| 2913 | + regmap_update_bits(wm8996->regmap, WM8996_DAC2_RIGHT_VOLUME, | |
| 2914 | + WM8996_DAC2_VU, WM8996_DAC2_VU); | |
| 2915 | + | |
| 2916 | + regmap_update_bits(wm8996->regmap, WM8996_OUTPUT1_LEFT_VOLUME, | |
| 2917 | + WM8996_DAC1_VU, WM8996_DAC1_VU); | |
| 2918 | + regmap_update_bits(wm8996->regmap, WM8996_OUTPUT1_RIGHT_VOLUME, | |
| 2919 | + WM8996_DAC1_VU, WM8996_DAC1_VU); | |
| 2920 | + regmap_update_bits(wm8996->regmap, WM8996_OUTPUT2_LEFT_VOLUME, | |
| 2921 | + WM8996_DAC2_VU, WM8996_DAC2_VU); | |
| 2922 | + regmap_update_bits(wm8996->regmap, WM8996_OUTPUT2_RIGHT_VOLUME, | |
| 2923 | + WM8996_DAC2_VU, WM8996_DAC2_VU); | |
| 2924 | + | |
| 2925 | + regmap_update_bits(wm8996->regmap, WM8996_DSP1_TX_LEFT_VOLUME, | |
| 2926 | + WM8996_DSP1TX_VU, WM8996_DSP1TX_VU); | |
| 2927 | + regmap_update_bits(wm8996->regmap, WM8996_DSP1_TX_RIGHT_VOLUME, | |
| 2928 | + WM8996_DSP1TX_VU, WM8996_DSP1TX_VU); | |
| 2929 | + regmap_update_bits(wm8996->regmap, WM8996_DSP2_TX_LEFT_VOLUME, | |
| 2930 | + WM8996_DSP2TX_VU, WM8996_DSP2TX_VU); | |
| 2931 | + regmap_update_bits(wm8996->regmap, WM8996_DSP2_TX_RIGHT_VOLUME, | |
| 2932 | + WM8996_DSP2TX_VU, WM8996_DSP2TX_VU); | |
| 2933 | + | |
| 2934 | + regmap_update_bits(wm8996->regmap, WM8996_DSP1_RX_LEFT_VOLUME, | |
| 2935 | + WM8996_DSP1RX_VU, WM8996_DSP1RX_VU); | |
| 2936 | + regmap_update_bits(wm8996->regmap, WM8996_DSP1_RX_RIGHT_VOLUME, | |
| 2937 | + WM8996_DSP1RX_VU, WM8996_DSP1RX_VU); | |
| 2938 | + regmap_update_bits(wm8996->regmap, WM8996_DSP2_RX_LEFT_VOLUME, | |
| 2939 | + WM8996_DSP2RX_VU, WM8996_DSP2RX_VU); | |
| 2940 | + regmap_update_bits(wm8996->regmap, WM8996_DSP2_RX_RIGHT_VOLUME, | |
| 2941 | + WM8996_DSP2RX_VU, WM8996_DSP2RX_VU); | |
| 2942 | + | |
| 2943 | + /* No support currently for the underclocked TDM modes and | |
| 2944 | + * pick a default TDM layout with each channel pair working with | |
| 2945 | + * slots 0 and 1. */ | |
| 2946 | + regmap_update_bits(wm8996->regmap, | |
| 2947 | + WM8996_AIF1RX_CHANNEL_0_CONFIGURATION, | |
| 2948 | + WM8996_AIF1RX_CHAN0_SLOTS_MASK | | |
| 2949 | + WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | |
| 2950 | + 1 << WM8996_AIF1RX_CHAN0_SLOTS_SHIFT | 0); | |
| 2951 | + regmap_update_bits(wm8996->regmap, | |
| 2952 | + WM8996_AIF1RX_CHANNEL_1_CONFIGURATION, | |
| 2953 | + WM8996_AIF1RX_CHAN1_SLOTS_MASK | | |
| 2954 | + WM8996_AIF1RX_CHAN1_START_SLOT_MASK, | |
| 2955 | + 1 << WM8996_AIF1RX_CHAN1_SLOTS_SHIFT | 1); | |
| 2956 | + regmap_update_bits(wm8996->regmap, | |
| 2957 | + WM8996_AIF1RX_CHANNEL_2_CONFIGURATION, | |
| 2958 | + WM8996_AIF1RX_CHAN2_SLOTS_MASK | | |
| 2959 | + WM8996_AIF1RX_CHAN2_START_SLOT_MASK, | |
| 2960 | + 1 << WM8996_AIF1RX_CHAN2_SLOTS_SHIFT | 0); | |
| 2961 | + regmap_update_bits(wm8996->regmap, | |
| 2962 | + WM8996_AIF1RX_CHANNEL_3_CONFIGURATION, | |
| 2963 | + WM8996_AIF1RX_CHAN3_SLOTS_MASK | | |
| 2964 | + WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | |
| 2965 | + 1 << WM8996_AIF1RX_CHAN3_SLOTS_SHIFT | 1); | |
| 2966 | + regmap_update_bits(wm8996->regmap, | |
| 2967 | + WM8996_AIF1RX_CHANNEL_4_CONFIGURATION, | |
| 2968 | + WM8996_AIF1RX_CHAN4_SLOTS_MASK | | |
| 2969 | + WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | |
| 2970 | + 1 << WM8996_AIF1RX_CHAN4_SLOTS_SHIFT | 0); | |
| 2971 | + regmap_update_bits(wm8996->regmap, | |
| 2972 | + WM8996_AIF1RX_CHANNEL_5_CONFIGURATION, | |
| 2973 | + WM8996_AIF1RX_CHAN5_SLOTS_MASK | | |
| 2974 | + WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | |
| 2975 | + 1 << WM8996_AIF1RX_CHAN5_SLOTS_SHIFT | 1); | |
| 2976 | + | |
| 2977 | + regmap_update_bits(wm8996->regmap, | |
| 2978 | + WM8996_AIF2RX_CHANNEL_0_CONFIGURATION, | |
| 2979 | + WM8996_AIF2RX_CHAN0_SLOTS_MASK | | |
| 2980 | + WM8996_AIF2RX_CHAN0_START_SLOT_MASK, | |
| 2981 | + 1 << WM8996_AIF2RX_CHAN0_SLOTS_SHIFT | 0); | |
| 2982 | + regmap_update_bits(wm8996->regmap, | |
| 2983 | + WM8996_AIF2RX_CHANNEL_1_CONFIGURATION, | |
| 2984 | + WM8996_AIF2RX_CHAN1_SLOTS_MASK | | |
| 2985 | + WM8996_AIF2RX_CHAN1_START_SLOT_MASK, | |
| 2986 | + 1 << WM8996_AIF2RX_CHAN1_SLOTS_SHIFT | 1); | |
| 2987 | + | |
| 2988 | + regmap_update_bits(wm8996->regmap, | |
| 2989 | + WM8996_AIF1TX_CHANNEL_0_CONFIGURATION, | |
| 2990 | + WM8996_AIF1TX_CHAN0_SLOTS_MASK | | |
| 2991 | + WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | |
| 2992 | + 1 << WM8996_AIF1TX_CHAN0_SLOTS_SHIFT | 0); | |
| 2993 | + regmap_update_bits(wm8996->regmap, | |
| 2994 | + WM8996_AIF1TX_CHANNEL_1_CONFIGURATION, | |
| 2995 | + WM8996_AIF1TX_CHAN1_SLOTS_MASK | | |
| 2996 | + WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | |
| 2997 | + 1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1); | |
| 2998 | + regmap_update_bits(wm8996->regmap, | |
| 2999 | + WM8996_AIF1TX_CHANNEL_2_CONFIGURATION, | |
| 3000 | + WM8996_AIF1TX_CHAN2_SLOTS_MASK | | |
| 3001 | + WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | |
| 3002 | + 1 << WM8996_AIF1TX_CHAN2_SLOTS_SHIFT | 0); | |
| 3003 | + regmap_update_bits(wm8996->regmap, | |
| 3004 | + WM8996_AIF1TX_CHANNEL_3_CONFIGURATION, | |
| 3005 | + WM8996_AIF1TX_CHAN3_SLOTS_MASK | | |
| 3006 | + WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | |
| 3007 | + 1 << WM8996_AIF1TX_CHAN3_SLOTS_SHIFT | 1); | |
| 3008 | + regmap_update_bits(wm8996->regmap, | |
| 3009 | + WM8996_AIF1TX_CHANNEL_4_CONFIGURATION, | |
| 3010 | + WM8996_AIF1TX_CHAN4_SLOTS_MASK | | |
| 3011 | + WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | |
| 3012 | + 1 << WM8996_AIF1TX_CHAN4_SLOTS_SHIFT | 0); | |
| 3013 | + regmap_update_bits(wm8996->regmap, | |
| 3014 | + WM8996_AIF1TX_CHANNEL_5_CONFIGURATION, | |
| 3015 | + WM8996_AIF1TX_CHAN5_SLOTS_MASK | | |
| 3016 | + WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | |
| 3017 | + 1 << WM8996_AIF1TX_CHAN5_SLOTS_SHIFT | 1); | |
| 3018 | + | |
| 3019 | + regmap_update_bits(wm8996->regmap, | |
| 3020 | + WM8996_AIF2TX_CHANNEL_0_CONFIGURATION, | |
| 3021 | + WM8996_AIF2TX_CHAN0_SLOTS_MASK | | |
| 3022 | + WM8996_AIF2TX_CHAN0_START_SLOT_MASK, | |
| 3023 | + 1 << WM8996_AIF2TX_CHAN0_SLOTS_SHIFT | 0); | |
| 3024 | + regmap_update_bits(wm8996->regmap, | |
| 3025 | + WM8996_AIF1TX_CHANNEL_1_CONFIGURATION, | |
| 3026 | + WM8996_AIF2TX_CHAN1_SLOTS_MASK | | |
| 3027 | + WM8996_AIF2TX_CHAN1_START_SLOT_MASK, | |
| 3028 | + 1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1); | |
| 3029 | + | |
| 3030 | + /* If the TX LRCLK pins are not in LRCLK mode configure the | |
| 3031 | + * AIFs to source their clocks from the RX LRCLKs. | |
| 3032 | + */ | |
| 3033 | + ret = regmap_read(wm8996->regmap, WM8996_GPIO_1, ®); | |
| 3034 | + if (ret != 0) { | |
| 3035 | + dev_err(&i2c->dev, "Failed to read GPIO1: %d\n", ret); | |
| 3036 | + goto err_regmap; | |
| 3037 | + } | |
| 3038 | + | |
| 3039 | + if (reg & WM8996_GP1_FN_MASK) | |
| 3040 | + regmap_update_bits(wm8996->regmap, WM8996_AIF1_TX_LRCLK_2, | |
| 3041 | + WM8996_AIF1TX_LRCLK_MODE, | |
| 3042 | + WM8996_AIF1TX_LRCLK_MODE); | |
| 3043 | + | |
| 3044 | + ret = regmap_read(wm8996->regmap, WM8996_GPIO_2, ®); | |
| 3045 | + if (ret != 0) { | |
| 3046 | + dev_err(&i2c->dev, "Failed to read GPIO2: %d\n", ret); | |
| 3047 | + goto err_regmap; | |
| 3048 | + } | |
| 3049 | + | |
| 3050 | + if (reg & WM8996_GP2_FN_MASK) | |
| 3051 | + regmap_update_bits(wm8996->regmap, WM8996_AIF2_TX_LRCLK_2, | |
| 3052 | + WM8996_AIF2TX_LRCLK_MODE, | |
| 3053 | + WM8996_AIF2TX_LRCLK_MODE); | |
| 3054 | + | |
| 3215 | 3055 | wm8996_init_gpio(wm8996); |
| 3216 | 3056 | |
| 3217 | 3057 | ret = snd_soc_register_codec(&i2c->dev, |
| @@ -3225,7 +3065,6 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c, · 7 unmodified lines | ||
| 3225 | 3065 | err_gpiolib: |
| 3226 | 3066 | wm8996_free_gpio(wm8996); |
| 3227 | 3067 | err_regmap: |
| 3228 | − regmap_exit(wm8996->regmap); | |
| 3229 | 3068 | err_enable: |
| 3230 | 3069 | if (wm8996->pdata.ldo_ena > 0) |
| 3231 | 3070 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); |
| @@ -3241,14 +3080,18 @@ err: · 9 unmodified lines | ||
| 3241 | 3080 | static __devexit int wm8996_i2c_remove(struct i2c_client *client) |
| 3242 | 3081 | { |
| 3243 | 3082 | struct wm8996_priv *wm8996 = i2c_get_clientdata(client); |
| 3083 | + int i; | |
| 3244 | 3084 | |
| 3245 | 3085 | snd_soc_unregister_codec(&client->dev); |
| 3246 | 3086 | wm8996_free_gpio(wm8996); |
| 3247 | − regmap_exit(wm8996->regmap); | |
| 3248 | 3087 | if (wm8996->pdata.ldo_ena > 0) { |
| 3249 | 3088 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); |
| 3250 | 3089 | gpio_free(wm8996->pdata.ldo_ena); |
| 3251 | 3090 | } |
| 3091 | + for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) | |
| 3092 | + regulator_unregister_notifier(wm8996->supplies[i].consumer, | |
| 3093 | + &wm8996->disable_nb[i]); | |
| 3094 | + | |
| 3252 | 3095 | return 0; |
| 3253 | 3096 | } |
| 3254 | 3097 | |
| @@ -3,7 +3,7 @@ · 2 unmodified lines | ||
| 3 | 3 | * |
| 4 | 4 | * Author: Mark Brown |
| 5 | 5 | * |
| 6 | − * Copyright 2009 Wolfson Microelectronics plc | |
| 6 | + * Copyright 2009-12 Wolfson Microelectronics plc | |
| 7 | 7 | * |
| 8 | 8 | * This program is free software; you can redistribute it and/or modify |
| 9 | 9 | * it under the terms of the GNU General Public License version 2 as |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * ALSA SoC WM9090 driver |
| 3 | 3 | * |
| 4 | − * Copyright 2009, 2010 Wolfson Microelectronics | |
| 4 | + * Copyright 2009-12 Wolfson Microelectronics | |
| 5 | 5 | * |
| 6 | 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
| 7 | 7 | * |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * wm9712.c -- ALSA Soc WM9712 codec support |
| 3 | 3 | * |
| 4 | − * Copyright 2006 Wolfson Microelectronics PLC. | |
| 4 | + * Copyright 2006-12 Wolfson Microelectronics PLC. | |
| 5 | 5 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
| 6 | 6 | * |
| 7 | 7 | * This program is free software; you can redistribute it and/or modify it |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * wm9713.c -- ALSA Soc WM9713 codec support |
| 3 | 3 | * |
| 4 | − * Copyright 2006 Wolfson Microelectronics PLC. | |
| 4 | + * Copyright 2006-10 Wolfson Microelectronics PLC. | |
| 5 | 5 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
| 6 | 6 | * |
| 7 | 7 | * This program is free software; you can redistribute it and/or modify it |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * wm_hubs.c -- WM8993/4 common code |
| 3 | 3 | * |
| 4 | − * Copyright 2009 Wolfson Microelectronics plc | |
| 4 | + * Copyright 2009-12 Wolfson Microelectronics plc | |
| 5 | 5 | * |
| 6 | 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
| 7 | 7 | * |
| @@ -0,0 +1,9 @@ | ||
| 1 | +config SND_DESIGNWARE_I2S | |
| 2 | + tristate "Synopsys I2S Device Driver" | |
| 3 | + depends on CLKDEV_LOOKUP | |
| 4 | + help | |
| 5 | + Say Y or M if you want to add support for I2S driver for | |
| 6 | + Synopsys desigwnware I2S device. The device supports upto | |
| 7 | + maximum of 8 channels each for play and record. | |
| 8 | + | |
| 9 | + | |
| @@ -0,0 +1,3 @@ | ||
| 1 | +# SYNOPSYS Platform Support | |
| 2 | +obj-$(CONFIG_SND_DESIGNWARE_I2S) += designware_i2s.o | |
| 3 | + | |
| @@ -0,0 +1,455 @@ | ||
| 1 | +/* | |
| 2 | + * ALSA SoC Synopsys I2S Audio Layer | |
| 3 | + * | |
| 4 | + * sound/soc/spear/designware_i2s.c | |
| 5 | + * | |
| 6 | + * Copyright (C) 2010 ST Microelectronics | |
| 7 | + * Rajeev Kumar <rajeev-dlh.kumar@st.com> | |
| 8 | + * | |
| 9 | + * This file is licensed under the terms of the GNU General Public | |
| 10 | + * License version 2. This program is licensed "as is" without any | |
| 11 | + * warranty of any kind, whether express or implied. | |
| 12 | + */ | |
| 13 | + | |
| 14 | +#include <linux/clk.h> | |
| 15 | +#include <linux/device.h> | |
| 16 | +#include <linux/init.h> | |
| 17 | +#include <linux/io.h> | |
| 18 | +#include <linux/interrupt.h> | |
| 19 | +#include <linux/module.h> | |
| 20 | +#include <linux/slab.h> | |
| 21 | +#include <sound/designware_i2s.h> | |
| 22 | +#include <sound/pcm.h> | |
| 23 | +#include <sound/pcm_params.h> | |
| 24 | +#include <sound/soc.h> | |
| 25 | + | |
| 26 | +/* common register for all channel */ | |
| 27 | +#define IER 0x000 | |
| 28 | +#define IRER 0x004 | |
| 29 | +#define ITER 0x008 | |
| 30 | +#define CER 0x00C | |
| 31 | +#define CCR 0x010 | |
| 32 | +#define RXFFR 0x014 | |
| 33 | +#define TXFFR 0x018 | |
| 34 | + | |
| 35 | +/* I2STxRxRegisters for all channels */ | |
| 36 | +#define LRBR_LTHR(x) (0x40 * x + 0x020) | |
| 37 | +#define RRBR_RTHR(x) (0x40 * x + 0x024) | |
| 38 | +#define RER(x) (0x40 * x + 0x028) | |
| 39 | +#define TER(x) (0x40 * x + 0x02C) | |
| 40 | +#define RCR(x) (0x40 * x + 0x030) | |
| 41 | +#define TCR(x) (0x40 * x + 0x034) | |
| 42 | +#define ISR(x) (0x40 * x + 0x038) | |
| 43 | +#define IMR(x) (0x40 * x + 0x03C) | |
| 44 | +#define ROR(x) (0x40 * x + 0x040) | |
| 45 | +#define TOR(x) (0x40 * x + 0x044) | |
| 46 | +#define RFCR(x) (0x40 * x + 0x048) | |
| 47 | +#define TFCR(x) (0x40 * x + 0x04C) | |
| 48 | +#define RFF(x) (0x40 * x + 0x050) | |
| 49 | +#define TFF(x) (0x40 * x + 0x054) | |
| 50 | + | |
| 51 | +/* I2SCOMPRegisters */ | |
| 52 | +#define I2S_COMP_PARAM_2 0x01F0 | |
| 53 | +#define I2S_COMP_PARAM_1 0x01F4 | |
| 54 | +#define I2S_COMP_VERSION 0x01F8 | |
| 55 | +#define I2S_COMP_TYPE 0x01FC | |
| 56 | + | |
| 57 | +#define MAX_CHANNEL_NUM 8 | |
| 58 | +#define MIN_CHANNEL_NUM 2 | |
| 59 | + | |
| 60 | +struct dw_i2s_dev { | |
| 61 | + void __iomem *i2s_base; | |
| 62 | + struct clk *clk; | |
| 63 | + int active; | |
| 64 | + unsigned int capability; | |
| 65 | + struct device *dev; | |
| 66 | + | |
| 67 | + /* data related to DMA transfers b/w i2s and DMAC */ | |
| 68 | + struct i2s_dma_data play_dma_data; | |
| 69 | + struct i2s_dma_data capture_dma_data; | |
| 70 | + struct i2s_clk_config_data config; | |
| 71 | + int (*i2s_clk_cfg)(struct i2s_clk_config_data *config); | |
| 72 | +}; | |
| 73 | + | |
| 74 | +static inline void i2s_write_reg(void __iomem *io_base, int reg, u32 val) | |
| 75 | +{ | |
| 76 | + writel(val, io_base + reg); | |
| 77 | +} | |
| 78 | + | |
| 79 | +static inline u32 i2s_read_reg(void __iomem *io_base, int reg) | |
| 80 | +{ | |
| 81 | + return readl(io_base + reg); | |
| 82 | +} | |
| 83 | + | |
| 84 | +static inline void i2s_disable_channels(struct dw_i2s_dev *dev, u32 stream) | |
| 85 | +{ | |
| 86 | + u32 i = 0; | |
| 87 | + | |
| 88 | + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | |
| 89 | + for (i = 0; i < 4; i++) | |
| 90 | + i2s_write_reg(dev->i2s_base, TER(i), 0); | |
| 91 | + } else { | |
| 92 | + for (i = 0; i < 4; i++) | |
| 93 | + i2s_write_reg(dev->i2s_base, RER(i), 0); | |
| 94 | + } | |
| 95 | +} | |
| 96 | + | |
| 97 | +static inline void i2s_clear_irqs(struct dw_i2s_dev *dev, u32 stream) | |
| 98 | +{ | |
| 99 | + u32 i = 0; | |
| 100 | + | |
| 101 | + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | |
| 102 | + for (i = 0; i < 4; i++) | |
| 103 | + i2s_write_reg(dev->i2s_base, TOR(i), 0); | |
| 104 | + } else { | |
| 105 | + for (i = 0; i < 4; i++) | |
| 106 | + i2s_write_reg(dev->i2s_base, ROR(i), 0); | |
| 107 | + } | |
| 108 | +} | |
| 109 | + | |
| 110 | +static void i2s_start(struct dw_i2s_dev *dev, | |
| 111 | + struct snd_pcm_substream *substream) | |
| 112 | +{ | |
| 113 | + | |
| 114 | + i2s_write_reg(dev->i2s_base, IER, 1); | |
| 115 | + | |
| 116 | + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | |
| 117 | + i2s_write_reg(dev->i2s_base, ITER, 1); | |
| 118 | + else | |
| 119 | + i2s_write_reg(dev->i2s_base, IRER, 1); | |
| 120 | + | |
| 121 | + i2s_write_reg(dev->i2s_base, CER, 1); | |
| 122 | +} | |
| 123 | + | |
| 124 | +static void i2s_stop(struct dw_i2s_dev *dev, | |
| 125 | + struct snd_pcm_substream *substream) | |
| 126 | +{ | |
| 127 | + u32 i = 0, irq; | |
| 128 | + | |
| 129 | + i2s_clear_irqs(dev, substream->stream); | |
| 130 | + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | |
| 131 | + i2s_write_reg(dev->i2s_base, ITER, 0); | |
| 132 | + | |
| 133 | + for (i = 0; i < 4; i++) { | |
| 134 | + irq = i2s_read_reg(dev->i2s_base, IMR(i)); | |
| 135 | + i2s_write_reg(dev->i2s_base, IMR(i), irq | 0x30); | |
| 136 | + } | |
| 137 | + } else { | |
| 138 | + i2s_write_reg(dev->i2s_base, IRER, 0); | |
| 139 | + | |
| 140 | + for (i = 0; i < 4; i++) { | |
| 141 | + irq = i2s_read_reg(dev->i2s_base, IMR(i)); | |
| 142 | + i2s_write_reg(dev->i2s_base, IMR(i), irq | 0x03); | |
| 143 | + } | |
| 144 | + } | |
| 145 | + | |
| 146 | + if (!dev->active) { | |
| 147 | + i2s_write_reg(dev->i2s_base, CER, 0); | |
| 148 | + i2s_write_reg(dev->i2s_base, IER, 0); | |
| 149 | + } | |
| 150 | +} | |
| 151 | + | |
| 152 | +static int dw_i2s_startup(struct snd_pcm_substream *substream, | |
| 153 | + struct snd_soc_dai *cpu_dai) | |
| 154 | +{ | |
| 155 | + struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); | |
| 156 | + struct i2s_dma_data *dma_data = NULL; | |
| 157 | + | |
| 158 | + if (!(dev->capability & DWC_I2S_RECORD) && | |
| 159 | + (substream->stream == SNDRV_PCM_STREAM_CAPTURE)) | |
| 160 | + return -EINVAL; | |
| 161 | + | |
| 162 | + if (!(dev->capability & DWC_I2S_PLAY) && | |
| 163 | + (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) | |
| 164 | + return -EINVAL; | |
| 165 | + | |
| 166 | + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | |
| 167 | + dma_data = &dev->play_dma_data; | |
| 168 | + else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | |
| 169 | + dma_data = &dev->capture_dma_data; | |
| 170 | + | |
| 171 | + snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)dma_data); | |
| 172 | + | |
| 173 | + return 0; | |
| 174 | +} | |
| 175 | + | |
| 176 | +static int dw_i2s_hw_params(struct snd_pcm_substream *substream, | |
| 177 | + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | |
| 178 | +{ | |
| 179 | + struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); | |
| 180 | + struct i2s_clk_config_data *config = &dev->config; | |
| 181 | + u32 ccr, xfer_resolution, ch_reg, irq; | |
| 182 | + int ret; | |
| 183 | + | |
| 184 | + switch (params_format(params)) { | |
| 185 | + case SNDRV_PCM_FORMAT_S16_LE: | |
| 186 | + config->data_width = 16; | |
| 187 | + ccr = 0x00; | |
| 188 | + xfer_resolution = 0x02; | |
| 189 | + break; | |
| 190 | + | |
| 191 | + case SNDRV_PCM_FORMAT_S24_LE: | |
| 192 | + config->data_width = 24; | |
| 193 | + ccr = 0x08; | |
| 194 | + xfer_resolution = 0x04; | |
| 195 | + break; | |
| 196 | + | |
| 197 | + case SNDRV_PCM_FORMAT_S32_LE: | |
| 198 | + config->data_width = 32; | |
| 199 | + ccr = 0x10; | |
| 200 | + xfer_resolution = 0x05; | |
| 201 | + break; | |
| 202 | + | |
| 203 | + default: | |
| 204 | + dev_err(dev->dev, "designware-i2s: unsuppted PCM fmt"); | |
| 205 | + return -EINVAL; | |
| 206 | + } | |
| 207 | + | |
| 208 | + config->chan_nr = params_channels(params); | |
| 209 | + | |
| 210 | + switch (config->chan_nr) { | |
| 211 | + case EIGHT_CHANNEL_SUPPORT: | |
| 212 | + ch_reg = 3; | |
| 213 | + case SIX_CHANNEL_SUPPORT: | |
| 214 | + ch_reg = 2; | |
| 215 | + case FOUR_CHANNEL_SUPPORT: | |
| 216 | + ch_reg = 1; | |
| 217 | + case TWO_CHANNEL_SUPPORT: | |
| 218 | + ch_reg = 0; | |
| 219 | + break; | |
| 220 | + default: | |
| 221 | + dev_err(dev->dev, "channel not supported\n"); | |
| 222 | + } | |
| 223 | + | |
| 224 | + i2s_disable_channels(dev, substream->stream); | |
| 225 | + | |
| 226 | + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | |
| 227 | + i2s_write_reg(dev->i2s_base, TCR(ch_reg), xfer_resolution); | |
| 228 | + i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02); | |
| 229 | + irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg)); | |
| 230 | + i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30); | |
| 231 | + i2s_write_reg(dev->i2s_base, TER(ch_reg), 1); | |
| 232 | + } else { | |
| 233 | + i2s_write_reg(dev->i2s_base, RCR(ch_reg), xfer_resolution); | |
| 234 | + i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07); | |
| 235 | + irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg)); | |
| 236 | + i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03); | |
| 237 | + i2s_write_reg(dev->i2s_base, RER(ch_reg), 1); | |
| 238 | + } | |
| 239 | + | |
| 240 | + i2s_write_reg(dev->i2s_base, CCR, ccr); | |
| 241 | + | |
| 242 | + config->sample_rate = params_rate(params); | |
| 243 | + | |
| 244 | + if (!dev->i2s_clk_cfg) | |
| 245 | + return -EINVAL; | |
| 246 | + | |
| 247 | + ret = dev->i2s_clk_cfg(config); | |
| 248 | + if (ret < 0) { | |
| 249 | + dev_err(dev->dev, "runtime audio clk config fail\n"); | |
| 250 | + return ret; | |
| 251 | + } | |
| 252 | + | |
| 253 | + return 0; | |
| 254 | +} | |
| 255 | + | |
| 256 | +static void dw_i2s_shutdown(struct snd_pcm_substream *substream, | |
| 257 | + struct snd_soc_dai *dai) | |
| 258 | +{ | |
| 259 | + snd_soc_dai_set_dma_data(dai, substream, NULL); | |
| 260 | +} | |
| 261 | + | |
| 262 | +static int dw_i2s_trigger(struct snd_pcm_substream *substream, | |
| 263 | + int cmd, struct snd_soc_dai *dai) | |
| 264 | +{ | |
| 265 | + struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); | |
| 266 | + int ret = 0; | |
| 267 | + | |
| 268 | + switch (cmd) { | |
| 269 | + case SNDRV_PCM_TRIGGER_START: | |
| 270 | + case SNDRV_PCM_TRIGGER_RESUME: | |
| 271 | + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | |
| 272 | + dev->active++; | |
| 273 | + i2s_start(dev, substream); | |
| 274 | + break; | |
| 275 | + | |
| 276 | + case SNDRV_PCM_TRIGGER_STOP: | |
| 277 | + case SNDRV_PCM_TRIGGER_SUSPEND: | |
| 278 | + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | |
| 279 | + dev->active--; | |
| 280 | + i2s_stop(dev, substream); | |
| 281 | + break; | |
| 282 | + default: | |
| 283 | + ret = -EINVAL; | |
| 284 | + break; | |
| 285 | + } | |
| 286 | + return ret; | |
| 287 | +} | |
| 288 | + | |
| 289 | +static struct snd_soc_dai_ops dw_i2s_dai_ops = { | |
| 290 | + .startup = dw_i2s_startup, | |
| 291 | + .shutdown = dw_i2s_shutdown, | |
| 292 | + .hw_params = dw_i2s_hw_params, | |
| 293 | + .trigger = dw_i2s_trigger, | |
| 294 | +}; | |
| 295 | + | |
| 296 | +#ifdef CONFIG_PM | |
| 297 | + | |
| 298 | +static int dw_i2s_suspend(struct snd_soc_dai *dai) | |
| 299 | +{ | |
| 300 | + struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); | |
| 301 | + | |
| 302 | + clk_disable(dev->clk); | |
| 303 | + return 0; | |
| 304 | +} | |
| 305 | + | |
| 306 | +static int dw_i2s_resume(struct snd_soc_dai *dai) | |
| 307 | +{ | |
| 308 | + struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); | |
| 309 | + | |
| 310 | + clk_enable(dev->clk); | |
| 311 | + return 0; | |
| 312 | +} | |
| 313 | + | |
| 314 | +#else | |
| 315 | +#define dw_i2s_suspend NULL | |
| 316 | +#define dw_i2s_resume NULL | |
| 317 | +#endif | |
| 318 | + | |
| 319 | +static int dw_i2s_probe(struct platform_device *pdev) | |
| 320 | +{ | |
| 321 | + const struct i2s_platform_data *pdata = pdev->dev.platform_data; | |
| 322 | + struct dw_i2s_dev *dev; | |
| 323 | + struct resource *res; | |
| 324 | + int ret; | |
| 325 | + unsigned int cap; | |
| 326 | + struct snd_soc_dai_driver *dw_i2s_dai; | |
| 327 | + | |
| 328 | + if (!pdata) { | |
| 329 | + dev_err(&pdev->dev, "Invalid platform data\n"); | |
| 330 | + return -EINVAL; | |
| 331 | + } | |
| 332 | + | |
| 333 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 334 | + if (!res) { | |
| 335 | + dev_err(&pdev->dev, "no i2s resource defined\n"); | |
| 336 | + return -ENODEV; | |
| 337 | + } | |
| 338 | + | |
| 339 | + if (!devm_request_mem_region(&pdev->dev, res->start, | |
| 340 | + resource_size(res), pdev->name)) { | |
| 341 | + dev_err(&pdev->dev, "i2s region already claimed\n"); | |
| 342 | + return -EBUSY; | |
| 343 | + } | |
| 344 | + | |
| 345 | + dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); | |
| 346 | + if (!dev) { | |
| 347 | + dev_warn(&pdev->dev, "kzalloc fail\n"); | |
| 348 | + return -ENOMEM; | |
| 349 | + } | |
| 350 | + | |
| 351 | + dev->i2s_base = devm_ioremap(&pdev->dev, res->start, | |
| 352 | + resource_size(res)); | |
| 353 | + if (!dev->i2s_base) { | |
| 354 | + dev_err(&pdev->dev, "ioremap fail for i2s_region\n"); | |
| 355 | + return -ENOMEM; | |
| 356 | + } | |
| 357 | + | |
| 358 | + cap = pdata->cap; | |
| 359 | + dev->capability = cap; | |
| 360 | + dev->i2s_clk_cfg = pdata->i2s_clk_cfg; | |
| 361 | + | |
| 362 | + /* Set DMA slaves info */ | |
| 363 | + | |
| 364 | + dev->play_dma_data.data = pdata->play_dma_data; | |
| 365 | + dev->capture_dma_data.data = pdata->capture_dma_data; | |
| 366 | + dev->play_dma_data.addr = res->start + I2S_TXDMA; | |
| 367 | + dev->capture_dma_data.addr = res->start + I2S_RXDMA; | |
| 368 | + dev->play_dma_data.max_burst = 16; | |
| 369 | + dev->capture_dma_data.max_burst = 16; | |
| 370 | + dev->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; | |
| 371 | + dev->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; | |
| 372 | + dev->play_dma_data.filter = pdata->filter; | |
83 more lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 175 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 298 lines aren’t shown here.
This diff is large: its 481 lines aren’t shown here.
This diff is large: its 93 lines aren’t shown here.
This diff is large: its 174 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 133 lines aren’t shown here.
This diff is large: its 451 lines aren’t shown here.
This diff is large: its 384 lines aren’t shown here.
This diff is large: its 68 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 298 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 390 lines aren’t shown here.
This diff is large: its 80 lines aren’t shown here.
This diff is large: its 215 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 212 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 78 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 206 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 108 lines aren’t shown here.
This diff is large: its 136 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 386 lines aren’t shown here.
This diff is large: its 66 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 114 lines aren’t shown here.
This diff is large: its 432 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 319 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 194 lines aren’t shown here.