diff options
| -rw-r--r-- | Documentation/devicetree/bindings/sound/ti,tas5086.txt | 11 | ||||
| -rw-r--r-- | sound/soc/codecs/tas5086.c | 330 |
2 files changed, 337 insertions, 4 deletions
diff --git a/Documentation/devicetree/bindings/sound/ti,tas5086.txt b/Documentation/devicetree/bindings/sound/ti,tas5086.txt index 8ea4f5b4818d..d2866a0d6a26 100644 --- a/Documentation/devicetree/bindings/sound/ti,tas5086.txt +++ b/Documentation/devicetree/bindings/sound/ti,tas5086.txt | |||
| @@ -20,6 +20,17 @@ Optional properties: | |||
| 20 | When not specified, the hardware default of 1300ms | 20 | When not specified, the hardware default of 1300ms |
| 21 | is retained. | 21 | is retained. |
| 22 | 22 | ||
| 23 | - ti,mid-z-channel-X: Boolean properties, X being a number from 1 to 6. | ||
| 24 | If given, channel X will start with the Mid-Z start | ||
| 25 | sequence, otherwise the default Low-Z scheme is used. | ||
| 26 | |||
| 27 | The correct configuration depends on how the power | ||
| 28 | stages connected to the PWM output pins work. Not all | ||
| 29 | power stages are compatible to Mid-Z - please refer | ||
| 30 | to the datasheets for more details. | ||
| 31 | |||
| 32 | Most systems should not set any of these properties. | ||
| 33 | |||
| 23 | Examples: | 34 | Examples: |
| 24 | 35 | ||
| 25 | i2c_bus { | 36 | i2c_bus { |
diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c index d447c4aa1d5e..6d31d88f7204 100644 --- a/sound/soc/codecs/tas5086.c +++ b/sound/soc/codecs/tas5086.c | |||
| @@ -83,6 +83,14 @@ | |||
| 83 | #define TAS5086_SPLIT_CAP_CHARGE 0x1a /* Split cap charge period register */ | 83 | #define TAS5086_SPLIT_CAP_CHARGE 0x1a /* Split cap charge period register */ |
| 84 | #define TAS5086_OSC_TRIM 0x1b /* Oscillator trim register */ | 84 | #define TAS5086_OSC_TRIM 0x1b /* Oscillator trim register */ |
| 85 | #define TAS5086_BKNDERR 0x1c | 85 | #define TAS5086_BKNDERR 0x1c |
| 86 | #define TAS5086_INPUT_MUX 0x20 | ||
| 87 | #define TAS5086_PWM_OUTPUT_MUX 0x25 | ||
| 88 | |||
| 89 | #define TAS5086_MAX_REGISTER TAS5086_PWM_OUTPUT_MUX | ||
| 90 | |||
| 91 | #define TAS5086_PWM_START_MIDZ_FOR_START_1 (1 << 7) | ||
| 92 | #define TAS5086_PWM_START_MIDZ_FOR_START_2 (1 << 6) | ||
| 93 | #define TAS5086_PWM_START_CHANNEL_MASK (0x3f) | ||
| 86 | 94 | ||
| 87 | /* | 95 | /* |
| 88 | * Default TAS5086 power-up configuration | 96 | * Default TAS5086 power-up configuration |
| @@ -119,9 +127,30 @@ static const struct reg_default tas5086_reg_defaults[] = { | |||
| 119 | { 0x1c, 0x05 }, | 127 | { 0x1c, 0x05 }, |
| 120 | }; | 128 | }; |
| 121 | 129 | ||
| 130 | static int tas5086_register_size(struct device *dev, unsigned int reg) | ||
| 131 | { | ||
| 132 | switch (reg) { | ||
| 133 | case TAS5086_CLOCK_CONTROL ... TAS5086_BKNDERR: | ||
| 134 | return 1; | ||
| 135 | case TAS5086_INPUT_MUX: | ||
| 136 | case TAS5086_PWM_OUTPUT_MUX: | ||
| 137 | return 4; | ||
| 138 | } | ||
| 139 | |||
| 140 | dev_err(dev, "Unsupported register address: %d\n", reg); | ||
| 141 | return 0; | ||
| 142 | } | ||
| 143 | |||
| 122 | static bool tas5086_accessible_reg(struct device *dev, unsigned int reg) | 144 | static bool tas5086_accessible_reg(struct device *dev, unsigned int reg) |
| 123 | { | 145 | { |
| 124 | return !((reg == 0x0f) || (reg >= 0x11 && reg <= 0x17)); | 146 | switch (reg) { |
| 147 | case 0x0f: | ||
| 148 | case 0x11 ... 0x17: | ||
| 149 | case 0x1d ... 0x1f: | ||
| 150 | return false; | ||
| 151 | default: | ||
| 152 | return true; | ||
| 153 | } | ||
| 125 | } | 154 | } |
| 126 | 155 | ||
| 127 | static bool tas5086_volatile_reg(struct device *dev, unsigned int reg) | 156 | static bool tas5086_volatile_reg(struct device *dev, unsigned int reg) |
| @@ -140,6 +169,76 @@ static bool tas5086_writeable_reg(struct device *dev, unsigned int reg) | |||
| 140 | return tas5086_accessible_reg(dev, reg) && (reg != TAS5086_DEV_ID); | 169 | return tas5086_accessible_reg(dev, reg) && (reg != TAS5086_DEV_ID); |
| 141 | } | 170 | } |
| 142 | 171 | ||
| 172 | static int tas5086_reg_write(void *context, unsigned int reg, | ||
| 173 | unsigned int value) | ||
| 174 | { | ||
| 175 | struct i2c_client *client = context; | ||
| 176 | unsigned int i, size; | ||
| 177 | uint8_t buf[5]; | ||
| 178 | int ret; | ||
| 179 | |||
| 180 | size = tas5086_register_size(&client->dev, reg); | ||
| 181 | if (size == 0) | ||
| 182 | return -EINVAL; | ||
| 183 | |||
| 184 | buf[0] = reg; | ||
| 185 | |||
| 186 | for (i = size; i >= 1; --i) { | ||
| 187 | buf[i] = value; | ||
| 188 | value >>= 8; | ||
| 189 | } | ||
| 190 | |||
| 191 | ret = i2c_master_send(client, buf, size + 1); | ||
| 192 | if (ret == size + 1) | ||
| 193 | return 0; | ||
| 194 | else if (ret < 0) | ||
| 195 | return ret; | ||
| 196 | else | ||
| 197 | return -EIO; | ||
| 198 | } | ||
| 199 | |||
| 200 | static int tas5086_reg_read(void *context, unsigned int reg, | ||
| 201 | unsigned int *value) | ||
| 202 | { | ||
| 203 | struct i2c_client *client = context; | ||
| 204 | uint8_t send_buf, recv_buf[4]; | ||
| 205 | struct i2c_msg msgs[2]; | ||
| 206 | unsigned int size; | ||
| 207 | unsigned int i; | ||
| 208 | int ret; | ||
| 209 | |||
| 210 | size = tas5086_register_size(&client->dev, reg); | ||
| 211 | if (size == 0) | ||
| 212 | return -EINVAL; | ||
| 213 | |||
| 214 | send_buf = reg; | ||
| 215 | |||
| 216 | msgs[0].addr = client->addr; | ||
| 217 | msgs[0].len = sizeof(send_buf); | ||
| 218 | msgs[0].buf = &send_buf; | ||
| 219 | msgs[0].flags = 0; | ||
| 220 | |||
| 221 | msgs[1].addr = client->addr; | ||
| 222 | msgs[1].len = size; | ||
| 223 | msgs[1].buf = recv_buf; | ||
| 224 | msgs[1].flags = I2C_M_RD; | ||
| 225 | |||
| 226 | ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
| 227 | if (ret < 0) | ||
| 228 | return ret; | ||
| 229 | else if (ret != ARRAY_SIZE(msgs)) | ||
| 230 | return -EIO; | ||
| 231 | |||
| 232 | *value = 0; | ||
| 233 | |||
| 234 | for (i = 0; i < size; i++) { | ||
| 235 | *value <<= 8; | ||
| 236 | *value |= recv_buf[i]; | ||
| 237 | } | ||
| 238 | |||
| 239 | return 0; | ||
| 240 | } | ||
| 241 | |||
| 143 | struct tas5086_private { | 242 | struct tas5086_private { |
| 144 | struct regmap *regmap; | 243 | struct regmap *regmap; |
| 145 | unsigned int mclk, sclk; | 244 | unsigned int mclk, sclk; |
| @@ -376,6 +475,202 @@ static const struct snd_kcontrol_new tas5086_controls[] = { | |||
| 376 | tas5086_get_deemph, tas5086_put_deemph), | 475 | tas5086_get_deemph, tas5086_put_deemph), |
| 377 | }; | 476 | }; |
| 378 | 477 | ||
| 478 | /* Input mux controls */ | ||
| 479 | static const char *tas5086_dapm_sdin_texts[] = | ||
| 480 | { | ||
| 481 | "SDIN1-L", "SDIN1-R", "SDIN2-L", "SDIN2-R", | ||
| 482 | "SDIN3-L", "SDIN3-R", "Ground (0)", "nc" | ||
| 483 | }; | ||
| 484 | |||
| 485 | static const struct soc_enum tas5086_dapm_input_mux_enum[] = { | ||
| 486 | SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 20, 8, tas5086_dapm_sdin_texts), | ||
| 487 | SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 16, 8, tas5086_dapm_sdin_texts), | ||
| 488 | SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 12, 8, tas5086_dapm_sdin_texts), | ||
| 489 | SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 8, 8, tas5086_dapm_sdin_texts), | ||
| 490 | SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 4, 8, tas5086_dapm_sdin_texts), | ||
| 491 | SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 0, 8, tas5086_dapm_sdin_texts), | ||
| 492 | }; | ||
| 493 | |||
| 494 | static const struct snd_kcontrol_new tas5086_dapm_input_mux_controls[] = { | ||
| 495 | SOC_DAPM_ENUM("Channel 1 input", tas5086_dapm_input_mux_enum[0]), | ||
| 496 | SOC_DAPM_ENUM("Channel 2 input", tas5086_dapm_input_mux_enum[1]), | ||
| 497 | SOC_DAPM_ENUM("Channel 3 input", tas5086_dapm_input_mux_enum[2]), | ||
| 498 | SOC_DAPM_ENUM("Channel 4 input", tas5086_dapm_input_mux_enum[3]), | ||
| 499 | SOC_DAPM_ENUM("Channel 5 input", tas5086_dapm_input_mux_enum[4]), | ||
| 500 | SOC_DAPM_ENUM("Channel 6 input", tas5086_dapm_input_mux_enum[5]), | ||
| 501 | }; | ||
| 502 | |||
| 503 | /* Output mux controls */ | ||
| 504 | static const char *tas5086_dapm_channel_texts[] = | ||
| 505 | { "Channel 1 Mux", "Channel 2 Mux", "Channel 3 Mux", | ||
| 506 | "Channel 4 Mux", "Channel 5 Mux", "Channel 6 Mux" }; | ||
| 507 | |||
| 508 | static const struct soc_enum tas5086_dapm_output_mux_enum[] = { | ||
| 509 | SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 20, 6, tas5086_dapm_channel_texts), | ||
| 510 | SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 16, 6, tas5086_dapm_channel_texts), | ||
| 511 | SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 12, 6, tas5086_dapm_channel_texts), | ||
| 512 | SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 8, 6, tas5086_dapm_channel_texts), | ||
| 513 | SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 4, 6, tas5086_dapm_channel_texts), | ||
| 514 | SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 0, 6, tas5086_dapm_channel_texts), | ||
| 515 | }; | ||
| 516 | |||
| 517 | static const struct snd_kcontrol_new tas5086_dapm_output_mux_controls[] = { | ||
| 518 | SOC_DAPM_ENUM("PWM1 Output", tas5086_dapm_output_mux_enum[0]), | ||
| 519 | SOC_DAPM_ENUM("PWM2 Output", tas5086_dapm_output_mux_enum[1]), | ||
| 520 | SOC_DAPM_ENUM("PWM3 Output", tas5086_dapm_output_mux_enum[2]), | ||
| 521 | SOC_DAPM_ENUM("PWM4 Output", tas5086_dapm_output_mux_enum[3]), | ||
| 522 | SOC_DAPM_ENUM("PWM5 Output", tas5086_dapm_output_mux_enum[4]), | ||
| 523 | SOC_DAPM_ENUM("PWM6 Output", tas5086_dapm_output_mux_enum[5]), | ||
| 524 | }; | ||
| 525 | |||
| 526 | static const struct snd_soc_dapm_widget tas5086_dapm_widgets[] = { | ||
| 527 | SND_SOC_DAPM_INPUT("SDIN1-L"), | ||
| 528 | SND_SOC_DAPM_INPUT("SDIN1-R"), | ||
| 529 | SND_SOC_DAPM_INPUT("SDIN2-L"), | ||
| 530 | SND_SOC_DAPM_INPUT("SDIN2-R"), | ||
| 531 | SND_SOC_DAPM_INPUT("SDIN3-L"), | ||
| 532 | SND_SOC_DAPM_INPUT("SDIN3-R"), | ||
| 533 | SND_SOC_DAPM_INPUT("SDIN4-L"), | ||
| 534 | SND_SOC_DAPM_INPUT("SDIN4-R"), | ||
| 535 | |||
| 536 | SND_SOC_DAPM_OUTPUT("PWM1"), | ||
| 537 | SND_SOC_DAPM_OUTPUT("PWM2"), | ||
| 538 | SND_SOC_DAPM_OUTPUT("PWM3"), | ||
| 539 | SND_SOC_DAPM_OUTPUT("PWM4"), | ||
| 540 | SND_SOC_DAPM_OUTPUT("PWM5"), | ||
| 541 | SND_SOC_DAPM_OUTPUT("PWM6"), | ||
| 542 | |||
| 543 | SND_SOC_DAPM_MUX("Channel 1 Mux", SND_SOC_NOPM, 0, 0, | ||
| 544 | &tas5086_dapm_input_mux_controls[0]), | ||
| 545 | SND_SOC_DAPM_MUX("Channel 2 Mux", SND_SOC_NOPM, 0, 0, | ||
| 546 | &tas5086_dapm_input_mux_controls[1]), | ||
| 547 | SND_SOC_DAPM_MUX("Channel 3 Mux", SND_SOC_NOPM, 0, 0, | ||
| 548 | &tas5086_dapm_input_mux_controls[2]), | ||
| 549 | SND_SOC_DAPM_MUX("Channel 4 Mux", SND_SOC_NOPM, 0, 0, | ||
| 550 | &tas5086_dapm_input_mux_controls[3]), | ||
| 551 | SND_SOC_DAPM_MUX("Channel 5 Mux", SND_SOC_NOPM, 0, 0, | ||
| 552 | &tas5086_dapm_input_mux_controls[4]), | ||
| 553 | SND_SOC_DAPM_MUX("Channel 6 Mux", SND_SOC_NOPM, 0, 0, | ||
| 554 | &tas5086_dapm_input_mux_controls[5]), | ||
| 555 | |||
| 556 | SND_SOC_DAPM_MUX("PWM1 Mux", SND_SOC_NOPM, 0, 0, | ||
| 557 | &tas5086_dapm_output_mux_controls[0]), | ||
| 558 | SND_SOC_DAPM_MUX("PWM2 Mux", SND_SOC_NOPM, 0, 0, | ||
| 559 | &tas5086_dapm_output_mux_controls[1]), | ||
| 560 | SND_SOC_DAPM_MUX("PWM3 Mux", SND_SOC_NOPM, 0, 0, | ||
| 561 | &tas5086_dapm_output_mux_controls[2]), | ||
| 562 | SND_SOC_DAPM_MUX("PWM4 Mux", SND_SOC_NOPM, 0, 0, | ||
| 563 | &tas5086_dapm_output_mux_controls[3]), | ||
| 564 | SND_SOC_DAPM_MUX("PWM5 Mux", SND_SOC_NOPM, 0, 0, | ||
| 565 | &tas5086_dapm_output_mux_controls[4]), | ||
| 566 | SND_SOC_DAPM_MUX("PWM6 Mux", SND_SOC_NOPM, 0, 0, | ||
| 567 | &tas5086_dapm_output_mux_controls[5]), | ||
| 568 | }; | ||
| 569 | |||
| 570 | static const struct snd_soc_dapm_route tas5086_dapm_routes[] = { | ||
| 571 | /* SDIN inputs -> channel muxes */ | ||
| 572 | { "Channel 1 Mux", "SDIN1-L", "SDIN1-L" }, | ||
| 573 | { "Channel 1 Mux", "SDIN1-R", "SDIN1-R" }, | ||
| 574 | { "Channel 1 Mux", "SDIN2-L", "SDIN2-L" }, | ||
| 575 | { "Channel 1 Mux", "SDIN2-R", "SDIN2-R" }, | ||
| 576 | { "Channel 1 Mux", "SDIN3-L", "SDIN3-L" }, | ||
| 577 | { "Channel 1 Mux", "SDIN3-R", "SDIN3-R" }, | ||
| 578 | |||
| 579 | { "Channel 2 Mux", "SDIN1-L", "SDIN1-L" }, | ||
| 580 | { "Channel 2 Mux", "SDIN1-R", "SDIN1-R" }, | ||
| 581 | { "Channel 2 Mux", "SDIN2-L", "SDIN2-L" }, | ||
| 582 | { "Channel 2 Mux", "SDIN2-R", "SDIN2-R" }, | ||
| 583 | { "Channel 2 Mux", "SDIN3-L", "SDIN3-L" }, | ||
| 584 | { "Channel 2 Mux", "SDIN3-R", "SDIN3-R" }, | ||
| 585 | |||
| 586 | { "Channel 2 Mux", "SDIN1-L", "SDIN1-L" }, | ||
| 587 | { "Channel 2 Mux", "SDIN1-R", "SDIN1-R" }, | ||
| 588 | { "Channel 2 Mux", "SDIN2-L", "SDIN2-L" }, | ||
| 589 | { "Channel 2 Mux", "SDIN2-R", "SDIN2-R" }, | ||
| 590 | { "Channel 2 Mux", "SDIN3-L", "SDIN3-L" }, | ||
| 591 | { "Channel 2 Mux", "SDIN3-R", "SDIN3-R" }, | ||
| 592 | |||
| 593 | { "Channel 3 Mux", "SDIN1-L", "SDIN1-L" }, | ||
| 594 | { "Channel 3 Mux", "SDIN1-R", "SDIN1-R" }, | ||
| 595 | { "Channel 3 Mux", "SDIN2-L", "SDIN2-L" }, | ||
| 596 | { "Channel 3 Mux", "SDIN2-R", "SDIN2-R" }, | ||
| 597 | { "Channel 3 Mux", "SDIN3-L", "SDIN3-L" }, | ||
| 598 | { "Channel 3 Mux", "SDIN3-R", "SDIN3-R" }, | ||
| 599 | |||
| 600 | { "Channel 4 Mux", "SDIN1-L", "SDIN1-L" }, | ||
| 601 | { "Channel 4 Mux", "SDIN1-R", "SDIN1-R" }, | ||
| 602 | { "Channel 4 Mux", "SDIN2-L", "SDIN2-L" }, | ||
| 603 | { "Channel 4 Mux", "SDIN2-R", "SDIN2-R" }, | ||
| 604 | { "Channel 4 Mux", "SDIN3-L", "SDIN3-L" }, | ||
| 605 | { "Channel 4 Mux", "SDIN3-R", "SDIN3-R" }, | ||
| 606 | |||
| 607 | { "Channel 5 Mux", "SDIN1-L", "SDIN1-L" }, | ||
| 608 | { "Channel 5 Mux", "SDIN1-R", "SDIN1-R" }, | ||
| 609 | { "Channel 5 Mux", "SDIN2-L", "SDIN2-L" }, | ||
| 610 | { "Channel 5 Mux", "SDIN2-R", "SDIN2-R" }, | ||
| 611 | { "Channel 5 Mux", "SDIN3-L", "SDIN3-L" }, | ||
| 612 | { "Channel 5 Mux", "SDIN3-R", "SDIN3-R" }, | ||
| 613 | |||
| 614 | { "Channel 6 Mux", "SDIN1-L", "SDIN1-L" }, | ||
| 615 | { "Channel 6 Mux", "SDIN1-R", "SDIN1-R" }, | ||
| 616 | { "Channel 6 Mux", "SDIN2-L", "SDIN2-L" }, | ||
| 617 | { "Channel 6 Mux", "SDIN2-R", "SDIN2-R" }, | ||
| 618 | { "Channel 6 Mux", "SDIN3-L", "SDIN3-L" }, | ||
| 619 | { "Channel 6 Mux", "SDIN3-R", "SDIN3-R" }, | ||
| 620 | |||
| 621 | /* Channel muxes -> PWM muxes */ | ||
| 622 | { "PWM1 Mux", "Channel 1 Mux", "Channel 1 Mux" }, | ||
| 623 | { "PWM2 Mux", "Channel 1 Mux", "Channel 1 Mux" }, | ||
| 624 | { "PWM3 Mux", "Channel 1 Mux", "Channel 1 Mux" }, | ||
| 625 | { "PWM4 Mux", "Channel 1 Mux", "Channel 1 Mux" }, | ||
| 626 | { "PWM5 Mux", "Channel 1 Mux", "Channel 1 Mux" }, | ||
| 627 | { "PWM6 Mux", "Channel 1 Mux", "Channel 1 Mux" }, | ||
| 628 | |||
| 629 | { "PWM1 Mux", "Channel 2 Mux", "Channel 2 Mux" }, | ||
| 630 | { "PWM2 Mux", "Channel 2 Mux", "Channel 2 Mux" }, | ||
| 631 | { "PWM3 Mux", "Channel 2 Mux", "Channel 2 Mux" }, | ||
| 632 | { "PWM4 Mux", "Channel 2 Mux", "Channel 2 Mux" }, | ||
| 633 | { "PWM5 Mux", "Channel 2 Mux", "Channel 2 Mux" }, | ||
| 634 | { "PWM6 Mux", "Channel 2 Mux", "Channel 2 Mux" }, | ||
| 635 | |||
| 636 | { "PWM1 Mux", "Channel 3 Mux", "Channel 3 Mux" }, | ||
| 637 | { "PWM2 Mux", "Channel 3 Mux", "Channel 3 Mux" }, | ||
| 638 | { "PWM3 Mux", "Channel 3 Mux", "Channel 3 Mux" }, | ||
| 639 | { "PWM4 Mux", "Channel 3 Mux", "Channel 3 Mux" }, | ||
| 640 | { "PWM5 Mux", "Channel 3 Mux", "Channel 3 Mux" }, | ||
| 641 | { "PWM6 Mux", "Channel 3 Mux", "Channel 3 Mux" }, | ||
| 642 | |||
| 643 | { "PWM1 Mux", "Channel 4 Mux", "Channel 4 Mux" }, | ||
| 644 | { "PWM2 Mux", "Channel 4 Mux", "Channel 4 Mux" }, | ||
| 645 | { "PWM3 Mux", "Channel 4 Mux", "Channel 4 Mux" }, | ||
| 646 | { "PWM4 Mux", "Channel 4 Mux", "Channel 4 Mux" }, | ||
| 647 | { "PWM5 Mux", "Channel 4 Mux", "Channel 4 Mux" }, | ||
| 648 | { "PWM6 Mux", "Channel 4 Mux", "Channel 4 Mux" }, | ||
| 649 | |||
| 650 | { "PWM1 Mux", "Channel 5 Mux", "Channel 5 Mux" }, | ||
| 651 | { "PWM2 Mux", "Channel 5 Mux", "Channel 5 Mux" }, | ||
| 652 | { "PWM3 Mux", "Channel 5 Mux", "Channel 5 Mux" }, | ||
| 653 | { "PWM4 Mux", "Channel 5 Mux", "Channel 5 Mux" }, | ||
| 654 | { "PWM5 Mux", "Channel 5 Mux", "Channel 5 Mux" }, | ||
| 655 | { "PWM6 Mux", "Channel 5 Mux", "Channel 5 Mux" }, | ||
| 656 | |||
| 657 | { "PWM1 Mux", "Channel 6 Mux", "Channel 6 Mux" }, | ||
| 658 | { "PWM2 Mux", "Channel 6 Mux", "Channel 6 Mux" }, | ||
| 659 | { "PWM3 Mux", "Channel 6 Mux", "Channel 6 Mux" }, | ||
| 660 | { "PWM4 Mux", "Channel 6 Mux", "Channel 6 Mux" }, | ||
| 661 | { "PWM5 Mux", "Channel 6 Mux", "Channel 6 Mux" }, | ||
| 662 | { "PWM6 Mux", "Channel 6 Mux", "Channel 6 Mux" }, | ||
| 663 | |||
| 664 | /* The PWM muxes are directly connected to the PWM outputs */ | ||
| 665 | { "PWM1", NULL, "PWM1 Mux" }, | ||
| 666 | { "PWM2", NULL, "PWM2 Mux" }, | ||
| 667 | { "PWM3", NULL, "PWM3 Mux" }, | ||
| 668 | { "PWM4", NULL, "PWM4 Mux" }, | ||
| 669 | { "PWM5", NULL, "PWM5 Mux" }, | ||
| 670 | { "PWM6", NULL, "PWM6 Mux" }, | ||
| 671 | |||
| 672 | }; | ||
| 673 | |||
| 379 | static const struct snd_soc_dai_ops tas5086_dai_ops = { | 674 | static const struct snd_soc_dai_ops tas5086_dai_ops = { |
| 380 | .hw_params = tas5086_hw_params, | 675 | .hw_params = tas5086_hw_params, |
| 381 | .set_sysclk = tas5086_set_dai_sysclk, | 676 | .set_sysclk = tas5086_set_dai_sysclk, |
| @@ -426,13 +721,34 @@ static int tas5086_probe(struct snd_soc_codec *codec) | |||
| 426 | { | 721 | { |
| 427 | struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); | 722 | struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); |
| 428 | int charge_period = 1300000; /* hardware default is 1300 ms */ | 723 | int charge_period = 1300000; /* hardware default is 1300 ms */ |
| 724 | u8 pwm_start_mid_z = 0; | ||
| 429 | int i, ret; | 725 | int i, ret; |
| 430 | 726 | ||
| 431 | if (of_match_device(of_match_ptr(tas5086_dt_ids), codec->dev)) { | 727 | if (of_match_device(of_match_ptr(tas5086_dt_ids), codec->dev)) { |
| 432 | struct device_node *of_node = codec->dev->of_node; | 728 | struct device_node *of_node = codec->dev->of_node; |
| 433 | of_property_read_u32(of_node, "ti,charge-period", &charge_period); | 729 | of_property_read_u32(of_node, "ti,charge-period", &charge_period); |
| 730 | |||
| 731 | for (i = 0; i < 6; i++) { | ||
| 732 | char name[25]; | ||
| 733 | |||
| 734 | snprintf(name, sizeof(name), | ||
| 735 | "ti,mid-z-channel-%d", i + 1); | ||
| 736 | |||
| 737 | if (of_get_property(of_node, name, NULL) != NULL) | ||
| 738 | pwm_start_mid_z |= 1 << i; | ||
| 739 | } | ||
| 434 | } | 740 | } |
| 435 | 741 | ||
| 742 | /* | ||
| 743 | * If any of the channels is configured to start in Mid-Z mode, | ||
| 744 | * configure 'part 1' of the PWM starts to use Mid-Z, and tell | ||
| 745 | * all configured mid-z channels to start start under 'part 1'. | ||
| 746 | */ | ||
| 747 | if (pwm_start_mid_z) | ||
| 748 | regmap_write(priv->regmap, TAS5086_PWM_START, | ||
| 749 | TAS5086_PWM_START_MIDZ_FOR_START_1 | | ||
| 750 | pwm_start_mid_z); | ||
| 751 | |||
| 436 | /* lookup and set split-capacitor charge period */ | 752 | /* lookup and set split-capacitor charge period */ |
| 437 | if (charge_period == 0) { | 753 | if (charge_period == 0) { |
| 438 | regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE, 0); | 754 | regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE, 0); |
| @@ -490,6 +806,10 @@ static struct snd_soc_codec_driver soc_codec_dev_tas5086 = { | |||
| 490 | .resume = tas5086_soc_resume, | 806 | .resume = tas5086_soc_resume, |
| 491 | .controls = tas5086_controls, | 807 | .controls = tas5086_controls, |
| 492 | .num_controls = ARRAY_SIZE(tas5086_controls), | 808 | .num_controls = ARRAY_SIZE(tas5086_controls), |
| 809 | .dapm_widgets = tas5086_dapm_widgets, | ||
| 810 | .num_dapm_widgets = ARRAY_SIZE(tas5086_dapm_widgets), | ||
| 811 | .dapm_routes = tas5086_dapm_routes, | ||
| 812 | .num_dapm_routes = ARRAY_SIZE(tas5086_dapm_routes), | ||
| 493 | }; | 813 | }; |
| 494 | 814 | ||
| 495 | static const struct i2c_device_id tas5086_i2c_id[] = { | 815 | static const struct i2c_device_id tas5086_i2c_id[] = { |
| @@ -500,14 +820,16 @@ MODULE_DEVICE_TABLE(i2c, tas5086_i2c_id); | |||
| 500 | 820 | ||
| 501 | static const struct regmap_config tas5086_regmap = { | 821 | static const struct regmap_config tas5086_regmap = { |
| 502 | .reg_bits = 8, | 822 | .reg_bits = 8, |
| 503 | .val_bits = 8, | 823 | .val_bits = 32, |
| 504 | .max_register = ARRAY_SIZE(tas5086_reg_defaults), | 824 | .max_register = TAS5086_MAX_REGISTER, |
| 505 | .reg_defaults = tas5086_reg_defaults, | 825 | .reg_defaults = tas5086_reg_defaults, |
| 506 | .num_reg_defaults = ARRAY_SIZE(tas5086_reg_defaults), | 826 | .num_reg_defaults = ARRAY_SIZE(tas5086_reg_defaults), |
| 507 | .cache_type = REGCACHE_RBTREE, | 827 | .cache_type = REGCACHE_RBTREE, |
| 508 | .volatile_reg = tas5086_volatile_reg, | 828 | .volatile_reg = tas5086_volatile_reg, |
| 509 | .writeable_reg = tas5086_writeable_reg, | 829 | .writeable_reg = tas5086_writeable_reg, |
| 510 | .readable_reg = tas5086_accessible_reg, | 830 | .readable_reg = tas5086_accessible_reg, |
| 831 | .reg_read = tas5086_reg_read, | ||
| 832 | .reg_write = tas5086_reg_write, | ||
| 511 | }; | 833 | }; |
| 512 | 834 | ||
| 513 | static int tas5086_i2c_probe(struct i2c_client *i2c, | 835 | static int tas5086_i2c_probe(struct i2c_client *i2c, |
| @@ -522,7 +844,7 @@ static int tas5086_i2c_probe(struct i2c_client *i2c, | |||
| 522 | if (!priv) | 844 | if (!priv) |
| 523 | return -ENOMEM; | 845 | return -ENOMEM; |
| 524 | 846 | ||
| 525 | priv->regmap = devm_regmap_init_i2c(i2c, &tas5086_regmap); | 847 | priv->regmap = devm_regmap_init(dev, NULL, i2c, &tas5086_regmap); |
| 526 | if (IS_ERR(priv->regmap)) { | 848 | if (IS_ERR(priv->regmap)) { |
| 527 | ret = PTR_ERR(priv->regmap); | 849 | ret = PTR_ERR(priv->regmap); |
| 528 | dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret); | 850 | dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret); |
