From nobody Sun Nov 24 23:17:21 2024 Received: from mail-lj1-f175.google.com (mail-lj1-f175.google.com [209.85.208.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BAB1019D8B7 for ; Fri, 1 Nov 2024 10:19:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1730456366; cv=none; b=dCILWeFdMl+vYZKJVU0BDZpG/eItukdAexiabFQlYfUURR8tiIIuSG9IaNe4qcb/Rv6YHoRN/+SYPPne2I1p1sH3TINIAFKsWmEvqODi85+ausoAzY1bi3mXdRHeLc+52d7AmKyT7o3eFcUMoelOfWrw4QHYMZt3IhCl1DMxzn8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1730456366; c=relaxed/simple; bh=b9CjlXHFjClXWt0twlUk/5oI0wepnqrV5DObVEdOLnI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=C+F7/5JmEKIjT4nkJuiNYuRFKwjLGGA8p3NaWrLzpsqOjlr9MXz4FsRL3EhUsRVXR+zWaNvvp1t2bkdFDyGdW2Csc9R3sa+hwx9QDVHeZfHp/HBg3VNNFwOT+9hvXRv4otiduqOnjYlrMD9PdMCo1Hpq/kjgUXDQ+3KwyxVx1oE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=nMTZdTob; arc=none smtp.client-ip=209.85.208.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="nMTZdTob" Received: by mail-lj1-f175.google.com with SMTP id 38308e7fff4ca-2fb518014b9so15291141fa.3 for ; Fri, 01 Nov 2024 03:19:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1730456362; x=1731061162; darn=vger.kernel.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=n+9MtGcN2xrmwOXfB2jupKXdcgjG7Kpy3ckztHv28T8=; b=nMTZdTobm+NGy+owGgv6S172Gzdvc9c7Fz9ca5j2NVe68WX51I0ObKxmkyzgpeJdF4 xgCTSRs4T/SM2kqVSHY4teE8iUermkwth5l/DjWvwGSLFGbW19ehNtZu0/fPBsceYOgk v5LC4+SYwSa54+d/vAKlMzJY9uiYeC0xPTkz9TSY+rfA1lu5uFwFPjoVdfJaJPcOsRwh 0qVBwc0QzDexb5hyGj4PRiFyeaFoU0IqAHkssoG2cRWcLphhGBVvhNbq/soBl4ghoY9d FNVs9jPc3wcje5OE+vUAt602IB0VIn0M1sv+nkJfJPsi3wZ/ldg8BMyUwyWmsWv5RKnP 6VQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730456362; x=1731061162; 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=n+9MtGcN2xrmwOXfB2jupKXdcgjG7Kpy3ckztHv28T8=; b=BkHZaClpgIIT0Sfah3X9UwSzZvD6AfBdRm/OXo3oqVcFt69WNbdzEljrhPvH4avfMr zPaHD2FMalZbcerCfk3jTBvcCkq/Yvh702GLzsVJM7j9QS26TWNo32Nj1a1IM5Gwv7ad pb6WIBlVVi+5IXYuBorFNVpVowqVcUGZb5Q2VC7r+n/LaehehQbRjaIINGGLez39VJ7A RxTFPiNwbFha2rTm3CpDApOv/CUU7qW/rZYrCWI/XsggoO9cWNo3D1T1xBs5CM6EkPV+ 1QRy9nF3GreN1Xl40fnk3QFK1InJh4XGtEWQ8NPERpt862ftvb3h1HJCtw7ALd/TLZVq 4Gww== X-Forwarded-Encrypted: i=1; AJvYcCXBr+CikQy7aHBZkXSvNDwMZIn6X3mn5sM7CxCDxOJHLSxT7ku1RJuXDrDtkuY2Tq6pHabnD7c0e5Yise4=@vger.kernel.org X-Gm-Message-State: AOJu0YwGCZmpvaxVPNgHkJ7UP4jMp862H0Q1SLw0HHG5LTRCqn8pmaW1 tx3PST6BMBL0Hxy0/daBNJsw5C3mI8JEEcrXJjckt0YeWkhdv9JXFBBLnl/IdI4= X-Google-Smtp-Source: AGHT+IHyA+CdBfomxIExGbO7aXkaZFF0poEJsxU0dhPD1rsn8uyC/pmfbOY6Stq6lph25Uew4kt0YQ== X-Received: by 2002:a05:651c:2123:b0:2fb:45cf:5eef with SMTP id 38308e7fff4ca-2fcbe04dc90mr116656431fa.30.1730456361878; Fri, 01 Nov 2024 03:19:21 -0700 (PDT) Received: from umbar.lan ([192.130.178.90]) by smtp.gmail.com with ESMTPSA id 38308e7fff4ca-2fdef5d6ef4sm5197031fa.48.2024.11.01.03.19.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 03:19:20 -0700 (PDT) From: Dmitry Baryshkov Date: Fri, 01 Nov 2024 12:19:06 +0200 Subject: [PATCH RFC v2 5/7] drm/bridge: lt9611: switch to using the DRM HDMI codec framework 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: quoted-printable Message-Id: <20241101-drm-bridge-hdmi-connector-v2-5-739ef9addf9e@linaro.org> References: <20241101-drm-bridge-hdmi-connector-v2-0-739ef9addf9e@linaro.org> In-Reply-To: <20241101-drm-bridge-hdmi-connector-v2-0-739ef9addf9e@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 Cc: 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=b9CjlXHFjClXWt0twlUk/5oI0wepnqrV5DObVEdOLnI=; b=owEBbQGS/pANAwAKAYs8ij4CKSjVAcsmYgBnJKsYN1LGiSPgOIWjskJ8XtYxymYjffJCPxoST PC8lPTitNuJATMEAAEKAB0WIQRMcISVXLJjVvC4lX+LPIo+Aiko1QUCZySrGAAKCRCLPIo+Aiko 1YyRB/sFNxzWLmdqbzWaCcuOmBGrE0CKhmcdCjqMfAF/TIXvghRUFbT4F4bYAVuS5yKeGEJ74Rq cp4TqLZ6cDLBp79MbvyT0zZqPuqiQuKnREjp3jppH+TPv8xrPKpMLUoyBKE7wYYkoxwztq1jOCt zBkXZWoypk8mUZnoa/wuWcb3BJubjsK5z895jIvpHC9UEUpxERMV83zPyT2zxX24fdQdqVdebt/ CybOVeWxV7ILVNW0swbgI4c8tbiQXFd3G7ZLhzkYIiaP3wi81TB/cvvBMe3Fy+gF3prOKH1mbgo WvA+VtJa/MfbJLulphgW/8tlMNvS6m0DOEM8xE3peeKIuiNJ X-Developer-Key: i=dmitry.baryshkov@linaro.org; a=openpgp; fpr=8F88381DD5C873E4AE487DA5199BF1243632046A 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/brid= ge/lontium-lt9611.c index 4fa0dfc5539a5786278221f7c13b6473ab320a9a..9d8b1c8d533c79bd91ae956aa4c= b74f3bab6de78 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; =20 bool ac_mode; =20 @@ -866,6 +865,10 @@ static int lt9611_hdmi_clear_infoframe(struct drm_brid= ge *bridge, unsigned int mask; =20 switch (type) { + case HDMI_INFOFRAME_TYPE_AUDIO: + mask =3D LT9611_INFOFRAME_AUDIO; + break; + case HDMI_INFOFRAME_TYPE_AVI: mask =3D LT9611_INFOFRAME_AVI; break; @@ -899,6 +902,11 @@ static int lt9611_hdmi_write_infoframe(struct drm_brid= ge *bridge, int i; =20 switch (type) { + case HDMI_INFOFRAME_TYPE_AUDIO: + mask =3D LT9611_INFOFRAME_AUDIO; + addr =3D 0x84b2; + break; + case HDMI_INFOFRAME_TYPE_AVI: mask =3D LT9611_INFOFRAME_AVI; addr =3D 0x8440; @@ -942,6 +950,55 @@ lt9611_hdmi_tmds_char_rate_valid(const struct drm_brid= ge *bridge, return MODE_OK; } =20 +static int lt9611_hdmi_codec_audio_startup(struct drm_connector *connector, + struct drm_bridge *bridge) +{ + struct lt9611 *lt9611 =3D 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 =3D bridge_to_lt9611(bridge); + + if (hparms->sample_rate =3D=3D 48000) + regmap_write(lt9611->regmap, 0x840f, 0x2b); + else if (hparms->sample_rate =3D=3D 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 *connect= or, + struct drm_bridge *bridge) +{ + struct lt9611 *lt9611 =3D 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 =3D { .attach =3D lt9611_bridge_attach, .mode_valid =3D lt9611_bridge_mode_valid, @@ -962,6 +1019,10 @@ static const struct drm_bridge_funcs lt9611_bridge_fu= ncs =3D { .hdmi_tmds_char_rate_valid =3D lt9611_hdmi_tmds_char_rate_valid, .hdmi_write_infoframe =3D lt9611_hdmi_write_infoframe, .hdmi_clear_infoframe =3D lt9611_hdmi_clear_infoframe, + + .hdmi_codec_audio_startup =3D lt9611_hdmi_codec_audio_startup, + .hdmi_codec_prepare =3D lt9611_hdmi_codec_prepare, + .hdmi_codec_audio_shutdown =3D lt9611_hdmi_codec_audio_shutdown, }; =20 static int lt9611_parse_dt(struct device *dev, @@ -1015,102 +1076,6 @@ static int lt9611_read_device_rev(struct lt9611 *lt= 9611) return ret; } =20 -static int lt9611_hdmi_hw_params(struct device *dev, void *data, - struct hdmi_codec_daifmt *fmt, - struct hdmi_codec_params *hparms) -{ - struct lt9611 *lt9611 =3D data; - - if (hparms->sample_rate =3D=3D 48000) - regmap_write(lt9611->regmap, 0x840f, 0x2b); - else if (hparms->sample_rate =3D=3D 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 =3D 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 =3D 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 =3D of_graph_parse_endpoint(endpoint, &of_ep); - if (ret < 0) - return ret; - - /* - * HDMI sound should be located as reg =3D <2> - * Then, it is sound port 0 - */ - if (of_ep.port =3D=3D 2) - return 0; - - return -EINVAL; -} - -static const struct hdmi_codec_ops lt9611_codec_ops =3D { - .hw_params =3D lt9611_hdmi_hw_params, - .audio_shutdown =3D lt9611_audio_shutdown, - .audio_startup =3D lt9611_audio_startup, - .get_dai_id =3D lt9611_hdmi_i2s_get_dai_id, -}; - -static struct hdmi_codec_pdata codec_data =3D { - .ops =3D <9611_codec_ops, - .max_i2s_channels =3D 8, - .i2s =3D 1, -}; - -static int lt9611_audio_init(struct device *dev, struct lt9611 *lt9611) -{ - codec_data.data =3D lt9611; - lt9611->audio_pdev =3D - 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 =3D NULL; - } -} - static int lt9611_probe(struct i2c_client *client) { struct lt9611 *lt9611; @@ -1174,6 +1139,9 @@ static int lt9611_probe(struct i2c_client *client) =20 i2c_set_clientdata(client, lt9611); =20 + /* Disable Audio InfoFrame, enabled by default */ + regmap_update_bits(lt9611->regmap, 0x843d, LT9611_INFOFRAME_AUDIO, 0); + lt9611->bridge.funcs =3D <9611_bridge_funcs; lt9611->bridge.of_node =3D client->dev.of_node; lt9611->bridge.ops =3D DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | @@ -1182,6 +1150,10 @@ static int lt9611_probe(struct i2c_client *client) lt9611->bridge.type =3D DRM_MODE_CONNECTOR_HDMIA; lt9611->bridge.vendor =3D "Lontium"; lt9611->bridge.product =3D "LT9611"; + lt9611->bridge.hdmi_codec_max_i2s_channels =3D 8; + lt9611->bridge.hdmi_codec_i2s =3D 1; + lt9611->bridge.hdmi_codec_dev =3D dev; + lt9611->bridge.hdmi_codec_dai_port =3D 2; =20 drm_bridge_add(<9611->bridge); =20 @@ -1203,10 +1175,6 @@ static int lt9611_probe(struct i2c_client *client) =20 lt9611_enable_hpd_interrupts(lt9611); =20 - ret =3D lt9611_audio_init(dev, lt9611); - if (ret) - goto err_remove_bridge; - return 0; =20 err_remove_bridge: @@ -1227,7 +1195,6 @@ static void lt9611_remove(struct i2c_client *client) struct lt9611 *lt9611 =3D i2c_get_clientdata(client); =20 disable_irq(client->irq); - lt9611_audio_exit(lt9611); drm_bridge_remove(<9611->bridge); =20 regulator_bulk_disable(ARRAY_SIZE(lt9611->supplies), lt9611->supplies); --=20 2.39.5