From patchwork Sun Dec 1 00:44:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 13889423 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 290C6D7361B for ; Sun, 1 Dec 2024 00:50:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=O72gbUDbM7kl3JMP7ZBWI3LnDF87C5Sg9KKzLKy42H4=; b=bF7YDgdsnhHdygElQ2Oe9FRyEV /nf6ydFbeetF29ie4iRjnpQ/7v+gNGcWW6p5m6Q+6hbKg2JbQRhqA42bIRR75txR4PhSZgKzU8FE7 fGtIUioAM2UPaAnzVXV1ajAaUbhYqTJetkB3PBDosRgRwVBGpvJKTj5BT41bo4R7806gK9l0FYdQF OhOkSAY7IvHhEa5e9HVfeBkPrD81u5Y6IFetcz++qbOFeMSbkgvj04vOR8SuXRm6TAsIh5et9e6NR MWEcHsjFGapXGS/64Q72SLh/1pPv2f0seSjrUSEvoF0WgNomxyEew7NzG3nIUwkELu9UXoGo0wKhq U36iwA0A==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tHYAF-00000002prw-41Lu; Sun, 01 Dec 2024 00:50:19 +0000 Received: from mail-ed1-x52e.google.com ([2a00:1450:4864:20::52e]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tHY4c-00000002oYc-0tK2 for linux-arm-kernel@lists.infradead.org; Sun, 01 Dec 2024 00:44:31 +0000 Received: by mail-ed1-x52e.google.com with SMTP id 4fb4d7f45d1cf-5d0cd8a0e91so1138698a12.3 for ; Sat, 30 Nov 2024 16:44:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1733013869; x=1733618669; darn=lists.infradead.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=O72gbUDbM7kl3JMP7ZBWI3LnDF87C5Sg9KKzLKy42H4=; b=SNmnIpt71LjILHxztV31ZH8q+7c8qCwhUZaqX9vZSleU0eRAoz6U/ndDBuwxrGm2Ro ybEru9s6t1pte5MxNnU3RYzan6fWVMV8X+2FBOJqJcuK/e7J15Xm/86gAhL60vr+Iw/z 85DpLZv+mk+dbpa1HhKY2UMJ/ndIX5jLBpU9O0YktdeLPOI6vrdY+mQOrFqjy80iL/an 5pMS6s+DslKa5MIkNs/U7s36sGnKrrgwmu0RlhFd8x6MObCAQIPnzLmwmOYIq/XheVOp cNC05gwMBkvdLzkyVBINhK2NK7BW09n+Dk872SMF/B64UqWJ58KIL2Pjt2DzaK44KSf3 ax2w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733013869; x=1733618669; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=O72gbUDbM7kl3JMP7ZBWI3LnDF87C5Sg9KKzLKy42H4=; b=rbUxKLsatpmDT6P5FWSbPf+OZkbGAEtXB6nfs4/i1QjcFPXmEIRhbj3oE6xburJoTr bAloeL03VSP+XK/1uoFvoIY528gWhv8LrFCMeG/6jTwwQXlHxKnVjpGKUW+2V67JzguN EQGuf25Eg/3Cdz/QmaleVnOARPqfMHPYDJFtbCxoIez+ieLdytLiIco3xh3LZXnjLQ3K Jabkdbh1BhSBiHGhIbiNuXAXIKwoJMYtpT9AzpIiw1TZMp6aGiDir52LYIMuXW9seqHt PfaN/sk36TvwPKPPRQt8HgR9veCHUNxGpES/69ckbM5vJ1wTfR7kFJNUrmIqEoO3IC5F MXwg== X-Forwarded-Encrypted: i=1; AJvYcCVfRbIdEobvBTJPjG1Ko6WYLT9WY8Ms5+ugG3GsfYl9GEn9RMRLeT1FqKCnHIG5Db2hC7a261MLfZQ2bhipbUEx@lists.infradead.org X-Gm-Message-State: AOJu0YysNLE5Wh7oZvPxT75QF/41tuId+7vWMqXTML2PGqVAAY4nAf8W QHGV1xD94I0f+/qbbS2lCzBQUh0VZPJ7T4GrpZWkHFS4ct1KcV0ibQ4AJfEsZNg= X-Gm-Gg: ASbGncsk7k2Y0M8OXzHgVu4P0ISoob9oo95COCVfXjXmfMP4d/igw7vLMjoVCyrznyA nAUYGJs3ha8DfMApRofCThFu3sqzWQkZw0bllgoMStz3VJannejhMN4MV856E4zH59RkZFqEv9F jKoJEk8CSO32cz9LH5jcJOMiGdSIHJJtYP1QYPzOAxTp7Gs+B6yrVKppKvdHvb04zmw4vHR4Qr/ H0jMlh5lfM2WHwSKwuS25d5dnRUey59FYyB6Fe88wpsIPKHgbsogAjV2A== X-Google-Smtp-Source: AGHT+IEE4L3VUqVftuJEN2sm9JoYQq9hfUq52f3dulYx8DO99poV3eRa3t+gDAWD+mD+8EsMpBO8DQ== X-Received: by 2002:a05:6402:3213:b0:5d0:b040:4616 with SMTP id 4fb4d7f45d1cf-5d0b040decbmr10137668a12.28.1733013868829; Sat, 30 Nov 2024 16:44:28 -0800 (PST) Received: from umbar.lan ([192.130.178.90]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5d097e8d817sm3400359a12.63.2024.11.30.16.44.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 30 Nov 2024 16:44:27 -0800 (PST) From: Dmitry Baryshkov Date: Sun, 01 Dec 2024 02:44:09 +0200 Subject: [PATCH v5 5/9] drm/bridge: lt9611: switch to using the DRM HDMI codec framework MIME-Version: 1.0 Message-Id: <20241201-drm-bridge-hdmi-connector-v5-5-b5316e82f61a@linaro.org> References: <20241201-drm-bridge-hdmi-connector-v5-0-b5316e82f61a@linaro.org> In-Reply-To: <20241201-drm-bridge-hdmi-connector-v5-0-b5316e82f61a@linaro.org> To: Andrzej Hajda , Neil Armstrong , Robert Foss , Laurent Pinchart , Jonas Karlman , Jernej Skrabec , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Jaroslav Kysela , Takashi Iwai , Liam Girdwood , Mark Brown , Phong LE , Inki Dae , Seung-Woo Kim , Kyungmin Park , Krzysztof Kozlowski , Alim Akhtar , Russell King , Chun-Kuang Hu , Philipp Zabel , Matthias Brugger , AngeloGioacchino Del Regno , Sandy Huang , =?utf-8?q?Heiko_St=C3=BCbner?= , Andy Yan , Alain Volmat , Raphael Gallais-Pou , Dave Stevenson , =?utf-8?q?Ma=C3=ADra_Cana?= =?utf-8?q?l?= , Raspberry Pi Kernel Maintenance Cc: Jani Nikula , dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-sound@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, linux-mediatek@lists.infradead.org, linux-rockchip@lists.infradead.org X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=7869; i=dmitry.baryshkov@linaro.org; h=from:subject:message-id; bh=bt7FTSnaJ4ZdPpnvHjWH+URnk6jSCm36E7PfRw7YH9s=; b=owEBbQGS/pANAwAKAYs8ij4CKSjVAcsmYgBnS7FY7Cah0p2oeaHoAxF6UtGVwFktOgn6OOKkS DzRC31nQr+JATMEAAEKAB0WIQRMcISVXLJjVvC4lX+LPIo+Aiko1QUCZ0uxWAAKCRCLPIo+Aiko 1TB5B/4j77N/gCHdGuv0kwJ5aNKYBwVMlEWLN9wEs/c9rpQxBxqWqcIy9elPVCP7Zm8jEf81gIK bD5rfRa+wAVJKYo7Jgeivi9k/ep1H+5xiXbnQW7J+MMotbksGWTTi4FJruQfa3pBQXWvxuOHTfA aG0s6EduaxnYX4fGUWDpvnA3ukIgb7UO5GXiBygLFDA/5QZ/2afpifyw6eceVM1fNg+knxzcIwj 3tpnQLg2S2NwSUh9dHa81sI5MHYMkzKRN5REihWHXkhjO6PJ38It+zGv8fiJ0QqIPNoXL1Bdb1g mdUAXk1UKBISVFwBkozmW2tnlsEYVUwp9RUUSPg5FBqeQrzg X-Developer-Key: i=dmitry.baryshkov@linaro.org; a=openpgp; fpr=8F88381DD5C873E4AE487DA5199BF1243632046A X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241130_164430_431260_8F33A5C8 X-CRM114-Status: GOOD ( 18.43 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Make the Lontium LT9611 DSI-to-HDMI bridge driver use the DRM HDMI Codec framework. This enables programming of Audio InfoFrames using the HDMI Connector interface and also enables support for the missing features, including the ELD retrieval and better hotplug support. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/bridge/lontium-lt9611.c | 171 +++++++++++++------------------- 1 file changed, 69 insertions(+), 102 deletions(-) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c index 6bc1b2476847c3bccbbf9874bb384c1f60674da6..f3ac67440a941327308ddf1fbb77744c6a8fe42e 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611.c @@ -45,7 +45,6 @@ struct lt9611 { struct device_node *dsi1_node; struct mipi_dsi_device *dsi0; struct mipi_dsi_device *dsi1; - struct platform_device *audio_pdev; bool ac_mode; @@ -866,6 +865,10 @@ static int lt9611_hdmi_clear_infoframe(struct drm_bridge *bridge, unsigned int mask; switch (type) { + case HDMI_INFOFRAME_TYPE_AUDIO: + mask = LT9611_INFOFRAME_AUDIO; + break; + case HDMI_INFOFRAME_TYPE_AVI: mask = LT9611_INFOFRAME_AVI; break; @@ -899,6 +902,11 @@ static int lt9611_hdmi_write_infoframe(struct drm_bridge *bridge, int i; switch (type) { + case HDMI_INFOFRAME_TYPE_AUDIO: + mask = LT9611_INFOFRAME_AUDIO; + addr = 0x84b2; + break; + case HDMI_INFOFRAME_TYPE_AVI: mask = LT9611_INFOFRAME_AVI; addr = 0x8440; @@ -942,6 +950,55 @@ lt9611_hdmi_tmds_char_rate_valid(const struct drm_bridge *bridge, return MODE_OK; } +static int lt9611_hdmi_codec_audio_startup(struct drm_connector *connector, + struct drm_bridge *bridge) +{ + struct lt9611 *lt9611 = bridge_to_lt9611(bridge); + + regmap_write(lt9611->regmap, 0x82d6, 0x8c); + regmap_write(lt9611->regmap, 0x82d7, 0x04); + + regmap_write(lt9611->regmap, 0x8406, 0x08); + regmap_write(lt9611->regmap, 0x8407, 0x10); + + regmap_write(lt9611->regmap, 0x8434, 0xd5); + + return 0; +} + +static int lt9611_hdmi_codec_prepare(struct drm_connector *connector, + struct drm_bridge *bridge, + struct hdmi_codec_daifmt *fmt, + struct hdmi_codec_params *hparms) +{ + struct lt9611 *lt9611 = bridge_to_lt9611(bridge); + + if (hparms->sample_rate == 48000) + regmap_write(lt9611->regmap, 0x840f, 0x2b); + else if (hparms->sample_rate == 96000) + regmap_write(lt9611->regmap, 0x840f, 0xab); + else + return -EINVAL; + + regmap_write(lt9611->regmap, 0x8435, 0x00); + regmap_write(lt9611->regmap, 0x8436, 0x18); + regmap_write(lt9611->regmap, 0x8437, 0x00); + + return drm_atomic_helper_connector_hdmi_update_audio_infoframe(connector, + &hparms->cea); +} + +static void lt9611_hdmi_codec_audio_shutdown(struct drm_connector *connector, + struct drm_bridge *bridge) +{ + struct lt9611 *lt9611 = bridge_to_lt9611(bridge); + + drm_atomic_helper_connector_hdmi_clear_audio_infoframe(connector); + + regmap_write(lt9611->regmap, 0x8406, 0x00); + regmap_write(lt9611->regmap, 0x8407, 0x00); +} + static const struct drm_bridge_funcs lt9611_bridge_funcs = { .attach = lt9611_bridge_attach, .mode_valid = lt9611_bridge_mode_valid, @@ -962,6 +1019,10 @@ static const struct drm_bridge_funcs lt9611_bridge_funcs = { .hdmi_tmds_char_rate_valid = lt9611_hdmi_tmds_char_rate_valid, .hdmi_write_infoframe = lt9611_hdmi_write_infoframe, .hdmi_clear_infoframe = lt9611_hdmi_clear_infoframe, + + .hdmi_codec_audio_startup = lt9611_hdmi_codec_audio_startup, + .hdmi_codec_prepare = lt9611_hdmi_codec_prepare, + .hdmi_codec_audio_shutdown = lt9611_hdmi_codec_audio_shutdown, }; static int lt9611_parse_dt(struct device *dev, @@ -1015,102 +1076,6 @@ static int lt9611_read_device_rev(struct lt9611 *lt9611) return ret; } -static int lt9611_hdmi_hw_params(struct device *dev, void *data, - struct hdmi_codec_daifmt *fmt, - struct hdmi_codec_params *hparms) -{ - struct lt9611 *lt9611 = data; - - if (hparms->sample_rate == 48000) - regmap_write(lt9611->regmap, 0x840f, 0x2b); - else if (hparms->sample_rate == 96000) - regmap_write(lt9611->regmap, 0x840f, 0xab); - else - return -EINVAL; - - regmap_write(lt9611->regmap, 0x8435, 0x00); - regmap_write(lt9611->regmap, 0x8436, 0x18); - regmap_write(lt9611->regmap, 0x8437, 0x00); - - return 0; -} - -static int lt9611_audio_startup(struct device *dev, void *data) -{ - struct lt9611 *lt9611 = data; - - regmap_write(lt9611->regmap, 0x82d6, 0x8c); - regmap_write(lt9611->regmap, 0x82d7, 0x04); - - regmap_write(lt9611->regmap, 0x8406, 0x08); - regmap_write(lt9611->regmap, 0x8407, 0x10); - - regmap_write(lt9611->regmap, 0x8434, 0xd5); - - return 0; -} - -static void lt9611_audio_shutdown(struct device *dev, void *data) -{ - struct lt9611 *lt9611 = data; - - regmap_write(lt9611->regmap, 0x8406, 0x00); - regmap_write(lt9611->regmap, 0x8407, 0x00); -} - -static int lt9611_hdmi_i2s_get_dai_id(struct snd_soc_component *component, - struct device_node *endpoint, - void *data) -{ - struct of_endpoint of_ep; - int ret; - - ret = of_graph_parse_endpoint(endpoint, &of_ep); - if (ret < 0) - return ret; - - /* - * HDMI sound should be located as reg = <2> - * Then, it is sound port 0 - */ - if (of_ep.port == 2) - return 0; - - return -EINVAL; -} - -static const struct hdmi_codec_ops lt9611_codec_ops = { - .hw_params = lt9611_hdmi_hw_params, - .audio_shutdown = lt9611_audio_shutdown, - .audio_startup = lt9611_audio_startup, - .get_dai_id = lt9611_hdmi_i2s_get_dai_id, -}; - -static struct hdmi_codec_pdata codec_data = { - .ops = <9611_codec_ops, - .max_i2s_channels = 8, - .i2s = 1, -}; - -static int lt9611_audio_init(struct device *dev, struct lt9611 *lt9611) -{ - codec_data.data = lt9611; - lt9611->audio_pdev = - platform_device_register_data(dev, HDMI_CODEC_DRV_NAME, - PLATFORM_DEVID_AUTO, - &codec_data, sizeof(codec_data)); - - return PTR_ERR_OR_ZERO(lt9611->audio_pdev); -} - -static void lt9611_audio_exit(struct lt9611 *lt9611) -{ - if (lt9611->audio_pdev) { - platform_device_unregister(lt9611->audio_pdev); - lt9611->audio_pdev = NULL; - } -} - static int lt9611_probe(struct i2c_client *client) { struct lt9611 *lt9611; @@ -1174,6 +1139,9 @@ static int lt9611_probe(struct i2c_client *client) i2c_set_clientdata(client, lt9611); + /* Disable Audio InfoFrame, enabled by default */ + regmap_update_bits(lt9611->regmap, 0x843d, LT9611_INFOFRAME_AUDIO, 0); + lt9611->bridge.funcs = <9611_bridge_funcs; lt9611->bridge.of_node = client->dev.of_node; lt9611->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | @@ -1182,6 +1150,10 @@ static int lt9611_probe(struct i2c_client *client) lt9611->bridge.type = DRM_MODE_CONNECTOR_HDMIA; lt9611->bridge.vendor = "Lontium"; lt9611->bridge.product = "LT9611"; + lt9611->bridge.hdmi_codec_max_i2s_channels = 8; + lt9611->bridge.hdmi_codec_i2s = 1; + lt9611->bridge.hdmi_codec_dev = dev; + lt9611->bridge.hdmi_codec_dai_port = 2; drm_bridge_add(<9611->bridge); @@ -1203,10 +1175,6 @@ static int lt9611_probe(struct i2c_client *client) lt9611_enable_hpd_interrupts(lt9611); - ret = lt9611_audio_init(dev, lt9611); - if (ret) - goto err_remove_bridge; - return 0; err_remove_bridge: @@ -1227,7 +1195,6 @@ static void lt9611_remove(struct i2c_client *client) struct lt9611 *lt9611 = i2c_get_clientdata(client); disable_irq(client->irq); - lt9611_audio_exit(lt9611); drm_bridge_remove(<9611->bridge); regulator_bulk_disable(ARRAY_SIZE(lt9611->supplies), lt9611->supplies);