* [PATCH] OMAPDSS: HDMI: Rework function to calculate N/CTS params
@ 2013-01-11 0:53 Ricardo Neri
0 siblings, 0 replies; only message in thread
From: Ricardo Neri @ 2013-01-11 0:53 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: dzuniga, linux-omap, Ricardo Neri
The function is reworked to be more readable and fix wrong computations at two
corner cases:
*It takes advantage of the properties of the N and CTS values to recursively
compute the parameters for the highest audio sample rates.
*Fix an overflow in the computation of CTS that was happening with the
pclk = 148.5MHz, fs=176.4kHz and color of 36 bits/pixel use case.
*The N value is updated for the pclk=27.027MHz, fs=32kHz and color of
30 bits/pixel use case to produce a CTS value that is closer to an
integer and, therefore, produce less clock drift. However, no valid
value of N can yield to an integer CTS value for such use case.
Signed-off-by: Ricardo Neri <rneri@dextratech.com>
---
| 142 ++++++++++++++++++++--------------------
1 file changed, 70 insertions(+), 72 deletions(-)
--git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 769d082..0857834 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -824,100 +824,98 @@ static void hdmi_put_clocks(void)
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts)
{
+ int r;
u32 deep_color;
- bool deep_color_correct = false;
u32 pclk = hdmi.ip_data.cfg.timings.pixel_clock;
- if (n == NULL || cts == NULL)
+ if (n == NULL || cts == NULL || sample_freq == 0)
return -EINVAL;
/* TODO: When implemented, query deep color mode here. */
deep_color = 100;
- /*
- * When using deep color, the default N value (as in the HDMI
- * specification) yields to an non-integer CTS. Hence, we
- * modify it while keeping the restrictions described in
- * section 7.2.1 of the HDMI 1.4a specification.
- */
switch (sample_freq) {
case 32000:
- case 48000:
- case 96000:
- case 192000:
- if (deep_color == 125)
- if (pclk == 27027 || pclk == 74250)
- deep_color_correct = true;
- if (deep_color == 150)
- if (pclk == 27027)
- deep_color_correct = true;
- break;
- case 44100:
- case 88200:
- case 176400:
- if (deep_color == 125)
- if (pclk == 27027)
- deep_color_correct = true;
- break;
- default:
- return -EINVAL;
- }
-
- if (deep_color_correct) {
- switch (sample_freq) {
- case 32000:
+ if (deep_color == 125 && pclk == 74250) {
*n = 8192;
break;
- case 44100:
- *n = 12544;
+ }
+
+ if (deep_color == 125 && pclk == 27027) {
+ /*
+ * For this specific configuration, no value within the
+ * allowed interval of N (as per the HDMI spec) will
+ * produce an integer value of CTS. The value we use
+ * here will produce CTS = 11587.000427246, which is
+ * slightly larger than the integer. This difference
+ * could cause the audio clock at the sink to slowly
+ * drift. The true solution requires alternating between
+ * two CTS relevant values with careful timing in order
+ * to, on average, obtain the true CTS float value.
+ */
+ *n = 13529;
break;
- case 48000:
+ }
+
+ if (deep_color == 150 && pclk == 27027) {
*n = 8192;
break;
- case 88200:
- *n = 25088;
- break;
- case 96000:
- *n = 16384;
- break;
- case 176400:
- *n = 50176;
- break;
- case 192000:
- *n = 32768;
- break;
- default:
- return -EINVAL;
}
- } else {
- switch (sample_freq) {
- case 32000:
- *n = 4096;
- break;
- case 44100:
- *n = 6272;
- break;
- case 48000:
- *n = 6144;
- break;
- case 88200:
+
+ *n = 4096;
+ break;
+ case 44100:
+ if (deep_color == 125 && pclk == 27027) {
*n = 12544;
break;
- case 96000:
- *n = 12288;
- break;
- case 176400:
- *n = 25088;
+ }
+
+ *n = 6272;
+ break;
+ case 48000:
+ if (deep_color == 125 && (pclk == 27027 || pclk == 74250)) {
+ *n = 8192;
break;
- case 192000:
- *n = 24576;
+ }
+
+ if (deep_color == 150 && pclk == 27027) {
+ *n = 8192;
break;
- default:
- return -EINVAL;
}
+
+ *n = 6144;
+ break;
+ case 88200:
+ r = hdmi_compute_acr(44100, n, cts);
+ *n *= 2;
+ return r;
+ case 96000:
+ r = hdmi_compute_acr(48000, n, cts);
+ *n *= 2;
+ return r;
+ case 176400:
+ r = hdmi_compute_acr(44100, n, cts);
+ *n *= 4;
+ return r;
+ case 192000:
+ r = hdmi_compute_acr(48000, n, cts);
+ *n *= 4;
+ return r;
+ default:
+ return -EINVAL;
}
- /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
- *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10);
+
+ /*
+ * Calculate CTS. See HDMI 1.3a or 1.4a specifications. Preserve the
+ * remainder in case N is not a multiple of 128.
+ */
+ *cts = (*n / 128) * pclk * deep_color;
+ *cts += (*n % 128) * pclk * deep_color / 128;
+ *cts /= (sample_freq / 10);
+
+ if ((pclk * (*n / 128) * deep_color) % (sample_freq / 10))
+ DSSWARN("CTS is not integer fs[%u]pclk[%u]N[%u]\n",
+ sample_freq, pclk, *n);
return 0;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2013-01-11 0:53 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-01-11 0:53 [PATCH] OMAPDSS: HDMI: Rework function to calculate N/CTS params Ricardo Neri
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).