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 * 1000ULL; 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, in meson_encoder_hdmi_set_vclk()
111 "vclk:%lluHz phy=%lluHz venc=%lluHz hdmi=%lluHz enci=%d\n", in meson_encoder_hdmi_set_vclk()
113 priv->venc.hdmi_use_enci); in meson_encoder_hdmi_set_vclk()
116 venc_freq, hdmi_freq, priv->venc.hdmi_use_enci); in meson_encoder_hdmi_set_vclk()
124 struct meson_drm *priv = encoder_hdmi->priv; in meson_encoder_hdmi_mode_valid()
125 bool is_hdmi2_sink = display_info->hdmi.scdc.supported; in meson_encoder_hdmi_mode_valid()
126 unsigned long long clock = mode->clock * 1000ULL; in meson_encoder_hdmi_mode_valid()
134 dev_dbg(priv->dev, "Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode)); in meson_encoder_hdmi_mode_valid()
136 /* If sink does not support 540MHz, reject the non-420 HDMI2 modes */ in meson_encoder_hdmi_mode_valid()
137 if (display_info->max_tmds_clock && in meson_encoder_hdmi_mode_valid()
138 mode->clock > display_info->max_tmds_clock && in meson_encoder_hdmi_mode_valid()
143 /* Check against non-VIC supported modes */ in meson_encoder_hdmi_mode_valid()
166 if (mode->flags & DRM_MODE_FLAG_DBLCLK) in meson_encoder_hdmi_mode_valid()
181 if (mode->flags & DRM_MODE_FLAG_DBLCLK) in meson_encoder_hdmi_mode_valid()
184 dev_dbg(priv->dev, in meson_encoder_hdmi_mode_valid()
185 "%s: vclk:%lluHz phy=%lluHz venc=%lluHz hdmi=%lluHz\n", in meson_encoder_hdmi_mode_valid()
196 struct meson_drm *priv = encoder_hdmi->priv; in meson_encoder_hdmi_atomic_enable()
200 struct drm_connector *connector; in meson_encoder_hdmi_atomic_enable() local
204 connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); in meson_encoder_hdmi_atomic_enable()
205 if (WARN_ON(!connector)) in meson_encoder_hdmi_atomic_enable()
208 conn_state = drm_atomic_get_new_connector_state(state, connector); in meson_encoder_hdmi_atomic_enable()
212 crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); in meson_encoder_hdmi_atomic_enable()
216 mode = &crtc_state->adjusted_mode; in meson_encoder_hdmi_atomic_enable()
220 dev_dbg(priv->dev, "\"%s\" vic %d\n", mode->name, vic); in meson_encoder_hdmi_atomic_enable()
222 if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24) { in meson_encoder_hdmi_atomic_enable()
225 } else if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYVY8_1X16) in meson_encoder_hdmi_atomic_enable()
228 /* VENC + VENC-DVI Mode setup */ in meson_encoder_hdmi_atomic_enable()
234 if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24) in meson_encoder_hdmi_atomic_enable()
235 /* Setup YUV420 to HDMI-TX, no 10bit diphering */ in meson_encoder_hdmi_atomic_enable()
237 priv->io_base + _REG(VPU_HDMI_FMT_CTRL)); in meson_encoder_hdmi_atomic_enable()
238 else if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYVY8_1X16) in meson_encoder_hdmi_atomic_enable()
239 /* Setup YUV422 to HDMI-TX, no 10bit diphering */ in meson_encoder_hdmi_atomic_enable()
241 priv->io_base + _REG(VPU_HDMI_FMT_CTRL)); in meson_encoder_hdmi_atomic_enable()
243 /* Setup YUV444 to HDMI-TX, no 10bit diphering */ in meson_encoder_hdmi_atomic_enable()
244 writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL)); in meson_encoder_hdmi_atomic_enable()
246 dev_dbg(priv->dev, "%s\n", priv->venc.hdmi_use_enci ? "VENCI" : "VENCP"); in meson_encoder_hdmi_atomic_enable()
248 if (priv->venc.hdmi_use_enci) in meson_encoder_hdmi_atomic_enable()
249 writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN)); in meson_encoder_hdmi_atomic_enable()
251 writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN)); in meson_encoder_hdmi_atomic_enable()
258 struct meson_drm *priv = encoder_hdmi->priv; in meson_encoder_hdmi_atomic_disable()
261 priv->io_base + _REG(VPU_HDMI_SETTING)); in meson_encoder_hdmi_atomic_disable()
263 writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN)); in meson_encoder_hdmi_atomic_disable()
264 writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN)); in meson_encoder_hdmi_atomic_disable()
311 drm_atomic_get_old_connector_state(conn_state->state, conn_state->connector); in meson_encoder_hdmi_atomic_check()
312 struct meson_drm *priv = encoder_hdmi->priv; in meson_encoder_hdmi_atomic_check()
314 encoder_hdmi->output_bus_fmt = bridge_state->output_bus_cfg.format; in meson_encoder_hdmi_atomic_check()
316 dev_dbg(priv->dev, "output_bus_fmt %lx\n", encoder_hdmi->output_bus_fmt); in meson_encoder_hdmi_atomic_check()
319 crtc_state->mode_changed = true; in meson_encoder_hdmi_atomic_check()
329 if (!encoder_hdmi->cec_notifier) in meson_encoder_hdmi_hpd_notify()
336 drm_edid = drm_bridge_edid_read(encoder_hdmi->next_bridge, in meson_encoder_hdmi_hpd_notify()
337 encoder_hdmi->connector); in meson_encoder_hdmi_hpd_notify()
343 * cec_notifier_set_phys_addr(encoder_hdmi->cec_notifier, in meson_encoder_hdmi_hpd_notify()
344 * connector->display_info.source_physical_address) from a path in meson_encoder_hdmi_hpd_notify()
350 cec_notifier_set_phys_addr_from_edid(encoder_hdmi->cec_notifier, edid); in meson_encoder_hdmi_hpd_notify()
354 cec_notifier_phys_addr_invalidate(encoder_hdmi->cec_notifier); in meson_encoder_hdmi_hpd_notify()
378 meson_encoder_hdmi = devm_kzalloc(priv->dev, sizeof(*meson_encoder_hdmi), GFP_KERNEL); in meson_encoder_hdmi_probe()
380 return -ENOMEM; in meson_encoder_hdmi_probe()
382 /* HDMI Transceiver Bridge */ in meson_encoder_hdmi_probe()
383 remote = of_graph_get_remote_node(priv->dev->of_node, 1, 0); in meson_encoder_hdmi_probe()
385 dev_err(priv->dev, "HDMI transceiver device is disabled"); in meson_encoder_hdmi_probe()
389 meson_encoder_hdmi->next_bridge = of_drm_find_bridge(remote); in meson_encoder_hdmi_probe()
390 if (!meson_encoder_hdmi->next_bridge) { in meson_encoder_hdmi_probe()
391 ret = dev_err_probe(priv->dev, -EPROBE_DEFER, in meson_encoder_hdmi_probe()
392 "Failed to find HDMI transceiver bridge\n"); in meson_encoder_hdmi_probe()
396 /* HDMI Encoder Bridge */ in meson_encoder_hdmi_probe()
397 meson_encoder_hdmi->bridge.funcs = &meson_encoder_hdmi_bridge_funcs; in meson_encoder_hdmi_probe()
398 meson_encoder_hdmi->bridge.of_node = priv->dev->of_node; in meson_encoder_hdmi_probe()
399 meson_encoder_hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA; in meson_encoder_hdmi_probe()
400 meson_encoder_hdmi->bridge.interlace_allowed = true; in meson_encoder_hdmi_probe()
402 drm_bridge_add(&meson_encoder_hdmi->bridge); in meson_encoder_hdmi_probe()
404 meson_encoder_hdmi->priv = priv; in meson_encoder_hdmi_probe()
407 ret = drm_simple_encoder_init(priv->drm, &meson_encoder_hdmi->encoder, in meson_encoder_hdmi_probe()
410 dev_err_probe(priv->dev, ret, "Failed to init HDMI encoder\n"); in meson_encoder_hdmi_probe()
414 meson_encoder_hdmi->encoder.possible_crtcs = BIT(0); in meson_encoder_hdmi_probe()
416 /* Attach HDMI Encoder Bridge to Encoder */ in meson_encoder_hdmi_probe()
417 ret = drm_bridge_attach(&meson_encoder_hdmi->encoder, &meson_encoder_hdmi->bridge, NULL, in meson_encoder_hdmi_probe()
420 dev_err_probe(priv->dev, ret, "Failed to attach bridge\n"); in meson_encoder_hdmi_probe()
424 /* Initialize & attach Bridge Connector */ in meson_encoder_hdmi_probe()
425 meson_encoder_hdmi->connector = drm_bridge_connector_init(priv->drm, in meson_encoder_hdmi_probe()
426 &meson_encoder_hdmi->encoder); in meson_encoder_hdmi_probe()
427 if (IS_ERR(meson_encoder_hdmi->connector)) { in meson_encoder_hdmi_probe()
428 ret = dev_err_probe(priv->dev, in meson_encoder_hdmi_probe()
429 PTR_ERR(meson_encoder_hdmi->connector), in meson_encoder_hdmi_probe()
430 "Unable to create HDMI bridge connector\n"); in meson_encoder_hdmi_probe()
433 drm_connector_attach_encoder(meson_encoder_hdmi->connector, in meson_encoder_hdmi_probe()
434 &meson_encoder_hdmi->encoder); in meson_encoder_hdmi_probe()
438 …* encoder->[hdmi encoder bridge]->[dw-hdmi bridge]->[display connector bridge]->[display connector] in meson_encoder_hdmi_probe()
443 * connector to have a state. in meson_encoder_hdmi_probe()
445 drm_atomic_helper_connector_reset(meson_encoder_hdmi->connector); in meson_encoder_hdmi_probe()
450 drm_connector_attach_hdr_output_metadata_property(meson_encoder_hdmi->connector); in meson_encoder_hdmi_probe()
452 drm_connector_attach_max_bpc_property(meson_encoder_hdmi->connector, 8, 8); in meson_encoder_hdmi_probe()
455 meson_encoder_hdmi->connector->ycbcr_420_allowed = true; in meson_encoder_hdmi_probe()
463 cec_fill_conn_info_from_drm(&conn_info, meson_encoder_hdmi->connector); in meson_encoder_hdmi_probe()
465 notifier = cec_notifier_conn_register(&pdev->dev, NULL, &conn_info); in meson_encoder_hdmi_probe()
467 put_device(&pdev->dev); in meson_encoder_hdmi_probe()
468 return -ENOMEM; in meson_encoder_hdmi_probe()
471 meson_encoder_hdmi->cec_notifier = notifier; in meson_encoder_hdmi_probe()
474 priv->encoders[MESON_ENC_HDMI] = meson_encoder_hdmi; in meson_encoder_hdmi_probe()
476 dev_dbg(priv->dev, "HDMI encoder initialized\n"); in meson_encoder_hdmi_probe()
489 if (priv->encoders[MESON_ENC_HDMI]) { in meson_encoder_hdmi_remove()
490 meson_encoder_hdmi = priv->encoders[MESON_ENC_HDMI]; in meson_encoder_hdmi_remove()
491 drm_bridge_remove(&meson_encoder_hdmi->bridge); in meson_encoder_hdmi_remove()