Lines Matching +full:display +full:- +full:bridge
1 // SPDX-License-Identifier: GPL-2.0-only
10 #include <drm/display/drm_hdmi_helper.h>
11 #include <drm/display/drm_hdmi_state_helper.h>
16 static void msm_hdmi_power_on(struct drm_bridge *bridge) in msm_hdmi_power_on() argument
18 struct drm_device *dev = bridge->dev; in msm_hdmi_power_on()
19 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); in msm_hdmi_power_on()
20 struct hdmi *hdmi = hdmi_bridge->hdmi; in msm_hdmi_power_on()
23 pm_runtime_resume_and_get(&hdmi->pdev->dev); in msm_hdmi_power_on()
25 if (hdmi->extp_clk) { in msm_hdmi_power_on()
26 DBG("pixclock: %lu", hdmi->pixclock); in msm_hdmi_power_on()
27 ret = clk_set_rate(hdmi->extp_clk, hdmi->pixclock); in msm_hdmi_power_on()
29 DRM_DEV_ERROR(dev->dev, "failed to set extp clk rate: %d\n", ret); in msm_hdmi_power_on()
31 ret = clk_prepare_enable(hdmi->extp_clk); in msm_hdmi_power_on()
33 DRM_DEV_ERROR(dev->dev, "failed to enable extp clk: %d\n", ret); in msm_hdmi_power_on()
37 static void power_off(struct drm_bridge *bridge) in power_off() argument
39 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); in power_off()
40 struct hdmi *hdmi = hdmi_bridge->hdmi; in power_off()
47 if (hdmi->extp_clk) in power_off()
48 clk_disable_unprepare(hdmi->extp_clk); in power_off()
50 pm_runtime_put(&hdmi->pdev->dev); in power_off()
64 if (len != HDMI_INFOFRAME_SIZE(AVI) || len - 3 > sizeof(buf)) { in msm_hdmi_config_avi_infoframe()
65 DRM_DEV_ERROR(&hdmi->pdev->dev, in msm_hdmi_config_avi_infoframe()
67 return -EINVAL; in msm_hdmi_config_avi_infoframe()
76 memcpy(buf, &buffer[3], len - 3); in msm_hdmi_config_avi_infoframe()
102 DRM_DEV_ERROR(&hdmi->pdev->dev, in msm_hdmi_config_audio_infoframe()
104 return -EINVAL; in msm_hdmi_config_audio_infoframe()
136 if (len != HDMI_INFOFRAME_SIZE(SPD) || len - 3 > sizeof(buf)) { in msm_hdmi_config_spd_infoframe()
137 DRM_DEV_ERROR(&hdmi->pdev->dev, in msm_hdmi_config_spd_infoframe()
139 return -EINVAL; in msm_hdmi_config_spd_infoframe()
148 memcpy(buf, &buffer[3], len - 3); in msm_hdmi_config_spd_infoframe()
170 len - 3 > sizeof(buf)) { in msm_hdmi_config_hdmi_infoframe()
171 DRM_DEV_ERROR(&hdmi->pdev->dev, in msm_hdmi_config_hdmi_infoframe()
173 return -EINVAL; in msm_hdmi_config_hdmi_infoframe()
182 memcpy(buf, &buffer[3], len - 3); in msm_hdmi_config_hdmi_infoframe()
197 static int msm_hdmi_bridge_clear_infoframe(struct drm_bridge *bridge, in msm_hdmi_bridge_clear_infoframe() argument
200 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); in msm_hdmi_bridge_clear_infoframe()
201 struct hdmi *hdmi = hdmi_bridge->hdmi; in msm_hdmi_bridge_clear_infoframe()
251 drm_dbg_driver(hdmi_bridge->base.dev, "Unsupported infoframe type %x\n", type); in msm_hdmi_bridge_clear_infoframe()
257 static int msm_hdmi_bridge_write_infoframe(struct drm_bridge *bridge, in msm_hdmi_bridge_write_infoframe() argument
261 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); in msm_hdmi_bridge_write_infoframe()
262 struct hdmi *hdmi = hdmi_bridge->hdmi; in msm_hdmi_bridge_write_infoframe()
264 msm_hdmi_bridge_clear_infoframe(bridge, type); in msm_hdmi_bridge_write_infoframe()
276 drm_dbg_driver(hdmi_bridge->base.dev, "Unsupported infoframe type %x\n", type); in msm_hdmi_bridge_write_infoframe()
284 static void msm_hdmi_bridge_atomic_pre_enable(struct drm_bridge *bridge, in msm_hdmi_bridge_atomic_pre_enable() argument
287 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); in msm_hdmi_bridge_atomic_pre_enable()
288 struct hdmi *hdmi = hdmi_bridge->hdmi; in msm_hdmi_bridge_atomic_pre_enable()
289 struct hdmi_phy *phy = hdmi->phy; in msm_hdmi_bridge_atomic_pre_enable()
290 struct drm_encoder *encoder = bridge->encoder; in msm_hdmi_bridge_atomic_pre_enable()
299 crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); in msm_hdmi_bridge_atomic_pre_enable()
301 hdmi->pixclock = conn_state->hdmi.tmds_char_rate; in msm_hdmi_bridge_atomic_pre_enable()
303 msm_hdmi_set_timings(hdmi, &crtc_state->adjusted_mode); in msm_hdmi_bridge_atomic_pre_enable()
305 mutex_lock(&hdmi->state_mutex); in msm_hdmi_bridge_atomic_pre_enable()
306 if (!hdmi->power_on) { in msm_hdmi_bridge_atomic_pre_enable()
308 msm_hdmi_power_on(bridge); in msm_hdmi_bridge_atomic_pre_enable()
309 hdmi->power_on = true; in msm_hdmi_bridge_atomic_pre_enable()
311 mutex_unlock(&hdmi->state_mutex); in msm_hdmi_bridge_atomic_pre_enable()
313 if (connector->display_info.is_hdmi) in msm_hdmi_bridge_atomic_pre_enable()
318 msm_hdmi_phy_powerup(phy, hdmi->pixclock); in msm_hdmi_bridge_atomic_pre_enable()
322 if (hdmi->hdcp_ctrl) in msm_hdmi_bridge_atomic_pre_enable()
323 msm_hdmi_hdcp_on(hdmi->hdcp_ctrl); in msm_hdmi_bridge_atomic_pre_enable()
326 static void msm_hdmi_bridge_atomic_post_disable(struct drm_bridge *bridge, in msm_hdmi_bridge_atomic_post_disable() argument
329 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); in msm_hdmi_bridge_atomic_post_disable()
330 struct hdmi *hdmi = hdmi_bridge->hdmi; in msm_hdmi_bridge_atomic_post_disable()
331 struct hdmi_phy *phy = hdmi->phy; in msm_hdmi_bridge_atomic_post_disable()
333 if (hdmi->hdcp_ctrl) in msm_hdmi_bridge_atomic_post_disable()
334 msm_hdmi_hdcp_off(hdmi->hdcp_ctrl); in msm_hdmi_bridge_atomic_post_disable()
339 mutex_lock(&hdmi->state_mutex); in msm_hdmi_bridge_atomic_post_disable()
340 msm_hdmi_set_mode(hdmi, hdmi->hpd_enabled); in msm_hdmi_bridge_atomic_post_disable()
344 if (hdmi->power_on) { in msm_hdmi_bridge_atomic_post_disable()
345 power_off(bridge); in msm_hdmi_bridge_atomic_post_disable()
346 hdmi->power_on = false; in msm_hdmi_bridge_atomic_post_disable()
347 if (hdmi->connector->display_info.is_hdmi) in msm_hdmi_bridge_atomic_post_disable()
351 mutex_unlock(&hdmi->state_mutex); in msm_hdmi_bridge_atomic_post_disable()
360 hstart = mode->htotal - mode->hsync_start; in msm_hdmi_set_timings()
361 hend = mode->htotal - mode->hsync_start + mode->hdisplay; in msm_hdmi_set_timings()
363 vstart = mode->vtotal - mode->vsync_start - 1; in msm_hdmi_set_timings()
364 vend = mode->vtotal - mode->vsync_start + mode->vdisplay - 1; in msm_hdmi_set_timings()
367 mode->htotal, mode->vtotal, hstart, hend, vstart, vend); in msm_hdmi_set_timings()
370 HDMI_TOTAL_H_TOTAL(mode->htotal - 1) | in msm_hdmi_set_timings()
371 HDMI_TOTAL_V_TOTAL(mode->vtotal - 1)); in msm_hdmi_set_timings()
380 if (mode->flags & DRM_MODE_FLAG_INTERLACE) { in msm_hdmi_set_timings()
382 HDMI_VSYNC_TOTAL_F2_V_TOTAL(mode->vtotal)); in msm_hdmi_set_timings()
395 if (mode->flags & DRM_MODE_FLAG_NHSYNC) in msm_hdmi_set_timings()
397 if (mode->flags & DRM_MODE_FLAG_NVSYNC) in msm_hdmi_set_timings()
399 if (mode->flags & DRM_MODE_FLAG_INTERLACE) in msm_hdmi_set_timings()
405 static const struct drm_edid *msm_hdmi_bridge_edid_read(struct drm_bridge *bridge, in msm_hdmi_bridge_edid_read() argument
408 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); in msm_hdmi_bridge_edid_read()
409 struct hdmi *hdmi = hdmi_bridge->hdmi; in msm_hdmi_bridge_edid_read()
416 drm_edid = drm_edid_read_ddc(connector, hdmi->i2c); in msm_hdmi_bridge_edid_read()
423 static enum drm_mode_status msm_hdmi_bridge_tmds_char_rate_valid(const struct drm_bridge *bridge, in msm_hdmi_bridge_tmds_char_rate_valid() argument
427 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); in msm_hdmi_bridge_tmds_char_rate_valid()
428 struct hdmi *hdmi = hdmi_bridge->hdmi; in msm_hdmi_bridge_tmds_char_rate_valid()
429 struct msm_drm_private *priv = bridge->dev->dev_private; in msm_hdmi_bridge_tmds_char_rate_valid()
430 struct msm_kms *kms = priv->kms; in msm_hdmi_bridge_tmds_char_rate_valid()
437 if (kms->funcs->round_pixclk) in msm_hdmi_bridge_tmds_char_rate_valid()
438 actual = kms->funcs->round_pixclk(kms, in msm_hdmi_bridge_tmds_char_rate_valid()
440 hdmi_bridge->hdmi->encoder); in msm_hdmi_bridge_tmds_char_rate_valid()
441 else if (hdmi->extp_clk) in msm_hdmi_bridge_tmds_char_rate_valid()
442 actual = clk_round_rate(hdmi->extp_clk, tmds_rate); in msm_hdmi_bridge_tmds_char_rate_valid()
476 struct drm_bridge *bridge = &hdmi_bridge->base; in msm_hdmi_hotplug_work() local
478 drm_bridge_hpd_notify(bridge, drm_bridge_detect(bridge, hdmi_bridge->hdmi->connector)); in msm_hdmi_hotplug_work()
481 /* initialize bridge */
484 struct drm_bridge *bridge = NULL; in msm_hdmi_bridge_init() local
488 hdmi_bridge = devm_drm_bridge_alloc(hdmi->dev->dev, struct hdmi_bridge, base, in msm_hdmi_bridge_init()
493 hdmi_bridge->hdmi = hdmi; in msm_hdmi_bridge_init()
494 INIT_WORK(&hdmi_bridge->hpd_work, msm_hdmi_hotplug_work); in msm_hdmi_bridge_init()
496 bridge = &hdmi_bridge->base; in msm_hdmi_bridge_init()
497 bridge->ddc = hdmi->i2c; in msm_hdmi_bridge_init()
498 bridge->type = DRM_MODE_CONNECTOR_HDMIA; in msm_hdmi_bridge_init()
499 bridge->vendor = "Qualcomm"; in msm_hdmi_bridge_init()
500 bridge->product = "Snapdragon"; in msm_hdmi_bridge_init()
501 bridge->ops = DRM_BRIDGE_OP_HPD | in msm_hdmi_bridge_init()
506 bridge->hdmi_audio_max_i2s_playback_channels = 8; in msm_hdmi_bridge_init()
507 bridge->hdmi_audio_dev = &hdmi->pdev->dev; in msm_hdmi_bridge_init()
508 bridge->hdmi_audio_dai_port = -1; in msm_hdmi_bridge_init()
510 ret = devm_drm_bridge_add(hdmi->dev->dev, bridge); in msm_hdmi_bridge_init()
514 ret = drm_bridge_attach(hdmi->encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR); in msm_hdmi_bridge_init()
518 hdmi->bridge = bridge; in msm_hdmi_bridge_init()