From patchwork Wed Jun 19 21:07:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Doug Anderson X-Patchwork-Id: 11005289 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A69731580 for ; Wed, 19 Jun 2019 21:11:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9432A2880C for ; Wed, 19 Jun 2019 21:11:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 87D6C28856; Wed, 19 Jun 2019 21:11:51 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 967982880C for ; Wed, 19 Jun 2019 21:11:50 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 5C86D6E46B; Wed, 19 Jun 2019 21:11:49 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-pf1-x443.google.com (mail-pf1-x443.google.com [IPv6:2607:f8b0:4864:20::443]) by gabe.freedesktop.org (Postfix) with ESMTPS id 572D56E46B for ; Wed, 19 Jun 2019 21:11:48 +0000 (UTC) Received: by mail-pf1-x443.google.com with SMTP id p184so313295pfp.7 for ; Wed, 19 Jun 2019 14:11:48 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=UqQ12c8oFg0dcVTOrMLNZkNDHBR+LaLcBh/sRyeBypc=; b=UPHYwEJNqPuGcZLX4KRoOGHLvalWU5glq2+BwT6G48dS/4wNA2NGGwAHBq0w46SxHd CQKWm12dCp6MIiumIxq87mQt12AkBiNBVILYIXckAi6UBDw9UghEDIPwltJq6V/zqSHS 3g4PaK+fuTrhZqKSJyLdf9Qpm7ZXZiueYEYCYhoAieNxcBZ2JA3FtDHAyu/MAbbfp6IF rrWBZfCqJE9Ti+OvnqxXEr/cfhJPZp5csi6Z0wtIyZF5e+Q4LHS/X6CyJAOmwRcL/HQZ o3KW79R91FKwOD98Q+dvSxhiQzYPkJi/dkN/ppEzfn1SC8lpTUZ5JGv9xN8uHo0UayLd t8OQ== X-Gm-Message-State: APjAAAVbDwYK+e2p7bS8Z+bDQENtKLJ6cH8F1kHD0MeWZTAcmKKUBuCg wEs2QYKdgTmFPzgVq7mZaiEetw== X-Google-Smtp-Source: APXvYqx/c2t5NAwX8FA7Uq82W2txp2Rp4HlmYnUIfyHTrU/eW2XjahPhf+pM0HN78yZeg0mPG3pJhg== X-Received: by 2002:a63:4e10:: with SMTP id c16mr9364838pgb.214.1560978707695; Wed, 19 Jun 2019 14:11:47 -0700 (PDT) Received: from tictac2.mtv.corp.google.com ([2620:15c:202:1:24fa:e766:52c9:e3b2]) by smtp.gmail.com with ESMTPSA id p7sm35319117pfp.131.2019.06.19.14.11.46 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Wed, 19 Jun 2019 14:11:46 -0700 (PDT) From: Douglas Anderson To: Andrzej Hajda , Laurent Pinchart , seanpaul@chromium.org Subject: [PATCH v2 1/2] drm/bridge/synopsys: dw-hdmi: Handle audio for more clock rates Date: Wed, 19 Jun 2019 14:07:17 -0700 Message-Id: <20190619210718.134951-1-dianders@chromium.org> X-Mailer: git-send-email 2.22.0.410.gd8fdbe21b5-goog MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=UqQ12c8oFg0dcVTOrMLNZkNDHBR+LaLcBh/sRyeBypc=; b=iC9Di/9ZfP4OrwV3ZKuhmT3/TWXjDaE8BipQuK4Mc8V4Wac6ZYwuWY88MLeJ+H8/GD GLMqFmf7buOvo4UFZFCCfc2Kj8U9iWaZAmw4FhQ/NSKRbb79uNm6j5a9ssPg++X1A0vO HmyVHVARdgLUPpYi/WEw4emKtf9OdEifHXQ0s= X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: jernej.skrabec@siol.net, narmstrong@baylibre.com, maxime.ripard@bootlin.com, David Airlie , jonas@kwiboo.se, Douglas Anderson , dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, dgreid@chromium.org, jbrunet@baylibre.com, Sam Ravnborg , cychiang@chromium.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP Let's add some better support for HDMI audio to dw_hdmi. Specifically: 1. For 44.1 kHz audio the old code made the assumption that an N of 6272 was right most of the time. That wasn't true and the new table should pick a more ideal value. 2. The new table has values from the HDMI spec for 297 MHz and 594 MHz. 3. There is now code to try to come up with a more idea N/CTS for clock rates that aren't in the table. This code is a bit slow because it iterates over every possible value of N and picks the best one, but it should make a good fallback. NOTES: - The oddest part of this patch comes about because computing the ideal N/CTS means knowing the _exact_ clock rate, not a rounded version of it. The drm framework makes this harder by rounding rates to kHz, but even if it didn't there might be cases where the ideal rate could only be calculated if we knew the real (non-integral) rate. This means that in cases where we know (or believe) that the true rate is something other than the rate we are told by drm. - This patch makes much less of a difference after the patch ("drm/bridge: dw-hdmi: Use automatic CTS generation mode when using non-AHB audio"), at least if you're using I2S audio. The main goal of picking a good N is to make it possible to get a nice integral CTS value, but if CTS is automatic then that's much less critical. Signed-off-by: Douglas Anderson --- Changes in v2: - Atop ("drm/bridge: dw-hdmi: Use automatic CTS generation mode when using non-AHB audio"). - Split out the ability of a platform to provide custom tables. drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 203 +++++++++++++++++----- 1 file changed, 162 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index de4c3669c83f..7cdffebcc7cb 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -60,6 +60,82 @@ enum hdmi_datamap { YCbCr422_12B = 0x12, }; +struct dw_hdmi_audio_tmds_n { + unsigned long tmds; + unsigned int n_32k; + unsigned int n_44k1; + unsigned int n_48k; +}; + +/* + * Unless otherwise noted, entries in this table are 100% optimization. + * Values can be obtained from hdmi_compute_n() but that function is + * slow so we pre-compute values we expect to see. + * + * All 32k and 48k values are expected to be the same (due to the way + * the math works) for any rate that's an exact kHz. + * + * If a particular platform knows that it makes a rate slightly + * differently then it should add a platform-specific match. + */ +static const struct dw_hdmi_audio_tmds_n common_tmds_n_table[] = { + /* Doesn't match computations, assumes real clock = 25.2 MHz / 1.001 */ + { .tmds = 25175000, .n_32k = 4576, .n_44k1 = 7007, .n_48k = 6864, }, + + { .tmds = 25200000, .n_32k = 4096, .n_44k1 = 5656, .n_48k = 6144, }, + { .tmds = 27000000, .n_32k = 4096, .n_44k1 = 5488, .n_48k = 6144, }, + { .tmds = 27027000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, }, + { .tmds = 28320000, .n_32k = 4096, .n_44k1 = 5586, .n_48k = 6144, }, + { .tmds = 30240000, .n_32k = 4096, .n_44k1 = 5642, .n_48k = 6144, }, + { .tmds = 31500000, .n_32k = 4096, .n_44k1 = 5600, .n_48k = 6144, }, + { .tmds = 32000000, .n_32k = 4096, .n_44k1 = 5733, .n_48k = 6144, }, + { .tmds = 33750000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, }, + { .tmds = 36000000, .n_32k = 4096, .n_44k1 = 5684, .n_48k = 6144, }, + { .tmds = 40000000, .n_32k = 4096, .n_44k1 = 5733, .n_48k = 6144, }, + { .tmds = 49500000, .n_32k = 4096, .n_44k1 = 5488, .n_48k = 6144, }, + { .tmds = 50000000, .n_32k = 4096, .n_44k1 = 5292, .n_48k = 6144, }, + { .tmds = 54000000, .n_32k = 4096, .n_44k1 = 5684, .n_48k = 6144, }, + { .tmds = 65000000, .n_32k = 4096, .n_44k1 = 7056, .n_48k = 6144, }, + { .tmds = 68250000, .n_32k = 4096, .n_44k1 = 5376, .n_48k = 6144, }, + { .tmds = 71000000, .n_32k = 4096, .n_44k1 = 7056, .n_48k = 6144, }, + { .tmds = 72000000, .n_32k = 4096, .n_44k1 = 5635, .n_48k = 6144, }, + { .tmds = 73250000, .n_32k = 4096, .n_44k1 = 14112, .n_48k = 6144, }, + + /* Doesn't match computations, assumes real clock = 74.25 MHz / 1.001 */ + { .tmds = 74176000, .n_32k = 11648, .n_44k1 = 17836, .n_48k = 11648, }, + + { .tmds = 74250000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, }, + { .tmds = 75000000, .n_32k = 4096, .n_44k1 = 5880, .n_48k = 6144, }, + { .tmds = 78750000, .n_32k = 4096, .n_44k1 = 5600, .n_48k = 6144, }, + { .tmds = 78800000, .n_32k = 4096, .n_44k1 = 5292, .n_48k = 6144, }, + { .tmds = 79500000, .n_32k = 4096, .n_44k1 = 4704, .n_48k = 6144, }, + { .tmds = 83500000, .n_32k = 4096, .n_44k1 = 7056, .n_48k = 6144, }, + { .tmds = 85500000, .n_32k = 4096, .n_44k1 = 5488, .n_48k = 6144, }, + { .tmds = 88750000, .n_32k = 4096, .n_44k1 = 14112, .n_48k = 6144, }, + { .tmds = 97750000, .n_32k = 4096, .n_44k1 = 14112, .n_48k = 6144, }, + { .tmds = 101000000, .n_32k = 4096, .n_44k1 = 7056, .n_48k = 6144, }, + { .tmds = 106500000, .n_32k = 4096, .n_44k1 = 4704, .n_48k = 6144, }, + { .tmds = 108000000, .n_32k = 4096, .n_44k1 = 5684, .n_48k = 6144, }, + { .tmds = 115500000, .n_32k = 4096, .n_44k1 = 5712, .n_48k = 6144, }, + { .tmds = 119000000, .n_32k = 4096, .n_44k1 = 5544, .n_48k = 6144, }, + { .tmds = 135000000, .n_32k = 4096, .n_44k1 = 5488, .n_48k = 6144, }, + { .tmds = 146250000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, }, + + /* Doesn't match computations, assumes real clock = 148.5 MHz / 1.001 */ + { .tmds = 148352000, .n_32k = 11648, .n_44k1 = 8918, .n_48k = 5824, }, + + { .tmds = 148500000, .n_32k = 4096, .n_44k1 = 5488, .n_48k = 6144, }, + { .tmds = 154000000, .n_32k = 4096, .n_44k1 = 5544, .n_48k = 6144, }, + { .tmds = 162000000, .n_32k = 4096, .n_44k1 = 5684, .n_48k = 6144, }, + + /* For 297 MHz+ HDMI spec has some other rule for setting N */ + { .tmds = 297000000, .n_32k = 3073, .n_44k1 = 4704, .n_48k = 5120, }, + { .tmds = 594000000, .n_32k = 3073, .n_44k1 = 9408, .n_48k = 10240, }, + + /* End of table */ + { .tmds = 0, .n_32k = 0, .n_44k1 = 0, .n_48k = 0, }, +}; + static const u16 csc_coeff_default[3][4] = { { 0x2000, 0x0000, 0x0000, 0x0000 }, { 0x0000, 0x2000, 0x0000, 0x0000 }, @@ -524,60 +600,105 @@ static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts, hdmi_writeb(hdmi, n & 0xff, HDMI_AUD_N1); } -static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk) +static int hdmi_match_tmds_n_table(struct dw_hdmi *hdmi, unsigned int freq, + unsigned long pixel_clk) { - unsigned int n = (128 * freq) / 1000; - unsigned int mult = 1; + const struct dw_hdmi_audio_tmds_n *tmds_n = NULL; + int mult = 1; + int i; while (freq > 48000) { mult *= 2; freq /= 2; } + for (i = 0; common_tmds_n_table[i].tmds != 0; i++) { + if (pixel_clk == common_tmds_n_table[i].tmds) { + tmds_n = &common_tmds_n_table[i]; + break; + } + } + + if (tmds_n == NULL) + return -ENOENT; + switch (freq) { case 32000: - if (pixel_clk == 25175000) - n = 4576; - else if (pixel_clk == 27027000) - n = 4096; - else if (pixel_clk == 74176000 || pixel_clk == 148352000) - n = 11648; - else - n = 4096; - n *= mult; - break; - + return tmds_n->n_32k * mult; case 44100: - if (pixel_clk == 25175000) - n = 7007; - else if (pixel_clk == 74176000) - n = 17836; - else if (pixel_clk == 148352000) - n = 8918; - else - n = 6272; - n *= mult; - break; - + return tmds_n->n_44k1 * mult; case 48000: - if (pixel_clk == 25175000) - n = 6864; - else if (pixel_clk == 27027000) - n = 6144; - else if (pixel_clk == 74176000) - n = 11648; - else if (pixel_clk == 148352000) - n = 5824; - else - n = 6144; - n *= mult; - break; - + return tmds_n->n_48k * mult; default: - break; + return -ENOENT; + } +} + +static u64 hdmi_audio_math_diff(unsigned int freq, unsigned int n, + unsigned int pixel_clk) +{ + u64 final, diff; + u64 cts; + + final = (u64)pixel_clk * n; + + cts = final; + do_div(cts, 128 * freq); + + diff = final - (u64)cts * (128 * freq); + + return diff; +} + +static unsigned int hdmi_compute_n(struct dw_hdmi *hdmi, unsigned int freq, + unsigned long pixel_clk) +{ + unsigned int min_n = DIV_ROUND_UP((128 * freq), 1500); + unsigned int max_n = (128 * freq) / 300; + unsigned int ideal_n = (128 * freq) / 1000; + unsigned int best_n_distance = ideal_n; + unsigned int best_n = 0; + u64 best_diff = U64_MAX; + int n; + + /* If the ideal N could satisfy the audio math, then just take it */ + if (hdmi_audio_math_diff(freq, ideal_n, pixel_clk) == 0) + return ideal_n; + + for (n = min_n; n <= max_n; n++) { + u64 diff = hdmi_audio_math_diff(freq, n, pixel_clk); + + if (diff < best_diff || (diff == best_diff && + abs(n - ideal_n) < best_n_distance)) { + best_n = n; + best_diff = diff; + best_n_distance = abs(best_n - ideal_n); + } + + /* + * The best N already satisfy the audio math, and also be + * the closest value to ideal N, so just cut the loop. + */ + if ((best_diff == 0) && (abs(n - ideal_n) > best_n_distance)) + break; } - return n; + return best_n; +} + +static unsigned int hdmi_find_n(struct dw_hdmi *hdmi, unsigned int freq, + unsigned long pixel_clk) +{ + int n; + + n = hdmi_match_tmds_n_table(hdmi, freq, pixel_clk); + if (n > 0) + return n; + + dev_warn(hdmi->dev, "Rate %lu missing; compute N dynamically\n", + pixel_clk); + + return hdmi_compute_n(hdmi, freq, pixel_clk); } static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi, @@ -588,7 +709,7 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi, u8 config3; u64 tmp; - n = hdmi_compute_n(sample_rate, pixel_clk); + n = hdmi_find_n(hdmi, sample_rate, pixel_clk); config3 = hdmi_readb(hdmi, HDMI_CONFIG3_ID); From patchwork Wed Jun 19 21:07:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Doug Anderson X-Patchwork-Id: 11005291 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7676914B6 for ; Wed, 19 Jun 2019 21:11:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6374028856 for ; Wed, 19 Jun 2019 21:11:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5740228857; Wed, 19 Jun 2019 21:11:55 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id EBCC928856 for ; Wed, 19 Jun 2019 21:11:54 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 0D5006E46C; Wed, 19 Jun 2019 21:11:54 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-pf1-x442.google.com (mail-pf1-x442.google.com [IPv6:2607:f8b0:4864:20::442]) by gabe.freedesktop.org (Postfix) with ESMTPS id B17D86E46C for ; Wed, 19 Jun 2019 21:11:49 +0000 (UTC) Received: by mail-pf1-x442.google.com with SMTP id d126so328620pfd.2 for ; Wed, 19 Jun 2019 14:11:49 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Hy05C9mn0/yIf2WjCYd8ymGDA+P844rg5bgddBHlUN8=; b=bY34Dd2TGo1snWhWXZbB45E4ke6wfb7op6o0rGmkZ8ScLOZys/fTixGqe3rBj/AH4l 5pysBquK65U2CTCgktPU3h+Gi8YcpVG7o7KN3FD6m/41+MFofz/Pfw6sv2VnzDdkiVmE XIZy0qrb6ZY6IZasNSYZsc5xQykKqcJkXAodP0Kq/Lp4GNI6bFLXwY2yRhTBR/XwVq3B ikRedALpFnILPJHwK5JfMRfpN1TWFfxaiTBR7qhlMCY1AYfwLFjmEUo2B/tHilwzYWI3 YdpTO+FSJx3gKC8IOEg+VyR4nXItCBBAGGIAf2oQVvSeQnSOX6NIDSpypNqKcjuTckmI FnnA== X-Gm-Message-State: APjAAAWzcKNLbCG3LoblGp7TMkGp22gAzXSMNs5UHsDXloJqiOYN5DCS z6WBek03Lo8lClO9YjWGN7DVCw== X-Google-Smtp-Source: APXvYqwXqPl24uyJF3v+5dkgkWEhaRF4Tfy/+nmYhsNEFIVfi0rh/PxJeKfAiWOS6/1USM4Ra2YThw== X-Received: by 2002:a63:6b46:: with SMTP id g67mr1788869pgc.45.1560978708910; Wed, 19 Jun 2019 14:11:48 -0700 (PDT) Received: from tictac2.mtv.corp.google.com ([2620:15c:202:1:24fa:e766:52c9:e3b2]) by smtp.gmail.com with ESMTPSA id p7sm35319117pfp.131.2019.06.19.14.11.47 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Wed, 19 Jun 2019 14:11:48 -0700 (PDT) From: Douglas Anderson To: Andrzej Hajda , Laurent Pinchart , seanpaul@chromium.org Subject: [PATCH v2 2/2] drm/bridge/synopsys: dw-hdmi: Allow platforms to provide custom audio tables Date: Wed, 19 Jun 2019 14:07:18 -0700 Message-Id: <20190619210718.134951-2-dianders@chromium.org> X-Mailer: git-send-email 2.22.0.410.gd8fdbe21b5-goog In-Reply-To: <20190619210718.134951-1-dianders@chromium.org> References: <20190619210718.134951-1-dianders@chromium.org> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Hy05C9mn0/yIf2WjCYd8ymGDA+P844rg5bgddBHlUN8=; b=KGpaeoheFWBtMSk4WBMgOkawtt9gRWlcsmiS6qSo8xgzQC0X5za9DjD3rUH7b2a0re Tfg2n0jZMP+ZXKpDk2U9LapSmaxrigwOaUBbPePTSX7TI28dHCYv/th/bDTLjH3Bs2tJ dt8drzYooa55fn0wXwevkiH+aWBOLbRRBPZMs= X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: jernej.skrabec@siol.net, narmstrong@baylibre.com, maxime.ripard@bootlin.com, Zheng Yang , David Airlie , jonas@kwiboo.se, Douglas Anderson , dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, dgreid@chromium.org, jbrunet@baylibre.com, Sam Ravnborg , Thomas Gleixner , cychiang@chromium.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP On some platforms using dw_hdmi it may not be possible to make an HDMI pixel clock exactly, but it may be possible to make a rate that is close enough to be within spec. For instance on rk3288 we can make 25,176,471 Hz instead of 25,174,825.1748... Hz (25.2 MHz / 1.001). A future patch to the rk3288 platform code could enable support for this clock rate and specify the N/CTS that would be ideal. NOTE: I haven't yet posted said patch due to complexities with knowing whether dw_hdmi can control the dynamic PLL on rk3288. Thus for now there are no users of this feature yet. Signed-off-by: Douglas Anderson --- Changes in v2: - Split out the ability of a platform to provide custom tables. drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 27 ++++++++++++++--------- include/drm/bridge/dw_hdmi.h | 8 +++++++ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 7cdffebcc7cb..b6027edf2942 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -60,13 +60,6 @@ enum hdmi_datamap { YCbCr422_12B = 0x12, }; -struct dw_hdmi_audio_tmds_n { - unsigned long tmds; - unsigned int n_32k; - unsigned int n_44k1; - unsigned int n_48k; -}; - /* * Unless otherwise noted, entries in this table are 100% optimization. * Values can be obtained from hdmi_compute_n() but that function is @@ -603,6 +596,7 @@ static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts, static int hdmi_match_tmds_n_table(struct dw_hdmi *hdmi, unsigned int freq, unsigned long pixel_clk) { + const struct dw_hdmi_plat_data *plat_data = hdmi->plat_data; const struct dw_hdmi_audio_tmds_n *tmds_n = NULL; int mult = 1; int i; @@ -612,10 +606,21 @@ static int hdmi_match_tmds_n_table(struct dw_hdmi *hdmi, unsigned int freq, freq /= 2; } - for (i = 0; common_tmds_n_table[i].tmds != 0; i++) { - if (pixel_clk == common_tmds_n_table[i].tmds) { - tmds_n = &common_tmds_n_table[i]; - break; + if (plat_data->tmds_n_table) { + for (i = 0; plat_data->tmds_n_table[i].tmds != 0; i++) { + if (pixel_clk == plat_data->tmds_n_table[i].tmds) { + tmds_n = &plat_data->tmds_n_table[i]; + break; + } + } + } + + if (tmds_n == NULL) { + for (i = 0; common_tmds_n_table[i].tmds != 0; i++) { + if (pixel_clk == common_tmds_n_table[i].tmds) { + tmds_n = &common_tmds_n_table[i]; + break; + } } } diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index c402364aec0d..5ee6b0a127aa 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -90,6 +90,13 @@ enum dw_hdmi_phy_type { DW_HDMI_PHY_VENDOR_PHY = 0xfe, }; +struct dw_hdmi_audio_tmds_n { + unsigned long tmds; + unsigned int n_32k; + unsigned int n_44k1; + unsigned int n_48k; +}; + struct dw_hdmi_mpll_config { unsigned long mpixelclock; struct { @@ -137,6 +144,7 @@ struct dw_hdmi_plat_data { const struct dw_hdmi_mpll_config *mpll_cfg; const struct dw_hdmi_curr_ctrl *cur_ctr; const struct dw_hdmi_phy_config *phy_config; + const struct dw_hdmi_audio_tmds_n *tmds_n_table; int (*configure_phy)(struct dw_hdmi *hdmi, const struct dw_hdmi_plat_data *pdata, unsigned long mpixelclock);