| .. | .. |
|---|
| 2 | 2 | /* |
|---|
| 3 | 3 | * ALSA SoC Texas Instruments TAS6424 Quad-Channel Audio Amplifier |
|---|
| 4 | 4 | * |
|---|
| 5 | | - * Copyright (C) 2016-2017 Texas Instruments Incorporated - http://www.ti.com/ |
|---|
| 5 | + * Copyright (C) 2016-2017 Texas Instruments Incorporated - https://www.ti.com/ |
|---|
| 6 | 6 | * Author: Andreas Dannenberg <dannenberg@ti.com> |
|---|
| 7 | 7 | * Andrew F. Davis <afd@ti.com> |
|---|
| 8 | 8 | */ |
|---|
| .. | .. |
|---|
| 41 | 41 | struct regmap *regmap; |
|---|
| 42 | 42 | struct regulator_bulk_data supplies[TAS6424_NUM_SUPPLIES]; |
|---|
| 43 | 43 | struct delayed_work fault_check_work; |
|---|
| 44 | + unsigned int last_cfault; |
|---|
| 44 | 45 | unsigned int last_fault1; |
|---|
| 45 | 46 | unsigned int last_fault2; |
|---|
| 46 | 47 | unsigned int last_warn; |
|---|
| .. | .. |
|---|
| 251 | 252 | return 0; |
|---|
| 252 | 253 | } |
|---|
| 253 | 254 | |
|---|
| 254 | | -static int tas6424_mute(struct snd_soc_dai *dai, int mute) |
|---|
| 255 | +static int tas6424_mute(struct snd_soc_dai *dai, int mute, int direction) |
|---|
| 255 | 256 | { |
|---|
| 256 | 257 | struct snd_soc_component *component = dai->component; |
|---|
| 257 | 258 | struct tas6424_data *tas6424 = snd_soc_component_get_drvdata(component); |
|---|
| .. | .. |
|---|
| 377 | 378 | .non_legacy_dai_naming = 1, |
|---|
| 378 | 379 | }; |
|---|
| 379 | 380 | |
|---|
| 380 | | -static struct snd_soc_dai_ops tas6424_speaker_dai_ops = { |
|---|
| 381 | +static const struct snd_soc_dai_ops tas6424_speaker_dai_ops = { |
|---|
| 381 | 382 | .hw_params = tas6424_hw_params, |
|---|
| 382 | 383 | .set_fmt = tas6424_set_dai_fmt, |
|---|
| 383 | 384 | .set_tdm_slot = tas6424_set_dai_tdm_slot, |
|---|
| 384 | | - .digital_mute = tas6424_mute, |
|---|
| 385 | + .mute_stream = tas6424_mute, |
|---|
| 386 | + .no_capture_mute = 1, |
|---|
| 385 | 387 | }; |
|---|
| 386 | 388 | |
|---|
| 387 | 389 | static struct snd_soc_dai_driver tas6424_dai[] = { |
|---|
| .. | .. |
|---|
| 406 | 408 | unsigned int reg; |
|---|
| 407 | 409 | int ret; |
|---|
| 408 | 410 | |
|---|
| 411 | + ret = regmap_read(tas6424->regmap, TAS6424_CHANNEL_FAULT, ®); |
|---|
| 412 | + if (ret < 0) { |
|---|
| 413 | + dev_err(dev, "failed to read CHANNEL_FAULT register: %d\n", ret); |
|---|
| 414 | + goto out; |
|---|
| 415 | + } |
|---|
| 416 | + |
|---|
| 417 | + if (!reg) { |
|---|
| 418 | + tas6424->last_cfault = reg; |
|---|
| 419 | + goto check_global_fault1_reg; |
|---|
| 420 | + } |
|---|
| 421 | + |
|---|
| 422 | + /* |
|---|
| 423 | + * Only flag errors once for a given occurrence. This is needed as |
|---|
| 424 | + * the TAS6424 will take time clearing the fault condition internally |
|---|
| 425 | + * during which we don't want to bombard the system with the same |
|---|
| 426 | + * error message over and over. |
|---|
| 427 | + */ |
|---|
| 428 | + if ((reg & TAS6424_FAULT_OC_CH1) && !(tas6424->last_cfault & TAS6424_FAULT_OC_CH1)) |
|---|
| 429 | + dev_crit(dev, "experienced a channel 1 overcurrent fault\n"); |
|---|
| 430 | + |
|---|
| 431 | + if ((reg & TAS6424_FAULT_OC_CH2) && !(tas6424->last_cfault & TAS6424_FAULT_OC_CH2)) |
|---|
| 432 | + dev_crit(dev, "experienced a channel 2 overcurrent fault\n"); |
|---|
| 433 | + |
|---|
| 434 | + if ((reg & TAS6424_FAULT_OC_CH3) && !(tas6424->last_cfault & TAS6424_FAULT_OC_CH3)) |
|---|
| 435 | + dev_crit(dev, "experienced a channel 3 overcurrent fault\n"); |
|---|
| 436 | + |
|---|
| 437 | + if ((reg & TAS6424_FAULT_OC_CH4) && !(tas6424->last_cfault & TAS6424_FAULT_OC_CH4)) |
|---|
| 438 | + dev_crit(dev, "experienced a channel 4 overcurrent fault\n"); |
|---|
| 439 | + |
|---|
| 440 | + if ((reg & TAS6424_FAULT_DC_CH1) && !(tas6424->last_cfault & TAS6424_FAULT_DC_CH1)) |
|---|
| 441 | + dev_crit(dev, "experienced a channel 1 DC fault\n"); |
|---|
| 442 | + |
|---|
| 443 | + if ((reg & TAS6424_FAULT_DC_CH2) && !(tas6424->last_cfault & TAS6424_FAULT_DC_CH2)) |
|---|
| 444 | + dev_crit(dev, "experienced a channel 2 DC fault\n"); |
|---|
| 445 | + |
|---|
| 446 | + if ((reg & TAS6424_FAULT_DC_CH3) && !(tas6424->last_cfault & TAS6424_FAULT_DC_CH3)) |
|---|
| 447 | + dev_crit(dev, "experienced a channel 3 DC fault\n"); |
|---|
| 448 | + |
|---|
| 449 | + if ((reg & TAS6424_FAULT_DC_CH4) && !(tas6424->last_cfault & TAS6424_FAULT_DC_CH4)) |
|---|
| 450 | + dev_crit(dev, "experienced a channel 4 DC fault\n"); |
|---|
| 451 | + |
|---|
| 452 | + /* Store current fault1 value so we can detect any changes next time */ |
|---|
| 453 | + tas6424->last_cfault = reg; |
|---|
| 454 | + |
|---|
| 455 | +check_global_fault1_reg: |
|---|
| 409 | 456 | ret = regmap_read(tas6424->regmap, TAS6424_GLOB_FAULT1, ®); |
|---|
| 410 | 457 | if (ret < 0) { |
|---|
| 411 | | - dev_err(dev, "failed to read FAULT1 register: %d\n", ret); |
|---|
| 458 | + dev_err(dev, "failed to read GLOB_FAULT1 register: %d\n", ret); |
|---|
| 412 | 459 | goto out; |
|---|
| 413 | 460 | } |
|---|
| 414 | 461 | |
|---|
| .. | .. |
|---|
| 429 | 476 | goto check_global_fault2_reg; |
|---|
| 430 | 477 | } |
|---|
| 431 | 478 | |
|---|
| 432 | | - /* |
|---|
| 433 | | - * Only flag errors once for a given occurrence. This is needed as |
|---|
| 434 | | - * the TAS6424 will take time clearing the fault condition internally |
|---|
| 435 | | - * during which we don't want to bombard the system with the same |
|---|
| 436 | | - * error message over and over. |
|---|
| 437 | | - */ |
|---|
| 438 | 479 | if ((reg & TAS6424_FAULT_PVDD_OV) && !(tas6424->last_fault1 & TAS6424_FAULT_PVDD_OV)) |
|---|
| 439 | 480 | dev_crit(dev, "experienced a PVDD overvoltage fault\n"); |
|---|
| 440 | 481 | |
|---|
| .. | .. |
|---|
| 453 | 494 | check_global_fault2_reg: |
|---|
| 454 | 495 | ret = regmap_read(tas6424->regmap, TAS6424_GLOB_FAULT2, ®); |
|---|
| 455 | 496 | if (ret < 0) { |
|---|
| 456 | | - dev_err(dev, "failed to read FAULT2 register: %d\n", ret); |
|---|
| 497 | + dev_err(dev, "failed to read GLOB_FAULT2 register: %d\n", ret); |
|---|
| 457 | 498 | goto out; |
|---|
| 458 | 499 | } |
|---|
| 459 | 500 | |
|---|
| .. | .. |
|---|
| 530 | 571 | /* Store current warn value so we can detect any changes next time */ |
|---|
| 531 | 572 | tas6424->last_warn = reg; |
|---|
| 532 | 573 | |
|---|
| 533 | | - /* Clear any faults by toggling the CLEAR_FAULT control bit */ |
|---|
| 574 | + /* Clear any warnings by toggling the CLEAR_FAULT control bit */ |
|---|
| 534 | 575 | ret = regmap_write_bits(tas6424->regmap, TAS6424_MISC_CTRL3, |
|---|
| 535 | 576 | TAS6424_CLEAR_FAULT, TAS6424_CLEAR_FAULT); |
|---|
| 536 | 577 | if (ret < 0) |
|---|