From patchwork Wed Oct 20 12:39:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Neil Armstrong X-Patchwork-Id: 12572289 X-Patchwork-Delegate: neil.armstrong@linaro.org 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3075DC433F5 for ; Wed, 20 Oct 2021 12:42:00 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id E91306103D for ; Wed, 20 Oct 2021 12:41:59 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org E91306103D Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=/qt85v0E009ZNTS1zGS8oPE2yUAczupZgqTjTqB31bY=; b=5C+U1+nPyomQZa 8K+kIAujI9dG9QqZNYvSVL3GS7lj50oR32ELx0d08QIPe9oW89oS8j+nUf94AxfRupi/bb2qGAAE9 WowOrGImXzIMzf7rsa1C3pzxR2vhe9RUn/M3H0GU0WRf9brI/O0MYmrznnbTo6iB/+S+qIXhGJrdo vI9jesUOQW3dAxCUaGVK4SwYW7pcsnf29cMD72xWwH+pwFj4M9qj0NZslrwWKvE5lzwImPcwZ2eA2 GcsMJebAJxSJNepH+64qFADzMF0GPHLYRZhegnJg8cf0Y7MwjoKQVGs5ofxY4WkyTZwJ3rk4bR3wk uMpesStvHc8qxxhrdNfQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mdAun-004Vol-P5; Wed, 20 Oct 2021 12:41:53 +0000 Received: from mail-wm1-x333.google.com ([2a00:1450:4864:20::333]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mdAsw-004UrJ-Sv for linux-amlogic@lists.infradead.org; Wed, 20 Oct 2021 12:40:03 +0000 Received: by mail-wm1-x333.google.com with SMTP id 67-20020a1c1946000000b0030d4c90fa87so9906743wmz.2 for ; Wed, 20 Oct 2021 05:39:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=/IFVpxHHJMHARIjdjaFpebNjFZaqu9DmMEXQC6d8lb8=; b=fQfz2s+GIjH1uU5O3aV4gRZQgQlDTXAi3ZHtBRiY0MWbjfbwsRPV+HHvL9uhEVivX9 CusCd4St2091KB5+whbMAidQabmHVLFWq6yDodC8C5aIAJMexkIZ0zLfs4G60dxLgLzA k2kMj+jdh/ZQUyfK3LR5Fx3N6G8+vNi0HurSQ/XMUvwuZOZNoAvc0mFG0vBIzMiCmI3o ax7U2UjMfzDwTd1PyUTy7MRTlCVioTf8F2V0Kfg6qfDro8eiix7YE8053M0EfJtdKYbL rDWDqVlnJqHk3dyoQmLCuiuCLuF3uJ4QPJN0b7m4ooHGJmCKxrDmhWVZQ03zFwx6WNTn Eq4w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=/IFVpxHHJMHARIjdjaFpebNjFZaqu9DmMEXQC6d8lb8=; b=W0k8eFvTvJDsfIOYxLRcJO0aTNeN+NWyXtbJwUuKPaP37u3+ikwWVA/oHPEJPxS6rc wKAqC01aDXwyjElKvYhQClAAvgCB1vNxSAAWVWg6UcGgqBTUF0Q/hcxBoVy5Z2qysSE0 EoX7dxLFKs2bd1v1d71lFKezozwmkY5GenHF2C+ifBGAKlWaz7rqHl2duo+BqDo33HR0 C6VlRitRPTP01+d3qTGB0H4uxUBiDokR4qJzhb3kTJazHo9l9ZaUJNsOb6OEiuP9MgaV sZmR3pjkaknnhpd4io6Kv6cLrvGB3TCOLdHM+95dvz9+4aXD7E3+I0ub4Z+L4WjDu/nR P+mg== X-Gm-Message-State: AOAM532K/hiEH6lffM+GJo1nLAubfVyjZNR2JdXmwTKFre1XeKu0pwBT 54xmCeS9qIfrLaxCRZqVPdZvwA== X-Google-Smtp-Source: ABdhPJx5PaHHkfj44R0jHo5Eflv7DvAaCo43R50VoGhU9CgRj98KJuZdQp4to6o81FLwm3sGVufnQA== X-Received: by 2002:a05:600c:378d:: with SMTP id o13mr8404439wmr.41.1634733597149; Wed, 20 Oct 2021 05:39:57 -0700 (PDT) Received: from localhost.localdomain ([2001:861:44c0:66c0:d31f:1512:8915:e439]) by smtp.gmail.com with ESMTPSA id b19sm5342680wmj.9.2021.10.20.05.39.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Oct 2021 05:39:56 -0700 (PDT) From: Neil Armstrong To: daniel@ffwll.ch, Laurent.pinchart@ideasonboard.com, sam@ravnborg.org Cc: martin.blumenstingl@googlemail.com, dri-devel@lists.freedesktop.org, linux-amlogic@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Neil Armstrong Subject: [PATCH v3 6/6] drm/meson: encoder_cvbs: switch to bridge with ATTACH_NO_CONNECTOR Date: Wed, 20 Oct 2021 14:39:47 +0200 Message-Id: <20211020123947.2585572-7-narmstrong@baylibre.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211020123947.2585572-1-narmstrong@baylibre.com> References: <20211020123947.2585572-1-narmstrong@baylibre.com> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=12904; h=from:subject; bh=OlNNTmN8nosYoeNKPBE53UzuRFb9R4pSq4LSfrZKnuU=; b=owEBbQKS/ZANAwAKAXfc29rIyEnRAcsmYgBhcA34ftCu2bQYD9BgERzGjB8Kv6U3gZ6EYg3Pbf2X sOB7GZyJAjMEAAEKAB0WIQQ9U8YmyFYF/h30LIt33NvayMhJ0QUCYXAN+AAKCRB33NvayMhJ0T5pD/ 9V1YFO4VRnw1txSSTLIOCukxA5xMFCG60fCaPJKrz3SP2K9mbvjgNMDv64J0wWNnNi+hYI3MoHJgYe HlGiUG6pVI2hoG1knDcD0xnBCme/yQos+D1VWlyytThYS5KgEjspl4xJd0bMzpKFHr1t/DEYTQQNUR KtS1ZBv/j/4s5eywzX/P9MBcMkiuhpa4E+RPUy7/7bNae57Bjr/Ajci060PWGGBgCoiu68NB2I8+sR A3uMg2N8pCxOZMlN0b9RYsrBplRtWjYIfr9Q2TsSqTWiPEhs+H/dYMwD2OsHhVnLDo1enrVKD7Me2V 0qHvTxM6S+CZMASm4Zx6+2cv8VOlXcigjDc/jp1pOXU5nP5F83i8l1K2qJyXnrQoDKFWGygy9pQq8X rPtga2U+6sWdqojR3EkcwcKjEE4tTmextefuqctUigRGb52VC5wwgf5cBOUGee1Va3+HjELeDCMCPM 51Gh8zI/NTfwPqmro8fTcItx1r6F3Lm1yTZF/Fz58ueDgbdfOvjTW5hPekC2ZfIb8+HX5ltqcae0kq E7p3W2gzt98B6j6TApYZWTayN6V4cWbHBk8pPGYqa0i7uJ9k30ZT2GF6daCgHi3WlYewoFG/c2Hl8k yuMSdLVacNYwGHLeooKtZGj6rYURnvHyDbuzqKy5u1d0x1ECNPhmTCTDFOOg== X-Developer-Key: i=narmstrong@baylibre.com; a=openpgp; fpr=89EC3D058446217450F22848169AB7B1A4CFF8AE X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211020_053958_962617_0A9F6D9B X-CRM114-Status: GOOD ( 18.86 ) X-BeenThere: linux-amlogic@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-amlogic" Errors-To: linux-amlogic-bounces+linux-amlogic=archiver.kernel.org@lists.infradead.org Drop the local connector and move all callback to bridge funcs in order to leverage the generic CVBS diplay connector. This will also permit adding custom cvbs connectors for ADC based HPD detection on some Amlogic SoC based boards. Signed-off-by: Neil Armstrong Acked-by: Sam Ravnborg Acked-by: Martin Blumenstingl --- drivers/gpu/drm/meson/meson_encoder_cvbs.c | 241 ++++++++++----------- 1 file changed, 116 insertions(+), 125 deletions(-) diff --git a/drivers/gpu/drm/meson/meson_encoder_cvbs.c b/drivers/gpu/drm/meson/meson_encoder_cvbs.c index 01024c5f610c..fd8db97ba8ba 100644 --- a/drivers/gpu/drm/meson/meson_encoder_cvbs.c +++ b/drivers/gpu/drm/meson/meson_encoder_cvbs.c @@ -13,10 +13,12 @@ #include #include +#include +#include #include #include #include -#include +#include #include "meson_registers.h" #include "meson_vclk.h" @@ -30,14 +32,13 @@ struct meson_encoder_cvbs { struct drm_encoder encoder; - struct drm_connector connector; + struct drm_bridge bridge; + struct drm_bridge *next_bridge; struct meson_drm *priv; }; -#define encoder_to_meson_encoder_cvbs(x) \ - container_of(x, struct meson_encoder_cvbs, encoder) -#define connector_to_meson_encoder_cvbs(x) \ - container_of(x, struct meson_encoder_cvbs, connector) +#define bridge_to_meson_encoder_cvbs(x) \ + container_of(x, struct meson_encoder_cvbs, bridge) /* Supported Modes */ @@ -81,32 +82,31 @@ meson_cvbs_get_mode(const struct drm_display_mode *req_mode) return NULL; } -/* Connector */ - -static void meson_cvbs_connector_destroy(struct drm_connector *connector) +static int meson_encoder_cvbs_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) { - drm_connector_cleanup(connector); -} + struct meson_encoder_cvbs *meson_encoder_cvbs = + bridge_to_meson_encoder_cvbs(bridge); -static enum drm_connector_status -meson_cvbs_connector_detect(struct drm_connector *connector, bool force) -{ - /* FIXME: Add load-detect or jack-detect if possible */ - return connector_status_connected; + return drm_bridge_attach(bridge->encoder, meson_encoder_cvbs->next_bridge, + &meson_encoder_cvbs->bridge, flags); } -static int meson_cvbs_connector_get_modes(struct drm_connector *connector) +static int meson_encoder_cvbs_get_modes(struct drm_bridge *bridge, + struct drm_connector *connector) { - struct drm_device *dev = connector->dev; + struct meson_encoder_cvbs *meson_encoder_cvbs = + bridge_to_meson_encoder_cvbs(bridge); + struct meson_drm *priv = meson_encoder_cvbs->priv; struct drm_display_mode *mode; int i; for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) { struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i]; - mode = drm_mode_duplicate(dev, &meson_mode->mode); + mode = drm_mode_duplicate(priv->drm, &meson_mode->mode); if (!mode) { - DRM_ERROR("Failed to create a new display mode\n"); + dev_err(priv->dev, "Failed to create a new display mode\n"); return 0; } @@ -116,40 +116,18 @@ static int meson_cvbs_connector_get_modes(struct drm_connector *connector) return i; } -static int meson_cvbs_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) +static int meson_encoder_cvbs_mode_valid(struct drm_bridge *bridge, + const struct drm_display_info *display_info, + const struct drm_display_mode *mode) { - /* Validate the modes added in get_modes */ - return MODE_OK; -} - -static const struct drm_connector_funcs meson_cvbs_connector_funcs = { - .detect = meson_cvbs_connector_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = meson_cvbs_connector_destroy, - .reset = drm_atomic_helper_connector_reset, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -}; + if (meson_cvbs_get_mode(mode)) + return MODE_OK; -static const -struct drm_connector_helper_funcs meson_cvbs_connector_helper_funcs = { - .get_modes = meson_cvbs_connector_get_modes, - .mode_valid = meson_cvbs_connector_mode_valid, -}; - -/* Encoder */ - -static void meson_encoder_cvbs_encoder_destroy(struct drm_encoder *encoder) -{ - drm_encoder_cleanup(encoder); + return MODE_BAD; } -static const struct drm_encoder_funcs meson_encoder_cvbs_encoder_funcs = { - .destroy = meson_encoder_cvbs_encoder_destroy, -}; - -static int meson_encoder_cvbs_encoder_atomic_check(struct drm_encoder *encoder, +static int meson_encoder_cvbs_atomic_check(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state) { @@ -159,27 +137,40 @@ static int meson_encoder_cvbs_encoder_atomic_check(struct drm_encoder *encoder, return -EINVAL; } -static void meson_encoder_cvbs_encoder_disable(struct drm_encoder *encoder) +static void meson_encoder_cvbs_atomic_enable(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state) { - struct meson_encoder_cvbs *meson_encoder_cvbs = - encoder_to_meson_encoder_cvbs(encoder); - struct meson_drm *priv = meson_encoder_cvbs->priv; + struct meson_encoder_cvbs *encoder_cvbs = bridge_to_meson_encoder_cvbs(bridge); + struct drm_atomic_state *state = bridge_state->base.state; + struct meson_drm *priv = encoder_cvbs->priv; + const struct meson_cvbs_mode *meson_mode; + struct drm_connector_state *conn_state; + struct drm_crtc_state *crtc_state; + struct drm_connector *connector; - /* Disable CVBS VDAC */ - if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) { - regmap_write(priv->hhi, HHI_VDAC_CNTL0_G12A, 0); - regmap_write(priv->hhi, HHI_VDAC_CNTL1_G12A, 0); - } else { - regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0); - regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8); - } -} + connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); + if (WARN_ON(!connector)) + return; -static void meson_encoder_cvbs_encoder_enable(struct drm_encoder *encoder) -{ - struct meson_encoder_cvbs *meson_encoder_cvbs = - encoder_to_meson_encoder_cvbs(encoder); - struct meson_drm *priv = meson_encoder_cvbs->priv; + conn_state = drm_atomic_get_new_connector_state(state, connector); + if (WARN_ON(!conn_state)) + return; + + crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); + if (WARN_ON(!crtc_state)) + return; + + meson_mode = meson_cvbs_get_mode(&crtc_state->adjusted_mode); + if (WARN_ON(!meson_mode)) + return; + + meson_venci_cvbs_mode_set(priv, meson_mode->enci); + + /* Setup 27MHz vclk2 for ENCI and VDAC */ + meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS, + MESON_VCLK_CVBS, MESON_VCLK_CVBS, + MESON_VCLK_CVBS, MESON_VCLK_CVBS, + true); /* VDAC0 source is not from ATV */ writel_bits_relaxed(VENC_VDAC_SEL_ATV_DMD, 0, @@ -198,96 +189,96 @@ static void meson_encoder_cvbs_encoder_enable(struct drm_encoder *encoder) } } -static void meson_encoder_cvbs_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) +static void meson_encoder_cvbs_atomic_disable(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state) { - const struct meson_cvbs_mode *meson_mode = meson_cvbs_get_mode(mode); struct meson_encoder_cvbs *meson_encoder_cvbs = - encoder_to_meson_encoder_cvbs(encoder); + bridge_to_meson_encoder_cvbs(bridge); struct meson_drm *priv = meson_encoder_cvbs->priv; - if (meson_mode) { - meson_venci_cvbs_mode_set(priv, meson_mode->enci); - - /* Setup 27MHz vclk2 for ENCI and VDAC */ - meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS, - MESON_VCLK_CVBS, MESON_VCLK_CVBS, - MESON_VCLK_CVBS, MESON_VCLK_CVBS, - true); + /* Disable CVBS VDAC */ + if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) { + regmap_write(priv->hhi, HHI_VDAC_CNTL0_G12A, 0); + regmap_write(priv->hhi, HHI_VDAC_CNTL1_G12A, 0); + } else { + regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0); + regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8); } } -static const struct drm_encoder_helper_funcs - meson_encoder_cvbs_encoder_helper_funcs = { - .atomic_check = meson_encoder_cvbs_encoder_atomic_check, - .disable = meson_encoder_cvbs_encoder_disable, - .enable = meson_encoder_cvbs_encoder_enable, - .mode_set = meson_encoder_cvbs_encoder_mode_set, +static const struct drm_bridge_funcs meson_encoder_cvbs_bridge_funcs = { + .attach = meson_encoder_cvbs_attach, + .mode_valid = meson_encoder_cvbs_mode_valid, + .get_modes = meson_encoder_cvbs_get_modes, + .atomic_enable = meson_encoder_cvbs_atomic_enable, + .atomic_disable = meson_encoder_cvbs_atomic_disable, + .atomic_check = meson_encoder_cvbs_atomic_check, + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, + .atomic_reset = drm_atomic_helper_bridge_reset, }; -static bool meson_encoder_cvbs_connector_is_available(struct meson_drm *priv) -{ - struct device_node *remote; - - remote = of_graph_get_remote_node(priv->dev->of_node, 0, 0); - if (!remote) - return false; - - of_node_put(remote); - return true; -} - int meson_encoder_cvbs_init(struct meson_drm *priv) { struct drm_device *drm = priv->drm; struct meson_encoder_cvbs *meson_encoder_cvbs; struct drm_connector *connector; - struct drm_encoder *encoder; + struct device_node *remote; int ret; - if (!meson_encoder_cvbs_connector_is_available(priv)) { + meson_encoder_cvbs = devm_kzalloc(priv->dev, sizeof(*meson_encoder_cvbs), GFP_KERNEL); + if (!meson_encoder_cvbs) + return -ENOMEM; + + /* CVBS Connector Bridge */ + remote = of_graph_get_remote_node(priv->dev->of_node, 0, 0); + if (!remote) { dev_info(drm->dev, "CVBS Output connector not available\n"); return 0; } - meson_encoder_cvbs = devm_kzalloc(priv->dev, sizeof(*meson_encoder_cvbs), - GFP_KERNEL); - if (!meson_encoder_cvbs) - return -ENOMEM; + meson_encoder_cvbs->next_bridge = of_drm_find_bridge(remote); + if (!meson_encoder_cvbs->next_bridge) { + dev_err(priv->dev, "Failed to find CVBS Connector bridge\n"); + return -EPROBE_DEFER; + } - meson_encoder_cvbs->priv = priv; - encoder = &meson_encoder_cvbs->encoder; - connector = &meson_encoder_cvbs->connector; + /* CVBS Encoder Bridge */ + meson_encoder_cvbs->bridge.funcs = &meson_encoder_cvbs_bridge_funcs; + meson_encoder_cvbs->bridge.of_node = priv->dev->of_node; + meson_encoder_cvbs->bridge.type = DRM_MODE_CONNECTOR_Composite; + meson_encoder_cvbs->bridge.ops = DRM_BRIDGE_OP_MODES; + meson_encoder_cvbs->bridge.interlace_allowed = true; - /* Connector */ + drm_bridge_add(&meson_encoder_cvbs->bridge); - drm_connector_helper_add(connector, - &meson_cvbs_connector_helper_funcs); + meson_encoder_cvbs->priv = priv; - ret = drm_connector_init(drm, connector, &meson_cvbs_connector_funcs, - DRM_MODE_CONNECTOR_Composite); + /* Encoder */ + ret = drm_simple_encoder_init(priv->drm, &meson_encoder_cvbs->encoder, + DRM_MODE_ENCODER_TVDAC); if (ret) { - dev_err(priv->dev, "Failed to init CVBS connector\n"); + dev_err(priv->dev, "Failed to init CVBS encoder: %d\n", ret); return ret; } - connector->interlace_allowed = 1; - - /* Encoder */ - - drm_encoder_helper_add(encoder, &meson_encoder_cvbs_encoder_helper_funcs); + meson_encoder_cvbs->encoder.possible_crtcs = BIT(0); - ret = drm_encoder_init(drm, encoder, &meson_encoder_cvbs_encoder_funcs, - DRM_MODE_ENCODER_TVDAC, "meson_encoder_cvbs"); + /* Attach CVBS Encoder Bridge to Encoder */ + ret = drm_bridge_attach(&meson_encoder_cvbs->encoder, &meson_encoder_cvbs->bridge, NULL, + DRM_BRIDGE_ATTACH_NO_CONNECTOR); if (ret) { - dev_err(priv->dev, "Failed to init CVBS encoder\n"); + dev_err(priv->dev, "Failed to attach bridge: %d\n", ret); return ret; } - encoder->possible_crtcs = BIT(0); - - drm_connector_attach_encoder(connector, encoder); + /* Initialize & attach Bridge Connector */ + connector = drm_bridge_connector_init(priv->drm, &meson_encoder_cvbs->encoder); + if (IS_ERR(connector)) { + dev_err(priv->dev, "Unable to create CVBS bridge connector\n"); + return PTR_ERR(connector); + } + drm_connector_attach_encoder(connector, &meson_encoder_cvbs->encoder); return 0; }