diff options
| author | Takashi Iwai <tiwai@suse.de> | 2009-12-01 09:57:01 -0500 |
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2009-12-01 09:57:01 -0500 |
| commit | 980f31c46b3c7895ad926fbb43c8edac6ce193ff (patch) | |
| tree | ec61a87b42ce8e6eb24554d8a56173ef75aefdd2 | |
| parent | 9e298f449e667833c4cafad040ce8025a8ba1eed (diff) | |
| parent | 6ef80706184be792499a4485a7957f2660b6a076 (diff) | |
Merge branch 'topic/ice1724-quartet' into topic/hda
| -rw-r--r-- | include/sound/ak4113.h | 321 | ||||
| -rw-r--r-- | include/sound/ak4114.h | 12 | ||||
| -rw-r--r-- | include/sound/ak4xxx-adda.h | 5 | ||||
| -rw-r--r-- | sound/i2c/other/Makefile | 3 | ||||
| -rw-r--r-- | sound/i2c/other/ak4113.c | 639 | ||||
| -rw-r--r-- | sound/i2c/other/ak4xxx-adda.c | 136 | ||||
| -rw-r--r-- | sound/pci/ice1712/Makefile | 2 | ||||
| -rw-r--r-- | sound/pci/ice1712/ice1712.c | 12 | ||||
| -rw-r--r-- | sound/pci/ice1712/ice1712.h | 14 | ||||
| -rw-r--r-- | sound/pci/ice1712/ice1724.c | 103 | ||||
| -rw-r--r-- | sound/pci/ice1712/juli.c | 24 | ||||
| -rw-r--r-- | sound/pci/ice1712/quartet.c | 1130 | ||||
| -rw-r--r-- | sound/pci/ice1712/quartet.h | 10 |
13 files changed, 2326 insertions, 85 deletions
diff --git a/include/sound/ak4113.h b/include/sound/ak4113.h new file mode 100644 index 000000000000..8988edae1609 --- /dev/null +++ b/include/sound/ak4113.h | |||
| @@ -0,0 +1,321 @@ | |||
| 1 | #ifndef __SOUND_AK4113_H | ||
| 2 | #define __SOUND_AK4113_H | ||
| 3 | |||
| 4 | /* | ||
| 5 | * Routines for Asahi Kasei AK4113 | ||
| 6 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz>, | ||
| 7 | * Copyright (c) by Pavel Hofman <pavel.hofman@ivitera.com>, | ||
| 8 | * | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation; either version 2 of the License, or | ||
| 13 | * (at your option) any later version. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * GNU General Public License for more details. | ||
| 19 | * | ||
| 20 | * You should have received a copy of the GNU General Public License | ||
| 21 | * along with this program; if not, write to the Free Software | ||
| 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 23 | * | ||
| 24 | */ | ||
| 25 | |||
| 26 | /* AK4113 registers */ | ||
| 27 | /* power down */ | ||
| 28 | #define AK4113_REG_PWRDN 0x00 | ||
| 29 | /* format control */ | ||
| 30 | #define AK4113_REG_FORMAT 0x01 | ||
| 31 | /* input/output control */ | ||
| 32 | #define AK4113_REG_IO0 0x02 | ||
| 33 | /* input/output control */ | ||
| 34 | #define AK4113_REG_IO1 0x03 | ||
| 35 | /* interrupt0 mask */ | ||
| 36 | #define AK4113_REG_INT0_MASK 0x04 | ||
| 37 | /* interrupt1 mask */ | ||
| 38 | #define AK4113_REG_INT1_MASK 0x05 | ||
| 39 | /* DAT mask & DTS select */ | ||
| 40 | #define AK4113_REG_DATDTS 0x06 | ||
| 41 | /* receiver status 0 */ | ||
| 42 | #define AK4113_REG_RCS0 0x07 | ||
| 43 | /* receiver status 1 */ | ||
| 44 | #define AK4113_REG_RCS1 0x08 | ||
| 45 | /* receiver status 2 */ | ||
| 46 | #define AK4113_REG_RCS2 0x09 | ||
| 47 | /* RX channel status byte 0 */ | ||
| 48 | #define AK4113_REG_RXCSB0 0x0a | ||
| 49 | /* RX channel status byte 1 */ | ||
| 50 | #define AK4113_REG_RXCSB1 0x0b | ||
| 51 | /* RX channel status byte 2 */ | ||
| 52 | #define AK4113_REG_RXCSB2 0x0c | ||
| 53 | /* RX channel status byte 3 */ | ||
| 54 | #define AK4113_REG_RXCSB3 0x0d | ||
| 55 | /* RX channel status byte 4 */ | ||
| 56 | #define AK4113_REG_RXCSB4 0x0e | ||
| 57 | /* burst preamble Pc byte 0 */ | ||
| 58 | #define AK4113_REG_Pc0 0x0f | ||
| 59 | /* burst preamble Pc byte 1 */ | ||
| 60 | #define AK4113_REG_Pc1 0x10 | ||
| 61 | /* burst preamble Pd byte 0 */ | ||
| 62 | #define AK4113_REG_Pd0 0x11 | ||
| 63 | /* burst preamble Pd byte 1 */ | ||
| 64 | #define AK4113_REG_Pd1 0x12 | ||
| 65 | /* Q-subcode address + control */ | ||
| 66 | #define AK4113_REG_QSUB_ADDR 0x13 | ||
| 67 | /* Q-subcode track */ | ||
| 68 | #define AK4113_REG_QSUB_TRACK 0x14 | ||
| 69 | /* Q-subcode index */ | ||
| 70 | #define AK4113_REG_QSUB_INDEX 0x15 | ||
| 71 | /* Q-subcode minute */ | ||
| 72 | #define AK4113_REG_QSUB_MINUTE 0x16 | ||
| 73 | /* Q-subcode second */ | ||
| 74 | #define AK4113_REG_QSUB_SECOND 0x17 | ||
| 75 | /* Q-subcode frame */ | ||
| 76 | #define AK4113_REG_QSUB_FRAME 0x18 | ||
| 77 | /* Q-subcode zero */ | ||
| 78 | #define AK4113_REG_QSUB_ZERO 0x19 | ||
| 79 | /* Q-subcode absolute minute */ | ||
| 80 | #define AK4113_REG_QSUB_ABSMIN 0x1a | ||
| 81 | /* Q-subcode absolute second */ | ||
| 82 | #define AK4113_REG_QSUB_ABSSEC 0x1b | ||
| 83 | /* Q-subcode absolute frame */ | ||
| 84 | #define AK4113_REG_QSUB_ABSFRM 0x1c | ||
| 85 | |||
| 86 | /* sizes */ | ||
| 87 | #define AK4113_REG_RXCSB_SIZE ((AK4113_REG_RXCSB4-AK4113_REG_RXCSB0)+1) | ||
| 88 | #define AK4113_REG_QSUB_SIZE ((AK4113_REG_QSUB_ABSFRM-AK4113_REG_QSUB_ADDR)\ | ||
| 89 | +1) | ||
| 90 | |||
| 91 | #define AK4113_WRITABLE_REGS (AK4113_REG_DATDTS + 1) | ||
| 92 | |||
| 93 | /* AK4113_REG_PWRDN bits */ | ||
| 94 | /* Channel Status Select */ | ||
| 95 | #define AK4113_CS12 (1<<7) | ||
| 96 | /* Block Start & C/U Output Mode */ | ||
| 97 | #define AK4113_BCU (1<<6) | ||
| 98 | /* Master Clock Operation Select */ | ||
| 99 | #define AK4113_CM1 (1<<5) | ||
| 100 | /* Master Clock Operation Select */ | ||
| 101 | #define AK4113_CM0 (1<<4) | ||
| 102 | /* Master Clock Frequency Select */ | ||
| 103 | #define AK4113_OCKS1 (1<<3) | ||
| 104 | /* Master Clock Frequency Select */ | ||
| 105 | #define AK4113_OCKS0 (1<<2) | ||
| 106 | /* 0 = power down, 1 = normal operation */ | ||
| 107 | #define AK4113_PWN (1<<1) | ||
| 108 | /* 0 = reset & initialize (except thisregister), 1 = normal operation */ | ||
| 109 | #define AK4113_RST (1<<0) | ||
| 110 | |||
| 111 | /* AK4113_REQ_FORMAT bits */ | ||
| 112 | /* V/TX Output select: 0 = Validity Flag Output, 1 = TX */ | ||
| 113 | #define AK4113_VTX (1<<7) | ||
| 114 | /* Audio Data Control */ | ||
| 115 | #define AK4113_DIF2 (1<<6) | ||
| 116 | /* Audio Data Control */ | ||
| 117 | #define AK4113_DIF1 (1<<5) | ||
| 118 | /* Audio Data Control */ | ||
| 119 | #define AK4113_DIF0 (1<<4) | ||
| 120 | /* Deemphasis Autodetect Enable (1 = enable) */ | ||
| 121 | #define AK4113_DEAU (1<<3) | ||
| 122 | /* 32kHz-48kHz Deemphasis Control */ | ||
| 123 | #define AK4113_DEM1 (1<<2) | ||
| 124 | /* 32kHz-48kHz Deemphasis Control */ | ||
| 125 | #define AK4113_DEM0 (1<<1) | ||
| 126 | #define AK4113_DEM_OFF (AK4113_DEM0) | ||
| 127 | #define AK4113_DEM_44KHZ (0) | ||
| 128 | #define AK4113_DEM_48KHZ (AK4113_DEM1) | ||
| 129 | #define AK4113_DEM_32KHZ (AK4113_DEM0|AK4113_DEM1) | ||
| 130 | /* STDO: 16-bit, right justified */ | ||
| 131 | #define AK4113_DIF_16R (0) | ||
| 132 | /* STDO: 18-bit, right justified */ | ||
| 133 | #define AK4113_DIF_18R (AK4113_DIF0) | ||
| 134 | /* STDO: 20-bit, right justified */ | ||
| 135 | #define AK4113_DIF_20R (AK4113_DIF1) | ||
| 136 | /* STDO: 24-bit, right justified */ | ||
| 137 | #define AK4113_DIF_24R (AK4113_DIF1|AK4113_DIF0) | ||
| 138 | /* STDO: 24-bit, left justified */ | ||
| 139 | #define AK4113_DIF_24L (AK4113_DIF2) | ||
| 140 | /* STDO: I2S */ | ||
| 141 | #define AK4113_DIF_24I2S (AK4113_DIF2|AK4113_DIF0) | ||
| 142 | /* STDO: 24-bit, left justified; LRCLK, BICK = Input */ | ||
| 143 | #define AK4113_DIF_I24L (AK4113_DIF2|AK4113_DIF1) | ||
| 144 | /* STDO: I2S; LRCLK, BICK = Input */ | ||
| 145 | #define AK4113_DIF_I24I2S (AK4113_DIF2|AK4113_DIF1|AK4113_DIF0) | ||
| 146 | |||
| 147 | /* AK4113_REG_IO0 */ | ||
| 148 | /* XTL1=0,XTL0=0 -> 11.2896Mhz; XTL1=0,XTL0=1 -> 12.288Mhz */ | ||
| 149 | #define AK4113_XTL1 (1<<6) | ||
| 150 | /* XTL1=1,XTL0=0 -> 24.576Mhz; XTL1=1,XTL0=1 -> use channel status */ | ||
| 151 | #define AK4113_XTL0 (1<<5) | ||
| 152 | /* Block Start Signal Output: 0 = U-bit, 1 = C-bit (req. BCU = 1) */ | ||
| 153 | #define AK4113_UCE (1<<4) | ||
| 154 | /* TX Output Enable (1 = enable) */ | ||
| 155 | #define AK4113_TXE (1<<3) | ||
| 156 | /* Output Through Data Selector for TX pin */ | ||
| 157 | #define AK4113_OPS2 (1<<2) | ||
| 158 | /* Output Through Data Selector for TX pin */ | ||
| 159 | #define AK4113_OPS1 (1<<1) | ||
| 160 | /* Output Through Data Selector for TX pin */ | ||
| 161 | #define AK4113_OPS0 (1<<0) | ||
| 162 | /* 11.2896 MHz ref. Xtal freq. */ | ||
| 163 | #define AK4113_XTL_11_2896M (0) | ||
| 164 | /* 12.288 MHz ref. Xtal freq. */ | ||
| 165 | #define AK4113_XTL_12_288M (AK4113_XTL0) | ||
| 166 | /* 24.576 MHz ref. Xtal freq. */ | ||
| 167 | #define AK4113_XTL_24_576M (AK4113_XTL1) | ||
| 168 | |||
| 169 | /* AK4113_REG_IO1 */ | ||
| 170 | /* Interrupt 0 pin Hold */ | ||
| 171 | #define AK4113_EFH1 (1<<7) | ||
| 172 | /* Interrupt 0 pin Hold */ | ||
| 173 | #define AK4113_EFH0 (1<<6) | ||
| 174 | #define AK4113_EFH_512LRCLK (0) | ||
| 175 | #define AK4113_EFH_1024LRCLK (AK4113_EFH0) | ||
| 176 | #define AK4113_EFH_2048LRCLK (AK4113_EFH1) | ||
| 177 | #define AK4113_EFH_4096LRCLK (AK4113_EFH1|AK4113_EFH0) | ||
| 178 | /* PLL Lock Time: 0 = 384/fs, 1 = 1/fs */ | ||
| 179 | #define AK4113_FAST (1<<5) | ||
| 180 | /* MCKO2 Output Select: 0 = CMx/OCKSx, 1 = Xtal */ | ||
| 181 | #define AK4113_XMCK (1<<4) | ||
| 182 | /* MCKO2 Output Freq. Select: 0 = x1, 1 = x0.5 (req. XMCK = 1) */ | ||
| 183 | #define AK4113_DIV (1<<3) | ||
| 184 | /* Input Recovery Data Select */ | ||
| 185 | #define AK4113_IPS2 (1<<2) | ||
| 186 | /* Input Recovery Data Select */ | ||
| 187 | #define AK4113_IPS1 (1<<1) | ||
| 188 | /* Input Recovery Data Select */ | ||
| 189 | #define AK4113_IPS0 (1<<0) | ||
| 190 | #define AK4113_IPS(x) ((x)&7) | ||
| 191 | |||
| 192 | /* AK4113_REG_INT0_MASK && AK4113_REG_INT1_MASK*/ | ||
| 193 | /* mask enable for QINT bit */ | ||
| 194 | #define AK4113_MQI (1<<7) | ||
| 195 | /* mask enable for AUTO bit */ | ||
| 196 | #define AK4113_MAUT (1<<6) | ||
| 197 | /* mask enable for CINT bit */ | ||
| 198 | #define AK4113_MCIT (1<<5) | ||
| 199 | /* mask enable for UNLOCK bit */ | ||
| 200 | #define AK4113_MULK (1<<4) | ||
| 201 | /* mask enable for V bit */ | ||
| 202 | #define AK4113_V (1<<3) | ||
| 203 | /* mask enable for STC bit */ | ||
| 204 | #define AK4113_STC (1<<2) | ||
| 205 | /* mask enable for AUDN bit */ | ||
| 206 | #define AK4113_MAN (1<<1) | ||
| 207 | /* mask enable for PAR bit */ | ||
| 208 | #define AK4113_MPR (1<<0) | ||
| 209 | |||
| 210 | /* AK4113_REG_DATDTS */ | ||
| 211 | /* DAT Start ID Counter */ | ||
| 212 | #define AK4113_DCNT (1<<4) | ||
| 213 | /* DTS-CD 16-bit Sync Word Detect */ | ||
| 214 | #define AK4113_DTS16 (1<<3) | ||
| 215 | /* DTS-CD 14-bit Sync Word Detect */ | ||
| 216 | #define AK4113_DTS14 (1<<2) | ||
| 217 | /* mask enable for DAT bit (if 1, no INT1 effect */ | ||
| 218 | #define AK4113_MDAT1 (1<<1) | ||
| 219 | /* mask enable for DAT bit (if 1, no INT0 effect */ | ||
| 220 | #define AK4113_MDAT0 (1<<0) | ||
| 221 | |||
| 222 | /* AK4113_REG_RCS0 */ | ||
| 223 | /* Q-subcode buffer interrupt, 0 = no change, 1 = changed */ | ||
| 224 | #define AK4113_QINT (1<<7) | ||
| 225 | /* Non-PCM or DTS stream auto detection, 0 = no detect, 1 = detect */ | ||
| 226 | #define AK4113_AUTO (1<<6) | ||
| 227 | /* channel status buffer interrupt, 0 = no change, 1 = change */ | ||
| 228 | #define AK4113_CINT (1<<5) | ||
| 229 | /* PLL lock status, 0 = lock, 1 = unlock */ | ||
| 230 | #define AK4113_UNLCK (1<<4) | ||
| 231 | /* Validity bit, 0 = valid, 1 = invalid */ | ||
| 232 | #define AK4113_V (1<<3) | ||
| 233 | /* sampling frequency or Pre-emphasis change, 0 = no detect, 1 = detect */ | ||
| 234 | #define AK4113_STC (1<<2) | ||
| 235 | /* audio bit output, 0 = audio, 1 = non-audio */ | ||
| 236 | #define AK4113_AUDION (1<<1) | ||
| 237 | /* parity error or biphase error status, 0 = no error, 1 = error */ | ||
| 238 | #define AK4113_PAR (1<<0) | ||
| 239 | |||
| 240 | /* AK4113_REG_RCS1 */ | ||
| 241 | /* sampling frequency detection */ | ||
| 242 | #define AK4113_FS3 (1<<7) | ||
| 243 | #define AK4113_FS2 (1<<6) | ||
| 244 | #define AK4113_FS1 (1<<5) | ||
| 245 | #define AK4113_FS0 (1<<4) | ||
| 246 | /* Pre-emphasis detect, 0 = OFF, 1 = ON */ | ||
| 247 | #define AK4113_PEM (1<<3) | ||
| 248 | /* DAT Start ID Detect, 0 = no detect, 1 = detect */ | ||
| 249 | #define AK4113_DAT (1<<2) | ||
| 250 | /* DTS-CD bit audio stream detect, 0 = no detect, 1 = detect */ | ||
| 251 | #define AK4113_DTSCD (1<<1) | ||
| 252 | /* Non-PCM bit stream detection, 0 = no detect, 1 = detect */ | ||
| 253 | #define AK4113_NPCM (1<<0) | ||
| 254 | #define AK4113_FS_8000HZ (AK4113_FS3|AK4113_FS0) | ||
| 255 | #define AK4113_FS_11025HZ (AK4113_FS2|AK4113_FS0) | ||
| 256 | #define AK4113_FS_16000HZ (AK4113_FS2|AK4113_FS1|AK4113_FS0) | ||
| 257 | #define AK4113_FS_22050HZ (AK4113_FS2) | ||
| 258 | #define AK4113_FS_24000HZ (AK4113_FS2|AK4113_FS1) | ||
| 259 | #define AK4113_FS_32000HZ (AK4113_FS1|AK4113_FS0) | ||
| 260 | #define AK4113_FS_44100HZ (0) | ||
| 261 | #define AK4113_FS_48000HZ (AK4113_FS1) | ||
| 262 | #define AK4113_FS_64000HZ (AK4113_FS3|AK4113_FS1|AK4113_FS0) | ||
| 263 | #define AK4113_FS_88200HZ (AK4113_FS3) | ||
| 264 | #define AK4113_FS_96000HZ (AK4113_FS3|AK4113_FS1) | ||
| 265 | #define AK4113_FS_176400HZ (AK4113_FS3|AK4113_FS2) | ||
| 266 | #define AK4113_FS_192000HZ (AK4113_FS3|AK4113_FS2|AK4113_FS1) | ||
| 267 | |||
| 268 | /* AK4113_REG_RCS2 */ | ||
| 269 | /* CRC for Q-subcode, 0 = no error, 1 = error */ | ||
| 270 | #define AK4113_QCRC (1<<1) | ||
| 271 | /* CRC for channel status, 0 = no error, 1 = error */ | ||
| 272 | #define AK4113_CCRC (1<<0) | ||
| 273 | |||
| 274 | /* flags for snd_ak4113_check_rate_and_errors() */ | ||
| 275 | #define AK4113_CHECK_NO_STAT (1<<0) /* no statistics */ | ||
| 276 | #define AK4113_CHECK_NO_RATE (1<<1) /* no rate check */ | ||
| 277 | |||
| 278 | #define AK4113_CONTROLS 13 | ||
| 279 | |||
| 280 | typedef void (ak4113_write_t)(void *private_data, unsigned char addr, | ||
| 281 | unsigned char data); | ||
| 282 | typedef unsigned char (ak4113_read_t)(void *private_data, unsigned char addr); | ||
| 283 | |||
| 284 | struct ak4113 { | ||
| 285 | struct snd_card *card; | ||
| 286 | ak4113_write_t *write; | ||
| 287 | ak4113_read_t *read; | ||
| 288 | void *private_data; | ||
| 289 | unsigned int init:1; | ||
| 290 | spinlock_t lock; | ||
| 291 | unsigned char regmap[AK4113_WRITABLE_REGS]; | ||
| 292 | struct snd_kcontrol *kctls[AK4113_CONTROLS]; | ||
| 293 | struct snd_pcm_substream *substream; | ||
| 294 | unsigned long parity_errors; | ||
| 295 | unsigned long v_bit_errors; | ||
| 296 | unsigned long qcrc_errors; | ||
| 297 | unsigned long ccrc_errors; | ||
| 298 | unsigned char rcs0; | ||
| 299 | unsigned char rcs1; | ||
| 300 | unsigned char rcs2; | ||
| 301 | struct delayed_work work; | ||
| 302 | unsigned int check_flags; | ||
| 303 | void *change_callback_private; | ||
| 304 | void (*change_callback)(struct ak4113 *ak4113, unsigned char c0, | ||
| 305 | unsigned char c1); | ||
| 306 | }; | ||
| 307 | |||
| 308 | int snd_ak4113_create(struct snd_card *card, ak4113_read_t *read, | ||
| 309 | ak4113_write_t *write, | ||
| 310 | const unsigned char pgm[AK4113_WRITABLE_REGS], | ||
| 311 | void *private_data, struct ak4113 **r_ak4113); | ||
| 312 | void snd_ak4113_reg_write(struct ak4113 *ak4113, unsigned char reg, | ||
| 313 | unsigned char mask, unsigned char val); | ||
| 314 | void snd_ak4113_reinit(struct ak4113 *ak4113); | ||
| 315 | int snd_ak4113_build(struct ak4113 *ak4113, | ||
| 316 | struct snd_pcm_substream *capture_substream); | ||
| 317 | int snd_ak4113_external_rate(struct ak4113 *ak4113); | ||
| 318 | int snd_ak4113_check_rate_and_errors(struct ak4113 *ak4113, unsigned int flags); | ||
| 319 | |||
| 320 | #endif /* __SOUND_AK4113_H */ | ||
| 321 | |||
diff --git a/include/sound/ak4114.h b/include/sound/ak4114.h index d293d36a66b8..3ce69fd92523 100644 --- a/include/sound/ak4114.h +++ b/include/sound/ak4114.h | |||
| @@ -95,13 +95,13 @@ | |||
| 95 | 95 | ||
| 96 | /* AK4114_REG_IO0 */ | 96 | /* AK4114_REG_IO0 */ |
| 97 | #define AK4114_TX1E (1<<7) /* TX1 Output Enable (1 = enable) */ | 97 | #define AK4114_TX1E (1<<7) /* TX1 Output Enable (1 = enable) */ |
| 98 | #define AK4114_OPS12 (1<<2) /* Output Though Data Selector for TX1 pin */ | 98 | #define AK4114_OPS12 (1<<6) /* Output Data Selector for TX1 pin */ |
| 99 | #define AK4114_OPS11 (1<<1) /* Output Though Data Selector for TX1 pin */ | 99 | #define AK4114_OPS11 (1<<5) /* Output Data Selector for TX1 pin */ |
| 100 | #define AK4114_OPS10 (1<<0) /* Output Though Data Selector for TX1 pin */ | 100 | #define AK4114_OPS10 (1<<4) /* Output Data Selector for TX1 pin */ |
| 101 | #define AK4114_TX0E (1<<3) /* TX0 Output Enable (1 = enable) */ | 101 | #define AK4114_TX0E (1<<3) /* TX0 Output Enable (1 = enable) */ |
| 102 | #define AK4114_OPS02 (1<<2) /* Output Though Data Selector for TX0 pin */ | 102 | #define AK4114_OPS02 (1<<2) /* Output Data Selector for TX0 pin */ |
| 103 | #define AK4114_OPS01 (1<<1) /* Output Though Data Selector for TX0 pin */ | 103 | #define AK4114_OPS01 (1<<1) /* Output Data Selector for TX0 pin */ |
| 104 | #define AK4114_OPS00 (1<<0) /* Output Though Data Selector for TX0 pin */ | 104 | #define AK4114_OPS00 (1<<0) /* Output Data Selector for TX0 pin */ |
| 105 | 105 | ||
| 106 | /* AK4114_REG_IO1 */ | 106 | /* AK4114_REG_IO1 */ |
| 107 | #define AK4114_EFH1 (1<<7) /* Interrupt 0 pin Hold */ | 107 | #define AK4114_EFH1 (1<<7) /* Interrupt 0 pin Hold */ |
diff --git a/include/sound/ak4xxx-adda.h b/include/sound/ak4xxx-adda.h index 891cf1aea8b1..030b87c2f6d4 100644 --- a/include/sound/ak4xxx-adda.h +++ b/include/sound/ak4xxx-adda.h | |||
| @@ -68,7 +68,7 @@ struct snd_akm4xxx { | |||
| 68 | enum { | 68 | enum { |
| 69 | SND_AK4524, SND_AK4528, SND_AK4529, | 69 | SND_AK4524, SND_AK4528, SND_AK4529, |
| 70 | SND_AK4355, SND_AK4358, SND_AK4381, | 70 | SND_AK4355, SND_AK4358, SND_AK4381, |
| 71 | SND_AK5365 | 71 | SND_AK5365, SND_AK4620, |
| 72 | } type; | 72 | } type; |
| 73 | 73 | ||
| 74 | /* (array) information of combined codecs */ | 74 | /* (array) information of combined codecs */ |
| @@ -76,6 +76,9 @@ struct snd_akm4xxx { | |||
| 76 | const struct snd_akm4xxx_adc_channel *adc_info; | 76 | const struct snd_akm4xxx_adc_channel *adc_info; |
| 77 | 77 | ||
| 78 | struct snd_ak4xxx_ops ops; | 78 | struct snd_ak4xxx_ops ops; |
| 79 | unsigned int num_chips; | ||
| 80 | unsigned int total_regs; | ||
| 81 | const char *name; | ||
| 79 | }; | 82 | }; |
| 80 | 83 | ||
| 81 | void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, | 84 | void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, |
diff --git a/sound/i2c/other/Makefile b/sound/i2c/other/Makefile index 703d954238f4..2dad40f3f622 100644 --- a/sound/i2c/other/Makefile +++ b/sound/i2c/other/Makefile | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | snd-ak4114-objs := ak4114.o | 6 | snd-ak4114-objs := ak4114.o |
| 7 | snd-ak4117-objs := ak4117.o | 7 | snd-ak4117-objs := ak4117.o |
| 8 | snd-ak4113-objs := ak4113.o | ||
| 8 | snd-ak4xxx-adda-objs := ak4xxx-adda.o | 9 | snd-ak4xxx-adda-objs := ak4xxx-adda.o |
| 9 | snd-pt2258-objs := pt2258.o | 10 | snd-pt2258-objs := pt2258.o |
| 10 | snd-tea575x-tuner-objs := tea575x-tuner.o | 11 | snd-tea575x-tuner-objs := tea575x-tuner.o |
| @@ -12,5 +13,5 @@ snd-tea575x-tuner-objs := tea575x-tuner.o | |||
| 12 | # Module Dependency | 13 | # Module Dependency |
| 13 | obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o | 14 | obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o |
| 14 | obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o | 15 | obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o |
| 15 | obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4xxx-adda.o snd-pt2258.o | 16 | obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o |
| 16 | obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o | 17 | obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o |
diff --git a/sound/i2c/other/ak4113.c b/sound/i2c/other/ak4113.c new file mode 100644 index 000000000000..fff62cc8607c --- /dev/null +++ b/sound/i2c/other/ak4113.c | |||
| @@ -0,0 +1,639 @@ | |||
| 1 | /* | ||
| 2 | * Routines for control of the AK4113 via I2C/4-wire serial interface | ||
| 3 | * IEC958 (S/PDIF) receiver by Asahi Kasei | ||
| 4 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> | ||
| 5 | * Copyright (c) by Pavel Hofman <pavel.hofman@ivitera.com> | ||
| 6 | * | ||
| 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 as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 21 | * | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/slab.h> | ||
| 25 | #include <linux/delay.h> | ||
| 26 | #include <sound/core.h> | ||
| 27 | #include <sound/control.h> | ||
| 28 | #include <sound/pcm.h> | ||
| 29 | #include <sound/ak4113.h> | ||
| 30 | #include <sound/asoundef.h> | ||
| 31 | #include <sound/info.h> | ||
| 32 | |||
| 33 | MODULE_AUTHOR("Pavel Hofman <pavel.hofman@ivitera.com>"); | ||
| 34 | MODULE_DESCRIPTION("AK4113 IEC958 (S/PDIF) receiver by Asahi Kasei"); | ||
| 35 | MODULE_LICENSE("GPL"); | ||
| 36 | |||
| 37 | #define AK4113_ADDR 0x00 /* fixed address */ | ||
| 38 | |||
| 39 | static void ak4113_stats(struct work_struct *work); | ||
| 40 | static void ak4113_init_regs(struct ak4113 *chip); | ||
| 41 | |||
| 42 | |||
| 43 | static void reg_write(struct ak4113 *ak4113, unsigned char reg, | ||
| 44 | unsigned char val) | ||
| 45 | { | ||
| 46 | ak4113->write(ak4113->private_data, reg, val); | ||
| 47 | if (reg < sizeof(ak4113->regmap)) | ||
| 48 | ak4113->regmap[reg] = val; | ||
| 49 | } | ||
| 50 | |||
| 51 | static inline unsigned char reg_read(struct ak4113 *ak4113, unsigned char reg) | ||
| 52 | { | ||
| 53 | return ak4113->read(ak4113->private_data, reg); | ||
| 54 | } | ||
| 55 | |||
| 56 | static void snd_ak4113_free(struct ak4113 *chip) | ||
| 57 | { | ||
| 58 | chip->init = 1; /* don't schedule new work */ | ||
| 59 | mb(); | ||
| 60 | cancel_delayed_work(&chip->work); | ||
| 61 | flush_scheduled_work(); | ||
| 62 | kfree(chip); | ||
| 63 | } | ||
| 64 | |||
| 65 | static int snd_ak4113_dev_free(struct snd_device *device) | ||
| 66 | { | ||
| 67 | struct ak4113 *chip = device->device_data; | ||
| 68 | snd_ak4113_free(chip); | ||
| 69 | return 0; | ||
| 70 | } | ||
| 71 | |||
| 72 | int snd_ak4113_create(struct snd_card *card, ak4113_read_t *read, | ||
| 73 | ak4113_write_t *write, const unsigned char pgm[5], | ||
| 74 | void *private_data, struct ak4113 **r_ak4113) | ||
| 75 | { | ||
| 76 | struct ak4113 *chip; | ||
| 77 | int err = 0; | ||
| 78 | unsigned char reg; | ||
| 79 | static struct snd_device_ops ops = { | ||
| 80 | .dev_free = snd_ak4113_dev_free, | ||
| 81 | }; | ||
| 82 | |||
| 83 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
| 84 | if (chip == NULL) | ||
| 85 | return -ENOMEM; | ||
| 86 | spin_lock_init(&chip->lock); | ||
| 87 | chip->card = card; | ||
| 88 | chip->read = read; | ||
| 89 | chip->write = write; | ||
| 90 | chip->private_data = private_data; | ||
| 91 | INIT_DELAYED_WORK(&chip->work, ak4113_stats); | ||
| 92 | |||
| 93 | for (reg = 0; reg < AK4113_WRITABLE_REGS ; reg++) | ||
| 94 | chip->regmap[reg] = pgm[reg]; | ||
| 95 | ak4113_init_regs(chip); | ||
| 96 | |||
| 97 | chip->rcs0 = reg_read(chip, AK4113_REG_RCS0) & ~(AK4113_QINT | | ||
| 98 | AK4113_CINT | AK4113_STC); | ||
| 99 | chip->rcs1 = reg_read(chip, AK4113_REG_RCS1); | ||
| 100 | chip->rcs2 = reg_read(chip, AK4113_REG_RCS2); | ||
| 101 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); | ||
| 102 | if (err < 0) | ||
| 103 | goto __fail; | ||
| 104 | |||
| 105 | if (r_ak4113) | ||
| 106 | *r_ak4113 = chip; | ||
| 107 | return 0; | ||
| 108 | |||
| 109 | __fail: | ||
| 110 | snd_ak4113_free(chip); | ||
| 111 | return err < 0 ? err : -EIO; | ||
| 112 | } | ||
| 113 | EXPORT_SYMBOL_GPL(snd_ak4113_create); | ||
| 114 | |||
| 115 | void snd_ak4113_reg_write(struct ak4113 *chip, unsigned char reg, | ||
| 116 | unsigned char mask, unsigned char val) | ||
| 117 | { | ||
| 118 | if (reg >= AK4113_WRITABLE_REGS) | ||
| 119 | return; | ||
| 120 | reg_write(chip, reg, (chip->regmap[reg] & ~mask) | val); | ||
| 121 | } | ||
| 122 | EXPORT_SYMBOL_GPL(snd_ak4113_reg_write); | ||
| 123 | |||
| 124 | static void ak4113_init_regs(struct ak4113 *chip) | ||
| 125 | { | ||
| 126 | unsigned char old = chip->regmap[AK4113_REG_PWRDN], reg; | ||
| 127 | |||
| 128 | /* bring the chip to reset state and powerdown state */ | ||
| 129 | reg_write(chip, AK4113_REG_PWRDN, old & ~(AK4113_RST|AK4113_PWN)); | ||
| 130 | udelay(200); | ||
| 131 | /* release reset, but leave powerdown */ | ||
| 132 | reg_write(chip, AK4113_REG_PWRDN, (old | AK4113_RST) & ~AK4113_PWN); | ||
| 133 | udelay(200); | ||
| 134 | for (reg = 1; reg < AK4113_WRITABLE_REGS; reg++) | ||
| 135 | reg_write(chip, reg, chip->regmap[reg]); | ||
| 136 | /* release powerdown, everything is initialized now */ | ||
| 137 | reg_write(chip, AK4113_REG_PWRDN, old | AK4113_RST | AK4113_PWN); | ||
| 138 | } | ||
| 139 | |||
| 140 | void snd_ak4113_reinit(struct ak4113 *chip) | ||
| 141 | { | ||
| 142 | chip->init = 1; | ||
| 143 | mb(); | ||
| 144 | flush_scheduled_work(); | ||
| 145 | ak4113_init_regs(chip); | ||
| 146 | /* bring up statistics / event queing */ | ||
| 147 | chip->init = 0; | ||
| 148 | if (chip->kctls[0]) | ||
| 149 | schedule_delayed_work(&chip->work, HZ / 10); | ||
| 150 | } | ||
| 151 | EXPORT_SYMBOL_GPL(snd_ak4113_reinit); | ||
| 152 | |||
| 153 | static unsigned int external_rate(unsigned char rcs1) | ||
| 154 | { | ||
| 155 | switch (rcs1 & (AK4113_FS0|AK4113_FS1|AK4113_FS2|AK4113_FS3)) { | ||
| 156 | case AK4113_FS_8000HZ: | ||
| 157 | return 8000; | ||
| 158 | case AK4113_FS_11025HZ: | ||
| 159 | return 11025; | ||
| 160 | case AK4113_FS_16000HZ: | ||
| 161 | return 16000; | ||
| 162 | case AK4113_FS_22050HZ: | ||
| 163 | return 22050; | ||
| 164 | case AK4113_FS_24000HZ: | ||
| 165 | return 24000; | ||
| 166 | case AK4113_FS_32000HZ: | ||
| 167 | return 32000; | ||
| 168 | case AK4113_FS_44100HZ: | ||
| 169 | return 44100; | ||
| 170 | case AK4113_FS_48000HZ: | ||
| 171 | return 48000; | ||
| 172 | case AK4113_FS_64000HZ: | ||
| 173 | return 64000; | ||
| 174 | case AK4113_FS_88200HZ: | ||
| 175 | return 88200; | ||
| 176 | case AK4113_FS_96000HZ: | ||
| 177 | return 96000; | ||
| 178 | case AK4113_FS_176400HZ: | ||
| 179 | return 176400; | ||
| 180 | case AK4113_FS_192000HZ: | ||
| 181 | return 192000; | ||
| 182 | default: | ||
| 183 | return 0; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 187 | static int snd_ak4113_in_error_info(struct snd_kcontrol *kcontrol, | ||
| 188 | struct snd_ctl_elem_info *uinfo) | ||
| 189 | { | ||
| 190 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
| 191 | uinfo->count = 1; | ||
| 192 | uinfo->value.integer.min = 0; | ||
| 193 | uinfo->value.integer.max = LONG_MAX; | ||
| 194 | return 0; | ||
| 195 | } | ||
| 196 | |||
| 197 | static int snd_ak4113_in_error_get(struct snd_kcontrol *kcontrol, | ||
| 198 | struct snd_ctl_elem_value *ucontrol) | ||
| 199 | { | ||
| 200 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); | ||
| 201 | long *ptr; | ||
| 202 | |||
| 203 | spin_lock_irq(&chip->lock); | ||
| 204 | ptr = (long *)(((char *)chip) + kcontrol->private_value); | ||
| 205 | ucontrol->value.integer.value[0] = *ptr; | ||
| 206 | *ptr = 0; | ||
| 207 | spin_unlock_irq(&chip->lock); | ||
| 208 | return 0; | ||
| 209 | } | ||
| 210 | |||
| 211 | #define snd_ak4113_in_bit_info snd_ctl_boolean_mono_info | ||
| 212 | |||
| 213 | static int snd_ak4113_in_bit_get(struct snd_kcontrol *kcontrol, | ||
| 214 | struct snd_ctl_elem_value *ucontrol) | ||
| 215 | { | ||
| 216 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); | ||
| 217 | unsigned char reg = kcontrol->private_value & 0xff; | ||
| 218 | unsigned char bit = (kcontrol->private_value >> 8) & 0xff; | ||
| 219 | unsigned char inv = (kcontrol->private_value >> 31) & 1; | ||
| 220 | |||
| 221 | ucontrol->value.integer.value[0] = | ||
| 222 | ((reg_read(chip, reg) & (1 << bit)) ? 1 : 0) ^ inv; | ||
| 223 | return 0; | ||
| 224 | } | ||
| 225 | |||
| 226 | static int snd_ak4113_rx_info(struct snd_kcontrol *kcontrol, | ||
| 227 | struct snd_ctl_elem_info *uinfo) | ||
| 228 | { | ||
| 229 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
| 230 | uinfo->count = 1; | ||
| 231 | uinfo->value.integer.min = 0; | ||
| 232 | uinfo->value.integer.max = 5; | ||
| 233 | return 0; | ||
| 234 | } | ||
| 235 | |||
| 236 | static int snd_ak4113_rx_get(struct snd_kcontrol *kcontrol, | ||
| 237 | struct snd_ctl_elem_value *ucontrol) | ||
| 238 | { | ||
| 239 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); | ||
| 240 | |||
| 241 | ucontrol->value.integer.value[0] = | ||
| 242 | (AK4113_IPS(chip->regmap[AK4113_REG_IO1])); | ||
| 243 | return 0; | ||
| 244 | } | ||
| 245 | |||
| 246 | static int snd_ak4113_rx_put(struct snd_kcontrol *kcontrol, | ||
| 247 | struct snd_ctl_elem_value *ucontrol) | ||
| 248 | { | ||
| 249 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); | ||
| 250 | int change; | ||
| 251 | u8 old_val; | ||
| 252 | |||
| 253 | spin_lock_irq(&chip->lock); | ||
| 254 | old_val = chip->regmap[AK4113_REG_IO1]; | ||
| 255 | change = ucontrol->value.integer.value[0] != AK4113_IPS(old_val); | ||
| 256 | if (change) | ||
| 257 | reg_write(chip, AK4113_REG_IO1, | ||
| 258 | (old_val & (~AK4113_IPS(0xff))) | | ||
| 259 | (AK4113_IPS(ucontrol->value.integer.value[0]))); | ||
| 260 | spin_unlock_irq(&chip->lock); | ||
| 261 | return change; | ||
| 262 | } | ||
| 263 | |||
| 264 | static int snd_ak4113_rate_info(struct snd_kcontrol *kcontrol, | ||
| 265 | struct snd_ctl_elem_info *uinfo) | ||
| 266 | { | ||
| 267 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
| 268 | uinfo->count = 1; | ||
| 269 | uinfo->value.integer.min = 0; | ||
| 270 | uinfo->value.integer.max = 192000; | ||
| 271 | return 0; | ||
| 272 | } | ||
| 273 | |||
| 274 | static int snd_ak4113_rate_get(struct snd_kcontrol *kcontrol, | ||
| 275 | struct snd_ctl_elem_value *ucontrol) | ||
| 276 | { | ||
| 277 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); | ||
| 278 | |||
| 279 | ucontrol->value.integer.value[0] = external_rate(reg_read(chip, | ||
| 280 | AK4113_REG_RCS1)); | ||
| 281 | return 0; | ||
| 282 | } | ||
| 283 | |||
| 284 | static int snd_ak4113_spdif_info(struct snd_kcontrol *kcontrol, | ||
| 285 | struct snd_ctl_elem_info *uinfo) | ||
| 286 | { | ||
| 287 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; | ||
| 288 | uinfo->count = 1; | ||
| 289 | return 0; | ||
| 290 | } | ||
| 291 | |||
| 292 | static int snd_ak4113_spdif_get(struct snd_kcontrol *kcontrol, | ||
| 293 | struct snd_ctl_elem_value *ucontrol) | ||
| 294 | { | ||
| 295 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); | ||
| 296 | unsigned i; | ||
| 297 | |||
| 298 | for (i = 0; i < AK4113_REG_RXCSB_SIZE; i++) | ||
| 299 | ucontrol->value.iec958.status[i] = reg_read(chip, | ||
| 300 | AK4113_REG_RXCSB0 + i); | ||
| 301 | return 0; | ||
| 302 | } | ||
| 303 | |||
| 304 | static int snd_ak4113_spdif_mask_info(struct snd_kcontrol *kcontrol, | ||
| 305 | struct snd_ctl_elem_info *uinfo) | ||
| 306 | { | ||
| 307 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; | ||
| 308 | uinfo->count = 1; | ||
| 309 | return 0; | ||
| 310 | } | ||
| 311 | |||
| 312 | static int snd_ak4113_spdif_mask_get(struct snd_kcontrol *kcontrol, | ||
| 313 | struct snd_ctl_elem_value *ucontrol) | ||
| 314 | { | ||
| 315 | memset(ucontrol->value.iec958.status, 0xff, AK4113_REG_RXCSB_SIZE); | ||
| 316 | return 0; | ||
| 317 | } | ||
| 318 | |||
| 319 | static int snd_ak4113_spdif_pinfo(struct snd_kcontrol *kcontrol, | ||
| 320 | struct snd_ctl_elem_info *uinfo) | ||
| 321 | { | ||
| 322 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
| 323 | uinfo->value.integer.min = 0; | ||
| 324 | uinfo->value.integer.max = 0xffff; | ||
| 325 | uinfo->count = 4; | ||
| 326 | return 0; | ||
| 327 | } | ||
| 328 | |||
| 329 | static int snd_ak4113_spdif_pget(struct snd_kcontrol *kcontrol, | ||
| 330 | struct snd_ctl_elem_value *ucontrol) | ||
| 331 | { | ||
| 332 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); | ||
| 333 | unsigned short tmp; | ||
| 334 | |||
| 335 | ucontrol->value.integer.value[0] = 0xf8f2; | ||
| 336 | ucontrol->value.integer.value[1] = 0x4e1f; | ||
| 337 | tmp = reg_read(chip, AK4113_REG_Pc0) | | ||
| 338 | (reg_read(chip, AK4113_REG_Pc1) << 8); | ||
| 339 | ucontrol->value.integer.value[2] = tmp; | ||
| 340 | tmp = reg_read(chip, AK4113_REG_Pd0) | | ||
| 341 | (reg_read(chip, AK4113_REG_Pd1) << 8); | ||
| 342 | ucontrol->value.integer.value[3] = tmp; | ||
| 343 | return 0; | ||
| 344 | } | ||
| 345 | |||
| 346 | static int snd_ak4113_spdif_qinfo(struct snd_kcontrol *kcontrol, | ||
| 347 | struct snd_ctl_elem_info *uinfo) | ||
| 348 | { | ||
| 349 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; | ||
| 350 | uinfo->count = AK4113_REG_QSUB_SIZE; | ||
| 351 | return 0; | ||
| 352 | } | ||
| 353 | |||
| 354 | static int snd_ak4113_spdif_qget(struct snd_kcontrol *kcontrol, | ||
| 355 | struct snd_ctl_elem_value *ucontrol) | ||
| 356 | { | ||
| 357 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); | ||
| 358 | unsigned i; | ||
| 359 | |||
| 360 | for (i = 0; i < AK4113_REG_QSUB_SIZE; i++) | ||
| 361 | ucontrol->value.bytes.data[i] = reg_read(chip, | ||
| 362 | AK4113_REG_QSUB_ADDR + i); | ||
| 363 | return 0; | ||
| 364 | } | ||
| 365 | |||
| 366 | /* Don't forget to change AK4113_CONTROLS define!!! */ | ||
| 367 | static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = { | ||
| 368 | { | ||
| 369 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
| 370 | .name = "IEC958 Parity Errors", | ||
| 371 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
| 372 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
| 373 | .info = snd_ak4113_in_error_info, | ||
| 374 | .get = snd_ak4113_in_error_get, | ||
| 375 | .private_value = offsetof(struct ak4113, parity_errors), | ||
| 376 | }, | ||
| 377 | { | ||
| 378 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
| 379 | .name = "IEC958 V-Bit Errors", | ||
| 380 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
| 381 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
| 382 | .info = snd_ak4113_in_error_info, | ||
| 383 | .get = snd_ak4113_in_error_get, | ||
| 384 | .private_value = offsetof(struct ak4113, v_bit_errors), | ||
| 385 | }, | ||
| 386 | { | ||
| 387 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
| 388 | .name = "IEC958 C-CRC Errors", | ||
| 389 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
| 390 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
| 391 | .info = snd_ak4113_in_error_info, | ||
| 392 | .get = snd_ak4113_in_error_get, | ||
| 393 | .private_value = offsetof(struct ak4113, ccrc_errors), | ||
| 394 | }, | ||
| 395 | { | ||
| 396 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
| 397 | .name = "IEC958 Q-CRC Errors", | ||
| 398 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
| 399 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
| 400 | .info = snd_ak4113_in_error_info, | ||
| 401 | .get = snd_ak4113_in_error_get, | ||
| 402 | .private_value = offsetof(struct ak4113, qcrc_errors), | ||
| 403 | }, | ||
| 404 | { | ||
| 405 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
| 406 | .name = "IEC958 External Rate", | ||
| 407 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
| 408 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
| 409 | .info = snd_ak4113_rate_info, | ||
| 410 | .get = snd_ak4113_rate_get, | ||
| 411 | }, | ||
| 412 | { | ||
| 413 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
| 414 | .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK), | ||
| 415 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | ||
| 416 | .info = snd_ak4113_spdif_mask_info, | ||
| 417 | .get = snd_ak4113_spdif_mask_get, | ||
| 418 | }, | ||
| 419 | { | ||
| 420 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
| 421 | .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), | ||
| 422 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
| 423 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
| 424 | .info = snd_ak4113_spdif_info, | ||
| 425 | .get = snd_ak4113_spdif_get, | ||
| 426 | }, | ||
| 427 | { | ||
| 428 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
| 429 | .name = "IEC958 Preample Capture Default", | ||
| 430 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
| 431 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
| 432 | .info = snd_ak4113_spdif_pinfo, | ||
| 433 | .get = snd_ak4113_spdif_pget, | ||
| 434 | }, | ||
| 435 | { | ||
| 436 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
| 437 | .name = "IEC958 Q-subcode Capture Default", | ||
| 438 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
| 439 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
| 440 | .info = snd_ak4113_spdif_qinfo, | ||
| 441 | .get = snd_ak4113_spdif_qget, | ||
| 442 | }, | ||
| 443 | { | ||
| 444 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
| 445 | .name = "IEC958 Audio", | ||
| 446 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
| 447 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
| 448 | .info = snd_ak4113_in_bit_info, | ||
| 449 | .get = snd_ak4113_in_bit_get, | ||
| 450 | .private_value = (1<<31) | (1<<8) | AK4113_REG_RCS0, | ||
| 451 | }, | ||
| 452 | { | ||
| 453 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
| 454 | .name = "IEC958 Non-PCM Bitstream", | ||
| 455 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
| 456 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
| 457 | .info = snd_ak4113_in_bit_info, | ||
| 458 | .get = snd_ak4113_in_bit_get, | ||
| 459 | .private_value = (0<<8) | AK4113_REG_RCS1, | ||
| 460 | }, | ||
| 461 | { | ||
| 462 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
| 463 | .name = "IEC958 DTS Bitstream", | ||
| 464 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
| 465 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
| 466 | .info = snd_ak4113_in_bit_info, | ||
| 467 | .get = snd_ak4113_in_bit_get, | ||
| 468 | .private_value = (1<<8) | AK4113_REG_RCS1, | ||
| 469 | }, | ||
| 470 | { | ||
| 471 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
| 472 | .name = "AK4113 Input Select", | ||
| 473 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
| 474 | SNDRV_CTL_ELEM_ACCESS_WRITE, | ||
| 475 | .info = snd_ak4113_rx_info, | ||
| 476 | .get = snd_ak4113_rx_get, | ||
| 477 | .put = snd_ak4113_rx_put, | ||
| 478 | } | ||
| 479 | }; | ||
| 480 | |||
| 481 | static void snd_ak4113_proc_regs_read(struct snd_info_entry *entry, | ||
| 482 | struct snd_info_buffer *buffer) | ||
| 483 | { | ||
| 484 | struct ak4113 *ak4113 = entry->private_data; | ||
| 485 | int reg, val; | ||
| 486 | /* all ak4113 registers 0x00 - 0x1c */ | ||
| 487 | for (reg = 0; reg < 0x1d; reg++) { | ||
| 488 | val = reg_read(ak4113, reg); | ||
| 489 | snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val); | ||
| 490 | } | ||
| 491 | } | ||
| 492 | |||
| 493 | static void snd_ak4113_proc_init(struct ak4113 *ak4113) | ||
| 494 | { | ||
| 495 | struct snd_info_entry *entry; | ||
| 496 | if (!snd_card_proc_new(ak4113->card, "ak4113", &entry)) | ||
| 497 | snd_info_set_text_ops(entry, ak4113, snd_ak4113_proc_regs_read); | ||
| 498 | } | ||
| 499 | |||
| 500 | int snd_ak4113_build(struct ak4113 *ak4113, | ||
| 501 | struct snd_pcm_substream *cap_substream) | ||
| 502 | { | ||
| 503 | struct snd_kcontrol *kctl; | ||
| 504 | unsigned int idx; | ||
| 505 | int err; | ||
| 506 | |||
| 507 | if (snd_BUG_ON(!cap_substream)) | ||
| 508 | return -EINVAL; | ||
| 509 | ak4113->substream = cap_substream; | ||
| 510 | for (idx = 0; idx < AK4113_CONTROLS; idx++) { | ||
| 511 | kctl = snd_ctl_new1(&snd_ak4113_iec958_controls[idx], ak4113); | ||
| 512 | if (kctl == NULL) | ||
| 513 | return -ENOMEM; | ||
| 514 | kctl->id.device = cap_substream->pcm->device; | ||
| 515 | kctl->id.subdevice = cap_substream->number; | ||
| 516 | err = snd_ctl_add(ak4113->card, kctl); | ||
| 517 | if (err < 0) | ||
| 518 | return err; | ||
| 519 | ak4113->kctls[idx] = kctl; | ||
| 520 | } | ||
| 521 | snd_ak4113_proc_init(ak4113); | ||
| 522 | /* trigger workq */ | ||
| 523 | schedule_delayed_work(&ak4113->work, HZ / 10); | ||
| 524 | return 0; | ||
| 525 | } | ||
| 526 | EXPORT_SYMBOL_GPL(snd_ak4113_build); | ||
| 527 | |||
| 528 | int snd_ak4113_external_rate(struct ak4113 *ak4113) | ||
| 529 | { | ||
| 530 | unsigned char rcs1; | ||
| 531 | |||
| 532 | rcs1 = reg_read(ak4113, AK4113_REG_RCS1); | ||
| 533 | return external_rate(rcs1); | ||
| 534 | } | ||
| 535 | EXPORT_SYMBOL_GPL(snd_ak4113_external_rate); | ||
| 536 | |||
| 537 | int snd_ak4113_check_rate_and_errors(struct ak4113 *ak4113, unsigned int flags) | ||
| 538 | { | ||
| 539 | struct snd_pcm_runtime *runtime = | ||
| 540 | ak4113->substream ? ak4113->substream->runtime : NULL; | ||
| 541 | unsigned long _flags; | ||
| 542 | int res = 0; | ||
| 543 | unsigned char rcs0, rcs1, rcs2; | ||
| 544 | unsigned char c0, c1; | ||
| 545 | |||
| 546 | rcs1 = reg_read(ak4113, AK4113_REG_RCS1); | ||
| 547 | if (flags & AK4113_CHECK_NO_STAT) | ||
| 548 | goto __rate; | ||
| 549 | rcs0 = reg_read(ak4113, AK4113_REG_RCS0); | ||
| 550 | rcs2 = reg_read(ak4113, AK4113_REG_RCS2); | ||
| 551 | spin_lock_irqsave(&ak4113->lock, _flags); | ||
| 552 | if (rcs0 & AK4113_PAR) | ||
| 553 | ak4113->parity_errors++; | ||
| 554 | if (rcs0 & AK4113_V) | ||
| 555 | ak4113->v_bit_errors++; | ||
| 556 | if (rcs2 & AK4113_CCRC) | ||
| 557 | ak4113->ccrc_errors++; | ||
| 558 | if (rcs2 & AK4113_QCRC) | ||
| 559 | ak4113->qcrc_errors++; | ||
| 560 | c0 = (ak4113->rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC | | ||
| 561 | AK4113_AUDION | AK4113_AUTO | AK4113_UNLCK)) ^ | ||
| 562 | (rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC | | ||
| 563 | AK4113_AUDION | AK4113_AUTO | AK4113_UNLCK)); | ||
| 564 | c1 = (ak4113->rcs1 & (AK4113_DTSCD | AK4113_NPCM | AK4113_PEM | | ||
| 565 | AK4113_DAT | 0xf0)) ^ | ||
| 566 | (rcs1 & (AK4113_DTSCD | AK4113_NPCM | AK4113_PEM | | ||
| 567 | AK4113_DAT | 0xf0)); | ||
| 568 | ak4113->rcs0 = rcs0 & ~(AK4113_QINT | AK4113_CINT | AK4113_STC); | ||
| 569 | ak4113->rcs1 = rcs1; | ||
| 570 | ak4113->rcs2 = rcs2; | ||
| 571 | spin_unlock_irqrestore(&ak4113->lock, _flags); | ||
| 572 | |||
| 573 | if (rcs0 & AK4113_PAR) | ||
| 574 | snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
| 575 | &ak4113->kctls[0]->id); | ||
| 576 | if (rcs0 & AK4113_V) | ||
| 577 | snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
| 578 | &ak4113->kctls[1]->id); | ||
| 579 | if (rcs2 & AK4113_CCRC) | ||
| 580 | snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
| 581 | &ak4113->kctls[2]->id); | ||
| 582 | if (rcs2 & AK4113_QCRC) | ||
| 583 | snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
| 584 | &ak4113->kctls[3]->id); | ||
| 585 | |||
| 586 | /* rate change */ | ||
| 587 | if (c1 & 0xf0) | ||
| 588 | snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
| 589 | &ak4113->kctls[4]->id); | ||
| 590 | |||
| 591 | if ((c1 & AK4113_PEM) | (c0 & AK4113_CINT)) | ||
| 592 | snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
| 593 | &ak4113->kctls[6]->id); | ||
| 594 | if (c0 & AK4113_QINT) | ||
| 595 | snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
| 596 | &ak4113->kctls[8]->id); | ||
| 597 | |||
| 598 | if (c0 & AK4113_AUDION) | ||
| 599 | snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
| 600 | &ak4113->kctls[9]->id); | ||
| 601 | if (c1 & AK4113_NPCM) | ||
| 602 | snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
| 603 | &ak4113->kctls[10]->id); | ||
| 604 | if (c1 & AK4113_DTSCD) | ||
| 605 | snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
| 606 | &ak4113->kctls[11]->id); | ||
| 607 | |||
| 608 | if (ak4113->change_callback && (c0 | c1) != 0) | ||
| 609 | ak4113->change_callback(ak4113, c0, c1); | ||
| 610 | |||
| 611 | __rate: | ||
| 612 | /* compare rate */ | ||
| 613 | res = external_rate(rcs1); | ||
| 614 | if (!(flags & AK4113_CHECK_NO_RATE) && runtime && | ||
| 615 | (runtime->rate != res)) { | ||
| 616 | snd_pcm_stream_lock_irqsave(ak4113->substream, _flags); | ||
| 617 | if (snd_pcm_running(ak4113->substream)) { | ||
| 618 | /*printk(KERN_DEBUG "rate changed (%i <- %i)\n", | ||
| 619 | * runtime->rate, res); */ | ||
| 620 | snd_pcm_stop(ak4113->substream, | ||
| 621 | SNDRV_PCM_STATE_DRAINING); | ||
| 622 | wake_up(&runtime->sleep); | ||
| 623 | res = 1; | ||
| 624 | } | ||
| 625 | snd_pcm_stream_unlock_irqrestore(ak4113->substream, _flags); | ||
| 626 | } | ||
| 627 | return res; | ||
| 628 | } | ||
| 629 | EXPORT_SYMBOL_GPL(snd_ak4113_check_rate_and_errors); | ||
| 630 | |||
| 631 | static void ak4113_stats(struct work_struct *work) | ||
| 632 | { | ||
| 633 | struct ak4113 *chip = container_of(work, struct ak4113, work.work); | ||
| 634 | |||
| 635 | if (!chip->init) | ||
| 636 | snd_ak4113_check_rate_and_errors(chip, chip->check_flags); | ||
| 637 | |||
| 638 | schedule_delayed_work(&chip->work, HZ / 10); | ||
| 639 | } | ||
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c index ee47abab764e..1adb8a3c2b62 100644 --- a/sound/i2c/other/ak4xxx-adda.c +++ b/sound/i2c/other/ak4xxx-adda.c | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | * along with this program; if not, write to the Free Software | 19 | * along with this program; if not, write to the Free Software |
| 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 21 | * | 21 | * |
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | #include <asm/io.h> | 24 | #include <asm/io.h> |
| 25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <sound/control.h> | 29 | #include <sound/control.h> |
| 30 | #include <sound/tlv.h> | 30 | #include <sound/tlv.h> |
| 31 | #include <sound/ak4xxx-adda.h> | 31 | #include <sound/ak4xxx-adda.h> |
| 32 | #include <sound/info.h> | ||
| 32 | 33 | ||
| 33 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.de>"); | 34 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.de>"); |
| 34 | MODULE_DESCRIPTION("Routines for control of AK452x / AK43xx AD/DA converters"); | 35 | MODULE_DESCRIPTION("Routines for control of AK452x / AK43xx AD/DA converters"); |
| @@ -52,26 +53,21 @@ EXPORT_SYMBOL(snd_akm4xxx_write); | |||
| 52 | static void ak4524_reset(struct snd_akm4xxx *ak, int state) | 53 | static void ak4524_reset(struct snd_akm4xxx *ak, int state) |
| 53 | { | 54 | { |
| 54 | unsigned int chip; | 55 | unsigned int chip; |
| 55 | unsigned char reg, maxreg; | 56 | unsigned char reg; |
| 56 | 57 | ||
| 57 | if (ak->type == SND_AK4528) | ||
| 58 | maxreg = 0x06; | ||
| 59 | else | ||
| 60 | maxreg = 0x08; | ||
| 61 | for (chip = 0; chip < ak->num_dacs/2; chip++) { | 58 | for (chip = 0; chip < ak->num_dacs/2; chip++) { |
| 62 | snd_akm4xxx_write(ak, chip, 0x01, state ? 0x00 : 0x03); | 59 | snd_akm4xxx_write(ak, chip, 0x01, state ? 0x00 : 0x03); |
| 63 | if (state) | 60 | if (state) |
| 64 | continue; | 61 | continue; |
| 65 | /* DAC volumes */ | 62 | /* DAC volumes */ |
| 66 | for (reg = 0x04; reg < maxreg; reg++) | 63 | for (reg = 0x04; reg < ak->total_regs; reg++) |
| 67 | snd_akm4xxx_write(ak, chip, reg, | 64 | snd_akm4xxx_write(ak, chip, reg, |
| 68 | snd_akm4xxx_get(ak, chip, reg)); | 65 | snd_akm4xxx_get(ak, chip, reg)); |
| 69 | } | 66 | } |
| 70 | } | 67 | } |
| 71 | 68 | ||
| 72 | /* reset procedure for AK4355 and AK4358 */ | 69 | /* reset procedure for AK4355 and AK4358 */ |
| 73 | static void ak435X_reset(struct snd_akm4xxx *ak, int state, | 70 | static void ak435X_reset(struct snd_akm4xxx *ak, int state) |
| 74 | unsigned char total_regs) | ||
| 75 | { | 71 | { |
| 76 | unsigned char reg; | 72 | unsigned char reg; |
| 77 | 73 | ||
| @@ -79,7 +75,7 @@ static void ak435X_reset(struct snd_akm4xxx *ak, int state, | |||
| 79 | snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */ | 75 | snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */ |
| 80 | return; | 76 | return; |
| 81 | } | 77 | } |
| 82 | for (reg = 0x00; reg < total_regs; reg++) | 78 | for (reg = 0x00; reg < ak->total_regs; reg++) |
| 83 | if (reg != 0x01) | 79 | if (reg != 0x01) |
| 84 | snd_akm4xxx_write(ak, 0, reg, | 80 | snd_akm4xxx_write(ak, 0, reg, |
| 85 | snd_akm4xxx_get(ak, 0, reg)); | 81 | snd_akm4xxx_get(ak, 0, reg)); |
| @@ -91,12 +87,11 @@ static void ak4381_reset(struct snd_akm4xxx *ak, int state) | |||
| 91 | { | 87 | { |
| 92 | unsigned int chip; | 88 | unsigned int chip; |
| 93 | unsigned char reg; | 89 | unsigned char reg; |
| 94 | |||
| 95 | for (chip = 0; chip < ak->num_dacs/2; chip++) { | 90 | for (chip = 0; chip < ak->num_dacs/2; chip++) { |
| 96 | snd_akm4xxx_write(ak, chip, 0x00, state ? 0x0c : 0x0f); | 91 | snd_akm4xxx_write(ak, chip, 0x00, state ? 0x0c : 0x0f); |
| 97 | if (state) | 92 | if (state) |
| 98 | continue; | 93 | continue; |
| 99 | for (reg = 0x01; reg < 0x05; reg++) | 94 | for (reg = 0x01; reg < ak->total_regs; reg++) |
| 100 | snd_akm4xxx_write(ak, chip, reg, | 95 | snd_akm4xxx_write(ak, chip, reg, |
| 101 | snd_akm4xxx_get(ak, chip, reg)); | 96 | snd_akm4xxx_get(ak, chip, reg)); |
| 102 | } | 97 | } |
| @@ -113,16 +108,17 @@ void snd_akm4xxx_reset(struct snd_akm4xxx *ak, int state) | |||
| 113 | switch (ak->type) { | 108 | switch (ak->type) { |
| 114 | case SND_AK4524: | 109 | case SND_AK4524: |
| 115 | case SND_AK4528: | 110 | case SND_AK4528: |
| 111 | case SND_AK4620: | ||
| 116 | ak4524_reset(ak, state); | 112 | ak4524_reset(ak, state); |
| 117 | break; | 113 | break; |
| 118 | case SND_AK4529: | 114 | case SND_AK4529: |
| 119 | /* FIXME: needed for ak4529? */ | 115 | /* FIXME: needed for ak4529? */ |
| 120 | break; | 116 | break; |
| 121 | case SND_AK4355: | 117 | case SND_AK4355: |
| 122 | ak435X_reset(ak, state, 0x0b); | 118 | ak435X_reset(ak, state); |
| 123 | break; | 119 | break; |
| 124 | case SND_AK4358: | 120 | case SND_AK4358: |
| 125 | ak435X_reset(ak, state, 0x10); | 121 | ak435X_reset(ak, state); |
| 126 | break; | 122 | break; |
| 127 | case SND_AK4381: | 123 | case SND_AK4381: |
| 128 | ak4381_reset(ak, state); | 124 | ak4381_reset(ak, state); |
| @@ -139,7 +135,7 @@ EXPORT_SYMBOL(snd_akm4xxx_reset); | |||
| 139 | * Volume conversion table for non-linear volumes | 135 | * Volume conversion table for non-linear volumes |
| 140 | * from -63.5dB (mute) to 0dB step 0.5dB | 136 | * from -63.5dB (mute) to 0dB step 0.5dB |
| 141 | * | 137 | * |
| 142 | * Used for AK4524 input/ouput attenuation, AK4528, and | 138 | * Used for AK4524/AK4620 input/ouput attenuation, AK4528, and |
| 143 | * AK5365 input attenuation | 139 | * AK5365 input attenuation |
| 144 | */ | 140 | */ |
| 145 | static const unsigned char vol_cvt_datt[128] = { | 141 | static const unsigned char vol_cvt_datt[128] = { |
| @@ -259,8 +255,22 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) | |||
| 259 | 0x00, 0x0f, /* 0: power-up, un-reset */ | 255 | 0x00, 0x0f, /* 0: power-up, un-reset */ |
| 260 | 0xff, 0xff | 256 | 0xff, 0xff |
| 261 | }; | 257 | }; |
| 258 | static const unsigned char inits_ak4620[] = { | ||
| 259 | 0x00, 0x07, /* 0: normal */ | ||
| 260 | 0x01, 0x00, /* 0: reset */ | ||
| 261 | 0x01, 0x02, /* 1: RSTAD */ | ||
| 262 | 0x01, 0x03, /* 1: RSTDA */ | ||
| 263 | 0x01, 0x0f, /* 1: normal */ | ||
| 264 | 0x02, 0x60, /* 2: 24bit I2S */ | ||
| 265 | 0x03, 0x01, /* 3: deemphasis off */ | ||
| 266 | 0x04, 0x00, /* 4: LIN muted */ | ||
| 267 | 0x05, 0x00, /* 5: RIN muted */ | ||
| 268 | 0x06, 0x00, /* 6: LOUT muted */ | ||
| 269 | 0x07, 0x00, /* 7: ROUT muted */ | ||
| 270 | 0xff, 0xff | ||
| 271 | }; | ||
| 262 | 272 | ||
| 263 | int chip, num_chips; | 273 | int chip; |
| 264 | const unsigned char *ptr, *inits; | 274 | const unsigned char *ptr, *inits; |
| 265 | unsigned char reg, data; | 275 | unsigned char reg, data; |
| 266 | 276 | ||
| @@ -270,42 +280,64 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) | |||
| 270 | switch (ak->type) { | 280 | switch (ak->type) { |
| 271 | case SND_AK4524: | 281 | case SND_AK4524: |
| 272 | inits = inits_ak4524; | 282 | inits = inits_ak4524; |
| 273 | num_chips = ak->num_dacs / 2; | 283 | ak->num_chips = ak->num_dacs / 2; |
| 284 | ak->name = "ak4524"; | ||
| 285 | ak->total_regs = 0x08; | ||
| 274 | break; | 286 | break; |
| 275 | case SND_AK4528: | 287 | case SND_AK4528: |
| 276 | inits = inits_ak4528; | 288 | inits = inits_ak4528; |
| 277 | num_chips = ak->num_dacs / 2; | 289 | ak->num_chips = ak->num_dacs / 2; |
| 290 | ak->name = "ak4528"; | ||
| 291 | ak->total_regs = 0x06; | ||
| 278 | break; | 292 | break; |
| 279 | case SND_AK4529: | 293 | case SND_AK4529: |
| 280 | inits = inits_ak4529; | 294 | inits = inits_ak4529; |
| 281 | num_chips = 1; | 295 | ak->num_chips = 1; |
| 296 | ak->name = "ak4529"; | ||
| 297 | ak->total_regs = 0x0d; | ||
| 282 | break; | 298 | break; |
| 283 | case SND_AK4355: | 299 | case SND_AK4355: |
| 284 | inits = inits_ak4355; | 300 | inits = inits_ak4355; |
| 285 | num_chips = 1; | 301 | ak->num_chips = 1; |
| 302 | ak->name = "ak4355"; | ||
| 303 | ak->total_regs = 0x0b; | ||
| 286 | break; | 304 | break; |
| 287 | case SND_AK4358: | 305 | case SND_AK4358: |
| 288 | inits = inits_ak4358; | 306 | inits = inits_ak4358; |
| 289 | num_chips = 1; | 307 | ak->num_chips = 1; |
| 308 | ak->name = "ak4358"; | ||
| 309 | ak->total_regs = 0x10; | ||
| 290 | break; | 310 | break; |
| 291 | case SND_AK4381: | 311 | case SND_AK4381: |
| 292 | inits = inits_ak4381; | 312 | inits = inits_ak4381; |
| 293 | num_chips = ak->num_dacs / 2; | 313 | ak->num_chips = ak->num_dacs / 2; |
| 314 | ak->name = "ak4381"; | ||
| 315 | ak->total_regs = 0x05; | ||
| 294 | break; | 316 | break; |
| 295 | case SND_AK5365: | 317 | case SND_AK5365: |
| 296 | /* FIXME: any init sequence? */ | 318 | /* FIXME: any init sequence? */ |
| 319 | ak->num_chips = 1; | ||
| 320 | ak->name = "ak5365"; | ||
| 321 | ak->total_regs = 0x08; | ||
| 297 | return; | 322 | return; |
| 323 | case SND_AK4620: | ||
| 324 | inits = inits_ak4620; | ||
| 325 | ak->num_chips = ak->num_dacs / 2; | ||
| 326 | ak->name = "ak4620"; | ||
| 327 | ak->total_regs = 0x08; | ||
| 328 | break; | ||
| 298 | default: | 329 | default: |
| 299 | snd_BUG(); | 330 | snd_BUG(); |
| 300 | return; | 331 | return; |
| 301 | } | 332 | } |
| 302 | 333 | ||
| 303 | for (chip = 0; chip < num_chips; chip++) { | 334 | for (chip = 0; chip < ak->num_chips; chip++) { |
| 304 | ptr = inits; | 335 | ptr = inits; |
| 305 | while (*ptr != 0xff) { | 336 | while (*ptr != 0xff) { |
| 306 | reg = *ptr++; | 337 | reg = *ptr++; |
| 307 | data = *ptr++; | 338 | data = *ptr++; |
| 308 | snd_akm4xxx_write(ak, chip, reg, data); | 339 | snd_akm4xxx_write(ak, chip, reg, data); |
| 340 | udelay(10); | ||
| 309 | } | 341 | } |
| 310 | } | 342 | } |
| 311 | } | 343 | } |
| @@ -688,6 +720,12 @@ static int build_dac_controls(struct snd_akm4xxx *ak) | |||
| 688 | AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); | 720 | AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); |
| 689 | knew.tlv.p = db_scale_linear; | 721 | knew.tlv.p = db_scale_linear; |
| 690 | break; | 722 | break; |
| 723 | case SND_AK4620: | ||
| 724 | /* register 6 & 7 */ | ||
| 725 | knew.private_value = | ||
| 726 | AK_COMPOSE(idx/2, (idx%2) + 6, 0, 255); | ||
| 727 | knew.tlv.p = db_scale_linear; | ||
| 728 | break; | ||
| 691 | default: | 729 | default: |
| 692 | return -EINVAL; | 730 | return -EINVAL; |
| 693 | } | 731 | } |
| @@ -704,10 +742,12 @@ static int build_dac_controls(struct snd_akm4xxx *ak) | |||
| 704 | 742 | ||
| 705 | static int build_adc_controls(struct snd_akm4xxx *ak) | 743 | static int build_adc_controls(struct snd_akm4xxx *ak) |
| 706 | { | 744 | { |
| 707 | int idx, err, mixer_ch, num_stereo; | 745 | int idx, err, mixer_ch, num_stereo, max_steps; |
| 708 | struct snd_kcontrol_new knew; | 746 | struct snd_kcontrol_new knew; |
| 709 | 747 | ||
| 710 | mixer_ch = 0; | 748 | mixer_ch = 0; |
| 749 | if (ak->type == SND_AK4528) | ||
| 750 | return 0; /* no controls */ | ||
| 711 | for (idx = 0; idx < ak->num_adcs;) { | 751 | for (idx = 0; idx < ak->num_adcs;) { |
| 712 | memset(&knew, 0, sizeof(knew)); | 752 | memset(&knew, 0, sizeof(knew)); |
| 713 | if (! ak->adc_info || ! ak->adc_info[mixer_ch].name) { | 753 | if (! ak->adc_info || ! ak->adc_info[mixer_ch].name) { |
| @@ -733,13 +773,12 @@ static int build_adc_controls(struct snd_akm4xxx *ak) | |||
| 733 | } | 773 | } |
| 734 | /* register 4 & 5 */ | 774 | /* register 4 & 5 */ |
| 735 | if (ak->type == SND_AK5365) | 775 | if (ak->type == SND_AK5365) |
| 736 | knew.private_value = | 776 | max_steps = 152; |
| 737 | AK_COMPOSE(idx/2, (idx%2) + 4, 0, 151) | | ||
| 738 | AK_VOL_CVT | AK_IPGA; | ||
| 739 | else | 777 | else |
| 740 | knew.private_value = | 778 | max_steps = 164; |
| 741 | AK_COMPOSE(idx/2, (idx%2) + 4, 0, 163) | | 779 | knew.private_value = |
| 742 | AK_VOL_CVT | AK_IPGA; | 780 | AK_COMPOSE(idx/2, (idx%2) + 4, 0, max_steps) | |
| 781 | AK_VOL_CVT | AK_IPGA; | ||
| 743 | knew.tlv.p = db_scale_vol_datt; | 782 | knew.tlv.p = db_scale_vol_datt; |
| 744 | err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); | 783 | err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); |
| 745 | if (err < 0) | 784 | if (err < 0) |
| @@ -808,6 +847,7 @@ static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs) | |||
| 808 | switch (ak->type) { | 847 | switch (ak->type) { |
| 809 | case SND_AK4524: | 848 | case SND_AK4524: |
| 810 | case SND_AK4528: | 849 | case SND_AK4528: |
| 850 | case SND_AK4620: | ||
| 811 | /* register 3 */ | 851 | /* register 3 */ |
| 812 | knew.private_value = AK_COMPOSE(idx, 3, 0, 0); | 852 | knew.private_value = AK_COMPOSE(idx, 3, 0, 0); |
| 813 | break; | 853 | break; |
| @@ -834,6 +874,35 @@ static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs) | |||
| 834 | return 0; | 874 | return 0; |
| 835 | } | 875 | } |
| 836 | 876 | ||
| 877 | #ifdef CONFIG_PROC_FS | ||
| 878 | static void proc_regs_read(struct snd_info_entry *entry, | ||
| 879 | struct snd_info_buffer *buffer) | ||
| 880 | { | ||
| 881 | struct snd_akm4xxx *ak = (struct snd_akm4xxx *)entry->private_data; | ||
| 882 | int reg, val, chip; | ||
| 883 | for (chip = 0; chip < ak->num_chips; chip++) { | ||
| 884 | for (reg = 0; reg < ak->total_regs; reg++) { | ||
| 885 | val = snd_akm4xxx_get(ak, chip, reg); | ||
| 886 | snd_iprintf(buffer, "chip %d: 0x%02x = 0x%02x\n", chip, | ||
| 887 | reg, val); | ||
| 888 | } | ||
| 889 | } | ||
| 890 | } | ||
| 891 | |||
| 892 | static int proc_init(struct snd_akm4xxx *ak) | ||
| 893 | { | ||
| 894 | struct snd_info_entry *entry; | ||
| 895 | int err; | ||
| 896 | err = snd_card_proc_new(ak->card, ak->name, &entry); | ||
| 897 | if (err < 0) | ||
| 898 | return err; | ||
| 899 | snd_info_set_text_ops(entry, ak, proc_regs_read); | ||
| 900 | return 0; | ||
| 901 | } | ||
| 902 | #else /* !CONFIG_PROC_FS */ | ||
| 903 | static int proc_init(struct snd_akm4xxx *ak) {} | ||
| 904 | #endif | ||
| 905 | |||
| 837 | int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) | 906 | int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) |
| 838 | { | 907 | { |
| 839 | int err, num_emphs; | 908 | int err, num_emphs; |
| @@ -845,18 +914,21 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) | |||
| 845 | err = build_adc_controls(ak); | 914 | err = build_adc_controls(ak); |
| 846 | if (err < 0) | 915 | if (err < 0) |
| 847 | return err; | 916 | return err; |
| 848 | |||
| 849 | if (ak->type == SND_AK4355 || ak->type == SND_AK4358) | 917 | if (ak->type == SND_AK4355 || ak->type == SND_AK4358) |
| 850 | num_emphs = 1; | 918 | num_emphs = 1; |
| 919 | else if (ak->type == SND_AK4620) | ||
| 920 | num_emphs = 0; | ||
| 851 | else | 921 | else |
| 852 | num_emphs = ak->num_dacs / 2; | 922 | num_emphs = ak->num_dacs / 2; |
| 853 | err = build_deemphasis(ak, num_emphs); | 923 | err = build_deemphasis(ak, num_emphs); |
| 854 | if (err < 0) | 924 | if (err < 0) |
| 855 | return err; | 925 | return err; |
| 926 | err = proc_init(ak); | ||
| 927 | if (err < 0) | ||
| 928 | return err; | ||
| 856 | 929 | ||
| 857 | return 0; | 930 | return 0; |
| 858 | } | 931 | } |
| 859 | |||
| 860 | EXPORT_SYMBOL(snd_akm4xxx_build_controls); | 932 | EXPORT_SYMBOL(snd_akm4xxx_build_controls); |
| 861 | 933 | ||
| 862 | static int __init alsa_akm4xxx_module_init(void) | 934 | static int __init alsa_akm4xxx_module_init(void) |
diff --git a/sound/pci/ice1712/Makefile b/sound/pci/ice1712/Makefile index 536eae2ccf94..f7ce33f00ea5 100644 --- a/sound/pci/ice1712/Makefile +++ b/sound/pci/ice1712/Makefile | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | snd-ice17xx-ak4xxx-objs := ak4xxx.o | 6 | snd-ice17xx-ak4xxx-objs := ak4xxx.o |
| 7 | snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o | 7 | snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o |
| 8 | snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o prodigy_hifi.o juli.o phase.o wtm.o se.o maya44.o | 8 | snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o prodigy_hifi.o juli.o phase.o wtm.o se.o maya44.o quartet.o |
| 9 | 9 | ||
| 10 | # Toplevel Module Dependency | 10 | # Toplevel Module Dependency |
| 11 | obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o | 11 | obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o |
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index d74033a2cfbe..c7cff6f8168a 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c | |||
| @@ -298,6 +298,16 @@ static void snd_ice1712_set_gpio_dir(struct snd_ice1712 *ice, unsigned int data) | |||
| 298 | inb(ICEREG(ice, DATA)); /* dummy read for pci-posting */ | 298 | inb(ICEREG(ice, DATA)); /* dummy read for pci-posting */ |
| 299 | } | 299 | } |
| 300 | 300 | ||
| 301 | static unsigned int snd_ice1712_get_gpio_dir(struct snd_ice1712 *ice) | ||
| 302 | { | ||
| 303 | return snd_ice1712_read(ice, ICE1712_IREG_GPIO_DIRECTION); | ||
| 304 | } | ||
| 305 | |||
| 306 | static unsigned int snd_ice1712_get_gpio_mask(struct snd_ice1712 *ice) | ||
| 307 | { | ||
| 308 | return snd_ice1712_read(ice, ICE1712_IREG_GPIO_WRITE_MASK); | ||
| 309 | } | ||
| 310 | |||
| 301 | static void snd_ice1712_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data) | 311 | static void snd_ice1712_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data) |
| 302 | { | 312 | { |
| 303 | snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, data); | 313 | snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, data); |
| @@ -2557,7 +2567,9 @@ static int __devinit snd_ice1712_create(struct snd_card *card, | |||
| 2557 | mutex_init(&ice->i2c_mutex); | 2567 | mutex_init(&ice->i2c_mutex); |
| 2558 | mutex_init(&ice->open_mutex); | 2568 | mutex_init(&ice->open_mutex); |
| 2559 | ice->gpio.set_mask = snd_ice1712_set_gpio_mask; | 2569 | ice->gpio.set_mask = snd_ice1712_set_gpio_mask; |
| 2570 | ice->gpio.get_mask = snd_ice1712_get_gpio_mask; | ||
| 2560 | ice->gpio.set_dir = snd_ice1712_set_gpio_dir; | 2571 | ice->gpio.set_dir = snd_ice1712_set_gpio_dir; |
| 2572 | ice->gpio.get_dir = snd_ice1712_get_gpio_dir; | ||
| 2561 | ice->gpio.set_data = snd_ice1712_set_gpio_data; | 2573 | ice->gpio.set_data = snd_ice1712_set_gpio_data; |
| 2562 | ice->gpio.get_data = snd_ice1712_get_gpio_data; | 2574 | ice->gpio.get_data = snd_ice1712_get_gpio_data; |
| 2563 | 2575 | ||
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h index 9da2dae64c5b..4615bca39e18 100644 --- a/sound/pci/ice1712/ice1712.h +++ b/sound/pci/ice1712/ice1712.h | |||
| @@ -359,7 +359,9 @@ struct snd_ice1712 { | |||
| 359 | unsigned int saved[2]; /* for ewx_i2c */ | 359 | unsigned int saved[2]; /* for ewx_i2c */ |
| 360 | /* operators */ | 360 | /* operators */ |
| 361 | void (*set_mask)(struct snd_ice1712 *ice, unsigned int data); | 361 | void (*set_mask)(struct snd_ice1712 *ice, unsigned int data); |
| 362 | unsigned int (*get_mask)(struct snd_ice1712 *ice); | ||
| 362 | void (*set_dir)(struct snd_ice1712 *ice, unsigned int data); | 363 | void (*set_dir)(struct snd_ice1712 *ice, unsigned int data); |
| 364 | unsigned int (*get_dir)(struct snd_ice1712 *ice); | ||
| 363 | void (*set_data)(struct snd_ice1712 *ice, unsigned int data); | 365 | void (*set_data)(struct snd_ice1712 *ice, unsigned int data); |
| 364 | unsigned int (*get_data)(struct snd_ice1712 *ice); | 366 | unsigned int (*get_data)(struct snd_ice1712 *ice); |
| 365 | /* misc operators - move to another place? */ | 367 | /* misc operators - move to another place? */ |
| @@ -377,8 +379,11 @@ struct snd_ice1712 { | |||
| 377 | unsigned int (*get_rate)(struct snd_ice1712 *ice); | 379 | unsigned int (*get_rate)(struct snd_ice1712 *ice); |
| 378 | void (*set_rate)(struct snd_ice1712 *ice, unsigned int rate); | 380 | void (*set_rate)(struct snd_ice1712 *ice, unsigned int rate); |
| 379 | unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate); | 381 | unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate); |
| 380 | void (*set_spdif_clock)(struct snd_ice1712 *ice); | 382 | int (*set_spdif_clock)(struct snd_ice1712 *ice, int type); |
| 381 | 383 | int (*get_spdif_master_type)(struct snd_ice1712 *ice); | |
| 384 | char **ext_clock_names; | ||
| 385 | int ext_clock_count; | ||
| 386 | void (*pro_open)(struct snd_ice1712 *, struct snd_pcm_substream *); | ||
| 382 | #ifdef CONFIG_PM | 387 | #ifdef CONFIG_PM |
| 383 | int (*pm_suspend)(struct snd_ice1712 *); | 388 | int (*pm_suspend)(struct snd_ice1712 *); |
| 384 | int (*pm_resume)(struct snd_ice1712 *); | 389 | int (*pm_resume)(struct snd_ice1712 *); |
| @@ -399,6 +404,11 @@ static inline void snd_ice1712_gpio_set_dir(struct snd_ice1712 *ice, unsigned in | |||
| 399 | ice->gpio.set_dir(ice, bits); | 404 | ice->gpio.set_dir(ice, bits); |
| 400 | } | 405 | } |
| 401 | 406 | ||
| 407 | static inline unsigned int snd_ice1712_gpio_get_dir(struct snd_ice1712 *ice) | ||
| 408 | { | ||
| 409 | return ice->gpio.get_dir(ice); | ||
| 410 | } | ||
| 411 | |||
| 402 | static inline void snd_ice1712_gpio_set_mask(struct snd_ice1712 *ice, unsigned int bits) | 412 | static inline void snd_ice1712_gpio_set_mask(struct snd_ice1712 *ice, unsigned int bits) |
| 403 | { | 413 | { |
| 404 | ice->gpio.set_mask(ice, bits); | 414 | ice->gpio.set_mask(ice, bits); |
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 10fc92c05574..ae29073eea93 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c | |||
| @@ -53,6 +53,7 @@ | |||
| 53 | #include "phase.h" | 53 | #include "phase.h" |
| 54 | #include "wtm.h" | 54 | #include "wtm.h" |
| 55 | #include "se.h" | 55 | #include "se.h" |
| 56 | #include "quartet.h" | ||
| 56 | 57 | ||
| 57 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | 58 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
| 58 | MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)"); | 59 | MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)"); |
| @@ -70,6 +71,7 @@ MODULE_SUPPORTED_DEVICE("{" | |||
| 70 | PHASE_DEVICE_DESC | 71 | PHASE_DEVICE_DESC |
| 71 | WTM_DEVICE_DESC | 72 | WTM_DEVICE_DESC |
| 72 | SE_DEVICE_DESC | 73 | SE_DEVICE_DESC |
| 74 | QTET_DEVICE_DESC | ||
| 73 | "{VIA,VT1720}," | 75 | "{VIA,VT1720}," |
| 74 | "{VIA,VT1724}," | 76 | "{VIA,VT1724}," |
| 75 | "{ICEnsemble,Generic ICE1724}," | 77 | "{ICEnsemble,Generic ICE1724}," |
| @@ -104,6 +106,8 @@ static int PRO_RATE_LOCKED; | |||
| 104 | static int PRO_RATE_RESET = 1; | 106 | static int PRO_RATE_RESET = 1; |
| 105 | static unsigned int PRO_RATE_DEFAULT = 44100; | 107 | static unsigned int PRO_RATE_DEFAULT = 44100; |
| 106 | 108 | ||
| 109 | static char *ext_clock_names[1] = { "IEC958 In" }; | ||
| 110 | |||
| 107 | /* | 111 | /* |
| 108 | * Basic I/O | 112 | * Basic I/O |
| 109 | */ | 113 | */ |
| @@ -118,9 +122,12 @@ static inline int stdclock_is_spdif_master(struct snd_ice1712 *ice) | |||
| 118 | return (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER) ? 1 : 0; | 122 | return (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER) ? 1 : 0; |
| 119 | } | 123 | } |
| 120 | 124 | ||
| 125 | /* | ||
| 126 | * locking rate makes sense only for internal clock mode | ||
| 127 | */ | ||
| 121 | static inline int is_pro_rate_locked(struct snd_ice1712 *ice) | 128 | static inline int is_pro_rate_locked(struct snd_ice1712 *ice) |
| 122 | { | 129 | { |
| 123 | return ice->is_spdif_master(ice) || PRO_RATE_LOCKED; | 130 | return (!ice->is_spdif_master(ice)) && PRO_RATE_LOCKED; |
| 124 | } | 131 | } |
| 125 | 132 | ||
| 126 | /* | 133 | /* |
| @@ -196,6 +203,12 @@ static void snd_vt1724_set_gpio_dir(struct snd_ice1712 *ice, unsigned int data) | |||
| 196 | inw(ICEREG1724(ice, GPIO_DIRECTION)); /* dummy read for pci-posting */ | 203 | inw(ICEREG1724(ice, GPIO_DIRECTION)); /* dummy read for pci-posting */ |
| 197 | } | 204 | } |
| 198 | 205 | ||
| 206 | /* get gpio direction 0 = read, 1 = write */ | ||
| 207 | static unsigned int snd_vt1724_get_gpio_dir(struct snd_ice1712 *ice) | ||
| 208 | { | ||
| 209 | return inl(ICEREG1724(ice, GPIO_DIRECTION)); | ||
| 210 | } | ||
| 211 | |||
| 199 | /* set the gpio mask (0 = writable) */ | 212 | /* set the gpio mask (0 = writable) */ |
| 200 | static void snd_vt1724_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data) | 213 | static void snd_vt1724_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data) |
| 201 | { | 214 | { |
| @@ -205,6 +218,17 @@ static void snd_vt1724_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data) | |||
| 205 | inw(ICEREG1724(ice, GPIO_WRITE_MASK)); /* dummy read for pci-posting */ | 218 | inw(ICEREG1724(ice, GPIO_WRITE_MASK)); /* dummy read for pci-posting */ |
| 206 | } | 219 | } |
| 207 | 220 | ||
| 221 | static unsigned int snd_vt1724_get_gpio_mask(struct snd_ice1712 *ice) | ||
| 222 | { | ||
| 223 | unsigned int mask; | ||
| 224 | if (!ice->vt1720) | ||
| 225 | mask = (unsigned int)inb(ICEREG1724(ice, GPIO_WRITE_MASK_22)); | ||
| 226 | else | ||
| 227 | mask = 0; | ||
| 228 | mask = (mask << 16) | inw(ICEREG1724(ice, GPIO_WRITE_MASK)); | ||
| 229 | return mask; | ||
| 230 | } | ||
| 231 | |||
| 208 | static void snd_vt1724_set_gpio_data(struct snd_ice1712 *ice, unsigned int data) | 232 | static void snd_vt1724_set_gpio_data(struct snd_ice1712 *ice, unsigned int data) |
| 209 | { | 233 | { |
| 210 | outw(data, ICEREG1724(ice, GPIO_DATA)); | 234 | outw(data, ICEREG1724(ice, GPIO_DATA)); |
| @@ -651,16 +675,22 @@ static int snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate, | |||
| 651 | return ((rate == ice->cur_rate) && !force) ? 0 : -EBUSY; | 675 | return ((rate == ice->cur_rate) && !force) ? 0 : -EBUSY; |
| 652 | } | 676 | } |
| 653 | if (!force && is_pro_rate_locked(ice)) { | 677 | if (!force && is_pro_rate_locked(ice)) { |
| 678 | /* comparing required and current rate - makes sense for | ||
| 679 | * internal clock only */ | ||
| 654 | spin_unlock_irqrestore(&ice->reg_lock, flags); | 680 | spin_unlock_irqrestore(&ice->reg_lock, flags); |
| 655 | return (rate == ice->cur_rate) ? 0 : -EBUSY; | 681 | return (rate == ice->cur_rate) ? 0 : -EBUSY; |
| 656 | } | 682 | } |
| 657 | 683 | ||
| 658 | old_rate = ice->get_rate(ice); | 684 | if (force || !ice->is_spdif_master(ice)) { |
| 659 | if (force || (old_rate != rate)) | 685 | /* force means the rate was switched by ucontrol, otherwise |
| 660 | ice->set_rate(ice, rate); | 686 | * setting clock rate for internal clock mode */ |
| 661 | else if (rate == ice->cur_rate) { | 687 | old_rate = ice->get_rate(ice); |
| 662 | spin_unlock_irqrestore(&ice->reg_lock, flags); | 688 | if (force || (old_rate != rate)) |
| 663 | return 0; | 689 | ice->set_rate(ice, rate); |
| 690 | else if (rate == ice->cur_rate) { | ||
| 691 | spin_unlock_irqrestore(&ice->reg_lock, flags); | ||
| 692 | return 0; | ||
| 693 | } | ||
| 664 | } | 694 | } |
| 665 | 695 | ||
| 666 | ice->cur_rate = rate; | 696 | ice->cur_rate = rate; |
| @@ -1016,6 +1046,8 @@ static int snd_vt1724_playback_pro_open(struct snd_pcm_substream *substream) | |||
| 1016 | VT1724_BUFFER_ALIGN); | 1046 | VT1724_BUFFER_ALIGN); |
| 1017 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, | 1047 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, |
| 1018 | VT1724_BUFFER_ALIGN); | 1048 | VT1724_BUFFER_ALIGN); |
| 1049 | if (ice->pro_open) | ||
| 1050 | ice->pro_open(ice, substream); | ||
| 1019 | return 0; | 1051 | return 0; |
| 1020 | } | 1052 | } |
| 1021 | 1053 | ||
| @@ -1034,6 +1066,8 @@ static int snd_vt1724_capture_pro_open(struct snd_pcm_substream *substream) | |||
| 1034 | VT1724_BUFFER_ALIGN); | 1066 | VT1724_BUFFER_ALIGN); |
| 1035 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, | 1067 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, |
| 1036 | VT1724_BUFFER_ALIGN); | 1068 | VT1724_BUFFER_ALIGN); |
| 1069 | if (ice->pro_open) | ||
| 1070 | ice->pro_open(ice, substream); | ||
| 1037 | return 0; | 1071 | return 0; |
| 1038 | } | 1072 | } |
| 1039 | 1073 | ||
| @@ -1787,15 +1821,21 @@ static int snd_vt1724_pro_internal_clock_info(struct snd_kcontrol *kcontrol, | |||
| 1787 | struct snd_ctl_elem_info *uinfo) | 1821 | struct snd_ctl_elem_info *uinfo) |
| 1788 | { | 1822 | { |
| 1789 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 1823 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
| 1790 | 1824 | int hw_rates_count = ice->hw_rates->count; | |
| 1791 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 1825 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
| 1792 | uinfo->count = 1; | 1826 | uinfo->count = 1; |
| 1793 | uinfo->value.enumerated.items = ice->hw_rates->count + 1; | 1827 | |
| 1828 | uinfo->value.enumerated.items = hw_rates_count + ice->ext_clock_count; | ||
| 1829 | /* upper limit - keep at top */ | ||
| 1794 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 1830 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) |
| 1795 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | 1831 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; |
| 1796 | if (uinfo->value.enumerated.item == uinfo->value.enumerated.items - 1) | 1832 | if (uinfo->value.enumerated.item >= hw_rates_count) |
| 1797 | strcpy(uinfo->value.enumerated.name, "IEC958 Input"); | 1833 | /* ext_clock items */ |
| 1834 | strcpy(uinfo->value.enumerated.name, | ||
| 1835 | ice->ext_clock_names[ | ||
| 1836 | uinfo->value.enumerated.item - hw_rates_count]); | ||
| 1798 | else | 1837 | else |
| 1838 | /* int clock items */ | ||
| 1799 | sprintf(uinfo->value.enumerated.name, "%d", | 1839 | sprintf(uinfo->value.enumerated.name, "%d", |
| 1800 | ice->hw_rates->list[uinfo->value.enumerated.item]); | 1840 | ice->hw_rates->list[uinfo->value.enumerated.item]); |
| 1801 | return 0; | 1841 | return 0; |
| @@ -1809,7 +1849,8 @@ static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol, | |||
| 1809 | 1849 | ||
| 1810 | spin_lock_irq(&ice->reg_lock); | 1850 | spin_lock_irq(&ice->reg_lock); |
| 1811 | if (ice->is_spdif_master(ice)) { | 1851 | if (ice->is_spdif_master(ice)) { |
| 1812 | ucontrol->value.enumerated.item[0] = ice->hw_rates->count; | 1852 | ucontrol->value.enumerated.item[0] = ice->hw_rates->count + |
| 1853 | ice->get_spdif_master_type(ice); | ||
| 1813 | } else { | 1854 | } else { |
| 1814 | rate = ice->get_rate(ice); | 1855 | rate = ice->get_rate(ice); |
| 1815 | ucontrol->value.enumerated.item[0] = 0; | 1856 | ucontrol->value.enumerated.item[0] = 0; |
| @@ -1824,8 +1865,14 @@ static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol, | |||
| 1824 | return 0; | 1865 | return 0; |
| 1825 | } | 1866 | } |
| 1826 | 1867 | ||
| 1868 | static int stdclock_get_spdif_master_type(struct snd_ice1712 *ice) | ||
| 1869 | { | ||
| 1870 | /* standard external clock - only single type - SPDIF IN */ | ||
| 1871 | return 0; | ||
| 1872 | } | ||
| 1873 | |||
| 1827 | /* setting clock to external - SPDIF */ | 1874 | /* setting clock to external - SPDIF */ |
| 1828 | static void stdclock_set_spdif_clock(struct snd_ice1712 *ice) | 1875 | static int stdclock_set_spdif_clock(struct snd_ice1712 *ice, int type) |
| 1829 | { | 1876 | { |
| 1830 | unsigned char oval; | 1877 | unsigned char oval; |
| 1831 | unsigned char i2s_oval; | 1878 | unsigned char i2s_oval; |
| @@ -1834,27 +1881,30 @@ static void stdclock_set_spdif_clock(struct snd_ice1712 *ice) | |||
| 1834 | /* setting 256fs */ | 1881 | /* setting 256fs */ |
| 1835 | i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT)); | 1882 | i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT)); |
| 1836 | outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X, ICEMT1724(ice, I2S_FORMAT)); | 1883 | outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X, ICEMT1724(ice, I2S_FORMAT)); |
| 1884 | return 0; | ||
| 1837 | } | 1885 | } |
| 1838 | 1886 | ||
| 1887 | |||
| 1839 | static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol, | 1888 | static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol, |
| 1840 | struct snd_ctl_elem_value *ucontrol) | 1889 | struct snd_ctl_elem_value *ucontrol) |
| 1841 | { | 1890 | { |
| 1842 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 1891 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
| 1843 | unsigned int old_rate, new_rate; | 1892 | unsigned int old_rate, new_rate; |
| 1844 | unsigned int item = ucontrol->value.enumerated.item[0]; | 1893 | unsigned int item = ucontrol->value.enumerated.item[0]; |
| 1845 | unsigned int spdif = ice->hw_rates->count; | 1894 | unsigned int first_ext_clock = ice->hw_rates->count; |
| 1846 | 1895 | ||
| 1847 | if (item > spdif) | 1896 | if (item > first_ext_clock + ice->ext_clock_count - 1) |
| 1848 | return -EINVAL; | 1897 | return -EINVAL; |
| 1849 | 1898 | ||
| 1899 | /* if rate = 0 => external clock */ | ||
| 1850 | spin_lock_irq(&ice->reg_lock); | 1900 | spin_lock_irq(&ice->reg_lock); |
| 1851 | if (ice->is_spdif_master(ice)) | 1901 | if (ice->is_spdif_master(ice)) |
| 1852 | old_rate = 0; | 1902 | old_rate = 0; |
| 1853 | else | 1903 | else |
| 1854 | old_rate = ice->get_rate(ice); | 1904 | old_rate = ice->get_rate(ice); |
| 1855 | if (item == spdif) { | 1905 | if (item >= first_ext_clock) { |
| 1856 | /* switching to external clock via SPDIF */ | 1906 | /* switching to external clock */ |
| 1857 | ice->set_spdif_clock(ice); | 1907 | ice->set_spdif_clock(ice, item - first_ext_clock); |
| 1858 | new_rate = 0; | 1908 | new_rate = 0; |
| 1859 | } else { | 1909 | } else { |
| 1860 | /* internal on-card clock */ | 1910 | /* internal on-card clock */ |
| @@ -1866,7 +1916,7 @@ static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol, | |||
| 1866 | } | 1916 | } |
| 1867 | spin_unlock_irq(&ice->reg_lock); | 1917 | spin_unlock_irq(&ice->reg_lock); |
| 1868 | 1918 | ||
| 1869 | /* the first reset to the SPDIF master mode? */ | 1919 | /* the first switch to the ext. clock mode? */ |
| 1870 | if (old_rate != new_rate && !new_rate) { | 1920 | if (old_rate != new_rate && !new_rate) { |
| 1871 | /* notify akm chips as well */ | 1921 | /* notify akm chips as well */ |
| 1872 | unsigned int i; | 1922 | unsigned int i; |
| @@ -2136,6 +2186,7 @@ static struct snd_ice1712_card_info *card_tables[] __devinitdata = { | |||
| 2136 | snd_vt1724_phase_cards, | 2186 | snd_vt1724_phase_cards, |
| 2137 | snd_vt1724_wtm_cards, | 2187 | snd_vt1724_wtm_cards, |
| 2138 | snd_vt1724_se_cards, | 2188 | snd_vt1724_se_cards, |
| 2189 | snd_vt1724_qtet_cards, | ||
| 2139 | NULL, | 2190 | NULL, |
| 2140 | }; | 2191 | }; |
| 2141 | 2192 | ||
| @@ -2434,7 +2485,9 @@ static int __devinit snd_vt1724_create(struct snd_card *card, | |||
| 2434 | mutex_init(&ice->open_mutex); | 2485 | mutex_init(&ice->open_mutex); |
| 2435 | mutex_init(&ice->i2c_mutex); | 2486 | mutex_init(&ice->i2c_mutex); |
| 2436 | ice->gpio.set_mask = snd_vt1724_set_gpio_mask; | 2487 | ice->gpio.set_mask = snd_vt1724_set_gpio_mask; |
| 2488 | ice->gpio.get_mask = snd_vt1724_get_gpio_mask; | ||
| 2437 | ice->gpio.set_dir = snd_vt1724_set_gpio_dir; | 2489 | ice->gpio.set_dir = snd_vt1724_set_gpio_dir; |
| 2490 | ice->gpio.get_dir = snd_vt1724_get_gpio_dir; | ||
| 2438 | ice->gpio.set_data = snd_vt1724_set_gpio_data; | 2491 | ice->gpio.set_data = snd_vt1724_set_gpio_data; |
| 2439 | ice->gpio.get_data = snd_vt1724_get_gpio_data; | 2492 | ice->gpio.get_data = snd_vt1724_get_gpio_data; |
| 2440 | ice->card = card; | 2493 | ice->card = card; |
| @@ -2522,6 +2575,9 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci, | |||
| 2522 | return err; | 2575 | return err; |
| 2523 | } | 2576 | } |
| 2524 | 2577 | ||
| 2578 | /* field init before calling chip_init */ | ||
| 2579 | ice->ext_clock_count = 0; | ||
| 2580 | |||
| 2525 | for (tbl = card_tables; *tbl; tbl++) { | 2581 | for (tbl = card_tables; *tbl; tbl++) { |
| 2526 | for (c = *tbl; c->subvendor; c++) { | 2582 | for (c = *tbl; c->subvendor; c++) { |
| 2527 | if (c->subvendor == ice->eeprom.subvendor) { | 2583 | if (c->subvendor == ice->eeprom.subvendor) { |
| @@ -2560,6 +2616,13 @@ __found: | |||
| 2560 | ice->set_mclk = stdclock_set_mclk; | 2616 | ice->set_mclk = stdclock_set_mclk; |
| 2561 | if (!ice->set_spdif_clock) | 2617 | if (!ice->set_spdif_clock) |
| 2562 | ice->set_spdif_clock = stdclock_set_spdif_clock; | 2618 | ice->set_spdif_clock = stdclock_set_spdif_clock; |
| 2619 | if (!ice->get_spdif_master_type) | ||
| 2620 | ice->get_spdif_master_type = stdclock_get_spdif_master_type; | ||
| 2621 | if (!ice->ext_clock_names) | ||
| 2622 | ice->ext_clock_names = ext_clock_names; | ||
| 2623 | if (!ice->ext_clock_count) | ||
| 2624 | ice->ext_clock_count = ARRAY_SIZE(ext_clock_names); | ||
| 2625 | |||
| 2563 | if (!ice->hw_rates) | 2626 | if (!ice->hw_rates) |
| 2564 | set_std_hw_rates(ice); | 2627 | set_std_hw_rates(ice); |
| 2565 | 2628 | ||
| @@ -2719,7 +2782,7 @@ static int snd_vt1724_resume(struct pci_dev *pci) | |||
| 2719 | 2782 | ||
| 2720 | if (ice->pm_saved_is_spdif_master) { | 2783 | if (ice->pm_saved_is_spdif_master) { |
| 2721 | /* switching to external clock via SPDIF */ | 2784 | /* switching to external clock via SPDIF */ |
| 2722 | ice->set_spdif_clock(ice); | 2785 | ice->set_spdif_clock(ice, 0); |
| 2723 | } else { | 2786 | } else { |
| 2724 | /* internal on-card clock */ | 2787 | /* internal on-card clock */ |
| 2725 | snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1); | 2788 | snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1); |
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c index fd948bfd9aef..4bed9633a4cd 100644 --- a/sound/pci/ice1712/juli.c +++ b/sound/pci/ice1712/juli.c | |||
| @@ -412,25 +412,6 @@ static struct snd_kcontrol_new juli_mute_controls[] __devinitdata = { | |||
| 412 | }, | 412 | }, |
| 413 | }; | 413 | }; |
| 414 | 414 | ||
| 415 | |||
| 416 | static void ak4358_proc_regs_read(struct snd_info_entry *entry, | ||
| 417 | struct snd_info_buffer *buffer) | ||
| 418 | { | ||
| 419 | struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data; | ||
| 420 | int reg, val; | ||
| 421 | for (reg = 0; reg <= 0xf; reg++) { | ||
| 422 | val = snd_akm4xxx_get(ice->akm, 0, reg); | ||
| 423 | snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val); | ||
| 424 | } | ||
| 425 | } | ||
| 426 | |||
| 427 | static void ak4358_proc_init(struct snd_ice1712 *ice) | ||
| 428 | { | ||
| 429 | struct snd_info_entry *entry; | ||
| 430 | if (!snd_card_proc_new(ice->card, "ak4358_codec", &entry)) | ||
| 431 | snd_info_set_text_ops(entry, ice, ak4358_proc_regs_read); | ||
| 432 | } | ||
| 433 | |||
| 434 | static char *slave_vols[] __devinitdata = { | 415 | static char *slave_vols[] __devinitdata = { |
| 435 | PCM_VOLUME, | 416 | PCM_VOLUME, |
| 436 | MONITOR_AN_IN_VOLUME, | 417 | MONITOR_AN_IN_VOLUME, |
| @@ -496,8 +477,6 @@ static int __devinit juli_add_controls(struct snd_ice1712 *ice) | |||
| 496 | /* only capture SPDIF over AK4114 */ | 477 | /* only capture SPDIF over AK4114 */ |
| 497 | err = snd_ak4114_build(spec->ak4114, NULL, | 478 | err = snd_ak4114_build(spec->ak4114, NULL, |
| 498 | ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); | 479 | ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); |
| 499 | |||
| 500 | ak4358_proc_init(ice); | ||
| 501 | if (err < 0) | 480 | if (err < 0) |
| 502 | return err; | 481 | return err; |
| 503 | return 0; | 482 | return 0; |
| @@ -550,13 +529,14 @@ static inline unsigned char juli_set_mclk(struct snd_ice1712 *ice, | |||
| 550 | } | 529 | } |
| 551 | 530 | ||
| 552 | /* setting clock to external - SPDIF */ | 531 | /* setting clock to external - SPDIF */ |
| 553 | static void juli_set_spdif_clock(struct snd_ice1712 *ice) | 532 | static int juli_set_spdif_clock(struct snd_ice1712 *ice, int type) |
| 554 | { | 533 | { |
| 555 | unsigned int old; | 534 | unsigned int old; |
| 556 | old = ice->gpio.get_data(ice); | 535 | old = ice->gpio.get_data(ice); |
| 557 | /* external clock (= 0), multiply 1x, 48kHz */ | 536 | /* external clock (= 0), multiply 1x, 48kHz */ |
| 558 | ice->gpio.set_data(ice, (old & ~GPIO_RATE_MASK) | GPIO_MULTI_1X | | 537 | ice->gpio.set_data(ice, (old & ~GPIO_RATE_MASK) | GPIO_MULTI_1X | |
| 559 | GPIO_FREQ_48KHZ); | 538 | GPIO_FREQ_48KHZ); |
| 539 | return 0; | ||
| 560 | } | 540 | } |
| 561 | 541 | ||
| 562 | /* Called when ak4114 detects change in the input SPDIF stream */ | 542 | /* Called when ak4114 detects change in the input SPDIF stream */ |
diff --git a/sound/pci/ice1712/quartet.c b/sound/pci/ice1712/quartet.c new file mode 100644 index 000000000000..1948632787e6 --- /dev/null +++ b/sound/pci/ice1712/quartet.c | |||
| @@ -0,0 +1,1130 @@ | |||
| 1 | /* | ||
| 2 | * ALSA driver for ICEnsemble VT1724 (Envy24HT) | ||
| 3 | * | ||
| 4 | * Lowlevel functions for Infrasonic Quartet | ||
| 5 | * | ||
| 6 | * Copyright (c) 2009 Pavel Hofman <pavel.hofman@ivitera.com> | ||
| 7 | * | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License as published by | ||
| 11 | * the Free Software Foundation; either version 2 of the License, or | ||
| 12 | * (at your option) any later version. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License | ||
| 20 | * along with this program; if not, write to the Free Software | ||
| 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 22 | * | ||
| 23 | */ | ||
| 24 | |||
| 25 | #include <asm/io.h> | ||
| 26 | #include <linux/delay.h> | ||
| 27 | #include <linux/interrupt.h> | ||
| 28 | #include <linux/init.h> | ||
| 29 | #include <linux/slab.h> | ||
| 30 | #include <sound/core.h> | ||
| 31 | #include <sound/tlv.h> | ||
| 32 | #include <sound/info.h> | ||
| 33 | |||
| 34 | #include "ice1712.h" | ||
| 35 | #include "envy24ht.h" | ||
| 36 | #include <sound/ak4113.h> | ||
| 37 | #include "quartet.h" | ||
| 38 | |||
| 39 | struct qtet_spec { | ||
| 40 | struct ak4113 *ak4113; | ||
| 41 | unsigned int scr; /* system control register */ | ||
| 42 | unsigned int mcr; /* monitoring control register */ | ||
| 43 | unsigned int cpld; /* cpld register */ | ||
| 44 | }; | ||
| 45 | |||
| 46 | struct qtet_kcontrol_private { | ||
| 47 | unsigned int bit; | ||
| 48 | void (*set_register)(struct snd_ice1712 *ice, unsigned int val); | ||
| 49 | unsigned int (*get_register)(struct snd_ice1712 *ice); | ||
| 50 | unsigned char *texts[2]; | ||
| 51 | }; | ||
| 52 | |||
| 53 | enum { | ||
| 54 | IN12_SEL = 0, | ||
| 55 | IN34_SEL, | ||
| 56 | AIN34_SEL, | ||
| 57 | COAX_OUT, | ||
| 58 | IN12_MON12, | ||
| 59 | IN12_MON34, | ||
| 60 | IN34_MON12, | ||
| 61 | IN34_MON34, | ||
| 62 | OUT12_MON34, | ||
| 63 | OUT34_MON12, | ||
| 64 | }; | ||
| 65 | |||
| 66 | static char *ext_clock_names[3] = {"IEC958 In", "Word Clock 1xFS", | ||
| 67 | "Word Clock 256xFS"}; | ||
| 68 | |||
| 69 | /* chip address on I2C bus */ | ||
| 70 | #define AK4113_ADDR 0x26 /* S/PDIF receiver */ | ||
| 71 | |||
| 72 | /* chip address on SPI bus */ | ||
| 73 | #define AK4620_ADDR 0x02 /* ADC/DAC */ | ||
| 74 | |||
| 75 | |||
| 76 | /* | ||
| 77 | * GPIO pins | ||
| 78 | */ | ||
| 79 | |||
| 80 | /* GPIO0 - O - DATA0, def. 0 */ | ||
| 81 | #define GPIO_D0 (1<<0) | ||
| 82 | /* GPIO1 - I/O - DATA1, Jack Detect Input0 (0:present, 1:missing), def. 1 */ | ||
| 83 | #define GPIO_D1_JACKDTC0 (1<<1) | ||
| 84 | /* GPIO2 - I/O - DATA2, Jack Detect Input1 (0:present, 1:missing), def. 1 */ | ||
| 85 | #define GPIO_D2_JACKDTC1 (1<<2) | ||
| 86 | /* GPIO3 - I/O - DATA3, def. 1 */ | ||
| 87 | #define GPIO_D3 (1<<3) | ||
| 88 | /* GPIO4 - I/O - DATA4, SPI CDTO, def. 1 */ | ||
| 89 | #define GPIO_D4_SPI_CDTO (1<<4) | ||
| 90 | /* GPIO5 - I/O - DATA5, SPI CCLK, def. 1 */ | ||
| 91 | #define GPIO_D5_SPI_CCLK (1<<5) | ||
| 92 | /* GPIO6 - I/O - DATA6, Cable Detect Input (0:detected, 1:not detected */ | ||
| 93 | #define GPIO_D6_CD (1<<6) | ||
| 94 | /* GPIO7 - I/O - DATA7, Device Detect Input (0:detected, 1:not detected */ | ||
| 95 | #define GPIO_D7_DD (1<<7) | ||
| 96 | /* GPIO8 - O - CPLD Chip Select, def. 1 */ | ||
| 97 | #define GPIO_CPLD_CSN (1<<8) | ||
| 98 | /* GPIO9 - O - CPLD register read/write (0:write, 1:read), def. 0 */ | ||
| 99 | #define GPIO_CPLD_RW (1<<9) | ||
| 100 | /* GPIO10 - O - SPI Chip Select for CODEC#0, def. 1 */ | ||
| 101 | #define GPIO_SPI_CSN0 (1<<10) | ||
| 102 | /* GPIO11 - O - SPI Chip Select for CODEC#1, def. 1 */ | ||
| 103 | #define GPIO_SPI_CSN1 (1<<11) | ||
| 104 | /* GPIO12 - O - Ex. Register Output Enable (0:enable, 1:disable), def. 1, | ||
| 105 | * init 0 */ | ||
| 106 | #define GPIO_EX_GPIOE (1<<12) | ||
| 107 | /* GPIO13 - O - Ex. Register0 Chip Select for System Control Register, | ||
| 108 | * def. 1 */ | ||
| 109 | #define GPIO_SCR (1<<13) | ||
| 110 | /* GPIO14 - O - Ex. Register1 Chip Select for Monitor Control Register, | ||
| 111 | * def. 1 */ | ||
| 112 | #define GPIO_MCR (1<<14) | ||
| 113 | |||
| 114 | #define GPIO_SPI_ALL (GPIO_D4_SPI_CDTO | GPIO_D5_SPI_CCLK |\ | ||
| 115 | GPIO_SPI_CSN0 | GPIO_SPI_CSN1) | ||
| 116 | |||
| 117 | #define GPIO_DATA_MASK (GPIO_D0 | GPIO_D1_JACKDTC0 | \ | ||
| 118 | GPIO_D2_JACKDTC1 | GPIO_D3 | \ | ||
| 119 | GPIO_D4_SPI_CDTO | GPIO_D5_SPI_CCLK | \ | ||
| 120 | GPIO_D6_CD | GPIO_D7_DD) | ||
| 121 | |||
| 122 | /* System Control Register GPIO_SCR data bits */ | ||
| 123 | /* Mic/Line select relay (0:line, 1:mic) */ | ||
| 124 | #define SCR_RELAY GPIO_D0 | ||
| 125 | /* Phantom power drive control (0:5V, 1:48V) */ | ||
| 126 | #define SCR_PHP_V GPIO_D1_JACKDTC0 | ||
| 127 | /* H/W mute control (0:Normal, 1:Mute) */ | ||
| 128 | #define SCR_MUTE GPIO_D2_JACKDTC1 | ||
| 129 | /* Phantom power control (0:Phantom on, 1:off) */ | ||
| 130 | #define SCR_PHP GPIO_D3 | ||
| 131 | /* Analog input 1/2 Source Select */ | ||
| 132 | #define SCR_AIN12_SEL0 GPIO_D4_SPI_CDTO | ||
| 133 | #define SCR_AIN12_SEL1 GPIO_D5_SPI_CCLK | ||
| 134 | /* Analog input 3/4 Source Select (0:line, 1:hi-z) */ | ||
| 135 | #define SCR_AIN34_SEL GPIO_D6_CD | ||
| 136 | /* Codec Power Down (0:power down, 1:normal) */ | ||
| 137 | #define SCR_CODEC_PDN GPIO_D7_DD | ||
| 138 | |||
| 139 | #define SCR_AIN12_LINE (0) | ||
| 140 | #define SCR_AIN12_MIC (SCR_AIN12_SEL0) | ||
| 141 | #define SCR_AIN12_LOWCUT (SCR_AIN12_SEL1 | SCR_AIN12_SEL0) | ||
| 142 | |||
| 143 | /* Monitor Control Register GPIO_MCR data bits */ | ||
| 144 | /* Input 1/2 to Monitor 1/2 (0:off, 1:on) */ | ||
| 145 | #define MCR_IN12_MON12 GPIO_D0 | ||
| 146 | /* Input 1/2 to Monitor 3/4 (0:off, 1:on) */ | ||
| 147 | #define MCR_IN12_MON34 GPIO_D1_JACKDTC0 | ||
| 148 | /* Input 3/4 to Monitor 1/2 (0:off, 1:on) */ | ||
| 149 | #define MCR_IN34_MON12 GPIO_D2_JACKDTC1 | ||
| 150 | /* Input 3/4 to Monitor 3/4 (0:off, 1:on) */ | ||
| 151 | #define MCR_IN34_MON34 GPIO_D3 | ||
| 152 | /* Output to Monitor 1/2 (0:off, 1:on) */ | ||
| 153 | #define MCR_OUT34_MON12 GPIO_D4_SPI_CDTO | ||
| 154 | /* Output to Monitor 3/4 (0:off, 1:on) */ | ||
| 155 | #define MCR_OUT12_MON34 GPIO_D5_SPI_CCLK | ||
| 156 | |||
| 157 | /* CPLD Register DATA bits */ | ||
| 158 | /* Clock Rate Select */ | ||
| 159 | #define CPLD_CKS0 GPIO_D0 | ||
| 160 | #define CPLD_CKS1 GPIO_D1_JACKDTC0 | ||
| 161 | #define CPLD_CKS2 GPIO_D2_JACKDTC1 | ||
| 162 | /* Sync Source Select (0:Internal, 1:External) */ | ||
| 163 | #define CPLD_SYNC_SEL GPIO_D3 | ||
| 164 | /* Word Clock FS Select (0:FS, 1:256FS) */ | ||
| 165 | #define CPLD_WORD_SEL GPIO_D4_SPI_CDTO | ||
| 166 | /* Coaxial Output Source (IS-Link) (0:SPDIF, 1:I2S) */ | ||
| 167 | #define CPLD_COAX_OUT GPIO_D5_SPI_CCLK | ||
| 168 | /* Input 1/2 Source Select (0:Analog12, 1:An34) */ | ||
| 169 | #define CPLD_IN12_SEL GPIO_D6_CD | ||
| 170 | /* Input 3/4 Source Select (0:Analog34, 1:Digital In) */ | ||
| 171 | #define CPLD_IN34_SEL GPIO_D7_DD | ||
| 172 | |||
| 173 | /* internal clock (CPLD_SYNC_SEL = 0) options */ | ||
| 174 | #define CPLD_CKS_44100HZ (0) | ||
| 175 | #define CPLD_CKS_48000HZ (CPLD_CKS0) | ||
| 176 | #define CPLD_CKS_88200HZ (CPLD_CKS1) | ||
| 177 | #define CPLD_CKS_96000HZ (CPLD_CKS1 | CPLD_CKS0) | ||
| 178 | #define CPLD_CKS_176400HZ (CPLD_CKS2) | ||
| 179 | #define CPLD_CKS_192000HZ (CPLD_CKS2 | CPLD_CKS0) | ||
| 180 | |||
| 181 | #define CPLD_CKS_MASK (CPLD_CKS0 | CPLD_CKS1 | CPLD_CKS2) | ||
| 182 | |||
| 183 | /* external clock (CPLD_SYNC_SEL = 1) options */ | ||
| 184 | /* external clock - SPDIF */ | ||
| 185 | #define CPLD_EXT_SPDIF (0 | CPLD_SYNC_SEL) | ||
| 186 | /* external clock - WordClock 1xfs */ | ||
| 187 | #define CPLD_EXT_WORDCLOCK_1FS (CPLD_CKS1 | CPLD_SYNC_SEL) | ||
| 188 | /* external clock - WordClock 256xfs */ | ||
| 189 | #define CPLD_EXT_WORDCLOCK_256FS (CPLD_CKS1 | CPLD_WORD_SEL |\ | ||
| 190 | CPLD_SYNC_SEL) | ||
| 191 | |||
| 192 | #define EXT_SPDIF_TYPE 0 | ||
| 193 | #define EXT_WORDCLOCK_1FS_TYPE 1 | ||
| 194 | #define EXT_WORDCLOCK_256FS_TYPE 2 | ||
| 195 | |||
| 196 | #define AK4620_DFS0 (1<<0) | ||
| 197 | #define AK4620_DFS1 (1<<1) | ||
| 198 | #define AK4620_CKS0 (1<<2) | ||
| 199 | #define AK4620_CKS1 (1<<3) | ||
| 200 | /* Clock and Format Control register */ | ||
| 201 | #define AK4620_DFS_REG 0x02 | ||
| 202 | |||
| 203 | /* Deem and Volume Control register */ | ||
| 204 | #define AK4620_DEEMVOL_REG 0x03 | ||
| 205 | #define AK4620_SMUTE (1<<7) | ||
| 206 | |||
| 207 | /* | ||
| 208 | * Conversion from int value to its binary form. Used for debugging. | ||
| 209 | * The output buffer must be allocated prior to calling the function. | ||
| 210 | */ | ||
| 211 | static char *get_binary(char *buffer, int value) | ||
| 212 | { | ||
| 213 | int i, j, pos; | ||
| 214 | pos = 0; | ||
| 215 | for (i = 0; i < 4; ++i) { | ||
| 216 | for (j = 0; j < 8; ++j) { | ||
| 217 | if (value & (1 << (31-(i*8 + j)))) | ||
| 218 | buffer[pos] = '1'; | ||
| 219 | else | ||
| 220 | buffer[pos] = '0'; | ||
| 221 | pos++; | ||
| 222 | } | ||
| 223 | if (i < 3) { | ||
| 224 | buffer[pos] = ' '; | ||
| 225 | pos++; | ||
| 226 | } | ||
| 227 | } | ||
| 228 | buffer[pos] = '\0'; | ||
| 229 | return buffer; | ||
| 230 | } | ||
| 231 | |||
| 232 | /* | ||
| 233 | * Initial setup of the conversion array GPIO <-> rate | ||
| 234 | */ | ||
| 235 | static unsigned int qtet_rates[] = { | ||
| 236 | 44100, 48000, 88200, | ||
| 237 | 96000, 176400, 192000, | ||
| 238 | }; | ||
| 239 | |||
| 240 | static unsigned int cks_vals[] = { | ||
| 241 | CPLD_CKS_44100HZ, CPLD_CKS_48000HZ, CPLD_CKS_88200HZ, | ||
| 242 | CPLD_CKS_96000HZ, CPLD_CKS_176400HZ, CPLD_CKS_192000HZ, | ||
| 243 | }; | ||
| 244 | |||
| 245 | static struct snd_pcm_hw_constraint_list qtet_rates_info = { | ||
| 246 | .count = ARRAY_SIZE(qtet_rates), | ||
| 247 | .list = qtet_rates, | ||
| 248 | .mask = 0, | ||
| 249 | }; | ||
| 250 | |||
| 251 | static void qtet_ak4113_write(void *private_data, unsigned char reg, | ||
| 252 | unsigned char val) | ||
| 253 | { | ||
| 254 | snd_vt1724_write_i2c((struct snd_ice1712 *)private_data, AK4113_ADDR, | ||
| 255 | reg, val); | ||
| 256 | } | ||
| 257 | |||
| 258 | static unsigned char qtet_ak4113_read(void *private_data, unsigned char reg) | ||
| 259 | { | ||
| 260 | return snd_vt1724_read_i2c((struct snd_ice1712 *)private_data, | ||
| 261 | AK4113_ADDR, reg); | ||
| 262 | } | ||
| 263 | |||
| 264 | |||
| 265 | /* | ||
| 266 | * AK4620 section | ||
| 267 | */ | ||
| 268 | |||
| 269 | /* | ||
| 270 | * Write data to addr register of ak4620 | ||
| 271 | */ | ||
| 272 | static void qtet_akm_write(struct snd_akm4xxx *ak, int chip, | ||
| 273 | unsigned char addr, unsigned char data) | ||
| 274 | { | ||
| 275 | unsigned int tmp, orig_dir; | ||
| 276 | int idx; | ||
| 277 | unsigned int addrdata; | ||
| 278 | struct snd_ice1712 *ice = ak->private_data[0]; | ||
| 279 | |||
| 280 | if (snd_BUG_ON(chip < 0 || chip >= 4)) | ||
| 281 | return; | ||
| 282 | /*printk(KERN_DEBUG "Writing to AK4620: chip=%d, addr=0x%x, | ||
| 283 | data=0x%x\n", chip, addr, data);*/ | ||
| 284 | orig_dir = ice->gpio.get_dir(ice); | ||
| 285 | ice->gpio.set_dir(ice, orig_dir | GPIO_SPI_ALL); | ||
| 286 | /* set mask - only SPI bits */ | ||
| 287 | ice->gpio.set_mask(ice, ~GPIO_SPI_ALL); | ||
| 288 | |||
| 289 | tmp = ice->gpio.get_data(ice); | ||
| 290 | /* high all */ | ||
| 291 | tmp |= GPIO_SPI_ALL; | ||
| 292 | ice->gpio.set_data(ice, tmp); | ||
| 293 | udelay(100); | ||
| 294 | /* drop chip select */ | ||
| 295 | if (chip) | ||
| 296 | /* CODEC 1 */ | ||
| 297 | tmp &= ~GPIO_SPI_CSN1; | ||
| 298 | else | ||
| 299 | tmp &= ~GPIO_SPI_CSN0; | ||
| 300 | ice->gpio.set_data(ice, tmp); | ||
| 301 | udelay(100); | ||
| 302 | |||
| 303 | /* build I2C address + data byte */ | ||
| 304 | addrdata = (AK4620_ADDR << 6) | 0x20 | (addr & 0x1f); | ||
| 305 | addrdata = (addrdata << 8) | data; | ||
| 306 | for (idx = 15; idx >= 0; idx--) { | ||
| 307 | /* drop clock */ | ||
| 308 | tmp &= ~GPIO_D5_SPI_CCLK; | ||
| 309 | ice->gpio.set_data(ice, tmp); | ||
| 310 | udelay(100); | ||
| 311 | /* set data */ | ||
| 312 | if (addrdata & (1 << idx)) | ||
| 313 | tmp |= GPIO_D4_SPI_CDTO; | ||
| 314 | else | ||
| 315 | tmp &= ~GPIO_D4_SPI_CDTO; | ||
| 316 | ice->gpio.set_data(ice, tmp); | ||
| 317 | udelay(100); | ||
| 318 | /* raise clock */ | ||
| 319 | tmp |= GPIO_D5_SPI_CCLK; | ||
| 320 | ice->gpio.set_data(ice, tmp); | ||
| 321 | udelay(100); | ||
| 322 | } | ||
| 323 | /* all back to 1 */ | ||
| 324 | tmp |= GPIO_SPI_ALL; | ||
| 325 | ice->gpio.set_data(ice, tmp); | ||
| 326 | udelay(100); | ||
| 327 | |||
| 328 | /* return all gpios to non-writable */ | ||
| 329 | ice->gpio.set_mask(ice, 0xffffff); | ||
| 330 | /* restore GPIOs direction */ | ||
| 331 | ice->gpio.set_dir(ice, orig_dir); | ||
| 332 | } | ||
| 333 | |||
| 334 | static void qtet_akm_set_regs(struct snd_akm4xxx *ak, unsigned char addr, | ||
| 335 | unsigned char mask, unsigned char value) | ||
| 336 | { | ||
| 337 | unsigned char tmp; | ||
| 338 | int chip; | ||
| 339 | for (chip = 0; chip < ak->num_chips; chip++) { | ||
| 340 | tmp = snd_akm4xxx_get(ak, chip, addr); | ||
| 341 | /* clear the bits */ | ||
| 342 | tmp &= ~mask; | ||
| 343 | /* set the new bits */ | ||
| 344 | tmp |= value; | ||
| 345 | snd_akm4xxx_write(ak, chip, addr, tmp); | ||
| 346 | } | ||
| 347 | } | ||
| 348 | |||
| 349 | /* | ||
| 350 | * change the rate of AK4620 | ||
| 351 | */ | ||
| 352 | static void qtet_akm_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate) | ||
| 353 | { | ||
| 354 | unsigned char ak4620_dfs; | ||
| 355 | |||
| 356 | if (rate == 0) /* no hint - S/PDIF input is master or the new spdif | ||
| 357 | input rate undetected, simply return */ | ||
| 358 | return; | ||
| 359 | |||
| 360 | /* adjust DFS on codecs - see datasheet */ | ||
| 361 | if (rate > 108000) | ||
| 362 | ak4620_dfs = AK4620_DFS1 | AK4620_CKS1; | ||
| 363 | else if (rate > 54000) | ||
| 364 | ak4620_dfs = AK4620_DFS0 | AK4620_CKS0; | ||
| 365 | else | ||
| 366 | ak4620_dfs = 0; | ||
| 367 | |||
| 368 | /* set new value */ | ||
| 369 | qtet_akm_set_regs(ak, AK4620_DFS_REG, AK4620_DFS0 | AK4620_DFS1 | | ||
| 370 | AK4620_CKS0 | AK4620_CKS1, ak4620_dfs); | ||
| 371 | } | ||
| 372 | |||
| 373 | #define AK_CONTROL(xname, xch) { .name = xname, .num_channels = xch } | ||
| 374 | |||
| 375 | #define PCM_12_PLAYBACK_VOLUME "PCM 1/2 Playback Volume" | ||
| 376 | #define PCM_34_PLAYBACK_VOLUME "PCM 3/4 Playback Volume" | ||
| 377 | #define PCM_12_CAPTURE_VOLUME "PCM 1/2 Capture Volume" | ||
| 378 | #define PCM_34_CAPTURE_VOLUME "PCM 3/4 Capture Volume" | ||
| 379 | |||
| 380 | static const struct snd_akm4xxx_dac_channel qtet_dac[] = { | ||
| 381 | AK_CONTROL(PCM_12_PLAYBACK_VOLUME, 2), | ||
| 382 | AK_CONTROL(PCM_34_PLAYBACK_VOLUME, 2), | ||
| 383 | }; | ||
| 384 | |||
| 385 | static const struct snd_akm4xxx_adc_channel qtet_adc[] = { | ||
| 386 | AK_CONTROL(PCM_12_CAPTURE_VOLUME, 2), | ||
| 387 | AK_CONTROL(PCM_34_CAPTURE_VOLUME, 2), | ||
| 388 | }; | ||
| 389 | |||
| 390 | static struct snd_akm4xxx akm_qtet_dac __devinitdata = { | ||
| 391 | .type = SND_AK4620, | ||
| 392 | .num_dacs = 4, /* DAC1 - Output 12 | ||
| 393 | */ | ||
| 394 | .num_adcs = 4, /* ADC1 - Input 12 | ||
| 395 | */ | ||
| 396 | .ops = { | ||
| 397 | .write = qtet_akm_write, | ||
| 398 | .set_rate_val = qtet_akm_set_rate_val, | ||
| 399 | }, | ||
| 400 | .dac_info = qtet_dac, | ||
| 401 | .adc_info = qtet_adc, | ||
| 402 | }; | ||
| 403 | |||
| 404 | /* Communication routines with the CPLD */ | ||
| 405 | |||
| 406 | |||
| 407 | /* Writes data to external register reg, both reg and data are | ||
| 408 | * GPIO representations */ | ||
| 409 | static void reg_write(struct snd_ice1712 *ice, unsigned int reg, | ||
| 410 | unsigned int data) | ||
| 411 | { | ||
| 412 | unsigned int tmp; | ||
| 413 | |||
| 414 | mutex_lock(&ice->gpio_mutex); | ||
| 415 | /* set direction of used GPIOs*/ | ||
| 416 | /* all outputs */ | ||
| 417 | tmp = 0x00ffff; | ||
| 418 | ice->gpio.set_dir(ice, tmp); | ||
| 419 | /* mask - writable bits */ | ||
| 420 | ice->gpio.set_mask(ice, ~(tmp)); | ||
| 421 | /* write the data */ | ||
| 422 | tmp = ice->gpio.get_data(ice); | ||
| 423 | tmp &= ~GPIO_DATA_MASK; | ||
| 424 | tmp |= data; | ||
| 425 | ice->gpio.set_data(ice, tmp); | ||
| 426 | udelay(100); | ||
| 427 | /* drop output enable */ | ||
| 428 | tmp &= ~GPIO_EX_GPIOE; | ||
| 429 | ice->gpio.set_data(ice, tmp); | ||
| 430 | udelay(100); | ||
| 431 | /* drop the register gpio */ | ||
| 432 | tmp &= ~reg; | ||
| 433 | ice->gpio.set_data(ice, tmp); | ||
| 434 | udelay(100); | ||
| 435 | /* raise the register GPIO */ | ||
| 436 | tmp |= reg; | ||
| 437 | ice->gpio.set_data(ice, tmp); | ||
| 438 | udelay(100); | ||
| 439 | |||
| 440 | /* raise all data gpios */ | ||
| 441 | tmp |= GPIO_DATA_MASK; | ||
| 442 | ice->gpio.set_data(ice, tmp); | ||
| 443 | /* mask - immutable bits */ | ||
| 444 | ice->gpio.set_mask(ice, 0xffffff); | ||
| 445 | /* outputs only 8-15 */ | ||
| 446 | ice->gpio.set_dir(ice, 0x00ff00); | ||
| 447 | mutex_unlock(&ice->gpio_mutex); | ||
| 448 | } | ||
| 449 | |||
| 450 | static unsigned int get_scr(struct snd_ice1712 *ice) | ||
| 451 | { | ||
| 452 | struct qtet_spec *spec = ice->spec; | ||
| 453 | return spec->scr; | ||
| 454 | } | ||
| 455 | |||
| 456 | static unsigned int get_mcr(struct snd_ice1712 *ice) | ||
| 457 | { | ||
| 458 | struct qtet_spec *spec = ice->spec; | ||
| 459 | return spec->mcr; | ||
| 460 | } | ||
| 461 | |||
| 462 | static unsigned int get_cpld(struct snd_ice1712 *ice) | ||
| 463 | { | ||
| 464 | struct qtet_spec *spec = ice->spec; | ||
| 465 | return spec->cpld; | ||
| 466 | } | ||
| 467 | |||
| 468 | static void set_scr(struct snd_ice1712 *ice, unsigned int val) | ||
| 469 | { | ||
| 470 | struct qtet_spec *spec = ice->spec; | ||
| 471 | reg_write(ice, GPIO_SCR, val); | ||
| 472 | spec->scr = val; | ||
| 473 | } | ||
| 474 | |||
| 475 | static void set_mcr(struct snd_ice1712 *ice, unsigned int val) | ||
| 476 | { | ||
| 477 | struct qtet_spec *spec = ice->spec; | ||
| 478 | reg_write(ice, GPIO_MCR, val); | ||
| 479 | spec->mcr = val; | ||
| 480 | } | ||
| 481 | |||
| 482 | static void set_cpld(struct snd_ice1712 *ice, unsigned int val) | ||
| 483 | { | ||
| 484 | struct qtet_spec *spec = ice->spec; | ||
| 485 | reg_write(ice, GPIO_CPLD_CSN, val); | ||
| 486 | spec->cpld = val; | ||
| 487 | } | ||
| 488 | #ifdef CONFIG_PROC_FS | ||
| 489 | static void proc_regs_read(struct snd_info_entry *entry, | ||
| 490 | struct snd_info_buffer *buffer) | ||
| 491 | { | ||
| 492 | struct snd_ice1712 *ice = entry->private_data; | ||
| 493 | char bin_buffer[36]; | ||
| 494 | |||
| 495 | snd_iprintf(buffer, "SCR: %s\n", get_binary(bin_buffer, | ||
| 496 | get_scr(ice))); | ||
| 497 | snd_iprintf(buffer, "MCR: %s\n", get_binary(bin_buffer, | ||
| 498 | get_mcr(ice))); | ||
| 499 | snd_iprintf(buffer, "CPLD: %s\n", get_binary(bin_buffer, | ||
| 500 | get_cpld(ice))); | ||
| 501 | } | ||
| 502 | |||
| 503 | static void proc_init(struct snd_ice1712 *ice) | ||
| 504 | { | ||
| 505 | struct snd_info_entry *entry; | ||
| 506 | if (!snd_card_proc_new(ice->card, "quartet", &entry)) | ||
| 507 | snd_info_set_text_ops(entry, ice, proc_regs_read); | ||
| 508 | } | ||
| 509 | #else /* !CONFIG_PROC_FS */ | ||
| 510 | static void proc_init(struct snd_ice1712 *ice) {} | ||
| 511 | #endif | ||
| 512 | |||
| 513 | static int qtet_mute_get(struct snd_kcontrol *kcontrol, | ||
| 514 | struct snd_ctl_elem_value *ucontrol) | ||
| 515 | { | ||
| 516 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
| 517 | unsigned int val; | ||
| 518 | val = get_scr(ice) & SCR_MUTE; | ||
| 519 | ucontrol->value.integer.value[0] = (val) ? 0 : 1; | ||
| 520 | return 0; | ||
| 521 | } | ||
| 522 | |||
| 523 | static int qtet_mute_put(struct snd_kcontrol *kcontrol, | ||
| 524 | struct snd_ctl_elem_value *ucontrol) | ||
| 525 | { | ||
| 526 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
| 527 | unsigned int old, new, smute; | ||
| 528 | old = get_scr(ice) & SCR_MUTE; | ||
| 529 | if (ucontrol->value.integer.value[0]) { | ||
| 530 | /* unmute */ | ||
| 531 | new = 0; | ||
| 532 | /* un-smuting DAC */ | ||
| 533 | smute = 0; | ||
| 534 | } else { | ||
| 535 | /* mute */ | ||
| 536 | new = SCR_MUTE; | ||
| 537 | /* smuting DAC */ | ||
| 538 | smute = AK4620_SMUTE; | ||
| 539 | } | ||
| 540 | if (old != new) { | ||
| 541 | struct snd_akm4xxx *ak = ice->akm; | ||
| 542 | set_scr(ice, (get_scr(ice) & ~SCR_MUTE) | new); | ||
| 543 | /* set smute */ | ||
| 544 | qtet_akm_set_regs(ak, AK4620_DEEMVOL_REG, AK4620_SMUTE, smute); | ||
| 545 | return 1; | ||
| 546 | } | ||
| 547 | /* no change */ | ||
| 548 | return 0; | ||
| 549 | } | ||
| 550 | |||
| 551 | static int qtet_ain12_enum_info(struct snd_kcontrol *kcontrol, | ||
| 552 | struct snd_ctl_elem_info *uinfo) | ||
| 553 | { | ||
| 554 | static char *texts[3] = {"Line In 1/2", "Mic", "Mic + Low-cut"}; | ||
| 555 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
| 556 | uinfo->count = 1; | ||
| 557 | uinfo->value.enumerated.items = ARRAY_SIZE(texts); | ||
| 558 | |||
| 559 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
| 560 | uinfo->value.enumerated.item = | ||
| 561 | uinfo->value.enumerated.items - 1; | ||
| 562 | strcpy(uinfo->value.enumerated.name, | ||
| 563 | texts[uinfo->value.enumerated.item]); | ||
| 564 | |||
| 565 | return 0; | ||
| 566 | } | ||
| 567 | |||
| 568 | static int qtet_ain12_sw_get(struct snd_kcontrol *kcontrol, | ||
| 569 | struct snd_ctl_elem_value *ucontrol) | ||
| 570 | { | ||
| 571 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
| 572 | unsigned int val, result; | ||
| 573 | val = get_scr(ice) & (SCR_AIN12_SEL1 | SCR_AIN12_SEL0); | ||
| 574 | switch (val) { | ||
| 575 | case SCR_AIN12_LINE: | ||
| 576 | result = 0; | ||
| 577 | break; | ||
| 578 | case SCR_AIN12_MIC: | ||
| 579 | result = 1; | ||
| 580 | break; | ||
| 581 | case SCR_AIN12_LOWCUT: | ||
| 582 | result = 2; | ||
| 583 | break; | ||
| 584 | default: | ||
| 585 | /* BUG - no other combinations allowed */ | ||
| 586 | snd_BUG(); | ||
| 587 | result = 0; | ||
| 588 | } | ||
| 589 | ucontrol->value.integer.value[0] = result; | ||
| 590 | return 0; | ||
| 591 | } | ||
| 592 | |||
| 593 | static int qtet_ain12_sw_put(struct snd_kcontrol *kcontrol, | ||
| 594 | struct snd_ctl_elem_value *ucontrol) | ||
| 595 | { | ||
| 596 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
| 597 | unsigned int old, new, tmp, masked_old; | ||
| 598 | old = new = get_scr(ice); | ||
| 599 | masked_old = old & (SCR_AIN12_SEL1 | SCR_AIN12_SEL0); | ||
| 600 | tmp = ucontrol->value.integer.value[0]; | ||
| 601 | if (tmp == 2) | ||
| 602 | tmp = 3; /* binary 10 is not supported */ | ||
| 603 | tmp <<= 4; /* shifting to SCR_AIN12_SEL0 */ | ||
| 604 | if (tmp != masked_old) { | ||
| 605 | /* change requested */ | ||
| 606 | switch (tmp) { | ||
| 607 | case SCR_AIN12_LINE: | ||
| 608 | new = old & ~(SCR_AIN12_SEL1 | SCR_AIN12_SEL0); | ||
| 609 | set_scr(ice, new); | ||
| 610 | /* turn off relay */ | ||
| 611 | new &= ~SCR_RELAY; | ||
| 612 | set_scr(ice, new); | ||
| 613 | break; | ||
| 614 | case SCR_AIN12_MIC: | ||
| 615 | /* turn on relay */ | ||
| 616 | new = old | SCR_RELAY; | ||
| 617 | set_scr(ice, new); | ||
| 618 | new = (new & ~SCR_AIN12_SEL1) | SCR_AIN12_SEL0; | ||
| 619 | set_scr(ice, new); | ||
| 620 | break; | ||
| 621 | case SCR_AIN12_LOWCUT: | ||
| 622 | /* turn on relay */ | ||
| 623 | new = old | SCR_RELAY; | ||
| 624 | set_scr(ice, new); | ||
| 625 | new |= SCR_AIN12_SEL1 | SCR_AIN12_SEL0; | ||
| 626 | set_scr(ice, new); | ||
| 627 | break; | ||
| 628 | default: | ||
| 629 | snd_BUG(); | ||
| 630 | } | ||
| 631 | return 1; | ||
| 632 | } | ||
| 633 | /* no change */ | ||
| 634 | return 0; | ||
| 635 | } | ||
| 636 | |||
| 637 | static int qtet_php_get(struct snd_kcontrol *kcontrol, | ||
| 638 | struct snd_ctl_elem_value *ucontrol) | ||
| 639 | { | ||
| 640 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
| 641 | unsigned int val; | ||
| 642 | /* if phantom voltage =48V, phantom on */ | ||
| 643 | val = get_scr(ice) & SCR_PHP_V; | ||
| 644 | ucontrol->value.integer.value[0] = val ? 1 : 0; | ||
| 645 | return 0; | ||
| 646 | } | ||
| 647 | |||
| 648 | static int qtet_php_put(struct snd_kcontrol *kcontrol, | ||
| 649 | struct snd_ctl_elem_value *ucontrol) | ||
| 650 | { | ||
| 651 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
| 652 | unsigned int old, new; | ||
| 653 | old = new = get_scr(ice); | ||
| 654 | if (ucontrol->value.integer.value[0] /* phantom on requested */ | ||
| 655 | && (~old & SCR_PHP_V)) /* 0 = voltage 5V */ { | ||
| 656 | /* is off, turn on */ | ||
| 657 | /* turn voltage on first, = 1 */ | ||
| 658 | new = old | SCR_PHP_V; | ||
| 659 | set_scr(ice, new); | ||
| 660 | /* turn phantom on, = 0 */ | ||
| 661 | new &= ~SCR_PHP; | ||
| 662 | set_scr(ice, new); | ||
| 663 | } else if (!ucontrol->value.integer.value[0] && (old & SCR_PHP_V)) { | ||
| 664 | /* phantom off requested and 1 = voltage 48V */ | ||
| 665 | /* is on, turn off */ | ||
| 666 | /* turn voltage off first, = 0 */ | ||
| 667 | new = old & ~SCR_PHP_V; | ||
| 668 | set_scr(ice, new); | ||
| 669 | /* turn phantom off, = 1 */ | ||
| 670 | new |= SCR_PHP; | ||
| 671 | set_scr(ice, new); | ||
| 672 | } | ||
| 673 | if (old != new) | ||
| 674 | return 1; | ||
| 675 | /* no change */ | ||
| 676 | return 0; | ||
| 677 | } | ||
| 678 | |||
| 679 | #define PRIV_SW(xid, xbit, xreg) [xid] = {.bit = xbit,\ | ||
| 680 | .set_register = set_##xreg,\ | ||
| 681 | .get_register = get_##xreg, } | ||
| 682 | |||
| 683 | |||
| 684 | #define PRIV_ENUM2(xid, xbit, xreg, xtext1, xtext2) [xid] = {.bit = xbit,\ | ||
| 685 | .set_register = set_##xreg,\ | ||
| 686 | .get_register = get_##xreg,\ | ||
| 687 | .texts = {xtext1, xtext2} } | ||
| 688 | |||
| 689 | static struct qtet_kcontrol_private qtet_privates[] = { | ||
| 690 | PRIV_ENUM2(IN12_SEL, CPLD_IN12_SEL, cpld, "An In 1/2", "An In 3/4"), | ||
| 691 | PRIV_ENUM2(IN34_SEL, CPLD_IN34_SEL, cpld, "An In 3/4", "IEC958 In"), | ||
| 692 | PRIV_ENUM2(AIN34_SEL, SCR_AIN34_SEL, scr, "Line In 3/4", "Hi-Z"), | ||
| 693 | PRIV_ENUM2(COAX_OUT, CPLD_COAX_OUT, cpld, "IEC958", "I2S"), | ||
| 694 | PRIV_SW(IN12_MON12, MCR_IN12_MON12, mcr), | ||
| 695 | PRIV_SW(IN12_MON34, MCR_IN12_MON34, mcr), | ||
| 696 | PRIV_SW(IN34_MON12, MCR_IN34_MON12, mcr), | ||
| 697 | PRIV_SW(IN34_MON34, MCR_IN34_MON34, mcr), | ||
| 698 | PRIV_SW(OUT12_MON34, MCR_OUT12_MON34, mcr), | ||
| 699 | PRIV_SW(OUT34_MON12, MCR_OUT34_MON12, mcr), | ||
| 700 | }; | ||
| 701 | |||
| 702 | static int qtet_enum_info(struct snd_kcontrol *kcontrol, | ||
| 703 | struct snd_ctl_elem_info *uinfo) | ||
| 704 | { | ||
| 705 | struct qtet_kcontrol_private private = | ||
| 706 | qtet_privates[kcontrol->private_value]; | ||
| 707 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
| 708 | uinfo->count = 1; | ||
| 709 | uinfo->value.enumerated.items = ARRAY_SIZE(private.texts); | ||
| 710 | |||
| 711 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
| 712 | uinfo->value.enumerated.item = | ||
| 713 | uinfo->value.enumerated.items - 1; | ||
| 714 | strcpy(uinfo->value.enumerated.name, | ||
| 715 | private.texts[uinfo->value.enumerated.item]); | ||
| 716 | |||
| 717 | return 0; | ||
| 718 | } | ||
| 719 | |||
| 720 | static int qtet_sw_get(struct snd_kcontrol *kcontrol, | ||
| 721 | struct snd_ctl_elem_value *ucontrol) | ||
| 722 | { | ||
| 723 | struct qtet_kcontrol_private private = | ||
| 724 | qtet_privates[kcontrol->private_value]; | ||
| 725 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
| 726 | ucontrol->value.integer.value[0] = | ||
| 727 | (private.get_register(ice) & private.bit) ? 1 : 0; | ||
| 728 | return 0; | ||
| 729 | } | ||
| 730 | |||
| 731 | static int qtet_sw_put(struct snd_kcontrol *kcontrol, | ||
| 732 | struct snd_ctl_elem_value *ucontrol) | ||
| 733 | { | ||
| 734 | struct qtet_kcontrol_private private = | ||
| 735 | qtet_privates[kcontrol->private_value]; | ||
| 736 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
| 737 | unsigned int old, new; | ||
| 738 | old = private.get_register(ice); | ||
| 739 | if (ucontrol->value.integer.value[0]) | ||
| 740 | new = old | private.bit; | ||
| 741 | else | ||
| 742 | new = old & ~private.bit; | ||
| 743 | if (old != new) { | ||
| 744 | private.set_register(ice, new); | ||
| 745 | return 1; | ||
| 746 | } | ||
| 747 | /* no change */ | ||
| 748 | return 0; | ||
| 749 | } | ||
| 750 | |||
| 751 | #define qtet_sw_info snd_ctl_boolean_mono_info | ||
| 752 | |||
| 753 | #define QTET_CONTROL(xname, xtype, xpriv) \ | ||
| 754 | {.iface = SNDRV_CTL_ELEM_IFACE_MIXER,\ | ||
| 755 | .name = xname,\ | ||
| 756 | .info = qtet_##xtype##_info,\ | ||
| 757 | .get = qtet_sw_get,\ | ||
| 758 | .put = qtet_sw_put,\ | ||
| 759 | .private_value = xpriv } | ||
| 760 | |||
| 761 | static struct snd_kcontrol_new qtet_controls[] __devinitdata = { | ||
| 762 | { | ||
| 763 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 764 | .name = "Master Playback Switch", | ||
| 765 | .info = qtet_sw_info, | ||
| 766 | .get = qtet_mute_get, | ||
| 767 | .put = qtet_mute_put, | ||
| 768 | .private_value = 0 | ||
| 769 | }, | ||
| 770 | { | ||
| 771 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 772 | .name = "Phantom Power", | ||
| 773 | .info = qtet_sw_info, | ||
| 774 | .get = qtet_php_get, | ||
| 775 | .put = qtet_php_put, | ||
| 776 | .private_value = 0 | ||
| 777 | }, | ||
| 778 | { | ||
| 779 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 780 | .name = "Analog In 1/2 Capture Switch", | ||
| 781 | .info = qtet_ain12_enum_info, | ||
| 782 | .get = qtet_ain12_sw_get, | ||
| 783 | .put = qtet_ain12_sw_put, | ||
| 784 | .private_value = 0 | ||
| 785 | }, | ||
| 786 | QTET_CONTROL("Analog In 3/4 Capture Switch", enum, AIN34_SEL), | ||
| 787 | QTET_CONTROL("PCM In 1/2 Capture Switch", enum, IN12_SEL), | ||
| 788 | QTET_CONTROL("PCM In 3/4 Capture Switch", enum, IN34_SEL), | ||
| 789 | QTET_CONTROL("Coax Output Source", enum, COAX_OUT), | ||
| 790 | QTET_CONTROL("Analog In 1/2 to Monitor 1/2", sw, IN12_MON12), | ||
| 791 | QTET_CONTROL("Analog In 1/2 to Monitor 3/4", sw, IN12_MON34), | ||
| 792 | QTET_CONTROL("Analog In 3/4 to Monitor 1/2", sw, IN34_MON12), | ||
| 793 | QTET_CONTROL("Analog In 3/4 to Monitor 3/4", sw, IN34_MON34), | ||
| 794 | QTET_CONTROL("Output 1/2 to Monitor 3/4", sw, OUT12_MON34), | ||
| 795 | QTET_CONTROL("Output 3/4 to Monitor 1/2", sw, OUT34_MON12), | ||
| 796 | }; | ||
| 797 | |||
| 798 | static char *slave_vols[] __devinitdata = { | ||
| 799 | PCM_12_PLAYBACK_VOLUME, | ||
| 800 | PCM_34_PLAYBACK_VOLUME, | ||
| 801 | NULL | ||
| 802 | }; | ||
| 803 | |||
| 804 | static __devinitdata | ||
| 805 | DECLARE_TLV_DB_SCALE(qtet_master_db_scale, -6350, 50, 1); | ||
| 806 | |||
| 807 | static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, | ||
| 808 | const char *name) | ||
| 809 | { | ||
| 810 | struct snd_ctl_elem_id sid; | ||
| 811 | memset(&sid, 0, sizeof(sid)); | ||
| 812 | /* FIXME: strcpy is bad. */ | ||
| 813 | strcpy(sid.name, name); | ||
| 814 | sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
| 815 | return snd_ctl_find_id(card, &sid); | ||
| 816 | } | ||
| 817 | |||
| 818 | static void __devinit add_slaves(struct snd_card *card, | ||
| 819 | struct snd_kcontrol *master, char **list) | ||
| 820 | { | ||
| 821 | for (; *list; list++) { | ||
| 822 | struct snd_kcontrol *slave = ctl_find(card, *list); | ||
| 823 | if (slave) | ||
| 824 | snd_ctl_add_slave(master, slave); | ||
| 825 | } | ||
| 826 | } | ||
| 827 | |||
| 828 | static int __devinit qtet_add_controls(struct snd_ice1712 *ice) | ||
| 829 | { | ||
| 830 | struct qtet_spec *spec = ice->spec; | ||
| 831 | int err, i; | ||
| 832 | struct snd_kcontrol *vmaster; | ||
| 833 | err = snd_ice1712_akm4xxx_build_controls(ice); | ||
| 834 | if (err < 0) | ||
| 835 | return err; | ||
| 836 | for (i = 0; i < ARRAY_SIZE(qtet_controls); i++) { | ||
| 837 | err = snd_ctl_add(ice->card, | ||
| 838 | snd_ctl_new1(&qtet_controls[i], ice)); | ||
| 839 | if (err < 0) | ||
| 840 | return err; | ||
| 841 | } | ||
| 842 | |||
| 843 | /* Create virtual master control */ | ||
| 844 | vmaster = snd_ctl_make_virtual_master("Master Playback Volume", | ||
| 845 | qtet_master_db_scale); | ||
| 846 | if (!vmaster) | ||
| 847 | return -ENOMEM; | ||
| 848 | add_slaves(ice->card, vmaster, slave_vols); | ||
| 849 | err = snd_ctl_add(ice->card, vmaster); | ||
| 850 | if (err < 0) | ||
| 851 | return err; | ||
| 852 | /* only capture SPDIF over AK4113 */ | ||
| 853 | err = snd_ak4113_build(spec->ak4113, | ||
| 854 | ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); | ||
| 855 | if (err < 0) | ||
| 856 | return err; | ||
| 857 | return 0; | ||
| 858 | } | ||
| 859 | |||
| 860 | static inline int qtet_is_spdif_master(struct snd_ice1712 *ice) | ||
| 861 | { | ||
| 862 | /* CPLD_SYNC_SEL: 0 = internal, 1 = external (i.e. spdif master) */ | ||
| 863 | return (get_cpld(ice) & CPLD_SYNC_SEL) ? 1 : 0; | ||
| 864 | } | ||
| 865 | |||
| 866 | static unsigned int qtet_get_rate(struct snd_ice1712 *ice) | ||
| 867 | { | ||
| 868 | int i; | ||
| 869 | unsigned char result; | ||
| 870 | |||
| 871 | result = get_cpld(ice) & CPLD_CKS_MASK; | ||
| 872 | for (i = 0; i < ARRAY_SIZE(cks_vals); i++) | ||
| 873 | if (cks_vals[i] == result) | ||
| 874 | return qtet_rates[i]; | ||
| 875 | return 0; | ||
| 876 | } | ||
| 877 | |||
| 878 | static int get_cks_val(int rate) | ||
| 879 | { | ||
| 880 | int i; | ||
| 881 | for (i = 0; i < ARRAY_SIZE(qtet_rates); i++) | ||
| 882 | if (qtet_rates[i] == rate) | ||
| 883 | return cks_vals[i]; | ||
| 884 | return 0; | ||
| 885 | } | ||
| 886 | |||
| 887 | /* setting new rate */ | ||
| 888 | static void qtet_set_rate(struct snd_ice1712 *ice, unsigned int rate) | ||
| 889 | { | ||
| 890 | unsigned int new; | ||
| 891 | unsigned char val; | ||
| 892 | /* switching ice1724 to external clock - supplied by ext. circuits */ | ||
| 893 | val = inb(ICEMT1724(ice, RATE)); | ||
| 894 | outb(val | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE)); | ||
| 895 | |||
| 896 | new = (get_cpld(ice) & ~CPLD_CKS_MASK) | get_cks_val(rate); | ||
| 897 | /* switch to internal clock, drop CPLD_SYNC_SEL */ | ||
| 898 | new &= ~CPLD_SYNC_SEL; | ||
| 899 | /* printk(KERN_DEBUG "QT - set_rate: old %x, new %x\n", | ||
| 900 | get_cpld(ice), new); */ | ||
| 901 | set_cpld(ice, new); | ||
| 902 | } | ||
| 903 | |||
| 904 | static inline unsigned char qtet_set_mclk(struct snd_ice1712 *ice, | ||
| 905 | unsigned int rate) | ||
| 906 | { | ||
| 907 | /* no change in master clock */ | ||
| 908 | return 0; | ||
| 909 | } | ||
| 910 | |||
| 911 | /* setting clock to external - SPDIF */ | ||
| 912 | static int qtet_set_spdif_clock(struct snd_ice1712 *ice, int type) | ||
| 913 | { | ||
| 914 | unsigned int old, new; | ||
| 915 | |||
| 916 | old = new = get_cpld(ice); | ||
| 917 | new &= ~(CPLD_CKS_MASK | CPLD_WORD_SEL); | ||
| 918 | switch (type) { | ||
| 919 | case EXT_SPDIF_TYPE: | ||
| 920 | new |= CPLD_EXT_SPDIF; | ||
| 921 | break; | ||
| 922 | case EXT_WORDCLOCK_1FS_TYPE: | ||
| 923 | new |= CPLD_EXT_WORDCLOCK_1FS; | ||
| 924 | break; | ||
| 925 | case EXT_WORDCLOCK_256FS_TYPE: | ||
| 926 | new |= CPLD_EXT_WORDCLOCK_256FS; | ||
| 927 | break; | ||
| 928 | default: | ||
| 929 | snd_BUG(); | ||
| 930 | } | ||
| 931 | if (old != new) { | ||
| 932 | set_cpld(ice, new); | ||
| 933 | /* changed */ | ||
| 934 | return 1; | ||
| 935 | } | ||
| 936 | return 0; | ||
| 937 | } | ||
| 938 | |||
| 939 | static int qtet_get_spdif_master_type(struct snd_ice1712 *ice) | ||
| 940 | { | ||
| 941 | unsigned int val; | ||
| 942 | int result; | ||
| 943 | val = get_cpld(ice); | ||
| 944 | /* checking only rate/clock-related bits */ | ||
| 945 | val &= (CPLD_CKS_MASK | CPLD_WORD_SEL | CPLD_SYNC_SEL); | ||
| 946 | if (!(val & CPLD_SYNC_SEL)) { | ||
| 947 | /* switched to internal clock, is not any external type */ | ||
| 948 | result = -1; | ||
| 949 | } else { | ||
| 950 | switch (val) { | ||
| 951 | case (CPLD_EXT_SPDIF): | ||
| 952 | result = EXT_SPDIF_TYPE; | ||
| 953 | break; | ||
| 954 | case (CPLD_EXT_WORDCLOCK_1FS): | ||
| 955 | result = EXT_WORDCLOCK_1FS_TYPE; | ||
| 956 | break; | ||
| 957 | case (CPLD_EXT_WORDCLOCK_256FS): | ||
| 958 | result = EXT_WORDCLOCK_256FS_TYPE; | ||
| 959 | break; | ||
| 960 | default: | ||
| 961 | /* undefined combination of external clock setup */ | ||
| 962 | snd_BUG(); | ||
| 963 | result = 0; | ||
| 964 | } | ||
| 965 | } | ||
| 966 | return result; | ||
| 967 | } | ||
| 968 | |||
| 969 | /* Called when ak4113 detects change in the input SPDIF stream */ | ||
| 970 | static void qtet_ak4113_change(struct ak4113 *ak4113, unsigned char c0, | ||
| 971 | unsigned char c1) | ||
| 972 | { | ||
| 973 | struct snd_ice1712 *ice = ak4113->change_callback_private; | ||
| 974 | int rate; | ||
| 975 | if ((qtet_get_spdif_master_type(ice) == EXT_SPDIF_TYPE) && | ||
| 976 | c1) { | ||
| 977 | /* only for SPDIF master mode, rate was changed */ | ||
| 978 | rate = snd_ak4113_external_rate(ak4113); | ||
| 979 | /* printk(KERN_DEBUG "ak4113 - input rate changed to %d\n", | ||
| 980 | rate); */ | ||
| 981 | qtet_akm_set_rate_val(ice->akm, rate); | ||
| 982 | } | ||
| 983 | } | ||
| 984 | |||
| 985 | /* | ||
| 986 | * If clock slaved to SPDIF-IN, setting runtime rate | ||
| 987 | * to the detected external rate | ||
| 988 | */ | ||
| 989 | static void qtet_spdif_in_open(struct snd_ice1712 *ice, | ||
| 990 | struct snd_pcm_substream *substream) | ||
| 991 | { | ||
| 992 | struct qtet_spec *spec = ice->spec; | ||
| 993 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
| 994 | int rate; | ||
| 995 | |||
| 996 | if (qtet_get_spdif_master_type(ice) != EXT_SPDIF_TYPE) | ||
| 997 | /* not external SPDIF, no rate limitation */ | ||
| 998 | return; | ||
| 999 | /* only external SPDIF can detect incoming sample rate */ | ||
| 1000 | rate = snd_ak4113_external_rate(spec->ak4113); | ||
| 1001 | if (rate >= runtime->hw.rate_min && rate <= runtime->hw.rate_max) { | ||
| 1002 | runtime->hw.rate_min = rate; | ||
| 1003 | runtime->hw.rate_max = rate; | ||
| 1004 | } | ||
| 1005 | } | ||
| 1006 | |||
| 1007 | /* | ||
| 1008 | * initialize the chip | ||
| 1009 | */ | ||
| 1010 | static int __devinit qtet_init(struct snd_ice1712 *ice) | ||
| 1011 | { | ||
| 1012 | static const unsigned char ak4113_init_vals[] = { | ||
| 1013 | /* AK4113_REG_PWRDN */ AK4113_RST | AK4113_PWN | | ||
| 1014 | AK4113_OCKS0 | AK4113_OCKS1, | ||
| 1015 | /* AK4113_REQ_FORMAT */ AK4113_DIF_I24I2S | AK4113_VTX | | ||
| 1016 | AK4113_DEM_OFF | AK4113_DEAU, | ||
| 1017 | /* AK4113_REG_IO0 */ AK4113_OPS2 | AK4113_TXE | | ||
| 1018 | AK4113_XTL_24_576M, | ||
| 1019 | /* AK4113_REG_IO1 */ AK4113_EFH_1024LRCLK | AK4113_IPS(0), | ||
| 1020 | /* AK4113_REG_INT0_MASK */ 0, | ||
| 1021 | /* AK4113_REG_INT1_MASK */ 0, | ||
| 1022 | /* AK4113_REG_DATDTS */ 0, | ||
| 1023 | }; | ||
| 1024 | int err; | ||
| 1025 | struct qtet_spec *spec; | ||
| 1026 | struct snd_akm4xxx *ak; | ||
| 1027 | unsigned char val; | ||
| 1028 | |||
| 1029 | /* switching ice1724 to external clock - supplied by ext. circuits */ | ||
| 1030 | val = inb(ICEMT1724(ice, RATE)); | ||
| 1031 | outb(val | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE)); | ||
| 1032 | |||
| 1033 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
| 1034 | if (!spec) | ||
| 1035 | return -ENOMEM; | ||
| 1036 | /* qtet is clocked by Xilinx array */ | ||
| 1037 | ice->hw_rates = &qtet_rates_info; | ||
| 1038 | ice->is_spdif_master = qtet_is_spdif_master; | ||
| 1039 | ice->get_rate = qtet_get_rate; | ||
| 1040 | ice->set_rate = qtet_set_rate; | ||
| 1041 | ice->set_mclk = qtet_set_mclk; | ||
| 1042 | ice->set_spdif_clock = qtet_set_spdif_clock; | ||
| 1043 | ice->get_spdif_master_type = qtet_get_spdif_master_type; | ||
| 1044 | ice->ext_clock_names = ext_clock_names; | ||
| 1045 | ice->ext_clock_count = ARRAY_SIZE(ext_clock_names); | ||
| 1046 | /* since Qtet can detect correct SPDIF-in rate, all streams can be | ||
| 1047 | * limited to this specific rate */ | ||
| 1048 | ice->spdif.ops.open = ice->pro_open = qtet_spdif_in_open; | ||
| 1049 | ice->spec = spec; | ||
| 1050 | |||
| 1051 | /* Mute Off */ | ||
| 1052 | /* SCR Initialize*/ | ||
| 1053 | /* keep codec power down first */ | ||
| 1054 | set_scr(ice, SCR_PHP); | ||
| 1055 | udelay(1); | ||
| 1056 | /* codec power up */ | ||
| 1057 | set_scr(ice, SCR_PHP | SCR_CODEC_PDN); | ||
| 1058 | |||
| 1059 | /* MCR Initialize */ | ||
| 1060 | set_mcr(ice, 0); | ||
| 1061 | |||
| 1062 | /* CPLD Initialize */ | ||
| 1063 | set_cpld(ice, 0); | ||
| 1064 | |||
| 1065 | |||
| 1066 | ice->num_total_dacs = 2; | ||
| 1067 | ice->num_total_adcs = 2; | ||
| 1068 | |||
| 1069 | ice->akm = kcalloc(2, sizeof(struct snd_akm4xxx), GFP_KERNEL); | ||
| 1070 | ak = ice->akm; | ||
| 1071 | if (!ak) | ||
| 1072 | return -ENOMEM; | ||
| 1073 | /* only one codec with two chips */ | ||
| 1074 | ice->akm_codecs = 1; | ||
| 1075 | err = snd_ice1712_akm4xxx_init(ak, &akm_qtet_dac, NULL, ice); | ||
| 1076 | if (err < 0) | ||
| 1077 | return err; | ||
| 1078 | err = snd_ak4113_create(ice->card, | ||
| 1079 | qtet_ak4113_read, | ||
| 1080 | qtet_ak4113_write, | ||
| 1081 | ak4113_init_vals, | ||
| 1082 | ice, &spec->ak4113); | ||
| 1083 | if (err < 0) | ||
| 1084 | return err; | ||
| 1085 | /* callback for codecs rate setting */ | ||
| 1086 | spec->ak4113->change_callback = qtet_ak4113_change; | ||
| 1087 | spec->ak4113->change_callback_private = ice; | ||
| 1088 | /* AK41143 in Quartet can detect external rate correctly | ||
| 1089 | * (i.e. check_flags = 0) */ | ||
| 1090 | spec->ak4113->check_flags = 0; | ||
| 1091 | |||
| 1092 | proc_init(ice); | ||
| 1093 | |||
| 1094 | qtet_set_rate(ice, 44100); | ||
| 1095 | return 0; | ||
| 1096 | } | ||
| 1097 | |||
| 1098 | static unsigned char qtet_eeprom[] __devinitdata = { | ||
| 1099 | [ICE_EEP2_SYSCONF] = 0x28, /* clock 256(24MHz), mpu401, 1xADC, | ||
| 1100 | 1xDACs, SPDIF in */ | ||
| 1101 | [ICE_EEP2_ACLINK] = 0x80, /* I2S */ | ||
| 1102 | [ICE_EEP2_I2S] = 0x78, /* 96k, 24bit, 192k */ | ||
| 1103 | [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, in, out-ext */ | ||
| 1104 | [ICE_EEP2_GPIO_DIR] = 0x00, /* 0-7 inputs, switched to output | ||
| 1105 | only during output operations */ | ||
| 1106 | [ICE_EEP2_GPIO_DIR1] = 0xff, /* 8-15 outputs */ | ||
| 1107 | [ICE_EEP2_GPIO_DIR2] = 0x00, | ||
| 1108 | [ICE_EEP2_GPIO_MASK] = 0xff, /* changed only for OUT operations */ | ||
| 1109 | [ICE_EEP2_GPIO_MASK1] = 0x00, | ||
| 1110 | [ICE_EEP2_GPIO_MASK2] = 0xff, | ||
| 1111 | |||
| 1112 | [ICE_EEP2_GPIO_STATE] = 0x00, /* inputs */ | ||
| 1113 | [ICE_EEP2_GPIO_STATE1] = 0x7d, /* all 1, but GPIO_CPLD_RW | ||
| 1114 | and GPIO15 always zero */ | ||
| 1115 | [ICE_EEP2_GPIO_STATE2] = 0x00, /* inputs */ | ||
| 1116 | }; | ||
| 1117 | |||
| 1118 | /* entry point */ | ||
| 1119 | struct snd_ice1712_card_info snd_vt1724_qtet_cards[] __devinitdata = { | ||
| 1120 | { | ||
| 1121 | .subvendor = VT1724_SUBDEVICE_QTET, | ||
| 1122 | .name = "Infrasonic Quartet", | ||
| 1123 | .model = "quartet", | ||
| 1124 | .chip_init = qtet_init, | ||
| 1125 | .build_controls = qtet_add_controls, | ||
| 1126 | .eeprom_size = sizeof(qtet_eeprom), | ||
| 1127 | .eeprom_data = qtet_eeprom, | ||
| 1128 | }, | ||
| 1129 | { } /* terminator */ | ||
| 1130 | }; | ||
diff --git a/sound/pci/ice1712/quartet.h b/sound/pci/ice1712/quartet.h new file mode 100644 index 000000000000..80809b72439a --- /dev/null +++ b/sound/pci/ice1712/quartet.h | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | #ifndef __SOUND_QTET_H | ||
| 2 | #define __SOUND_QTET_H | ||
| 3 | |||
| 4 | #define QTET_DEVICE_DESC "{Infrasonic,Quartet}," | ||
| 5 | |||
| 6 | #define VT1724_SUBDEVICE_QTET 0x30305349 /* Infrasonic Quartet */ | ||
| 7 | |||
| 8 | extern struct snd_ice1712_card_info snd_vt1724_qtet_cards[]; | ||
| 9 | |||
| 10 | #endif /* __SOUND_QTET_H */ | ||
