On Fri, May 23, 2014 at 1:34 PM, Dylan Reid <[email protected]> wrote:
> On Fri, May 23, 2014 at 12:05 PM, Stephen Warren <[email protected]>
> wrote:
>> On 05/22/2014 09:55 PM, Dylan Reid wrote:
>> ...
>>>>>>>>>> On Tue, May 20, 2014 at 2:55 PM, Stephen Warren
>>>>>>>>>> <[email protected]> wrote:
>> ...
>>>>>>>>>>> Now I have the same results as Thierry; speaker-test looks like it
>>>>>>>>>>> should be working, yet I don't hear any audio from the monitor. I
>>>>>>>>>>> know
>>>>>>>>>>> the monitor works, since I've used it extensively for testing
>>>>>>>>>>> GeForce
>>>>>>>>>>> GPU HDMI audio.
>> ...
>>> Took all day, but I did get to try this.
>>>
>>> on U-Boot commit d7782d0, flashed with Stephen's u-boot flasher from github.
>>>
>>> And kernel at 81d0207 - ARM: tegra: enable HD-Audio controller in defconfig
>>> plus the addition of the hda node "okay" to the jetson-tk1 DT.
>>>
>>> I can hear the jetson's audio on the TV. This is currently a sample
>>> size of one TV, I'll set up the Quantum Data tomorrow and check that
>>> it works there as well.
>>
>> I tried that same U-Boot commit (with a few device-mode USB patches on
>> top that shouldn't affect anything since I didn't use USB device mode)
>> and have the same results.
>>
>> My monitor is a Dell U2410 with sound bar.
I found one of these. I also didn't hear any audio. In fact I
couldn't get audio out of most monitors, TV sets worked fine.
hdmi.c couldn't configure audio for the pixel clock generated for the
monitor. Luckily I found a patch in our downstream tree that fixes
it.
video: tegra: Calculate HDMI audio CTS/N/AVAL values -- 7/25/11 author
swarren =)
Thanks for fixing this for me!
I can send this up unless you'd rather send it yourself.
I appended the patch moved to the new location of hdmi.c:
video: tegra: Calculate HDMI audio CTS/N/AVAL values
The current table-drive approach for determining the CTS/N/AVAL values
required for HDMI audio limits audio availability to a small set of
pixel clock frequencies. Allow audio in other cases by calculating the
CTS and N value dynamically where the tables don't contain
pre-calculated values.
---
drivers/gpu/drm/tegra/hdmi.c | 143 +++++++++++--------------------------------
1 file changed, 35 insertions(+), 108 deletions(-)
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index fec1a63..453e515 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -9,6 +9,7 @@
#include <linux/clk.h>
#include <linux/debugfs.h>
+#include <linux/gcd.h>
#include <linux/hdmi.h>
#include <linux/regulator/consumer.h>
#include <linux/reset.h>
@@ -104,61 +105,34 @@ struct tegra_hdmi_audio_config {
unsigned int aval;
};
-static const struct tegra_hdmi_audio_config tegra_hdmi_audio_32k[] = {
- { 25200000, 4096, 25200, 24000 },
- { 27000000, 4096, 27000, 24000 },
- { 74250000, 4096, 74250, 24000 },
- { 148500000, 4096, 148500, 24000 },
- { 0, 0, 0, 0 },
-};
-
-static const struct tegra_hdmi_audio_config tegra_hdmi_audio_44_1k[] = {
- { 25200000, 5880, 26250, 25000 },
- { 27000000, 5880, 28125, 25000 },
- { 74250000, 4704, 61875, 20000 },
- { 148500000, 4704, 123750, 20000 },
- { 0, 0, 0, 0 },
-};
-
-static const struct tegra_hdmi_audio_config tegra_hdmi_audio_48k[] = {
- { 25200000, 6144, 25200, 24000 },
- { 27000000, 6144, 27000, 24000 },
- { 74250000, 6144, 74250, 24000 },
- { 148500000, 6144, 148500, 24000 },
- { 0, 0, 0, 0 },
-};
-
-static const struct tegra_hdmi_audio_config tegra_hdmi_audio_88_2k[] = {
- { 25200000, 11760, 26250, 25000 },
- { 27000000, 11760, 28125, 25000 },
- { 74250000, 9408, 61875, 20000 },
- { 148500000, 9408, 123750, 20000 },
- { 0, 0, 0, 0 },
-};
-
-static const struct tegra_hdmi_audio_config tegra_hdmi_audio_96k[] = {
- { 25200000, 12288, 25200, 24000 },
- { 27000000, 12288, 27000, 24000 },
- { 74250000, 12288, 74250, 24000 },
- { 148500000, 12288, 148500, 24000 },
- { 0, 0, 0, 0 },
-};
+static int tegra_hdmi_calc_audio_cts_n(unsigned fs, unsigned pixel_rate,
+ unsigned *hda_cts, unsigned *hda_n,
+ unsigned *hda_aval)
+{
+ /* Ideal ACR interval is 1000 hz (1 ms) */
+ unsigned n_ideal = (128 * fs) / 1000;
+ unsigned cts = pixel_rate;
+ unsigned n = 128 * fs;
+ unsigned common_divisor = gcd(cts, n);
+ unsigned mult;
+
+ cts /= common_divisor;
+ n /= common_divisor;
+ mult = n_ideal / n;
+ if (mult) {
+ n *= mult;
+ cts *= mult;
+ }
-static const struct tegra_hdmi_audio_config tegra_hdmi_audio_176_4k[] = {
- { 25200000, 23520, 26250, 25000 },
- { 27000000, 23520, 28125, 25000 },
- { 74250000, 18816, 61875, 20000 },
- { 148500000, 18816, 123750, 20000 },
- { 0, 0, 0, 0 },
-};
+ if (cts < (1 << 20)) {
+ *hda_cts = cts;
+ *hda_n = n;
+ *hda_aval = 240000UL * n / (128 * fs / 100);
+ return 0;
+ }
-static const struct tegra_hdmi_audio_config tegra_hdmi_audio_192k[] = {
- { 25200000, 24576, 25200, 24000 },
- { 27000000, 24576, 27000, 24000 },
- { 74250000, 24576, 74250, 24000 },
- { 148500000, 24576, 148500, 24000 },
- { 0, 0, 0, 0 },
-};
+ return -EINVAL;
+}
static const struct tmds_config tegra20_tmds_config[] = {
{ /* slow pixel clock modes */
@@ -397,54 +371,6 @@ static const struct tmds_config tegra124_tmds_config[] = {
},
};
-static const struct tegra_hdmi_audio_config *
-tegra_hdmi_get_audio_config(unsigned int audio_freq, unsigned int pclk)
-{
- const struct tegra_hdmi_audio_config *table;
-
- switch (audio_freq) {
- case 32000:
- table = tegra_hdmi_audio_32k;
- break;
-
- case 44100:
- table = tegra_hdmi_audio_44_1k;
- break;
-
- case 48000:
- table = tegra_hdmi_audio_48k;
- break;
-
- case 88200:
- table = tegra_hdmi_audio_88_2k;
- break;
-
- case 96000:
- table = tegra_hdmi_audio_96k;
- break;
-
- case 176400:
- table = tegra_hdmi_audio_176_4k;
- break;
-
- case 192000:
- table = tegra_hdmi_audio_192k;
- break;
-
- default:
- return NULL;
- }
-
- while (table->pclk) {
- if (table->pclk == pclk)
- return table;
-
- table++;
- }
-
- return NULL;
-}
-
static void tegra_hdmi_setup_audio_fs_tables(struct tegra_hdmi *hdmi)
{
const unsigned int freqs[] = {
@@ -475,7 +401,7 @@ static void
tegra_hdmi_setup_audio_fs_tables(struct tegra_hdmi *hdmi)
static int tegra_hdmi_setup_audio(struct tegra_hdmi *hdmi, unsigned int pclk)
{
struct device_node *node = hdmi->dev->of_node;
- const struct tegra_hdmi_audio_config *config;
+ unsigned hda_n, hda_cts, hda_aval;
unsigned int offset = 0;
unsigned long value;
@@ -506,8 +432,9 @@ static int tegra_hdmi_setup_audio(struct
tegra_hdmi *hdmi, unsigned int pclk)
tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_CNTRL0);
}
- config = tegra_hdmi_get_audio_config(hdmi->audio_freq, pclk);
- if (!config) {
+ if (tegra_hdmi_calc_audio_cts_n(hdmi->audio_freq,
+ clk_get_rate(hdmi->clk),
+ &hda_cts, &hda_n, &hda_aval) < 0) {
dev_err(hdmi->dev, "cannot set audio to %u at %u pclk\n",
hdmi->audio_freq, pclk);
return -EINVAL;
@@ -516,13 +443,13 @@ static int tegra_hdmi_setup_audio(struct
tegra_hdmi *hdmi, unsigned int pclk)
tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_HDMI_ACR_CTRL);
value = AUDIO_N_RESETF | AUDIO_N_GENERATE_ALTERNATE |
- AUDIO_N_VALUE(config->n - 1);
+ AUDIO_N_VALUE(hda_n - 1);
tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_N);
- tegra_hdmi_writel(hdmi, ACR_SUBPACK_N(config->n) | ACR_ENABLE,
+ tegra_hdmi_writel(hdmi, ACR_SUBPACK_N(hda_n) | ACR_ENABLE,
HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH);
- value = ACR_SUBPACK_CTS(config->cts);
+ value = ACR_SUBPACK_CTS(hda_cts);
tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW);
value = SPARE_HW_CTS | SPARE_FORCE_SW_CTS | SPARE_CTS_RESET_VAL(1);
@@ -563,7 +490,7 @@ static int tegra_hdmi_setup_audio(struct
tegra_hdmi *hdmi, unsigned int pclk)
break;
}
- tegra_hdmi_writel(hdmi, config->aval, offset);
+ tegra_hdmi_writel(hdmi, hda_aval, offset);
}
tegra_hdmi_setup_audio_fs_tables(hdmi);
--
1.8.1.3.605.g02339dd
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html