patch_cs8409.c (165b81c4ac3062d61e5422c85fcd55e8d0f805da) | patch_cs8409.c (636eb9d26f29cd9e195a6bae783315284efa11da) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * HD audio interface patch for Cirrus Logic CS8409 HDA bridge chip 4 * 5 * Copyright (C) 2021 Cirrus Logic, Inc. and 6 * Cirrus Logic International Semiconductor Ltd. 7 */ 8 9#include <linux/init.h> 10#include <linux/slab.h> 11#include <linux/module.h> 12#include <sound/core.h> 13#include <linux/mutex.h> 14 15#include "patch_cs8409.h" 16 | 1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * HD audio interface patch for Cirrus Logic CS8409 HDA bridge chip 4 * 5 * Copyright (C) 2021 Cirrus Logic, Inc. and 6 * Cirrus Logic International Semiconductor Ltd. 7 */ 8 9#include <linux/init.h> 10#include <linux/slab.h> 11#include <linux/module.h> 12#include <sound/core.h> 13#include <linux/mutex.h> 14 15#include "patch_cs8409.h" 16 |
17/****************************************************************************** 18 * CS8409 Specific Functions 19 ******************************************************************************/ 20 |
|
17static int cs8409_parse_auto_config(struct hda_codec *codec) 18{ 19 struct cs8409_spec *spec = codec->spec; 20 int err; 21 int i; 22 23 err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0); 24 if (err < 0) --- 27 unchanged lines hidden (view full) --- 52 struct cs8409_spec *spec; 53 54 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 55 if (!spec) 56 return NULL; 57 codec->spec = spec; 58 spec->codec = codec; 59 codec->power_save_node = 1; | 21static int cs8409_parse_auto_config(struct hda_codec *codec) 22{ 23 struct cs8409_spec *spec = codec->spec; 24 int err; 25 int i; 26 27 err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0); 28 if (err < 0) --- 27 unchanged lines hidden (view full) --- 56 struct cs8409_spec *spec; 57 58 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 59 if (!spec) 60 return NULL; 61 codec->spec = spec; 62 spec->codec = codec; 63 codec->power_save_node = 1; |
64 mutex_init(&spec->i2c_mux); |
|
60 INIT_DELAYED_WORK(&spec->i2c_clk_work, cs8409_disable_i2c_clock_worker); 61 snd_hda_gen_spec_init(&spec->gen); 62 63 return spec; 64} 65 66static inline int cs8409_vendor_coef_get(struct hda_codec *codec, unsigned int idx) 67{ --- 296 unchanged lines hidden (view full) --- 364 return 0; 365 366error: 367 mutex_unlock(&spec->i2c_mux); 368 codec_err(codec, "I2C Bulk Write Failed 0x%02x\n", i2c_address); 369 return -EIO; 370} 371 | 65 INIT_DELAYED_WORK(&spec->i2c_clk_work, cs8409_disable_i2c_clock_worker); 66 snd_hda_gen_spec_init(&spec->gen); 67 68 return spec; 69} 70 71static inline int cs8409_vendor_coef_get(struct hda_codec *codec, unsigned int idx) 72{ --- 296 unchanged lines hidden (view full) --- 369 return 0; 370 371error: 372 mutex_unlock(&spec->i2c_mux); 373 codec_err(codec, "I2C Bulk Write Failed 0x%02x\n", i2c_address); 374 return -EIO; 375} 376 |
372int cs8409_cs42l42_volume_info(struct snd_kcontrol *kctrl, struct snd_ctl_elem_info *uinfo) | 377static int cs8409_init(struct hda_codec *codec) |
373{ | 378{ |
379 int ret = snd_hda_gen_init(codec); 380 381 if (!ret) 382 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT); 383 384 return ret; 385} 386 387static int cs8409_build_controls(struct hda_codec *codec) 388{ 389 int err; 390 391 err = snd_hda_gen_build_controls(codec); 392 if (err < 0) 393 return err; 394 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_BUILD); 395 396 return 0; 397} 398 399/* Enable/Disable Unsolicited Response for gpio(s) 3,4 */ 400static void cs8409_enable_ur(struct hda_codec *codec, int flag) 401{ 402 /* GPIO4 INT# and GPIO3 WAKE# */ 403 snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 404 flag ? CS8409_CS42L42_INT : 0); 405 406 snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_UNSOLICITED_ENABLE, 407 flag ? AC_UNSOL_ENABLED : 0); 408 409} 410 411static void cs8409_fix_caps(struct hda_codec *codec, unsigned int nid) 412{ 413 int caps; 414 415 /* CS8409 is simple HDA bridge and intended to be used with a remote 416 * companion codec. Most of input/output PIN(s) have only basic 417 * capabilities. Receive and Transmit NID(s) have only OUTC and INC 418 * capabilities and no presence detect capable (PDC) and call to 419 * snd_hda_gen_build_controls() will mark them as non detectable 420 * phantom jacks. However, a companion codec may be 421 * connected to these pins which supports jack detect 422 * capabilities. We have to override pin capabilities, 423 * otherwise they will not be created as input devices. 424 */ 425 caps = snd_hdac_read_parm(&codec->core, nid, AC_PAR_PIN_CAP); 426 if (caps >= 0) 427 snd_hdac_override_parm(&codec->core, nid, AC_PAR_PIN_CAP, 428 (caps | (AC_PINCAP_IMP_SENSE | AC_PINCAP_PRES_DETECT))); 429 430 snd_hda_override_wcaps(codec, nid, (get_wcaps(codec, nid) | AC_WCAP_UNSOL_CAP)); 431} 432 433/****************************************************************************** 434 * CS42L42 Specific Functions 435 ******************************************************************************/ 436 437int cs42l42_volume_info(struct snd_kcontrol *kctrl, struct snd_ctl_elem_info *uinfo) 438{ |
|
374 unsigned int ofs = get_amp_offset(kctrl); 375 u8 chs = get_amp_channels(kctrl); 376 377 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 378 uinfo->value.integer.step = 1; 379 uinfo->count = chs == 3 ? 2 : 1; 380 381 switch (ofs) { 382 case CS42L42_VOL_DAC: | 439 unsigned int ofs = get_amp_offset(kctrl); 440 u8 chs = get_amp_channels(kctrl); 441 442 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 443 uinfo->value.integer.step = 1; 444 uinfo->count = chs == 3 ? 2 : 1; 445 446 switch (ofs) { 447 case CS42L42_VOL_DAC: |
383 uinfo->value.integer.min = CS8409_CS42L42_HP_VOL_REAL_MIN; 384 uinfo->value.integer.max = CS8409_CS42L42_HP_VOL_REAL_MAX; | 448 uinfo->value.integer.min = CS42L42_HP_VOL_REAL_MIN; 449 uinfo->value.integer.max = CS42L42_HP_VOL_REAL_MAX; |
385 break; 386 case CS42L42_VOL_ADC: | 450 break; 451 case CS42L42_VOL_ADC: |
387 uinfo->value.integer.min = CS8409_CS42L42_AMIC_VOL_REAL_MIN; 388 uinfo->value.integer.max = CS8409_CS42L42_AMIC_VOL_REAL_MAX; | 452 uinfo->value.integer.min = CS42L42_AMIC_VOL_REAL_MIN; 453 uinfo->value.integer.max = CS42L42_AMIC_VOL_REAL_MAX; |
389 break; 390 default: 391 break; 392 } 393 394 return 0; 395} 396 | 454 break; 455 default: 456 break; 457 } 458 459 return 0; 460} 461 |
397int cs8409_cs42l42_volume_get(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl) | 462int cs42l42_volume_get(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl) |
398{ 399 struct hda_codec *codec = snd_kcontrol_chip(kctrl); 400 struct cs8409_spec *spec = codec->spec; 401 int chs = get_amp_channels(kctrl); 402 unsigned int ofs = get_amp_offset(kctrl); 403 long *valp = uctrl->value.integer.value; 404 405 switch (ofs) { --- 9 unchanged lines hidden (view full) --- 415 break; 416 default: 417 break; 418 } 419 420 return 0; 421} 422 | 463{ 464 struct hda_codec *codec = snd_kcontrol_chip(kctrl); 465 struct cs8409_spec *spec = codec->spec; 466 int chs = get_amp_channels(kctrl); 467 unsigned int ofs = get_amp_offset(kctrl); 468 long *valp = uctrl->value.integer.value; 469 470 switch (ofs) { --- 9 unchanged lines hidden (view full) --- 480 break; 481 default: 482 break; 483 } 484 485 return 0; 486} 487 |
423int cs8409_cs42l42_volume_put(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl) | 488int cs42l42_volume_put(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl) |
424{ 425 struct hda_codec *codec = snd_kcontrol_chip(kctrl); 426 struct cs8409_spec *spec = codec->spec; 427 int chs = get_amp_channels(kctrl); 428 unsigned int ofs = get_amp_offset(kctrl); 429 long *valp = uctrl->value.integer.value; 430 431 switch (ofs) { 432 case CS42L42_VOL_DAC: 433 if (chs & BIT(0)) { 434 spec->vol[ofs] = *valp; | 489{ 490 struct hda_codec *codec = snd_kcontrol_chip(kctrl); 491 struct cs8409_spec *spec = codec->spec; 492 int chs = get_amp_channels(kctrl); 493 unsigned int ofs = get_amp_offset(kctrl); 494 long *valp = uctrl->value.integer.value; 495 496 switch (ofs) { 497 case CS42L42_VOL_DAC: 498 if (chs & BIT(0)) { 499 spec->vol[ofs] = *valp; |
435 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS8409_CS42L42_REG_HS_VOL_CHA, 436 -(spec->vol[ofs]) & CS8409_CS42L42_REG_HS_VOL_MASK); | 500 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS42L42_REG_HS_VOL_CHA, 501 -(spec->vol[ofs]) & CS42L42_REG_HS_VOL_MASK); |
437 } 438 if (chs & BIT(1)) { 439 ofs++; 440 valp++; 441 spec->vol[ofs] = *valp; | 502 } 503 if (chs & BIT(1)) { 504 ofs++; 505 valp++; 506 spec->vol[ofs] = *valp; |
442 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS8409_CS42L42_REG_HS_VOL_CHB, 443 -(spec->vol[ofs]) & CS8409_CS42L42_REG_HS_VOL_MASK); | 507 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS42L42_REG_HS_VOL_CHB, 508 -(spec->vol[ofs]) & CS42L42_REG_HS_VOL_MASK); |
444 } 445 break; 446 case CS42L42_VOL_ADC: 447 if (chs & BIT(0)) { 448 spec->vol[ofs] = *valp; | 509 } 510 break; 511 case CS42L42_VOL_ADC: 512 if (chs & BIT(0)) { 513 spec->vol[ofs] = *valp; |
449 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS8409_CS42L42_REG_AMIC_VOL, 450 spec->vol[ofs] & CS8409_CS42L42_REG_AMIC_VOL_MASK); | 514 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS42L42_REG_AMIC_VOL, 515 spec->vol[ofs] & CS42L42_REG_AMIC_VOL_MASK); |
451 } 452 break; 453 default: 454 break; 455 } 456 457 return 0; 458} 459 | 516 } 517 break; 518 default: 519 break; 520 } 521 522 return 0; 523} 524 |
460/* Assert/release RTS# line to CS42L42 */ 461static void cs8409_cs42l42_reset(struct hda_codec *codec) 462{ 463 struct cs8409_spec *spec = codec->spec; 464 struct cs8409_i2c_param irq_regs[] = { 465 { 0x1308, 0x00 }, 466 { 0x1309, 0x00 }, 467 { 0x130A, 0x00 }, 468 { 0x130F, 0x00 }, 469 }; 470 471 /* Assert RTS# line */ 472 snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, 0); 473 /* wait ~10ms */ 474 usleep_range(10000, 15000); 475 /* Release RTS# line */ 476 snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, CS8409_CS42L42_RESET); 477 /* wait ~10ms */ 478 usleep_range(10000, 15000); 479 480 spec->cs42l42_suspended = 0; 481 spec->last_page = 0; 482 483 /* Clear interrupts, by reading interrupt status registers */ 484 cs8409_i2c_bulk_read(codec, CS42L42_I2C_ADDR, irq_regs, ARRAY_SIZE(irq_regs)); 485} 486 | |
487/* Configure CS42L42 slave codec for jack autodetect */ | 525/* Configure CS42L42 slave codec for jack autodetect */ |
488static void cs8409_cs42l42_enable_jack_detect(struct hda_codec *codec) | 526static void cs42l42_enable_jack_detect(struct hda_codec *codec) |
489{ 490 /* Set TIP_SENSE_EN for analog front-end of tip sense. 491 * Additionally set HSBIAS_SENSE_EN for some variants. 492 */ 493 if (codec->fixup_id == CS8409_WARLOCK || codec->fixup_id == CS8409_BULLSEYE) 494 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b70, 0x0020); 495 else 496 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b70, 0x00a0); --- 6 unchanged lines hidden (view full) --- 503 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b71, 0x00C0); 504 /* Clear interrupts status */ 505 cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130f); 506 /* Enable interrupt */ 507 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1320, 0xF3); 508} 509 510/* Enable and run CS42L42 slave codec jack auto detect */ | 527{ 528 /* Set TIP_SENSE_EN for analog front-end of tip sense. 529 * Additionally set HSBIAS_SENSE_EN for some variants. 530 */ 531 if (codec->fixup_id == CS8409_WARLOCK || codec->fixup_id == CS8409_BULLSEYE) 532 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b70, 0x0020); 533 else 534 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b70, 0x00a0); --- 6 unchanged lines hidden (view full) --- 541 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b71, 0x00C0); 542 /* Clear interrupts status */ 543 cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130f); 544 /* Enable interrupt */ 545 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1320, 0xF3); 546} 547 548/* Enable and run CS42L42 slave codec jack auto detect */ |
511static void cs8409_cs42l42_run_jack_detect(struct hda_codec *codec) | 549static void cs42l42_run_jack_detect(struct hda_codec *codec) |
512{ 513 /* Clear interrupts */ 514 cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1308); 515 cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1b77); 516 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1320, 0xFF); 517 cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130f); 518 519 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1102, 0x87); --- 5 unchanged lines hidden (view full) --- 525 usleep_range(110000, 200000); 526 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x111f, 0x77); 527 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1120, 0xc0); 528 /* Wait ~10ms */ 529 usleep_range(10000, 25000); 530 531} 532 | 550{ 551 /* Clear interrupts */ 552 cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1308); 553 cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1b77); 554 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1320, 0xFF); 555 cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130f); 556 557 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1102, 0x87); --- 5 unchanged lines hidden (view full) --- 563 usleep_range(110000, 200000); 564 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x111f, 0x77); 565 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1120, 0xc0); 566 /* Wait ~10ms */ 567 usleep_range(10000, 25000); 568 569} 570 |
533/* 534 * In the case of CS8409 we do not have unsolicited events from NID's 0x24 535 * and 0x34 where hs mic and hp are connected. Companion codec CS42L42 will 536 * generate interrupt via gpio 4 to notify jack events. We have to overwrite 537 * generic snd_hda_jack_unsol_event(), read CS42L42 jack detect status registers 538 * and then notify status via generic snd_hda_jack_unsol_event() call. 539 */ 540static void cs8409_jack_unsol_event(struct hda_codec *codec, unsigned int res) | 571static int cs42l42_jack_unsol_event(struct hda_codec *codec) |
541{ 542 struct cs8409_spec *spec = codec->spec; 543 int status_changed = 0; 544 int reg_cdc_status; 545 int reg_hs_status; 546 int reg_ts_status; 547 int type; | 572{ 573 struct cs8409_spec *spec = codec->spec; 574 int status_changed = 0; 575 int reg_cdc_status; 576 int reg_hs_status; 577 int reg_ts_status; 578 int type; |
548 struct hda_jack_tbl *jk; | |
549 | 579 |
550 /* jack_unsol_event() will be called every time gpio line changing state. 551 * In this case gpio4 line goes up as a result of reading interrupt status 552 * registers in previous cs8409_jack_unsol_event() call. 553 * We don't need to handle this event, ignoring... 554 */ 555 if (res & CS8409_CS42L42_INT) 556 return; 557 | |
558 /* Read jack detect status registers */ 559 reg_cdc_status = cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1308); 560 reg_hs_status = cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1124); 561 reg_ts_status = cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130f); 562 563 /* If status values are < 0, read error has occurred. */ 564 if (reg_cdc_status < 0 || reg_hs_status < 0 || reg_ts_status < 0) | 580 /* Read jack detect status registers */ 581 reg_cdc_status = cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1308); 582 reg_hs_status = cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1124); 583 reg_ts_status = cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130f); 584 585 /* If status values are < 0, read error has occurred. */ 586 if (reg_cdc_status < 0 || reg_hs_status < 0 || reg_ts_status < 0) |
565 return; | 587 return -EIO; |
566 567 /* HSDET_AUTO_DONE */ 568 if (reg_cdc_status & CS42L42_HSDET_AUTO_DONE) { 569 570 /* Disable HSDET_AUTO_DONE */ 571 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x131b, 0xFF); 572 573 type = ((reg_hs_status & CS42L42_HSTYPE_MASK) + 1); --- 20 unchanged lines hidden (view full) --- 594 595 /* Re-Enable Tip Sense Interrupt */ 596 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1320, 0xF3); 597 598 } else { 599 /* TIP_SENSE INSERT/REMOVE */ 600 switch (reg_ts_status) { 601 case CS42L42_JACK_INSERTED: | 588 589 /* HSDET_AUTO_DONE */ 590 if (reg_cdc_status & CS42L42_HSDET_AUTO_DONE) { 591 592 /* Disable HSDET_AUTO_DONE */ 593 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x131b, 0xFF); 594 595 type = ((reg_hs_status & CS42L42_HSTYPE_MASK) + 1); --- 20 unchanged lines hidden (view full) --- 616 617 /* Re-Enable Tip Sense Interrupt */ 618 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1320, 0xF3); 619 620 } else { 621 /* TIP_SENSE INSERT/REMOVE */ 622 switch (reg_ts_status) { 623 case CS42L42_JACK_INSERTED: |
602 cs8409_cs42l42_run_jack_detect(codec); | 624 cs42l42_run_jack_detect(codec); |
603 break; 604 605 case CS42L42_JACK_REMOVED: 606 if (spec->cs42l42_hp_jack_in || spec->cs42l42_mic_jack_in) { 607 status_changed = 1; 608 spec->cs42l42_hp_jack_in = 0; 609 spec->cs42l42_mic_jack_in = 0; 610 } 611 break; 612 613 default: 614 /* jack in transition */ 615 status_changed = 0; 616 break; 617 } 618 } 619 | 625 break; 626 627 case CS42L42_JACK_REMOVED: 628 if (spec->cs42l42_hp_jack_in || spec->cs42l42_mic_jack_in) { 629 status_changed = 1; 630 spec->cs42l42_hp_jack_in = 0; 631 spec->cs42l42_mic_jack_in = 0; 632 } 633 break; 634 635 default: 636 /* jack in transition */ 637 status_changed = 0; 638 break; 639 } 640 } 641 |
620 if (status_changed) { | 642 return status_changed; 643} |
621 | 644 |
645/* Assert/release RTS# line to CS42L42 */ 646static void cs42l42_reset(struct hda_codec *codec) 647{ 648 struct cs8409_spec *spec = codec->spec; 649 struct cs8409_i2c_param irq_regs[] = { 650 { 0x1308, 0x00 }, 651 { 0x1309, 0x00 }, 652 { 0x130A, 0x00 }, 653 { 0x130F, 0x00 }, 654 }; 655 656 /* Assert RTS# line */ 657 snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, 0); 658 /* wait ~10ms */ 659 usleep_range(10000, 15000); 660 /* Release RTS# line */ 661 snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, CS8409_CS42L42_RESET); 662 /* wait ~10ms */ 663 usleep_range(10000, 15000); 664 665 spec->cs42l42_suspended = 0; 666 spec->last_page = 0; 667 668 /* Clear interrupts, by reading interrupt status registers */ 669 cs8409_i2c_bulk_read(codec, CS42L42_I2C_ADDR, irq_regs, ARRAY_SIZE(irq_regs)); 670} 671 672#ifdef CONFIG_PM 673static void cs42l42_suspend(struct hda_codec *codec) 674{ 675 /* Power down CS42L42 ASP/EQ/MIX/HP */ 676 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1101, 0xfe); 677} 678#endif 679 680static void cs8409_free(struct hda_codec *codec) 681{ 682 struct cs8409_spec *spec = codec->spec; 683 684 /* Cancel i2c clock disable timer, and disable clock if left enabled */ 685 cancel_delayed_work_sync(&spec->i2c_clk_work); 686 cs8409_disable_i2c_clock(codec); 687 688 snd_hda_gen_free(codec); 689} 690 691/****************************************************************************** 692 * BULLSEYE / WARLOCK / CYBORG Specific Functions 693 * CS8409/CS42L42 694 ******************************************************************************/ 695 696/* 697 * In the case of CS8409 we do not have unsolicited events from NID's 0x24 698 * and 0x34 where hs mic and hp are connected. Companion codec CS42L42 will 699 * generate interrupt via gpio 4 to notify jack events. We have to overwrite 700 * generic snd_hda_jack_unsol_event(), read CS42L42 jack detect status registers 701 * and then notify status via generic snd_hda_jack_unsol_event() call. 702 */ 703static void cs8409_jack_unsol_event(struct hda_codec *codec, unsigned int res) 704{ 705 struct cs8409_spec *spec = codec->spec; 706 struct hda_jack_tbl *jk; 707 708 /* jack_unsol_event() will be called every time gpio line changing state. 709 * In this case gpio4 line goes up as a result of reading interrupt status 710 * registers in previous cs8409_jack_unsol_event() call. 711 * We don't need to handle this event, ignoring... 712 */ 713 if (res & CS8409_CS42L42_INT) 714 return; 715 716 if (cs42l42_jack_unsol_event(codec)) { |
|
622 snd_hda_set_pin_ctl(codec, CS8409_CS42L42_SPK_PIN_NID, 623 spec->cs42l42_hp_jack_in ? 0 : PIN_OUT); | 717 snd_hda_set_pin_ctl(codec, CS8409_CS42L42_SPK_PIN_NID, 718 spec->cs42l42_hp_jack_in ? 0 : PIN_OUT); |
624 | |
625 /* Report jack*/ 626 jk = snd_hda_jack_tbl_get_mst(codec, CS8409_CS42L42_HP_PIN_NID, 0); | 719 /* Report jack*/ 720 jk = snd_hda_jack_tbl_get_mst(codec, CS8409_CS42L42_HP_PIN_NID, 0); |
627 if (jk) { | 721 if (jk) |
628 snd_hda_jack_unsol_event(codec, (jk->tag << AC_UNSOL_RES_TAG_SHIFT) & 629 AC_UNSOL_RES_TAG); | 722 snd_hda_jack_unsol_event(codec, (jk->tag << AC_UNSOL_RES_TAG_SHIFT) & 723 AC_UNSOL_RES_TAG); |
630 } | |
631 /* Report jack*/ 632 jk = snd_hda_jack_tbl_get_mst(codec, CS8409_CS42L42_AMIC_PIN_NID, 0); | 724 /* Report jack*/ 725 jk = snd_hda_jack_tbl_get_mst(codec, CS8409_CS42L42_AMIC_PIN_NID, 0); |
633 if (jk) { | 726 if (jk) |
634 snd_hda_jack_unsol_event(codec, (jk->tag << AC_UNSOL_RES_TAG_SHIFT) & 635 AC_UNSOL_RES_TAG); | 727 snd_hda_jack_unsol_event(codec, (jk->tag << AC_UNSOL_RES_TAG_SHIFT) & 728 AC_UNSOL_RES_TAG); |
636 } | |
637 } 638} 639 | 729 } 730} 731 |
640/* Enable/Disable Unsolicited Response for gpio(s) 3,4 */ 641static void cs8409_enable_ur(struct hda_codec *codec, int flag) 642{ 643 /* GPIO4 INT# and GPIO3 WAKE# */ 644 snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 645 flag ? CS8409_CS42L42_INT : 0); 646 647 snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_UNSOLICITED_ENABLE, 648 flag ? AC_UNSOL_ENABLED : 0); 649 650} 651 | |
652#ifdef CONFIG_PM 653/* Manage PDREF, when transition to D3hot */ | 732#ifdef CONFIG_PM 733/* Manage PDREF, when transition to D3hot */ |
654static int cs8409_suspend(struct hda_codec *codec) | 734static int cs8409_cs42l42_suspend(struct hda_codec *codec) |
655{ 656 struct cs8409_spec *spec = codec->spec; 657 658 cs8409_enable_ur(codec, 0); 659 | 735{ 736 struct cs8409_spec *spec = codec->spec; 737 738 cs8409_enable_ur(codec, 0); 739 |
660 /* Power down CS42L42 ASP/EQ/MIX/HP */ 661 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1101, 0xfe); | 740 cs42l42_suspend(codec); |
662 663 spec->cs42l42_suspended = 1; 664 665 /* Assert CS42L42 RTS# line */ 666 snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, 0); 667 668 /* Cancel i2c clock disable timer, and disable clock if left enabled */ 669 cancel_delayed_work_sync(&spec->i2c_clk_work); 670 cs8409_disable_i2c_clock(codec); 671 672 snd_hda_shutup_pins(codec); 673 674 return 0; 675} 676#endif 677 | 741 742 spec->cs42l42_suspended = 1; 743 744 /* Assert CS42L42 RTS# line */ 745 snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, 0); 746 747 /* Cancel i2c clock disable timer, and disable clock if left enabled */ 748 cancel_delayed_work_sync(&spec->i2c_clk_work); 749 cs8409_disable_i2c_clock(codec); 750 751 snd_hda_shutup_pins(codec); 752 753 return 0; 754} 755#endif 756 |
678static void cs8409_free(struct hda_codec *codec) 679{ 680 struct cs8409_spec *spec = codec->spec; 681 682 /* Cancel i2c clock disable timer, and disable clock if left enabled */ 683 cancel_delayed_work_sync(&spec->i2c_clk_work); 684 cs8409_disable_i2c_clock(codec); 685 686 snd_hda_gen_free(codec); 687} 688 | |
689/* Vendor specific HW configuration 690 * PLL, ASP, I2C, SPI, GPIOs, DMIC etc... 691 */ 692static void cs8409_cs42l42_hw_init(struct hda_codec *codec) 693{ 694 const struct cs8409_cir_param *seq = cs8409_cs42l42_hw_cfg; 695 const struct cs8409_cir_param *seq_bullseye = cs8409_cs42l42_bullseye_atn; 696 struct cs8409_spec *spec = codec->spec; --- 10 unchanged lines hidden (view full) --- 707 for (; seq->nid; seq++) 708 cs8409_vendor_coef_set(codec, seq->cir, seq->coeff); 709 710 if (codec->fixup_id == CS8409_BULLSEYE) 711 for (; seq_bullseye->nid; seq_bullseye++) 712 cs8409_vendor_coef_set(codec, seq_bullseye->cir, seq_bullseye->coeff); 713 714 /* Reset CS42L42 */ | 757/* Vendor specific HW configuration 758 * PLL, ASP, I2C, SPI, GPIOs, DMIC etc... 759 */ 760static void cs8409_cs42l42_hw_init(struct hda_codec *codec) 761{ 762 const struct cs8409_cir_param *seq = cs8409_cs42l42_hw_cfg; 763 const struct cs8409_cir_param *seq_bullseye = cs8409_cs42l42_bullseye_atn; 764 struct cs8409_spec *spec = codec->spec; --- 10 unchanged lines hidden (view full) --- 775 for (; seq->nid; seq++) 776 cs8409_vendor_coef_set(codec, seq->cir, seq->coeff); 777 778 if (codec->fixup_id == CS8409_BULLSEYE) 779 for (; seq_bullseye->nid; seq_bullseye++) 780 cs8409_vendor_coef_set(codec, seq_bullseye->cir, seq_bullseye->coeff); 781 782 /* Reset CS42L42 */ |
715 cs8409_cs42l42_reset(codec); | 783 cs42l42_reset(codec); |
716 717 /* Initialise CS42L42 companion codec */ 718 cs8409_i2c_bulk_write(codec, CS42L42_I2C_ADDR, cs42l42_init_reg_seq, 719 CS42L42_INIT_REG_SEQ_SIZE); 720 721 if (codec->fixup_id == CS8409_WARLOCK || codec->fixup_id == CS8409_CYBORG) { 722 /* FULL_SCALE_VOL = 0 for Warlock / Cyborg */ 723 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x2001, 0x01); 724 /* DMIC1_MO=00b, DMIC1/2_SR=1 */ 725 cs8409_vendor_coef_set(codec, 0x09, 0x0003); 726 } 727 728 /* Restore Volumes after Resume */ | 784 785 /* Initialise CS42L42 companion codec */ 786 cs8409_i2c_bulk_write(codec, CS42L42_I2C_ADDR, cs42l42_init_reg_seq, 787 CS42L42_INIT_REG_SEQ_SIZE); 788 789 if (codec->fixup_id == CS8409_WARLOCK || codec->fixup_id == CS8409_CYBORG) { 790 /* FULL_SCALE_VOL = 0 for Warlock / Cyborg */ 791 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x2001, 0x01); 792 /* DMIC1_MO=00b, DMIC1/2_SR=1 */ 793 cs8409_vendor_coef_set(codec, 0x09, 0x0003); 794 } 795 796 /* Restore Volumes after Resume */ |
729 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS8409_CS42L42_REG_HS_VOL_CHA, 730 -(spec->vol[1]) & CS8409_CS42L42_REG_HS_VOL_MASK); 731 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS8409_CS42L42_REG_HS_VOL_CHB, 732 -(spec->vol[2]) & CS8409_CS42L42_REG_HS_VOL_MASK); 733 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS8409_CS42L42_REG_AMIC_VOL, 734 spec->vol[0] & CS8409_CS42L42_REG_AMIC_VOL_MASK); | 797 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS42L42_REG_HS_VOL_CHA, 798 -(spec->vol[1]) & CS42L42_REG_HS_VOL_MASK); 799 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS42L42_REG_HS_VOL_CHB, 800 -(spec->vol[2]) & CS42L42_REG_HS_VOL_MASK); 801 cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS42L42_REG_AMIC_VOL, 802 spec->vol[0] & CS42L42_REG_AMIC_VOL_MASK); |
735 | 803 |
736 cs8409_cs42l42_enable_jack_detect(codec); | 804 cs42l42_enable_jack_detect(codec); |
737 738 /* Enable Unsolicited Response */ 739 cs8409_enable_ur(codec, 1); 740} 741 | 805 806 /* Enable Unsolicited Response */ 807 cs8409_enable_ur(codec, 1); 808} 809 |
742static int cs8409_cs42l42_init(struct hda_codec *codec) 743{ 744 int ret = snd_hda_gen_init(codec); 745 746 if (!ret) 747 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT); 748 749 return ret; 750} 751 752static int cs8409_build_controls(struct hda_codec *codec) 753{ 754 int err; 755 756 err = snd_hda_gen_build_controls(codec); 757 if (err < 0) 758 return err; 759 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_BUILD); 760 761 return 0; 762} 763 | |
764static const struct hda_codec_ops cs8409_cs42l42_patch_ops = { 765 .build_controls = cs8409_build_controls, 766 .build_pcms = snd_hda_gen_build_pcms, | 810static const struct hda_codec_ops cs8409_cs42l42_patch_ops = { 811 .build_controls = cs8409_build_controls, 812 .build_pcms = snd_hda_gen_build_pcms, |
767 .init = cs8409_cs42l42_init, | 813 .init = cs8409_init, |
768 .free = cs8409_free, 769 .unsol_event = cs8409_jack_unsol_event, 770#ifdef CONFIG_PM | 814 .free = cs8409_free, 815 .unsol_event = cs8409_jack_unsol_event, 816#ifdef CONFIG_PM |
771 .suspend = cs8409_suspend, | 817 .suspend = cs8409_cs42l42_suspend, |
772#endif 773}; 774 775static int cs8409_cs42l42_exec_verb(struct hdac_device *dev, unsigned int cmd, unsigned int flags, 776 unsigned int *res) 777{ 778 struct hda_codec *codec = container_of(dev, struct hda_codec, core); 779 struct cs8409_spec *spec = codec->spec; --- 26 unchanged lines hidden (view full) --- 806 } 807 808 return spec->exec_verb(dev, cmd, flags, res); 809} 810 811void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action) 812{ 813 struct cs8409_spec *spec = codec->spec; | 818#endif 819}; 820 821static int cs8409_cs42l42_exec_verb(struct hdac_device *dev, unsigned int cmd, unsigned int flags, 822 unsigned int *res) 823{ 824 struct hda_codec *codec = container_of(dev, struct hda_codec, core); 825 struct cs8409_spec *spec = codec->spec; --- 26 unchanged lines hidden (view full) --- 852 } 853 854 return spec->exec_verb(dev, cmd, flags, res); 855} 856 857void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action) 858{ 859 struct cs8409_spec *spec = codec->spec; |
814 int caps; | |
815 816 switch (action) { 817 case HDA_FIXUP_ACT_PRE_PROBE: 818 snd_hda_add_verbs(codec, cs8409_cs42l42_init_verbs); 819 /* verb exec op override */ 820 spec->exec_verb = codec->core.exec_verb; 821 codec->core.exec_verb = cs8409_cs42l42_exec_verb; 822 | 860 861 switch (action) { 862 case HDA_FIXUP_ACT_PRE_PROBE: 863 snd_hda_add_verbs(codec, cs8409_cs42l42_init_verbs); 864 /* verb exec op override */ 865 spec->exec_verb = codec->core.exec_verb; 866 codec->core.exec_verb = cs8409_cs42l42_exec_verb; 867 |
823 mutex_init(&spec->i2c_mux); 824 | |
825 codec->patch_ops = cs8409_cs42l42_patch_ops; 826 827 spec->gen.suppress_auto_mute = 1; 828 spec->gen.no_primary_hp = 1; 829 spec->gen.suppress_vmaster = 1; 830 831 /* GPIO 5 out, 3,4 in */ 832 spec->gpio_dir = CS8409_CS42L42_RESET; 833 spec->gpio_data = 0; 834 spec->gpio_mask = 0x03f; 835 836 spec->cs42l42_hp_jack_in = 0; 837 spec->cs42l42_mic_jack_in = 0; 838 spec->cs42l42_suspended = 1; 839 spec->paged = 1; 840 841 /* Basic initial sequence for specific hw configuration */ 842 snd_hda_sequence_write(codec, cs8409_cs42l42_init_verbs); 843 | 868 codec->patch_ops = cs8409_cs42l42_patch_ops; 869 870 spec->gen.suppress_auto_mute = 1; 871 spec->gen.no_primary_hp = 1; 872 spec->gen.suppress_vmaster = 1; 873 874 /* GPIO 5 out, 3,4 in */ 875 spec->gpio_dir = CS8409_CS42L42_RESET; 876 spec->gpio_data = 0; 877 spec->gpio_mask = 0x03f; 878 879 spec->cs42l42_hp_jack_in = 0; 880 spec->cs42l42_mic_jack_in = 0; 881 spec->cs42l42_suspended = 1; 882 spec->paged = 1; 883 884 /* Basic initial sequence for specific hw configuration */ 885 snd_hda_sequence_write(codec, cs8409_cs42l42_init_verbs); 886 |
844 /* CS8409 is simple HDA bridge and intended to be used with a remote 845 * companion codec. Most of input/output PIN(s) have only basic 846 * capabilities. NID(s) 0x24 and 0x34 have only OUTC and INC 847 * capabilities and no presence detect capable (PDC) and call to 848 * snd_hda_gen_build_controls() will mark them as non detectable 849 * phantom jacks. However, in this configuration companion codec 850 * CS42L42 is connected to these pins and it has jack detect 851 * capabilities. We have to override pin capabilities, 852 * otherwise they will not be created as input devices. 853 */ 854 caps = snd_hdac_read_parm(&codec->core, CS8409_CS42L42_HP_PIN_NID, 855 AC_PAR_PIN_CAP); 856 if (caps >= 0) 857 snd_hdac_override_parm(&codec->core, 858 CS8409_CS42L42_HP_PIN_NID, AC_PAR_PIN_CAP, 859 (caps | (AC_PINCAP_IMP_SENSE | AC_PINCAP_PRES_DETECT))); | 887 cs8409_fix_caps(codec, CS8409_CS42L42_HP_PIN_NID); 888 cs8409_fix_caps(codec, CS8409_CS42L42_AMIC_PIN_NID); |
860 | 889 |
861 caps = snd_hdac_read_parm(&codec->core, CS8409_CS42L42_AMIC_PIN_NID, 862 AC_PAR_PIN_CAP); 863 if (caps >= 0) 864 snd_hdac_override_parm(&codec->core, 865 CS8409_CS42L42_AMIC_PIN_NID, AC_PAR_PIN_CAP, 866 (caps | (AC_PINCAP_IMP_SENSE | AC_PINCAP_PRES_DETECT))); 867 868 snd_hda_override_wcaps(codec, CS8409_CS42L42_HP_PIN_NID, 869 (get_wcaps(codec, CS8409_CS42L42_HP_PIN_NID) | AC_WCAP_UNSOL_CAP)); 870 871 snd_hda_override_wcaps(codec, CS8409_CS42L42_AMIC_PIN_NID, 872 (get_wcaps(codec, CS8409_CS42L42_AMIC_PIN_NID) | AC_WCAP_UNSOL_CAP)); | |
873 break; 874 case HDA_FIXUP_ACT_PROBE: 875 /* Set initial DMIC volume to -26 dB */ 876 snd_hda_codec_amp_init_stereo(codec, CS8409_CS42L42_DMIC_ADC_PIN_NID, 877 HDA_INPUT, 0, 0xff, 0x19); 878 snd_hda_gen_add_kctl(&spec->gen, "Headphone Playback Volume", 879 &cs42l42_dac_volume_mixer); 880 snd_hda_gen_add_kctl(&spec->gen, "Mic Capture Volume", --- 7 unchanged lines hidden (view full) --- 888 cs8409_cs42l42_hw_init(codec); 889 fallthrough; 890 case HDA_FIXUP_ACT_BUILD: 891 /* Run jack auto detect first time on boot 892 * after controls have been added, to check if jack has 893 * been already plugged in. 894 * Run immediately after init. 895 */ | 890 break; 891 case HDA_FIXUP_ACT_PROBE: 892 /* Set initial DMIC volume to -26 dB */ 893 snd_hda_codec_amp_init_stereo(codec, CS8409_CS42L42_DMIC_ADC_PIN_NID, 894 HDA_INPUT, 0, 0xff, 0x19); 895 snd_hda_gen_add_kctl(&spec->gen, "Headphone Playback Volume", 896 &cs42l42_dac_volume_mixer); 897 snd_hda_gen_add_kctl(&spec->gen, "Mic Capture Volume", --- 7 unchanged lines hidden (view full) --- 905 cs8409_cs42l42_hw_init(codec); 906 fallthrough; 907 case HDA_FIXUP_ACT_BUILD: 908 /* Run jack auto detect first time on boot 909 * after controls have been added, to check if jack has 910 * been already plugged in. 911 * Run immediately after init. 912 */ |
896 cs8409_cs42l42_run_jack_detect(codec); | 913 cs42l42_run_jack_detect(codec); |
897 usleep_range(100000, 150000); 898 break; 899 default: 900 break; 901 } 902} 903 904static int patch_cs8409(struct hda_codec *codec) --- 37 unchanged lines hidden --- | 914 usleep_range(100000, 150000); 915 break; 916 default: 917 break; 918 } 919} 920 921static int patch_cs8409(struct hda_codec *codec) --- 37 unchanged lines hidden --- |