Received: by 2002:ab2:6857:0:b0:1ef:ffd0:ce49 with SMTP id l23csp3428099lqp; Tue, 26 Mar 2024 08:55:05 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCUkCF4KRjRs44K97iyucsCrVOy0QDOWJCqTtEtjoBAsAzYuZ4ibr+ZnWrRYCeIN6eNUNjXjthQvX1+1zrP1ZECGRw853Z9Kif/c5PZnIw== X-Google-Smtp-Source: AGHT+IHxvEhGoY/v+bvIyzVYC0nM4uW/VzI+V7lsqQgYz5x31gpbsV8IGrbvngWFBtRZ1Hx6NNh8 X-Received: by 2002:a17:902:9a07:b0:1de:fbc2:99f0 with SMTP id v7-20020a1709029a0700b001defbc299f0mr1336508plp.2.1711468505058; Tue, 26 Mar 2024 08:55:05 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1711468505; cv=pass; d=google.com; s=arc-20160816; b=e2ZM1TS+Jf+MiW4LCjIt+6pPvwodKh3qgK4/tNw2a86NJNd7H22gp492N8SEk38JrB bjombH817ZRZUG2i1IwFy0rovOPdT0q1EfaSWJJUDCVAwtVYgOFJ8vwkGnYrClBSaZKR cWr4FMhW4czyGl5BUcBNZzle2X1EBLzZ4BA1fwBI7oEmxL5uNH3Ii6EjvIDZOQ7Ex5fw ENyPudRdYov5Oh9/2GEm4tlGZ/Euzg0gRz7RWUcmEoQsHGPs+Ev+2m6cbeqermxz158L HKI+fTGiiizHhfSoXBJgsnDj90NK83fqiek9e1xV9c8jp0IenVXfzH9URvcP2COcSooE bv3A== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:list-unsubscribe:list-subscribe:list-id:precedence :subject:date:from:dkim-signature; bh=19mMGz0pZlNWoQFo6FCo03tAXzTJixBDqvLvqLs+nGM=; fh=8wcoxKk21hICD+6obVirG13fsSSMhKa/pufykSf87d0=; b=JB+Ci1PZjV7ATLBPIRdN/N/uKpT6JliuXaTREKM23dD/DR66SM2R7XyrimXBk0HFR7 yoP+T6L5SNhQkMwHFFc5GnTti4Z0rrWKHeDMw4I8y7VQ++fMRCg+S8pRvSdqYGLg/kZP cAkvqKcMAcgnkD52iaJIs/1vQ0hahchC7HZcVc1UemnaV0vlfbIqpKXLuUg1Y0519VpO fmz2GX3uV/RlvCCtB1pxN4CL/GVS1d+zOqCsCNQSVn6qpLrGL1rBt9Nf6nAS7behtzxn 9rRGY7zEe57VLijoneOBVsv91t+ibzbtp6wD/QO2E9VSsFF4R+Hh378JVz9uxsBlJ8jv imzg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=IJgSBPiY; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-119370-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-119370-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id n7-20020a170902e54700b001e02b2d53a5si6117462plf.335.2024.03.26.08.55.04 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Mar 2024 08:55:05 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-119370-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=IJgSBPiY; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-119370-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-119370-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id E1DF6323159 for ; Tue, 26 Mar 2024 15:47:25 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id B48DC13C83C; Tue, 26 Mar 2024 15:41:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="IJgSBPiY" Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9E2AE13E407; Tue, 26 Mar 2024 15:41:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711467662; cv=none; b=au8/r9K3bAL+9/Z+dCnXcXWBS2UgLVHz0GGZ6cMt0XoA0bBh55ePH+KllbdTR/QXq1Jvkli6Rn138vTuj4t05StKu7oEshyJLqrTRW4nTkr4644arM9NyLLr/6azKeMmPcghY5KXSJT3I9pmqNP+tHQYq1MeYGKN0/qA8Itm7Ng= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711467662; c=relaxed/simple; bh=0Jei25jBuuYJAKPLzz/1PwMOvUOkVr+WM5HlK6StDig=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ar0D5KR2nUJeNJSAeVjYhf9s3z15YocqIo+K2bmeCa+fbYgswf14QrrKuRFN9zDMzChxXpbsJ4kLKLajf2ITlQ5quR+l4txV7EeIKPN27IudBobNM8ufBBbTI7jAFsrmv4lLB1OKJkCcQU53w3CUiHCJGbYYpr1ZKN3QpjHWn6M= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IJgSBPiY; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2A22AC43330; Tue, 26 Mar 2024 15:41:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1711467662; bh=0Jei25jBuuYJAKPLzz/1PwMOvUOkVr+WM5HlK6StDig=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=IJgSBPiYi649ud7l0eZgjvJY3jNupnxngoBx/xXNQ7erqOievWoJM2ARaA36kUzwW FEZKAM8xaLOGu2fooYFYrksgN5iYl1N692dR1/bqauLMB4JVdLwQuRMPRVntKeXKtH 6UnW/5HZdzuHg2l2+MLIbJ0ODvwmcaAkc0G2gk7zbAEIacTrF44dbbfEXmnFwDTwsB 8ETCuRrLd/HYlKGYZXuaekoEzBWysM2dPXl83KdNNW1fD50i/OCektDht4UxFtpSI0 fltjI2pLLakwzY2tNkAYc8a+on5VSXPKr6aaC6X4EvG6PHLz7nfHkEKgbK3YSt+iKi H9AASq/jemRvQ== From: Maxime Ripard Date: Tue, 26 Mar 2024 16:40:15 +0100 Subject: [PATCH v11 11/28] drm/connector: hdmi: Calculate TMDS character rate Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20240326-kms-hdmi-connector-state-v11-11-c5680ffcf261@kernel.org> References: <20240326-kms-hdmi-connector-state-v11-0-c5680ffcf261@kernel.org> In-Reply-To: <20240326-kms-hdmi-connector-state-v11-0-c5680ffcf261@kernel.org> To: Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Jonathan Corbet , Sandy Huang , =?utf-8?q?Heiko_St=C3=BCbner?= , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland Cc: Hans Verkuil , Sebastian Wick , =?utf-8?q?Ville_Syrj=C3=A4l=C3=A4?= , dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-sunxi@lists.linux.dev, Maxime Ripard , Dave Stevenson X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=6362; i=mripard@kernel.org; h=from:subject:message-id; bh=0Jei25jBuuYJAKPLzz/1PwMOvUOkVr+WM5HlK6StDig=; b=owGbwMvMwCmsHn9OcpHtvjLG02pJDGlMb5KZbyVXtN725LUw/7ntxCtO+WkKqtO/HU8tZrvSJ q0196Rsx1QWBmFOBlkxRZYnMmGnl7cvrnKwX/kDZg4rE8gQBi5OAZiI7BrGava7yvn/d2x2U1fm Szr5MdZGvfRYlAKL8q8jy+aw/3t0u1Rq+s3HLaLViVHh2xl4/ptcZ6z3WMKx/69I3u3e3koprSf vjIPmrnnxYfYeFj/JP045bDzBexPfe7JzPr7gvdebXyfNuQ8A X-Developer-Key: i=mripard@kernel.org; a=openpgp; fpr=BE5675C37E818C8B5764241C254BCFC56BF6CE8D Most HDMI drivers have some code to calculate the TMDS character rate, usually to adjust an internal clock to match what the mode requires. Since the TMDS character rates mostly depends on the resolution, whether we need to repeat pixels or not, the bpc count and the format, we can now derive it from the HDMI connector state that stores all those infos and remove the duplication from drivers. Reviewed-by: Dave Stevenson Signed-off-by: Maxime Ripard --- drivers/gpu/drm/display/drm_hdmi_state_helper.c | 67 ++++++++++++++++++++++ drivers/gpu/drm/drm_atomic.c | 1 + drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 3 + include/drm/drm_connector.h | 5 ++ 4 files changed, 76 insertions(+) diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c index f6cd0612ea2c..08630561d864 100644 --- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c @@ -1,10 +1,11 @@ // SPDX-License-Identifier: MIT #include #include +#include #include /** * __drm_atomic_helper_connector_hdmi_reset() - Initializes all HDMI @drm_connector_state resources * @connector: DRM connector @@ -23,10 +24,67 @@ void __drm_atomic_helper_connector_hdmi_reset(struct drm_connector *connector, new_conn_state->max_bpc = max_bpc; new_conn_state->max_requested_bpc = max_bpc; } EXPORT_SYMBOL(__drm_atomic_helper_connector_hdmi_reset); +static const struct drm_display_mode * +connector_state_get_mode(const struct drm_connector_state *conn_state) +{ + struct drm_atomic_state *state; + struct drm_crtc_state *crtc_state; + struct drm_crtc *crtc; + + state = conn_state->state; + if (!state) + return NULL; + + crtc = conn_state->crtc; + if (!crtc) + return NULL; + + crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + if (!crtc_state) + return NULL; + + return &crtc_state->mode; +} + +static enum drm_mode_status +hdmi_clock_valid(const struct drm_connector *connector, + const struct drm_display_mode *mode, + unsigned long long clock) +{ + const struct drm_display_info *info = &connector->display_info; + + if (info->max_tmds_clock && clock > info->max_tmds_clock * 1000) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +static int +hdmi_compute_clock(const struct drm_connector *connector, + struct drm_connector_state *conn_state, + const struct drm_display_mode *mode, + unsigned int bpc, enum hdmi_colorspace fmt) +{ + enum drm_mode_status status; + unsigned long long clock; + + clock = drm_hdmi_compute_mode_clock(mode, bpc, fmt); + if (!clock) + return -EINVAL; + + status = hdmi_clock_valid(connector, mode, clock); + if (status != MODE_OK) + return -EINVAL; + + conn_state->hdmi.tmds_char_rate = clock; + + return 0; +} + /** * drm_atomic_helper_connector_hdmi_check() - Helper to check HDMI connector atomic state * @connector: DRM Connector * @state: the DRM State object * @@ -42,10 +100,19 @@ int drm_atomic_helper_connector_hdmi_check(struct drm_connector *connector, { struct drm_connector_state *old_conn_state = drm_atomic_get_old_connector_state(state, connector); struct drm_connector_state *new_conn_state = drm_atomic_get_new_connector_state(state, connector); + const struct drm_display_mode *mode = + connector_state_get_mode(new_conn_state); + int ret; + + ret = hdmi_compute_clock(connector, new_conn_state, mode, + new_conn_state->hdmi.output_bpc, + new_conn_state->hdmi.output_format); + if (ret) + return ret; if (old_conn_state->hdmi.output_bpc != new_conn_state->hdmi.output_bpc || old_conn_state->hdmi.output_format != new_conn_state->hdmi.output_format) { struct drm_crtc *crtc = new_conn_state->crtc; struct drm_crtc_state *crtc_state; diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 8730137baa86..26f9e525c0a0 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1146,10 +1146,11 @@ static void drm_atomic_connector_print_state(struct drm_printer *p, if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA || connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) { drm_printf(p, "\toutput_bpc=%u\n", state->hdmi.output_bpc); drm_printf(p, "\toutput_format=%s\n", drm_hdmi_connector_get_output_format_name(state->hdmi.output_format)); + drm_printf(p, "\ttmds_char_rate=%llu\n", state->hdmi.tmds_char_rate); } if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK) if (state->writeback_job && state->writeback_job->fb) drm_printf(p, "\tfb=%d\n", state->writeback_job->fb->base.id); diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c index 8bc1f9b0b12b..4f46a70a5017 100644 --- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c +++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c @@ -70,10 +70,13 @@ static int light_up_connector(struct kunit *test, KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); conn_state = drm_atomic_get_connector_state(state, connector); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); + conn_state->hdmi.output_bpc = connector->max_bpc; + conn_state->hdmi.output_format = HDMI_COLORSPACE_RGB; + ret = drm_atomic_set_crtc_for_connector(conn_state, crtc); KUNIT_EXPECT_EQ(test, ret, 0); crtc_state = drm_atomic_get_crtc_state(state, crtc); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 29883e6f8e50..54899c030031 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1047,10 +1047,15 @@ struct drm_connector_state { /** * @output_format: Pixel format to output in. */ enum hdmi_colorspace output_format; + + /** + * @tmds_char_rate: TMDS Character Rate, in Hz. + */ + unsigned long long tmds_char_rate; } hdmi; }; /** * struct drm_connector_funcs - control connectors on a given device -- 2.44.0