Lines Matching +full:hdmi +full:- +full:connector
1 // SPDX-License-Identifier: GPL-2.0-or-later
19 #include <media/cec-notifier.h>
29 #include <linux/media-bus-format.h>
42 struct drm_connector *connector; member
56 return drm_bridge_attach(bridge->encoder, encoder_hdmi->next_bridge, in meson_encoder_hdmi_attach()
57 &encoder_hdmi->bridge, flags); in meson_encoder_hdmi_attach()
64 cec_notifier_conn_unregister(encoder_hdmi->cec_notifier); in meson_encoder_hdmi_detach()
65 encoder_hdmi->cec_notifier = NULL; in meson_encoder_hdmi_detach()
71 struct meson_drm *priv = encoder_hdmi->priv; in meson_encoder_hdmi_set_vclk()
78 vclk_freq = mode->clock; in meson_encoder_hdmi_set_vclk()
81 if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24) in meson_encoder_hdmi_set_vclk()
94 if (mode->flags & DRM_MODE_FLAG_DBLCLK) in meson_encoder_hdmi_set_vclk()
102 encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24) in meson_encoder_hdmi_set_vclk()
107 if (mode->flags & DRM_MODE_FLAG_DBLCLK) in meson_encoder_hdmi_set_vclk()
110 dev_dbg(priv->dev, "vclk:%d phy=%d venc=%d hdmi=%d enci=%d\n", in meson_encoder_hdmi_set_vclk()
112 priv->venc.hdmi_use_enci); in meson_encoder_hdmi_set_vclk()
115 venc_freq, hdmi_freq, priv->venc.hdmi_use_enci); in meson_encoder_hdmi_set_vclk()
123 struct meson_drm *priv = encoder_hdmi->priv; in meson_encoder_hdmi_mode_valid()
124 bool is_hdmi2_sink = display_info->hdmi.scdc.supported; in meson_encoder_hdmi_mode_valid()
132 dev_dbg(priv->dev, "Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode)); in meson_encoder_hdmi_mode_valid()
134 /* If sink does not support 540MHz, reject the non-420 HDMI2 modes */ in meson_encoder_hdmi_mode_valid()
135 if (display_info->max_tmds_clock && in meson_encoder_hdmi_mode_valid()
136 mode->clock > display_info->max_tmds_clock && in meson_encoder_hdmi_mode_valid()
141 /* Check against non-VIC supported modes */ in meson_encoder_hdmi_mode_valid()
147 return meson_vclk_dmt_supported_freq(priv, mode->clock); in meson_encoder_hdmi_mode_valid()
152 vclk_freq = mode->clock; in meson_encoder_hdmi_mode_valid()
164 if (mode->flags & DRM_MODE_FLAG_DBLCLK) in meson_encoder_hdmi_mode_valid()
179 if (mode->flags & DRM_MODE_FLAG_DBLCLK) in meson_encoder_hdmi_mode_valid()
182 dev_dbg(priv->dev, "%s: vclk:%d phy=%d venc=%d hdmi=%d\n", in meson_encoder_hdmi_mode_valid()
192 struct drm_atomic_state *state = bridge_state->base.state; in meson_encoder_hdmi_atomic_enable()
194 struct meson_drm *priv = encoder_hdmi->priv; in meson_encoder_hdmi_atomic_enable()
198 struct drm_connector *connector; in meson_encoder_hdmi_atomic_enable() local
202 connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); in meson_encoder_hdmi_atomic_enable()
203 if (WARN_ON(!connector)) in meson_encoder_hdmi_atomic_enable()
206 conn_state = drm_atomic_get_new_connector_state(state, connector); in meson_encoder_hdmi_atomic_enable()
210 crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); in meson_encoder_hdmi_atomic_enable()
214 mode = &crtc_state->adjusted_mode; in meson_encoder_hdmi_atomic_enable()
218 dev_dbg(priv->dev, "\"%s\" vic %d\n", mode->name, vic); in meson_encoder_hdmi_atomic_enable()
220 if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24) { in meson_encoder_hdmi_atomic_enable()
223 } else if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYVY8_1X16) in meson_encoder_hdmi_atomic_enable()
226 /* VENC + VENC-DVI Mode setup */ in meson_encoder_hdmi_atomic_enable()
232 if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24) in meson_encoder_hdmi_atomic_enable()
233 /* Setup YUV420 to HDMI-TX, no 10bit diphering */ in meson_encoder_hdmi_atomic_enable()
235 priv->io_base + _REG(VPU_HDMI_FMT_CTRL)); in meson_encoder_hdmi_atomic_enable()
236 else if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYVY8_1X16) in meson_encoder_hdmi_atomic_enable()
237 /* Setup YUV422 to HDMI-TX, no 10bit diphering */ in meson_encoder_hdmi_atomic_enable()
239 priv->io_base + _REG(VPU_HDMI_FMT_CTRL)); in meson_encoder_hdmi_atomic_enable()
241 /* Setup YUV444 to HDMI-TX, no 10bit diphering */ in meson_encoder_hdmi_atomic_enable()
242 writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL)); in meson_encoder_hdmi_atomic_enable()
244 dev_dbg(priv->dev, "%s\n", priv->venc.hdmi_use_enci ? "VENCI" : "VENCP"); in meson_encoder_hdmi_atomic_enable()
246 if (priv->venc.hdmi_use_enci) in meson_encoder_hdmi_atomic_enable()
247 writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN)); in meson_encoder_hdmi_atomic_enable()
249 writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN)); in meson_encoder_hdmi_atomic_enable()
256 struct meson_drm *priv = encoder_hdmi->priv; in meson_encoder_hdmi_atomic_disable()
259 priv->io_base + _REG(VPU_HDMI_SETTING)); in meson_encoder_hdmi_atomic_disable()
261 writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN)); in meson_encoder_hdmi_atomic_disable()
262 writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN)); in meson_encoder_hdmi_atomic_disable()
309 drm_atomic_get_old_connector_state(conn_state->state, conn_state->connector); in meson_encoder_hdmi_atomic_check()
310 struct meson_drm *priv = encoder_hdmi->priv; in meson_encoder_hdmi_atomic_check()
312 encoder_hdmi->output_bus_fmt = bridge_state->output_bus_cfg.format; in meson_encoder_hdmi_atomic_check()
314 dev_dbg(priv->dev, "output_bus_fmt %lx\n", encoder_hdmi->output_bus_fmt); in meson_encoder_hdmi_atomic_check()
317 crtc_state->mode_changed = true; in meson_encoder_hdmi_atomic_check()
328 if (!encoder_hdmi->cec_notifier) in meson_encoder_hdmi_hpd_notify()
332 edid = drm_bridge_get_edid(encoder_hdmi->next_bridge, encoder_hdmi->connector); in meson_encoder_hdmi_hpd_notify()
336 cec_notifier_set_phys_addr_from_edid(encoder_hdmi->cec_notifier, edid); in meson_encoder_hdmi_hpd_notify()
340 cec_notifier_phys_addr_invalidate(encoder_hdmi->cec_notifier); in meson_encoder_hdmi_hpd_notify()
364 meson_encoder_hdmi = devm_kzalloc(priv->dev, sizeof(*meson_encoder_hdmi), GFP_KERNEL); in meson_encoder_hdmi_init()
366 return -ENOMEM; in meson_encoder_hdmi_init()
368 /* HDMI Transceiver Bridge */ in meson_encoder_hdmi_init()
369 remote = of_graph_get_remote_node(priv->dev->of_node, 1, 0); in meson_encoder_hdmi_init()
371 dev_err(priv->dev, "HDMI transceiver device is disabled"); in meson_encoder_hdmi_init()
375 meson_encoder_hdmi->next_bridge = of_drm_find_bridge(remote); in meson_encoder_hdmi_init()
376 if (!meson_encoder_hdmi->next_bridge) { in meson_encoder_hdmi_init()
377 dev_err(priv->dev, "Failed to find HDMI transceiver bridge\n"); in meson_encoder_hdmi_init()
378 ret = -EPROBE_DEFER; in meson_encoder_hdmi_init()
382 /* HDMI Encoder Bridge */ in meson_encoder_hdmi_init()
383 meson_encoder_hdmi->bridge.funcs = &meson_encoder_hdmi_bridge_funcs; in meson_encoder_hdmi_init()
384 meson_encoder_hdmi->bridge.of_node = priv->dev->of_node; in meson_encoder_hdmi_init()
385 meson_encoder_hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA; in meson_encoder_hdmi_init()
386 meson_encoder_hdmi->bridge.interlace_allowed = true; in meson_encoder_hdmi_init()
388 drm_bridge_add(&meson_encoder_hdmi->bridge); in meson_encoder_hdmi_init()
390 meson_encoder_hdmi->priv = priv; in meson_encoder_hdmi_init()
393 ret = drm_simple_encoder_init(priv->drm, &meson_encoder_hdmi->encoder, in meson_encoder_hdmi_init()
396 dev_err(priv->dev, "Failed to init HDMI encoder: %d\n", ret); in meson_encoder_hdmi_init()
400 meson_encoder_hdmi->encoder.possible_crtcs = BIT(0); in meson_encoder_hdmi_init()
402 /* Attach HDMI Encoder Bridge to Encoder */ in meson_encoder_hdmi_init()
403 ret = drm_bridge_attach(&meson_encoder_hdmi->encoder, &meson_encoder_hdmi->bridge, NULL, in meson_encoder_hdmi_init()
406 dev_err(priv->dev, "Failed to attach bridge: %d\n", ret); in meson_encoder_hdmi_init()
410 /* Initialize & attach Bridge Connector */ in meson_encoder_hdmi_init()
411 meson_encoder_hdmi->connector = drm_bridge_connector_init(priv->drm, in meson_encoder_hdmi_init()
412 &meson_encoder_hdmi->encoder); in meson_encoder_hdmi_init()
413 if (IS_ERR(meson_encoder_hdmi->connector)) { in meson_encoder_hdmi_init()
414 dev_err(priv->dev, "Unable to create HDMI bridge connector\n"); in meson_encoder_hdmi_init()
415 ret = PTR_ERR(meson_encoder_hdmi->connector); in meson_encoder_hdmi_init()
418 drm_connector_attach_encoder(meson_encoder_hdmi->connector, in meson_encoder_hdmi_init()
419 &meson_encoder_hdmi->encoder); in meson_encoder_hdmi_init()
423 …* encoder->[hdmi encoder bridge]->[dw-hdmi bridge]->[display connector bridge]->[display connector] in meson_encoder_hdmi_init()
428 * connector to have a state. in meson_encoder_hdmi_init()
430 drm_atomic_helper_connector_reset(meson_encoder_hdmi->connector); in meson_encoder_hdmi_init()
435 drm_connector_attach_hdr_output_metadata_property(meson_encoder_hdmi->connector); in meson_encoder_hdmi_init()
437 drm_connector_attach_max_bpc_property(meson_encoder_hdmi->connector, 8, 8); in meson_encoder_hdmi_init()
440 meson_encoder_hdmi->connector->ycbcr_420_allowed = true; in meson_encoder_hdmi_init()
448 cec_fill_conn_info_from_drm(&conn_info, meson_encoder_hdmi->connector); in meson_encoder_hdmi_init()
450 notifier = cec_notifier_conn_register(&pdev->dev, NULL, &conn_info); in meson_encoder_hdmi_init()
452 put_device(&pdev->dev); in meson_encoder_hdmi_init()
453 return -ENOMEM; in meson_encoder_hdmi_init()
456 meson_encoder_hdmi->cec_notifier = notifier; in meson_encoder_hdmi_init()
459 priv->encoders[MESON_ENC_HDMI] = meson_encoder_hdmi; in meson_encoder_hdmi_init()
461 dev_dbg(priv->dev, "HDMI encoder initialized\n"); in meson_encoder_hdmi_init()
474 if (priv->encoders[MESON_ENC_HDMI]) { in meson_encoder_hdmi_remove()
475 meson_encoder_hdmi = priv->encoders[MESON_ENC_HDMI]; in meson_encoder_hdmi_remove()
476 drm_bridge_remove(&meson_encoder_hdmi->bridge); in meson_encoder_hdmi_remove()