diff options
| author | Pavel Hofman <pavel.hofman@ivitera.com> | 2009-09-16 16:25:37 -0400 |
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2009-09-21 09:45:07 -0400 |
| commit | 42cfa276aebd28e5cc4350ff6c7d75f1cb84dd98 (patch) | |
| tree | 5456711f5170f5b1fec06aef201d01a24ed8777a | |
| parent | 8f34692f63d66805b51ff408f4067748d3c1c3fd (diff) | |
ALSA: ak4113 support
* complete support for ak4113
* based on code for ak4114 and ak4117
Signed-off-by: Pavel Hofman <pavel.hofman@ivitera.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
| -rw-r--r-- | include/sound/ak4113.h | 321 | ||||
| -rw-r--r-- | sound/i2c/other/Makefile | 3 | ||||
| -rw-r--r-- | sound/i2c/other/ak4113.c | 639 |
3 files changed, 962 insertions, 1 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/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 | } | ||
