diff options
author | Sameer Pujar <spujar@nvidia.com> | 2019-05-12 12:22:13 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2019-09-19 09:18:57 -0400 |
commit | 2b7eac2f7b1884da40275f5cc6aa119ced599626 (patch) | |
tree | 6fe4e8f9e98baf5ce081375052fb7a6908e5a25c /sound/pci/hda | |
parent | 2ef5d5c4ed7046965fdcaeeb0373798e468a1b2e (diff) |
ALSA: hda/tegra: add chip data
For few features or HW fixes, we have been using DT properties to pass
relevant information. These are not the standard DT bindings. Instead chip
specific information can be used in the driver. Below DT properties are
replaced with suitable chip data members.
1. nvidia,num-sdo-stripe --> war_sdo_lines
2. nvidia,avoid-compact-sdo-bw --> war_sdo_bw
3. nvidia,set-watermark-reg --> set_watermark
4. nvidia,apr-gsc-id --> set_gsc_id
[1] and [2] are HW issues related to Tegra194 and are getting fixed in next
Tegra chip (bug 200376557 and bug 200379206)
[3] and [4] are HW features for which currently added chip data members
to avoid using DT properties. Both by default are false and no programming
is done. Default watermark values will work. These will be removed once
user control is provided. The programming code is retained only for future
purpose.
DT for HDA is updated in other patches in the series, which involves
cleanup and adding compatibe for Tegra194. Other Tegra chips, as of now,
can use legacy DT compatible.
Bug 200454686
Change-Id: I32ccbccaef5ea6b796fb65c1ab9dc0869066887d
Signed-off-by: Sameer Pujar <spujar@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/2117482
(cherry picked from commit 0e013fb24bbb2490c8a706b041ef2e5db219c064)
Reviewed-on: https://git-master.nvidia.com/r/2192652
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Mohan Kumar D <mkumard@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Sharad Gupta <sharadg@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/hda_tegra.c | 55 |
1 files changed, 42 insertions, 13 deletions
diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index c326c79ce..0ef2f5718 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c | |||
@@ -87,10 +87,18 @@ static const struct of_device_id tegra_disb_pd[] = { | |||
87 | 87 | ||
88 | /* GSC_ID register */ | 88 | /* GSC_ID register */ |
89 | #define HDA_GSC_REG 0x1e0 | 89 | #define HDA_GSC_REG 0x1e0 |
90 | #define HDA_GSC_ID 10 | ||
90 | 91 | ||
91 | #define HDA_MAX_CODECS 8 | 92 | #define HDA_MAX_CODECS 8 |
92 | #define CHAR_BUF_SIZE_MAX 50 | 93 | #define CHAR_BUF_SIZE_MAX 50 |
93 | 94 | ||
95 | struct tegra_hda_chip_data { | ||
96 | unsigned int war_sdo_lines; | ||
97 | bool set_watermark; | ||
98 | bool war_sdo_bw; | ||
99 | bool set_gsc_id; | ||
100 | }; | ||
101 | |||
94 | struct hda_pcm_devices { | 102 | struct hda_pcm_devices { |
95 | struct azx_pcm *apcm; | 103 | struct azx_pcm *apcm; |
96 | struct kobject *kobj; | 104 | struct kobject *kobj; |
@@ -111,6 +119,7 @@ struct hda_tegra { | |||
111 | struct work_struct probe_work; | 119 | struct work_struct probe_work; |
112 | struct kobject *kobj; | 120 | struct kobject *kobj; |
113 | struct hda_pcm_devices *hda_pcm_dev; | 121 | struct hda_pcm_devices *hda_pcm_dev; |
122 | const struct tegra_hda_chip_data *cdata; | ||
114 | }; | 123 | }; |
115 | 124 | ||
116 | #ifdef CONFIG_PM | 125 | #ifdef CONFIG_PM |
@@ -452,6 +461,7 @@ static int hda_tegra_init_chip(struct azx *chip, struct platform_device *pdev) | |||
452 | 461 | ||
453 | static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) | 462 | static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) |
454 | { | 463 | { |
464 | struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip); | ||
455 | struct hdac_bus *bus = azx_bus(chip); | 465 | struct hdac_bus *bus = azx_bus(chip); |
456 | struct snd_card *card = chip->card; | 466 | struct snd_card *card = chip->card; |
457 | int err; | 467 | int err; |
@@ -476,11 +486,13 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) | |||
476 | 486 | ||
477 | synchronize_irq(bus->irq); | 487 | synchronize_irq(bus->irq); |
478 | 488 | ||
479 | /* WAR to override no. of SDO lines on T194 */ | 489 | /* |
480 | /* GCAP_NSDO is bits 19:18 in T_AZA_DBG_CFG_2 */ | 490 | * WAR to override no. of SDO lines on T194. |
481 | /* 0 for 1 SDO, 1 for 2 SDO, 2 for 4 SDO lines */ | 491 | * GCAP_NSDO is bits 19:18 in T_AZA_DBG_CFG_2 |
482 | if (!of_property_read_u32(pdev->dev.of_node, "nvidia,num-sdo-stripe", | 492 | * 0 for 1 SDO, 1 for 2 SDO, 2 for 4 SDO lines |
483 | &num_sdo_lines)) { | 493 | */ |
494 | if (hda->cdata && hda->cdata->war_sdo_lines) { | ||
495 | num_sdo_lines = hda->cdata->war_sdo_lines; | ||
484 | dev_info(card->dev, "Override SDO lines to %u\n", | 496 | dev_info(card->dev, "Override SDO lines to %u\n", |
485 | num_sdo_lines); | 497 | num_sdo_lines); |
486 | azx_fpci_updatel(chip, DBG_CFG_2, AZX_FPCI_GCAP_NSDO, | 498 | azx_fpci_updatel(chip, DBG_CFG_2, AZX_FPCI_GCAP_NSDO, |
@@ -592,8 +604,24 @@ static int hda_tegra_create(struct snd_card *card, | |||
592 | return 0; | 604 | return 0; |
593 | } | 605 | } |
594 | 606 | ||
607 | static const struct tegra_hda_chip_data tegra194_cdata = { | ||
608 | /* GCAP reg shows 2 SDO lines which does not reflect true capability */ | ||
609 | .war_sdo_lines = 4, | ||
610 | |||
611 | /* | ||
612 | * audio can support up to 4SDO lines, but 4SDO lines can not support | ||
613 | * 32K/44.1K/48K 2 channel 16bps audio format due to legacy design | ||
614 | * limitation. With below flag, following condition is avoided while | ||
615 | * deciding number of SDO lines for audio stripe functionality. | ||
616 | * { ((num_channels * bits_per_sample) / number of SDOs) = 8 } | ||
617 | * Ref: Section 5.3.2.3 (Revision 1.0a: HD audio spec.) | ||
618 | */ | ||
619 | .war_sdo_bw = true, | ||
620 | }; | ||
621 | |||
595 | static const struct of_device_id hda_tegra_match[] = { | 622 | static const struct of_device_id hda_tegra_match[] = { |
596 | { .compatible = "nvidia,tegra30-hda" }, | 623 | { .compatible = "nvidia,tegra30-hda" }, |
624 | { .compatible = "nvidia,tegra194-hda", .data = &tegra194_cdata}, | ||
597 | {}, | 625 | {}, |
598 | }; | 626 | }; |
599 | MODULE_DEVICE_TABLE(of, hda_tegra_match); | 627 | MODULE_DEVICE_TABLE(of, hda_tegra_match); |
@@ -616,6 +644,9 @@ static int hda_tegra_probe(struct platform_device *pdev) | |||
616 | hda->dev = &pdev->dev; | 644 | hda->dev = &pdev->dev; |
617 | chip = &hda->chip; | 645 | chip = &hda->chip; |
618 | 646 | ||
647 | /* chip data can be NULL for legacy hda devices */ | ||
648 | hda->cdata = of_device_get_match_data(&pdev->dev); | ||
649 | |||
619 | hda->partition_id = tegra_pd_get_powergate_id(tegra_disb_pd); | 650 | hda->partition_id = tegra_pd_get_powergate_id(tegra_disb_pd); |
620 | if (hda->partition_id < 0) { | 651 | if (hda->partition_id < 0) { |
621 | dev_err(&pdev->dev, "Failed to get hda power domain id\n"); | 652 | dev_err(&pdev->dev, "Failed to get hda power domain id\n"); |
@@ -772,8 +803,6 @@ static void hda_tegra_probe_work(struct work_struct *work) | |||
772 | struct hda_tegra *hda = container_of(work, struct hda_tegra, probe_work); | 803 | struct hda_tegra *hda = container_of(work, struct hda_tegra, probe_work); |
773 | struct azx *chip = &hda->chip; | 804 | struct azx *chip = &hda->chip; |
774 | struct platform_device *pdev = to_platform_device(hda->dev); | 805 | struct platform_device *pdev = to_platform_device(hda->dev); |
775 | struct device_node *np = pdev->dev.of_node; | ||
776 | int gsc_id; | ||
777 | struct hdac_bus *bus = azx_bus(chip); | 806 | struct hdac_bus *bus = azx_bus(chip); |
778 | int err; | 807 | int err; |
779 | 808 | ||
@@ -782,19 +811,19 @@ static void hda_tegra_probe_work(struct work_struct *work) | |||
782 | if (err < 0) | 811 | if (err < 0) |
783 | goto out_free; | 812 | goto out_free; |
784 | 813 | ||
785 | bus->avoid_compact_sdo_bw = of_property_read_bool(np, | 814 | if (hda->cdata) |
786 | "nvidia,avoid-compact-sdo-bw"); | 815 | bus->avoid_compact_sdo_bw = hda->cdata->war_sdo_bw; |
787 | 816 | ||
788 | /* Below code sets watermark registers to maximum */ | 817 | /* Below code sets watermark registers to maximum */ |
789 | /* value (same as default); only applicable to T194 */ | 818 | /* value (same as default); only applicable to T194 */ |
790 | if (of_property_read_bool(np, "nvidia,set-watermark-reg")) { | 819 | if (hda->cdata && hda->cdata->set_watermark) { |
791 | azx_fpci_writel(chip, FIFO_WATERMARK, 0x07070707); | 820 | azx_fpci_writel(chip, FIFO_WATERMARK, 0x07070707); |
792 | azx_fpci_writel(chip, BUFSZ_NUM_OF_FRAMES, 0x000a0a0a); | 821 | azx_fpci_writel(chip, BUFSZ_NUM_OF_FRAMES, 0x000a0a0a); |
793 | } | 822 | } |
794 | 823 | ||
795 | /* program HDA GSC_ID to get access to APR */ | 824 | /* program HDA_GSC_ID to get access to APR */ |
796 | if (of_property_read_u32(np, "nvidia,apr-gsc-id", &gsc_id) >= 0) | 825 | if (hda->cdata && hda->cdata->set_gsc_id) |
797 | hda_tegra_writel(gsc_id, hda->regs + HDA_GSC_REG); | 826 | hda_tegra_writel(HDA_GSC_ID, hda->regs + HDA_GSC_REG); |
798 | 827 | ||
799 | /* create codec instances */ | 828 | /* create codec instances */ |
800 | err = azx_probe_codecs(chip, HDA_MAX_CODECS); | 829 | err = azx_probe_codecs(chip, HDA_MAX_CODECS); |