1 // SPDX-License-Identifier: GPL-2.0-or-later 1 2 /* 3 * ALSA driver for ICEnsemble ICE1712 (Envy2 4 * 5 * Lowlevel functions for M-Audio Audiophile 6 * 7 * Copyright (c) 2003 Takashi Iwai <tiwai 8 */ 9 10 #include <linux/delay.h> 11 #include <linux/interrupt.h> 12 #include <linux/init.h> 13 #include <linux/slab.h> 14 #include <sound/core.h> 15 16 #include "ice1712.h" 17 #include "envy24ht.h" 18 #include "revo.h" 19 20 /* a non-standard I2C device for revo51 */ 21 struct revo51_spec { 22 struct snd_i2c_device *dev; 23 struct snd_pt2258 *pt2258; 24 struct ak4114 *ak4114; 25 }; 26 27 static void revo_i2s_mclk_changed(struct snd_i 28 { 29 /* assert PRST# to converters; MT05 bi 30 outb(inb(ICEMT1724(ice, AC97_CMD)) | 0 31 mdelay(5); 32 /* deassert PRST# */ 33 outb(inb(ICEMT1724(ice, AC97_CMD)) & ~ 34 } 35 36 /* 37 * change the rate of Envy24HT, AK4355 and AK4 38 */ 39 static void revo_set_rate_val(struct snd_akm4x 40 { 41 unsigned char old, tmp, dfs; 42 int reg, shift; 43 44 if (rate == 0) /* no hint - S/PDIF in 45 return; 46 47 /* adjust DFS on codecs */ 48 if (rate > 96000) 49 dfs = 2; 50 else if (rate > 48000) 51 dfs = 1; 52 else 53 dfs = 0; 54 55 if (ak->type == SND_AK4355 || ak->type 56 reg = 2; 57 shift = 4; 58 } else { 59 reg = 1; 60 shift = 3; 61 } 62 tmp = snd_akm4xxx_get(ak, 0, reg); 63 old = (tmp >> shift) & 0x03; 64 if (old == dfs) 65 return; 66 67 /* reset DFS */ 68 snd_akm4xxx_reset(ak, 1); 69 tmp = snd_akm4xxx_get(ak, 0, reg); 70 tmp &= ~(0x03 << shift); 71 tmp |= dfs << shift; 72 /* snd_akm4xxx_write(ak, 0, reg, tmp); 73 snd_akm4xxx_set(ak, 0, reg, tmp); /* v 74 snd_akm4xxx_reset(ak, 0); 75 } 76 77 /* 78 * I2C access to the PT2258 volume controller 79 */ 80 81 static void revo_i2c_start(struct snd_i2c_bus 82 { 83 struct snd_ice1712 *ice = bus->private 84 snd_ice1712_save_gpio_status(ice); 85 } 86 87 static void revo_i2c_stop(struct snd_i2c_bus * 88 { 89 struct snd_ice1712 *ice = bus->private 90 snd_ice1712_restore_gpio_status(ice); 91 } 92 93 static void revo_i2c_direction(struct snd_i2c_ 94 { 95 struct snd_ice1712 *ice = bus->private 96 unsigned int mask, val; 97 98 val = 0; 99 if (clock) 100 val |= VT1724_REVO_I2C_CLOCK; 101 if (data) 102 val |= VT1724_REVO_I2C_DATA; 103 mask = VT1724_REVO_I2C_CLOCK | VT1724_ 104 ice->gpio.direction &= ~mask; 105 ice->gpio.direction |= val; 106 snd_ice1712_gpio_set_dir(ice, ice->gpi 107 snd_ice1712_gpio_set_mask(ice, ~mask); 108 } 109 110 static void revo_i2c_setlines(struct snd_i2c_b 111 { 112 struct snd_ice1712 *ice = bus->private 113 unsigned int val = 0; 114 115 if (clk) 116 val |= VT1724_REVO_I2C_CLOCK; 117 if (data) 118 val |= VT1724_REVO_I2C_DATA; 119 snd_ice1712_gpio_write_bits(ice, 120 VT1724_REV 121 VT1724_REV 122 udelay(5); 123 } 124 125 static int revo_i2c_getdata(struct snd_i2c_bus 126 { 127 struct snd_ice1712 *ice = bus->private 128 int bit; 129 130 if (ack) 131 udelay(5); 132 bit = snd_ice1712_gpio_read_bits(ice, 133 return bit; 134 } 135 136 static struct snd_i2c_bit_ops revo51_bit_ops = 137 .start = revo_i2c_start, 138 .stop = revo_i2c_stop, 139 .direction = revo_i2c_direction, 140 .setlines = revo_i2c_setlines, 141 .getdata = revo_i2c_getdata, 142 }; 143 144 static int revo51_i2c_init(struct snd_ice1712 145 struct snd_pt2258 * 146 { 147 struct revo51_spec *spec; 148 int err; 149 150 spec = kzalloc(sizeof(*spec), GFP_KERN 151 if (!spec) 152 return -ENOMEM; 153 ice->spec = spec; 154 155 /* create the I2C bus */ 156 err = snd_i2c_bus_create(ice->card, "I 157 if (err < 0) 158 return err; 159 160 ice->i2c->private_data = ice; 161 ice->i2c->hw_ops.bit = &revo51_bit_ops 162 163 /* create the I2C device */ 164 err = snd_i2c_device_create(ice->i2c, 165 if (err < 0) 166 return err; 167 168 pt->card = ice->card; 169 pt->i2c_bus = ice->i2c; 170 pt->i2c_dev = spec->dev; 171 spec->pt2258 = pt; 172 173 snd_pt2258_reset(pt); 174 175 return 0; 176 } 177 178 /* 179 * initialize the chips on M-Audio Revolution 180 */ 181 182 #define AK_DAC(xname,xch) { .name = xname, .nu 183 184 static const struct snd_akm4xxx_dac_channel re 185 { 186 .name = "PCM Playback Volume", 187 .num_channels = 2, 188 /* front channels DAC supports 189 .switch_name = "PCM Playback S 190 }, 191 }; 192 193 static const struct snd_akm4xxx_dac_channel re 194 AK_DAC("PCM Center Playback Volume", 1 195 AK_DAC("PCM LFE Playback Volume", 1), 196 AK_DAC("PCM Side Playback Volume", 2), 197 AK_DAC("PCM Rear Playback Volume", 2), 198 }; 199 200 static const struct snd_akm4xxx_dac_channel re 201 AK_DAC("PCM Playback Volume", 2), 202 AK_DAC("PCM Center Playback Volume", 1 203 AK_DAC("PCM LFE Playback Volume", 1), 204 AK_DAC("PCM Rear Playback Volume", 2), 205 AK_DAC("PCM Headphone Volume", 2), 206 }; 207 208 static const char *revo51_adc_input_names[] = 209 "Mic", 210 "Line", 211 "CD", 212 NULL 213 }; 214 215 static const struct snd_akm4xxx_adc_channel re 216 { 217 .name = "PCM Capture Volume", 218 .switch_name = "PCM Capture Sw 219 .num_channels = 2, 220 .input_names = revo51_adc_inpu 221 }, 222 }; 223 224 static const struct snd_akm4xxx akm_revo_front 225 .type = SND_AK4381, 226 .num_dacs = 2, 227 .ops = { 228 .set_rate_val = revo_set_rate_ 229 }, 230 .dac_info = revo71_front, 231 }; 232 233 static const struct snd_ak4xxx_private akm_rev 234 .caddr = 1, 235 .cif = 0, 236 .data_mask = VT1724_REVO_CDOUT, 237 .clk_mask = VT1724_REVO_CCLK, 238 .cs_mask = VT1724_REVO_CS0 | VT1724_RE 239 .cs_addr = VT1724_REVO_CS0 | VT1724_RE 240 .cs_none = VT1724_REVO_CS0 | VT1724_RE 241 .add_flags = VT1724_REVO_CCLK, /* high 242 .mask_flags = 0, 243 }; 244 245 static const struct snd_akm4xxx akm_revo_surro 246 .type = SND_AK4355, 247 .idx_offset = 1, 248 .num_dacs = 6, 249 .ops = { 250 .set_rate_val = revo_set_rate_ 251 }, 252 .dac_info = revo71_surround, 253 }; 254 255 static const struct snd_ak4xxx_private akm_rev 256 .caddr = 3, 257 .cif = 0, 258 .data_mask = VT1724_REVO_CDOUT, 259 .clk_mask = VT1724_REVO_CCLK, 260 .cs_mask = VT1724_REVO_CS0 | VT1724_RE 261 .cs_addr = VT1724_REVO_CS0 | VT1724_RE 262 .cs_none = VT1724_REVO_CS0 | VT1724_RE 263 .add_flags = VT1724_REVO_CCLK, /* high 264 .mask_flags = 0, 265 }; 266 267 static const struct snd_akm4xxx akm_revo51 = { 268 .type = SND_AK4358, 269 .num_dacs = 8, 270 .ops = { 271 .set_rate_val = revo_set_rate_ 272 }, 273 .dac_info = revo51_dac, 274 }; 275 276 static const struct snd_ak4xxx_private akm_rev 277 .caddr = 2, 278 .cif = 0, 279 .data_mask = VT1724_REVO_CDOUT, 280 .clk_mask = VT1724_REVO_CCLK, 281 .cs_mask = VT1724_REVO_CS0 | VT1724_RE 282 .cs_addr = VT1724_REVO_CS1, 283 .cs_none = VT1724_REVO_CS0 | VT1724_RE 284 .add_flags = VT1724_REVO_CCLK, /* high 285 .mask_flags = 0, 286 }; 287 288 static const struct snd_akm4xxx akm_revo51_adc 289 .type = SND_AK5365, 290 .num_adcs = 2, 291 .adc_info = revo51_adc, 292 }; 293 294 static const struct snd_ak4xxx_private akm_rev 295 .caddr = 2, 296 .cif = 0, 297 .data_mask = VT1724_REVO_CDOUT, 298 .clk_mask = VT1724_REVO_CCLK, 299 .cs_mask = VT1724_REVO_CS0 | VT1724_RE 300 .cs_addr = VT1724_REVO_CS0, 301 .cs_none = VT1724_REVO_CS0 | VT1724_RE 302 .add_flags = VT1724_REVO_CCLK, /* high 303 .mask_flags = 0, 304 }; 305 306 static struct snd_pt2258 ptc_revo51_volume; 307 308 /* AK4358 for AP192 DAC, AK5385A for ADC */ 309 static void ap192_set_rate_val(struct snd_akm4 310 { 311 struct snd_ice1712 *ice = ak->private_ 312 int dfs; 313 314 revo_set_rate_val(ak, rate); 315 316 /* reset CKS */ 317 snd_ice1712_gpio_write_bits(ice, 1 << 318 /* reset DFS pins of AK5385A for ADC, 319 if (rate > 96000) 320 dfs = 2; 321 else if (rate > 48000) 322 dfs = 1; 323 else 324 dfs = 0; 325 snd_ice1712_gpio_write_bits(ice, 3 << 326 /* reset ADC */ 327 snd_ice1712_gpio_write_bits(ice, 1 << 328 snd_ice1712_gpio_write_bits(ice, 1 << 329 } 330 331 static const struct snd_akm4xxx_dac_channel ap 332 AK_DAC("PCM Playback Volume", 2) 333 }; 334 335 static const struct snd_akm4xxx akm_ap192 = { 336 .type = SND_AK4358, 337 .num_dacs = 2, 338 .ops = { 339 .set_rate_val = ap192_set_rate 340 }, 341 .dac_info = ap192_dac, 342 }; 343 344 static const struct snd_ak4xxx_private akm_ap1 345 .caddr = 2, 346 .cif = 0, 347 .data_mask = VT1724_REVO_CDOUT, 348 .clk_mask = VT1724_REVO_CCLK, 349 .cs_mask = VT1724_REVO_CS0 | VT1724_RE 350 .cs_addr = VT1724_REVO_CS3, 351 .cs_none = VT1724_REVO_CS0 | VT1724_RE 352 .add_flags = VT1724_REVO_CCLK, /* high 353 .mask_flags = 0, 354 }; 355 356 /* AK4114 support on Audiophile 192 */ 357 /* CDTO (pin 32) -- GPIO2 pin 52 358 * CDTI (pin 33) -- GPIO3 pin 53 (shared with 359 * CCLK (pin 34) -- GPIO1 pin 51 (shared with 360 * CSN (pin 35) -- GPIO7 pin 59 361 */ 362 #define AK4114_ADDR 0x00 363 364 static void write_data(struct snd_ice1712 *ice 365 unsigned int data, int 366 { 367 for (; idx >= 0; idx--) { 368 /* drop clock */ 369 gpio &= ~VT1724_REVO_CCLK; 370 snd_ice1712_gpio_write(ice, gp 371 udelay(1); 372 /* set data */ 373 if (data & (1 << idx)) 374 gpio |= VT1724_REVO_CD 375 else 376 gpio &= ~VT1724_REVO_C 377 snd_ice1712_gpio_write(ice, gp 378 udelay(1); 379 /* raise clock */ 380 gpio |= VT1724_REVO_CCLK; 381 snd_ice1712_gpio_write(ice, gp 382 udelay(1); 383 } 384 } 385 386 static unsigned char read_data(struct snd_ice1 387 int idx) 388 { 389 unsigned char data = 0; 390 391 for (; idx >= 0; idx--) { 392 /* drop clock */ 393 gpio &= ~VT1724_REVO_CCLK; 394 snd_ice1712_gpio_write(ice, gp 395 udelay(1); 396 /* read data */ 397 if (snd_ice1712_gpio_read(ice) 398 data |= (1 << idx); 399 udelay(1); 400 /* raise clock */ 401 gpio |= VT1724_REVO_CCLK; 402 snd_ice1712_gpio_write(ice, gp 403 udelay(1); 404 } 405 return data; 406 } 407 408 static unsigned int ap192_4wire_start(struct s 409 { 410 unsigned int tmp; 411 412 snd_ice1712_save_gpio_status(ice); 413 tmp = snd_ice1712_gpio_read(ice); 414 tmp |= VT1724_REVO_CCLK; /* high at in 415 tmp |= VT1724_REVO_CS0; 416 tmp &= ~VT1724_REVO_CS3; 417 snd_ice1712_gpio_write(ice, tmp); 418 udelay(1); 419 return tmp; 420 } 421 422 static void ap192_4wire_finish(struct snd_ice1 423 { 424 tmp |= VT1724_REVO_CS3; 425 tmp |= VT1724_REVO_CS0; 426 snd_ice1712_gpio_write(ice, tmp); 427 udelay(1); 428 snd_ice1712_restore_gpio_status(ice); 429 } 430 431 static void ap192_ak4114_write(void *private_d 432 unsigned char d 433 { 434 struct snd_ice1712 *ice = private_data 435 unsigned int tmp, addrdata; 436 437 tmp = ap192_4wire_start(ice); 438 addrdata = (AK4114_ADDR << 6) | 0x20 | 439 addrdata = (addrdata << 8) | data; 440 write_data(ice, tmp, addrdata, 15); 441 ap192_4wire_finish(ice, tmp); 442 } 443 444 static unsigned char ap192_ak4114_read(void *p 445 { 446 struct snd_ice1712 *ice = private_data 447 unsigned int tmp; 448 unsigned char data; 449 450 tmp = ap192_4wire_start(ice); 451 write_data(ice, tmp, (AK4114_ADDR << 6 452 data = read_data(ice, tmp, 7); 453 ap192_4wire_finish(ice, tmp); 454 return data; 455 } 456 457 static int ap192_ak4114_init(struct snd_ice171 458 { 459 static const unsigned char ak4114_init 460 AK4114_RST | AK4114_PWN | AK41 461 AK4114_DIF_I24I2S, 462 AK4114_TX1E, 463 AK4114_EFH_1024 | AK4114_DIT | 464 0, 465 0 466 }; 467 static const unsigned char ak4114_init 468 0x41, 0x02, 0x2c, 0x00, 0x00 469 }; 470 int err; 471 472 struct revo51_spec *spec; 473 spec = kzalloc(sizeof(*spec), GFP_KERN 474 if (!spec) 475 return -ENOMEM; 476 ice->spec = spec; 477 478 err = snd_ak4114_create(ice->card, 479 ap192_ak4114_ 480 ap192_ak4114_ 481 ak4114_init_v 482 ice, &spec->a 483 if (err < 0) 484 return err; 485 /* AK4114 in Revo cannot detect extern 486 * No reason to stop capture stream du 487 spec->ak4114->check_flags = AK4114_CHE 488 489 return 0; 490 } 491 492 static int revo_init(struct snd_ice1712 *ice) 493 { 494 struct snd_akm4xxx *ak; 495 int err; 496 497 /* determine I2C, DACs and ADCs */ 498 switch (ice->eeprom.subvendor) { 499 case VT1724_SUBDEVICE_REVOLUTION71: 500 ice->num_total_dacs = 8; 501 ice->num_total_adcs = 2; 502 ice->gpio.i2s_mclk_changed = r 503 break; 504 case VT1724_SUBDEVICE_REVOLUTION51: 505 ice->num_total_dacs = 8; 506 ice->num_total_adcs = 2; 507 break; 508 case VT1724_SUBDEVICE_AUDIOPHILE192: 509 ice->num_total_dacs = 2; 510 ice->num_total_adcs = 2; 511 break; 512 default: 513 snd_BUG(); 514 return -EINVAL; 515 } 516 517 /* second stage of initialization, ana 518 ak = ice->akm = kcalloc(2, sizeof(stru 519 if (! ak) 520 return -ENOMEM; 521 switch (ice->eeprom.subvendor) { 522 case VT1724_SUBDEVICE_REVOLUTION71: 523 ice->akm_codecs = 2; 524 err = snd_ice1712_akm4xxx_init 525 526 if (err < 0) 527 return err; 528 err = snd_ice1712_akm4xxx_init 529 530 if (err < 0) 531 return err; 532 /* unmute all codecs */ 533 snd_ice1712_gpio_write_bits(ic 534 535 break; 536 case VT1724_SUBDEVICE_REVOLUTION51: 537 ice->akm_codecs = 2; 538 err = snd_ice1712_akm4xxx_init 539 540 if (err < 0) 541 return err; 542 err = snd_ice1712_akm4xxx_init 543 544 if (err < 0) 545 return err; 546 err = revo51_i2c_init(ice, &pt 547 if (err < 0) 548 return err; 549 /* unmute all codecs */ 550 snd_ice1712_gpio_write_bits(ic 551 VT 552 break; 553 case VT1724_SUBDEVICE_AUDIOPHILE192: 554 ice->akm_codecs = 1; 555 err = snd_ice1712_akm4xxx_init 556 557 if (err < 0) 558 return err; 559 err = ap192_ak4114_init(ice); 560 if (err < 0) 561 return err; 562 563 /* unmute all codecs */ 564 snd_ice1712_gpio_write_bits(ic 565 VT 566 break; 567 } 568 569 return 0; 570 } 571 572 573 static int revo_add_controls(struct snd_ice171 574 { 575 struct revo51_spec *spec = ice->spec; 576 int err; 577 578 switch (ice->eeprom.subvendor) { 579 case VT1724_SUBDEVICE_REVOLUTION71: 580 err = snd_ice1712_akm4xxx_buil 581 if (err < 0) 582 return err; 583 break; 584 case VT1724_SUBDEVICE_REVOLUTION51: 585 err = snd_ice1712_akm4xxx_buil 586 if (err < 0) 587 return err; 588 spec = ice->spec; 589 err = snd_pt2258_build_control 590 if (err < 0) 591 return err; 592 break; 593 case VT1724_SUBDEVICE_AUDIOPHILE192: 594 err = snd_ice1712_akm4xxx_buil 595 if (err < 0) 596 return err; 597 /* only capture SPDIF over AK4 598 err = snd_ak4114_build(spec->a 599 ice->pcm->streams[SNDRV_PCM 600 if (err < 0) 601 return err; 602 break; 603 } 604 return 0; 605 } 606 607 /* entry point */ 608 struct snd_ice1712_card_info snd_vt1724_revo_c 609 { 610 .subvendor = VT1724_SUBDEVICE_ 611 .name = "M Audio Revolution-7. 612 .model = "revo71", 613 .chip_init = revo_init, 614 .build_controls = revo_add_con 615 }, 616 { 617 .subvendor = VT1724_SUBDEVICE_ 618 .name = "M Audio Revolution-5. 619 .model = "revo51", 620 .chip_init = revo_init, 621 .build_controls = revo_add_con 622 }, 623 { 624 .subvendor = VT1724_SUBDEVICE_ 625 .name = "M Audio Audiophile192 626 .model = "ap192", 627 .chip_init = revo_init, 628 .build_controls = revo_add_con 629 }, 630 { } /* terminator */ 631 }; 632
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.