Lines Matching +full:hdmi +full:- +full:connector
1 // SPDX-License-Identifier: GPL-2.0-only
10 * DOC: VC4 Falcon HDMI module
12 * The HDMI core has a state machine and a PHY. On BCM2835, most of
16 * HDMI infoframes are kept within a small packet ram, where each
19 * HDMI audio is implemented entirely within the HDMI IP block. A
20 * register in the HDMI encoder takes SPDIF frames from the DMA engine
21 * and transfers them over an internal MAI (multi-channel audio
25 * The driver's HDMI encoder does not yet support power management.
26 * The HDMI encoder's power domain and the HSM/pixel clocks are kept
27 * continuously running, and only the HDMI logic and packet ram are
30 * The driver does not yet support CEC control, though the HDMI
53 #include <sound/hdmi-codec.h>
117 struct drm_display_info *display = &vc4_hdmi->connector.display_info; in vc4_hdmi_supports_scrambling()
119 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_supports_scrambling()
121 if (!display->is_hdmi) in vc4_hdmi_supports_scrambling()
124 if (!display->hdmi.scdc.supported || in vc4_hdmi_supports_scrambling()
125 !display->hdmi.scdc.scrambling.supported) in vc4_hdmi_supports_scrambling()
142 struct drm_debugfs_entry *entry = m->private; in vc4_hdmi_debugfs_regs()
143 struct vc4_hdmi *vc4_hdmi = entry->file.data; in vc4_hdmi_debugfs_regs()
144 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_debugfs_regs()
149 return -ENODEV; in vc4_hdmi_debugfs_regs()
151 WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev)); in vc4_hdmi_debugfs_regs()
153 drm_print_regset32(&p, &vc4_hdmi->hdmi_regset); in vc4_hdmi_debugfs_regs()
154 drm_print_regset32(&p, &vc4_hdmi->hd_regset); in vc4_hdmi_debugfs_regs()
155 drm_print_regset32(&p, &vc4_hdmi->cec_regset); in vc4_hdmi_debugfs_regs()
156 drm_print_regset32(&p, &vc4_hdmi->csc_regset); in vc4_hdmi_debugfs_regs()
157 drm_print_regset32(&p, &vc4_hdmi->dvp_regset); in vc4_hdmi_debugfs_regs()
158 drm_print_regset32(&p, &vc4_hdmi->phy_regset); in vc4_hdmi_debugfs_regs()
159 drm_print_regset32(&p, &vc4_hdmi->ram_regset); in vc4_hdmi_debugfs_regs()
160 drm_print_regset32(&p, &vc4_hdmi->rm_regset); in vc4_hdmi_debugfs_regs()
162 pm_runtime_put(&vc4_hdmi->pdev->dev); in vc4_hdmi_debugfs_regs()
171 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_reset()
177 * connector->dev pointer might not be initialised yet. in vc4_hdmi_reset()
182 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_reset()
196 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_reset()
204 struct drm_device *drm = vc4_hdmi->connector.dev; in vc5_hdmi_reset()
210 * connector->dev pointer might not be initialised yet. in vc5_hdmi_reset()
215 reset_control_reset(vc4_hdmi->reset); in vc5_hdmi_reset()
217 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_reset()
224 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_reset()
233 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_cec_update_clk_div()
243 * connector yet and thus don't have a pointer to the DRM in vc4_hdmi_cec_update_clk_div()
249 cec_rate = clk_get_rate(vc4_hdmi->cec_clock); in vc4_hdmi_cec_update_clk_div()
251 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_update_clk_div()
264 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_update_clk_div()
273 static int vc4_hdmi_reset_link(struct drm_connector *connector, in vc4_hdmi_reset_link() argument
285 if (!connector) in vc4_hdmi_reset_link()
288 drm = connector->dev; in vc4_hdmi_reset_link()
289 ret = drm_modeset_lock(&drm->mode_config.connection_mutex, ctx); in vc4_hdmi_reset_link()
293 conn_state = connector->state; in vc4_hdmi_reset_link()
294 crtc = conn_state->crtc; in vc4_hdmi_reset_link()
298 ret = drm_modeset_lock(&crtc->mutex, ctx); in vc4_hdmi_reset_link()
302 crtc_state = crtc->state; in vc4_hdmi_reset_link()
303 if (!crtc_state->active) in vc4_hdmi_reset_link()
306 vc4_hdmi = connector_to_vc4_hdmi(connector); in vc4_hdmi_reset_link()
307 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_reset_link()
310 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_reset_link()
314 scrambling_needed = vc4_hdmi_mode_needs_scrambling(&vc4_hdmi->saved_adjusted_mode, in vc4_hdmi_reset_link()
315 vc4_hdmi->output_bpc, in vc4_hdmi_reset_link()
316 vc4_hdmi->output_format); in vc4_hdmi_reset_link()
318 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_reset_link()
322 if (conn_state->commit && in vc4_hdmi_reset_link()
323 !try_wait_for_completion(&conn_state->commit->hw_done)) { in vc4_hdmi_reset_link()
324 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_reset_link()
328 ret = drm_scdc_readb(connector->ddc, SCDC_TMDS_CONFIG, &config); in vc4_hdmi_reset_link()
331 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_reset_link()
336 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_reset_link()
340 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_reset_link()
343 * HDMI 2.0 says that one should not send scrambled data in vc4_hdmi_reset_link()
358 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_handle_hotplug() local
362 * NOTE: This function should really be called with vc4_hdmi->mutex in vc4_hdmi_handle_hotplug()
376 cec_phys_addr_invalidate(vc4_hdmi->cec_adap); in vc4_hdmi_handle_hotplug()
380 drm_atomic_helper_connector_hdmi_hotplug(connector, status); in vc4_hdmi_handle_hotplug()
382 cec_s_phys_addr(vc4_hdmi->cec_adap, in vc4_hdmi_handle_hotplug()
383 connector->display_info.source_physical_address, false); in vc4_hdmi_handle_hotplug()
389 ret = vc4_hdmi_reset_link(connector, ctx); in vc4_hdmi_handle_hotplug()
390 if (ret == -EDEADLK) { in vc4_hdmi_handle_hotplug()
399 static int vc4_hdmi_connector_detect_ctx(struct drm_connector *connector, in vc4_hdmi_connector_detect_ctx() argument
403 struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); in vc4_hdmi_connector_detect_ctx()
408 * NOTE: This function should really take vc4_hdmi->mutex, but in vc4_hdmi_connector_detect_ctx()
418 ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); in vc4_hdmi_connector_detect_ctx()
420 drm_err_once(connector->dev, "Failed to retain HDMI power domain: %d\n", in vc4_hdmi_connector_detect_ctx()
425 if (vc4_hdmi->hpd_gpio) { in vc4_hdmi_connector_detect_ctx()
426 if (gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio)) in vc4_hdmi_connector_detect_ctx()
429 if (vc4_hdmi->variant->hp_detect && in vc4_hdmi_connector_detect_ctx()
430 vc4_hdmi->variant->hp_detect(vc4_hdmi)) in vc4_hdmi_connector_detect_ctx()
435 pm_runtime_put(&vc4_hdmi->pdev->dev); in vc4_hdmi_connector_detect_ctx()
440 static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) in vc4_hdmi_connector_get_modes() argument
442 struct vc4_dev *vc4 = to_vc4_dev(connector->dev); in vc4_hdmi_connector_get_modes()
445 ret = drm_edid_connector_add_modes(connector); in vc4_hdmi_connector_get_modes()
447 if (!vc4->hvs->vc5_hdmi_enable_hdmi_20) { in vc4_hdmi_connector_get_modes()
448 struct drm_device *drm = connector->dev; in vc4_hdmi_connector_get_modes()
451 list_for_each_entry(mode, &connector->probed_modes, head) { in vc4_hdmi_connector_get_modes()
462 static int vc4_hdmi_connector_atomic_check(struct drm_connector *connector, in vc4_hdmi_connector_atomic_check() argument
466 drm_atomic_get_old_connector_state(state, connector); in vc4_hdmi_connector_atomic_check()
468 drm_atomic_get_new_connector_state(state, connector); in vc4_hdmi_connector_atomic_check()
469 struct drm_crtc *crtc = new_state->crtc; in vc4_hdmi_connector_atomic_check()
474 if (old_state->tv.margins.left != new_state->tv.margins.left || in vc4_hdmi_connector_atomic_check()
475 old_state->tv.margins.right != new_state->tv.margins.right || in vc4_hdmi_connector_atomic_check()
476 old_state->tv.margins.top != new_state->tv.margins.top || in vc4_hdmi_connector_atomic_check()
477 old_state->tv.margins.bottom != new_state->tv.margins.bottom) { in vc4_hdmi_connector_atomic_check()
489 * connector atomic_check is called as part of in vc4_hdmi_connector_atomic_check()
500 if (old_state->colorspace != new_state->colorspace) { in vc4_hdmi_connector_atomic_check()
507 crtc_state->mode_changed = true; in vc4_hdmi_connector_atomic_check()
510 return drm_atomic_helper_connector_hdmi_check(connector, state); in vc4_hdmi_connector_atomic_check()
513 static void vc4_hdmi_connector_reset(struct drm_connector *connector) in vc4_hdmi_connector_reset() argument
515 drm_atomic_helper_connector_reset(connector); in vc4_hdmi_connector_reset()
516 __drm_atomic_helper_connector_hdmi_reset(connector, connector->state); in vc4_hdmi_connector_reset()
517 drm_atomic_helper_connector_tv_margins_reset(connector); in vc4_hdmi_connector_reset()
541 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_connector_init() local
542 struct drm_encoder *encoder = &vc4_hdmi->encoder.base; in vc4_hdmi_connector_init()
546 if (vc4_hdmi->variant->supports_hdr) in vc4_hdmi_connector_init()
549 ret = drmm_connector_hdmi_init(dev, connector, in vc4_hdmi_connector_init()
554 vc4_hdmi->ddc, in vc4_hdmi_connector_init()
562 ret = drm_connector_hdmi_audio_init(connector, dev->dev, in vc4_hdmi_connector_init()
564 8, false, -1); in vc4_hdmi_connector_init()
568 drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs); in vc4_hdmi_connector_init()
572 * Allocate some default initial connector state with our reset helper. in vc4_hdmi_connector_init()
574 if (connector->funcs->reset) in vc4_hdmi_connector_init()
575 connector->funcs->reset(connector); in vc4_hdmi_connector_init()
577 /* Create and attach TV margin props to this connector. */ in vc4_hdmi_connector_init()
582 ret = drm_mode_create_hdmi_colorspace_property(connector, 0); in vc4_hdmi_connector_init()
586 drm_connector_attach_colorspace_property(connector); in vc4_hdmi_connector_init()
587 drm_connector_attach_tv_margin_properties(connector); in vc4_hdmi_connector_init()
589 connector->polled = (DRM_CONNECTOR_POLL_CONNECT | in vc4_hdmi_connector_init()
592 connector->interlace_allowed = 1; in vc4_hdmi_connector_init()
593 connector->doublescan_allowed = 0; in vc4_hdmi_connector_init()
594 connector->stereo_allowed = 1; in vc4_hdmi_connector_init()
596 ret = drm_connector_attach_broadcast_rgb_property(connector); in vc4_hdmi_connector_init()
600 drm_connector_attach_encoder(connector, encoder); in vc4_hdmi_connector_init()
609 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_stop_packet()
610 u32 packet_id = type - 0x80; in vc4_hdmi_stop_packet()
616 return -ENODEV; in vc4_hdmi_stop_packet()
618 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_stop_packet()
621 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_stop_packet()
632 static int vc4_hdmi_write_infoframe(struct drm_connector *connector, in vc4_hdmi_write_infoframe() argument
636 struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); in vc4_hdmi_write_infoframe()
637 struct drm_device *drm = connector->dev; in vc4_hdmi_write_infoframe()
638 u32 packet_id = type - 0x80; in vc4_hdmi_write_infoframe()
640 &vc4_hdmi->variant->registers[HDMI_RAM_PACKET_START]; in vc4_hdmi_write_infoframe()
641 u32 packet_reg = ram_packet_start->offset + VC4_HDMI_PACKET_STRIDE * packet_id; in vc4_hdmi_write_infoframe()
642 u32 packet_reg_next = ram_packet_start->offset + in vc4_hdmi_write_infoframe()
645 ram_packet_start->reg); in vc4_hdmi_write_infoframe()
656 ret = -ENOMEM; in vc4_hdmi_write_infoframe()
672 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_write_infoframe()
691 * infoframe and triggers a checksum error on hdmi analyser in vc4_hdmi_write_infoframe()
699 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_write_infoframe()
716 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_enable_scrambling() local
717 struct drm_device *drm = connector->dev; in vc4_hdmi_enable_scrambling()
718 const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; in vc4_hdmi_enable_scrambling()
722 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_enable_scrambling()
728 vc4_hdmi->output_bpc, in vc4_hdmi_enable_scrambling()
729 vc4_hdmi->output_format)) in vc4_hdmi_enable_scrambling()
735 drm_scdc_set_high_tmds_clock_ratio(connector, true); in vc4_hdmi_enable_scrambling()
736 drm_scdc_set_scrambling(connector, true); in vc4_hdmi_enable_scrambling()
738 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_enable_scrambling()
741 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_enable_scrambling()
745 vc4_hdmi->scdc_enabled = true; in vc4_hdmi_enable_scrambling()
747 queue_delayed_work(system_wq, &vc4_hdmi->scrambling_work, in vc4_hdmi_enable_scrambling()
754 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_disable_scrambling() local
755 struct drm_device *drm = connector->dev; in vc4_hdmi_disable_scrambling()
759 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_disable_scrambling()
761 if (!vc4_hdmi->scdc_enabled) in vc4_hdmi_disable_scrambling()
764 vc4_hdmi->scdc_enabled = false; in vc4_hdmi_disable_scrambling()
766 if (delayed_work_pending(&vc4_hdmi->scrambling_work)) in vc4_hdmi_disable_scrambling()
767 cancel_delayed_work_sync(&vc4_hdmi->scrambling_work); in vc4_hdmi_disable_scrambling()
772 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_disable_scrambling()
775 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_disable_scrambling()
777 drm_scdc_set_scrambling(connector, false); in vc4_hdmi_disable_scrambling()
778 drm_scdc_set_high_tmds_clock_ratio(connector, false); in vc4_hdmi_disable_scrambling()
788 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_scrambling_wq() local
790 if (drm_scdc_get_scrambling_status(connector)) in vc4_hdmi_scrambling_wq()
793 drm_scdc_set_high_tmds_clock_ratio(connector, true); in vc4_hdmi_scrambling_wq()
794 drm_scdc_set_scrambling(connector, true); in vc4_hdmi_scrambling_wq()
796 queue_delayed_work(system_wq, &vc4_hdmi->scrambling_work, in vc4_hdmi_scrambling_wq()
804 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_encoder_post_crtc_disable()
809 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_post_crtc_disable()
811 vc4_hdmi->packet_ram_enabled = false; in vc4_hdmi_encoder_post_crtc_disable()
816 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_disable()
822 if (vc4->gen >= VC4_GEN_6_C) in vc4_hdmi_encoder_post_crtc_disable()
826 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_disable()
834 if (vc4->gen < VC4_GEN_6_C) { in vc4_hdmi_encoder_post_crtc_disable()
835 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_disable()
839 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_disable()
847 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_post_crtc_disable()
854 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_encoder_post_crtc_powerdown()
859 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_post_crtc_powerdown()
864 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_powerdown()
867 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_powerdown()
869 if (vc4_hdmi->variant->phy_disable) in vc4_hdmi_encoder_post_crtc_powerdown()
870 vc4_hdmi->variant->phy_disable(vc4_hdmi); in vc4_hdmi_encoder_post_crtc_powerdown()
872 clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock); in vc4_hdmi_encoder_post_crtc_powerdown()
873 clk_disable_unprepare(vc4_hdmi->pixel_clock); in vc4_hdmi_encoder_post_crtc_powerdown()
875 ret = pm_runtime_put(&vc4_hdmi->pdev->dev); in vc4_hdmi_encoder_post_crtc_powerdown()
882 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_post_crtc_powerdown()
889 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_csc_setup()
897 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_csc_setup()
902 if (state->hdmi.is_limited_range) { in vc4_hdmi_csc_setup()
905 * Apply a colorspace conversion to squash 0-255 down in vc4_hdmi_csc_setup()
906 * to 16-235. The matrix here is: in vc4_hdmi_csc_setup()
929 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_csc_setup()
942 * Full range - unity
958 * colorspace conversion to squash 0-255 down to 16-235.
982 * [ -0.168736 -0.331264 0.500000 128 ]
983 * [ 0.500000 -0.418688 -0.081312 128 ]
993 * [ -0.147644 -0.289856 0.437500 128 ]
994 * [ 0.437500 -0.366352 -0.071148 128 ]
1013 * [ -0.114572 -0.385428 0.500000 128 ]
1014 * [ 0.500000 -0.454153 -0.045847 128 ]
1025 * [ -0.100268 -0.337232 0.437500 128 ]
1026 * [ 0.437500 -0.397386 -0.040114 128 ]
1045 * [ -0.139630 -0.360370 0.500000 128 ]
1046 * [ 0.500000 -0.459786 -0.040214 128 ]
1056 * [ -0.122176 -0.315324 0.437500 128 ]
1057 * [ 0.437500 -0.402312 -0.035188 128 ]
1068 lockdep_assert_held(&vc4_hdmi->hw_lock); in vc5_hdmi_set_csc_coeffs()
1081 lockdep_assert_held(&vc4_hdmi->hw_lock); in vc5_hdmi_set_csc_coeffs_swap()
1124 struct drm_device *drm = vc4_hdmi->connector.dev; in vc5_hdmi_csc_setup()
1125 unsigned int lim_range = state->hdmi.is_limited_range ? 1 : 0; in vc5_hdmi_csc_setup()
1138 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_csc_setup()
1140 switch (state->hdmi.output_format) { in vc5_hdmi_csc_setup()
1142 csc = vc5_hdmi_find_yuv_csc_coeffs(vc4_hdmi, state->colorspace, !!lim_range); in vc5_hdmi_csc_setup()
1148 csc = vc5_hdmi_find_yuv_csc_coeffs(vc4_hdmi, state->colorspace, !!lim_range); in vc5_hdmi_csc_setup()
1179 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_csc_setup()
1188 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_set_timings()
1189 bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; in vc4_hdmi_set_timings()
1190 bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; in vc4_hdmi_set_timings()
1191 bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; in vc4_hdmi_set_timings()
1192 u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1; in vc4_hdmi_set_timings()
1193 u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, in vc4_hdmi_set_timings()
1195 VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, in vc4_hdmi_set_timings()
1197 VC4_SET_FIELD(mode->crtc_vdisplay, VC4_HDMI_VERTA_VAL)); in vc4_hdmi_set_timings()
1199 VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end + in vc4_hdmi_set_timings()
1203 VC4_SET_FIELD(mode->crtc_vtotal - in vc4_hdmi_set_timings()
1204 mode->crtc_vsync_end, in vc4_hdmi_set_timings()
1213 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_set_timings()
1218 VC4_SET_FIELD(mode->hdisplay * pixel_rep, in vc4_hdmi_set_timings()
1222 VC4_SET_FIELD((mode->htotal - in vc4_hdmi_set_timings()
1223 mode->hsync_end) * pixel_rep, in vc4_hdmi_set_timings()
1225 VC4_SET_FIELD((mode->hsync_end - in vc4_hdmi_set_timings()
1226 mode->hsync_start) * pixel_rep, in vc4_hdmi_set_timings()
1228 VC4_SET_FIELD((mode->hsync_start - in vc4_hdmi_set_timings()
1229 mode->hdisplay) * pixel_rep, in vc4_hdmi_set_timings()
1240 reg |= VC4_SET_FIELD(pixel_rep - 1, VC4_HDMI_MISC_CONTROL_PIXEL_REP); in vc4_hdmi_set_timings()
1243 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_set_timings()
1252 struct drm_device *drm = vc4_hdmi->connector.dev; in vc5_hdmi_set_timings()
1253 bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; in vc5_hdmi_set_timings()
1254 bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; in vc5_hdmi_set_timings()
1255 bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; in vc5_hdmi_set_timings()
1256 u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1; in vc5_hdmi_set_timings()
1257 u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, in vc5_hdmi_set_timings()
1259 VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, in vc5_hdmi_set_timings()
1261 VC4_SET_FIELD(mode->crtc_vdisplay, VC5_HDMI_VERTA_VAL)); in vc5_hdmi_set_timings()
1262 u32 vertb = (VC4_SET_FIELD(mode->htotal >> (2 - pixel_rep), in vc5_hdmi_set_timings()
1264 VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end + in vc5_hdmi_set_timings()
1268 VC4_SET_FIELD(mode->crtc_vtotal - in vc5_hdmi_set_timings()
1269 mode->crtc_vsync_end, in vc5_hdmi_set_timings()
1279 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_set_timings()
1284 VC4_SET_FIELD(mode->hdisplay * pixel_rep, in vc5_hdmi_set_timings()
1286 VC4_SET_FIELD((mode->hsync_start - in vc5_hdmi_set_timings()
1287 mode->hdisplay) * pixel_rep, in vc5_hdmi_set_timings()
1291 VC4_SET_FIELD((mode->htotal - in vc5_hdmi_set_timings()
1292 mode->hsync_end) * pixel_rep, in vc5_hdmi_set_timings()
1294 VC4_SET_FIELD((mode->hsync_end - in vc5_hdmi_set_timings()
1295 mode->hsync_start) * pixel_rep, in vc5_hdmi_set_timings()
1304 switch (state->hdmi.output_bpc) { in vc5_hdmi_set_timings()
1318 * YCC422 is always 36-bit and not considered deep colour so in vc5_hdmi_set_timings()
1321 if (state->hdmi.output_format == HDMI_COLORSPACE_YUV422) { in vc5_hdmi_set_timings()
1345 reg |= VC4_SET_FIELD(pixel_rep - 1, VC5_HDMI_MISC_CONTROL_PIXEL_REP); in vc5_hdmi_set_timings()
1350 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_set_timings()
1357 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_recenter_fifo()
1366 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_recenter_fifo()
1376 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_recenter_fifo()
1380 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_recenter_fifo()
1387 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_recenter_fifo()
1401 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_encoder_pre_crtc_configure()
1402 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_encoder_pre_crtc_configure() local
1404 drm_atomic_get_new_connector_state(state, connector); in vc4_hdmi_encoder_pre_crtc_configure()
1405 const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; in vc4_hdmi_encoder_pre_crtc_configure()
1406 unsigned long long tmds_char_rate = conn_state->hdmi.tmds_char_rate; in vc4_hdmi_encoder_pre_crtc_configure()
1412 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_pre_crtc_configure()
1417 ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); in vc4_hdmi_encoder_pre_crtc_configure()
1424 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must in vc4_hdmi_encoder_pre_crtc_configure()
1426 * simulation. Otherwise, exact value is unimportant for HDMI in vc4_hdmi_encoder_pre_crtc_configure()
1433 * both clocks. Which, for RPi0-3 implies a maximum pixel clock of in vc4_hdmi_encoder_pre_crtc_configure()
1442 ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate); in vc4_hdmi_encoder_pre_crtc_configure()
1448 ret = clk_set_rate(vc4_hdmi->pixel_clock, tmds_char_rate); in vc4_hdmi_encoder_pre_crtc_configure()
1454 ret = clk_prepare_enable(vc4_hdmi->pixel_clock); in vc4_hdmi_encoder_pre_crtc_configure()
1469 ret = clk_set_min_rate(vc4_hdmi->pixel_bvb_clock, bvb_rate); in vc4_hdmi_encoder_pre_crtc_configure()
1475 ret = clk_prepare_enable(vc4_hdmi->pixel_bvb_clock); in vc4_hdmi_encoder_pre_crtc_configure()
1481 if (vc4_hdmi->variant->phy_init) in vc4_hdmi_encoder_pre_crtc_configure()
1482 vc4_hdmi->variant->phy_init(vc4_hdmi, conn_state); in vc4_hdmi_encoder_pre_crtc_configure()
1484 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_pre_crtc_configure()
1491 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_pre_crtc_configure()
1493 if (vc4_hdmi->variant->set_timings) in vc4_hdmi_encoder_pre_crtc_configure()
1494 vc4_hdmi->variant->set_timings(vc4_hdmi, conn_state, mode); in vc4_hdmi_encoder_pre_crtc_configure()
1498 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_pre_crtc_configure()
1503 clk_disable_unprepare(vc4_hdmi->pixel_clock); in vc4_hdmi_encoder_pre_crtc_configure()
1505 pm_runtime_put(&vc4_hdmi->pdev->dev); in vc4_hdmi_encoder_pre_crtc_configure()
1509 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_pre_crtc_configure()
1517 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_encoder_pre_crtc_enable()
1518 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_encoder_pre_crtc_enable() local
1519 const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; in vc4_hdmi_encoder_pre_crtc_enable()
1521 drm_atomic_get_new_connector_state(state, connector); in vc4_hdmi_encoder_pre_crtc_enable()
1525 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_pre_crtc_enable()
1530 if (vc4_hdmi->variant->csc_setup) in vc4_hdmi_encoder_pre_crtc_enable()
1531 vc4_hdmi->variant->csc_setup(vc4_hdmi, conn_state, mode); in vc4_hdmi_encoder_pre_crtc_enable()
1533 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_pre_crtc_enable()
1535 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_pre_crtc_enable()
1540 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_pre_crtc_enable()
1547 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_encoder_post_crtc_enable() local
1548 struct drm_device *drm = connector->dev; in vc4_hdmi_encoder_post_crtc_enable()
1549 const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; in vc4_hdmi_encoder_post_crtc_enable()
1550 struct drm_display_info *display = &vc4_hdmi->connector.display_info; in vc4_hdmi_encoder_post_crtc_enable()
1551 bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; in vc4_hdmi_encoder_post_crtc_enable()
1552 bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; in vc4_hdmi_encoder_post_crtc_enable()
1557 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_post_crtc_enable()
1562 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_enable()
1578 if (display->is_hdmi) { in vc4_hdmi_encoder_post_crtc_enable()
1583 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_enable()
1597 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_enable()
1605 if (display->is_hdmi) { in vc4_hdmi_encoder_post_crtc_enable()
1606 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_enable()
1614 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_enable()
1615 vc4_hdmi->packet_ram_enabled = true; in vc4_hdmi_encoder_post_crtc_enable()
1617 drm_atomic_helper_connector_hdmi_update_infoframes(connector, state); in vc4_hdmi_encoder_post_crtc_enable()
1626 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_post_crtc_enable()
1635 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_atomic_mode_set()
1636 drm_mode_copy(&vc4_hdmi->saved_adjusted_mode, in vc4_hdmi_encoder_atomic_mode_set()
1637 &crtc_state->adjusted_mode); in vc4_hdmi_encoder_atomic_mode_set()
1638 vc4_hdmi->output_bpc = conn_state->hdmi.output_bpc; in vc4_hdmi_encoder_atomic_mode_set()
1639 vc4_hdmi->output_format = conn_state->hdmi.output_format; in vc4_hdmi_encoder_atomic_mode_set()
1640 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_atomic_mode_set()
1644 vc4_hdmi_connector_clock_valid(const struct drm_connector *connector, in vc4_hdmi_connector_clock_valid() argument
1648 const struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); in vc4_hdmi_connector_clock_valid()
1649 struct vc4_dev *vc4 = to_vc4_dev(connector->dev); in vc4_hdmi_connector_clock_valid()
1651 if (clock > vc4_hdmi->variant->max_pixel_clock) in vc4_hdmi_connector_clock_valid()
1654 if (!vc4->hvs->vc5_hdmi_enable_hdmi_20 && clock > HDMI_14_MAX_TMDS_CLK) in vc4_hdmi_connector_clock_valid()
1658 if (!vc4->hvs->vc5_hdmi_enable_4096by2160 && in vc4_hdmi_connector_clock_valid()
1659 mode->hdisplay > 3840 && mode->vdisplay >= 2160 && in vc4_hdmi_connector_clock_valid()
1679 struct drm_display_mode *mode = &crtc_state->adjusted_mode; in vc4_hdmi_encoder_atomic_check()
1680 unsigned long long tmds_char_rate = mode->clock * 1000; in vc4_hdmi_encoder_atomic_check()
1683 if (vc4_hdmi->variant->unsupported_odd_h_timings) { in vc4_hdmi_encoder_atomic_check()
1684 if (mode->flags & DRM_MODE_FLAG_DBLCLK) { in vc4_hdmi_encoder_atomic_check()
1691 if ((mode->hsync_start - mode->hdisplay) & 1) in vc4_hdmi_encoder_atomic_check()
1692 mode->hsync_start--; in vc4_hdmi_encoder_atomic_check()
1693 if ((mode->hsync_end - mode->hsync_start) & 1) in vc4_hdmi_encoder_atomic_check()
1694 mode->hsync_end--; in vc4_hdmi_encoder_atomic_check()
1698 if ((mode->hdisplay % 2) || (mode->hsync_start % 2) || in vc4_hdmi_encoder_atomic_check()
1699 (mode->hsync_end % 2) || (mode->htotal % 2)) in vc4_hdmi_encoder_atomic_check()
1700 return -EINVAL; in vc4_hdmi_encoder_atomic_check()
1710 if (vc4_hdmi->disable_wifi_frequencies && in vc4_hdmi_encoder_atomic_check()
1713 mode->clock = 238560; in vc4_hdmi_encoder_atomic_check()
1714 tmds_char_rate = mode->clock * 1000; in vc4_hdmi_encoder_atomic_check()
1726 if (vc4_hdmi->variant->unsupported_odd_h_timings && in vc4_hdmi_encoder_mode_valid()
1727 !(mode->flags & DRM_MODE_FLAG_DBLCLK) && in vc4_hdmi_encoder_mode_valid()
1728 ((mode->hdisplay % 2) || (mode->hsync_start % 2) || in vc4_hdmi_encoder_mode_valid()
1729 (mode->hsync_end % 2) || (mode->htotal % 2))) in vc4_hdmi_encoder_mode_valid()
1743 struct drm_device *drm = encoder->dev; in vc4_hdmi_late_register()
1745 const struct vc4_hdmi_variant *variant = vc4_hdmi->variant; in vc4_hdmi_late_register()
1747 drm_debugfs_add_file(drm, variant->debugfs_name, in vc4_hdmi_late_register()
1783 struct drm_device *drm = vc4_hdmi->connector.dev; in vc5_hdmi_hp_detect()
1791 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_hp_detect()
1793 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_hp_detect()
1800 /* HDMI audio codec callbacks */
1804 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_audio_set_mai_clock()
1813 hsm_clock = clk_get_rate(vc4_hdmi->audio_clock); in vc4_hdmi_audio_set_mai_clock()
1821 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_set_mai_clock()
1824 VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M)); in vc4_hdmi_audio_set_mai_clock()
1825 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_set_mai_clock()
1832 const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; in vc4_hdmi_set_n_cts()
1836 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_set_n_cts()
1837 lockdep_assert_held(&vc4_hdmi->hw_lock); in vc4_hdmi_set_n_cts()
1840 tmp = (u64)(mode->clock * 1000) * n; in vc4_hdmi_set_n_cts()
1866 struct drm_display_info *display = &vc4_hdmi->connector.display_info; in vc4_hdmi_audio_can_stream()
1868 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_audio_can_stream()
1874 if (!display->is_hdmi) in vc4_hdmi_audio_can_stream()
1880 static int vc4_hdmi_audio_startup(struct drm_connector *connector) in vc4_hdmi_audio_startup() argument
1882 struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); in vc4_hdmi_audio_startup()
1883 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_audio_startup()
1888 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_audio_startup()
1891 ret = -ENODEV; in vc4_hdmi_audio_startup()
1896 ret = -ENOTSUPP; in vc4_hdmi_audio_startup()
1900 vc4_hdmi->audio.streaming = true; in vc4_hdmi_audio_startup()
1902 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_startup()
1909 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_startup()
1911 if (vc4_hdmi->variant->phy_rng_enable) in vc4_hdmi_audio_startup()
1912 vc4_hdmi->variant->phy_rng_enable(vc4_hdmi); in vc4_hdmi_audio_startup()
1917 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_audio_startup()
1924 struct device *dev = &vc4_hdmi->pdev->dev; in vc4_hdmi_audio_reset()
1928 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_audio_reset()
1930 vc4_hdmi->audio.streaming = false; in vc4_hdmi_audio_reset()
1935 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_reset()
1941 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_reset()
1944 static void vc4_hdmi_audio_shutdown(struct drm_connector *connector) in vc4_hdmi_audio_shutdown() argument
1946 struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); in vc4_hdmi_audio_shutdown()
1947 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_audio_shutdown()
1951 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_audio_shutdown()
1956 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_shutdown()
1963 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_shutdown()
1965 if (vc4_hdmi->variant->phy_rng_disable) in vc4_hdmi_audio_shutdown()
1966 vc4_hdmi->variant->phy_rng_disable(vc4_hdmi); in vc4_hdmi_audio_shutdown()
1968 vc4_hdmi->audio.streaming = false; in vc4_hdmi_audio_shutdown()
1974 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_audio_shutdown()
2015 /* HDMI audio codec callbacks */
2016 static int vc4_hdmi_audio_prepare(struct drm_connector *connector, in vc4_hdmi_audio_prepare() argument
2020 struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); in vc4_hdmi_audio_prepare()
2021 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_audio_prepare()
2023 unsigned int sample_rate = params->sample_rate; in vc4_hdmi_audio_prepare()
2024 unsigned int channels = params->channels; in vc4_hdmi_audio_prepare()
2033 dev_dbg(&vc4_hdmi->pdev->dev, "%s: %u Hz, %d bit, %d channels\n", __func__, in vc4_hdmi_audio_prepare()
2034 sample_rate, params->sample_width, channels); in vc4_hdmi_audio_prepare()
2036 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_audio_prepare()
2039 ret = -ENODEV; in vc4_hdmi_audio_prepare()
2044 ret = -EINVAL; in vc4_hdmi_audio_prepare()
2050 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_prepare()
2058 if (params->iec.status[0] & IEC958_AES0_NONAUDIO && in vc4_hdmi_audio_prepare()
2059 params->channels == 8) in vc4_hdmi_audio_prepare()
2069 /* The B frame identifier should match the value used by alsa-lib (8) */ in vc4_hdmi_audio_prepare()
2075 channel_mask = GENMASK(channels - 1, 0); in vc4_hdmi_audio_prepare()
2080 switch (vc4->gen) { in vc4_hdmi_audio_prepare()
2104 drm_err(drm, "Unknown VC4 generation: %d", vc4->gen); in vc4_hdmi_audio_prepare()
2113 channel_map = vc4_hdmi->variant->channel_map(vc4_hdmi, channel_mask); in vc4_hdmi_audio_prepare()
2119 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_prepare()
2121 ret = drm_atomic_helper_connector_hdmi_update_audio_infoframe(connector, in vc4_hdmi_audio_prepare()
2122 ¶ms->cea); in vc4_hdmi_audio_prepare()
2129 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_audio_prepare()
2135 .name = "vc4-hdmi-cpu-dai-component",
2143 snd_soc_dai_init_dma_data(dai, &vc4_hdmi->audio.dma_data, NULL); in vc4_hdmi_audio_cpu_dai_probe()
2153 .name = "vc4-hdmi-cpu-dai",
2168 .chan_names[SNDRV_PCM_STREAM_PLAYBACK] = "audio-rx",
2181 &vc4_hdmi->variant->registers[HDMI_MAI_DATA]; in vc4_hdmi_audio_init()
2182 struct snd_soc_dai_link *dai_link = &vc4_hdmi->audio.link; in vc4_hdmi_audio_init()
2183 struct snd_soc_card *card = &vc4_hdmi->audio.card; in vc4_hdmi_audio_init()
2184 struct device *dev = &vc4_hdmi->pdev->dev; in vc4_hdmi_audio_init()
2209 if (!of_find_property(dev->of_node, "dmas", &len) || !len) { in vc4_hdmi_audio_init()
2211 "'dmas' DT property is missing or empty, no HDMI audio\n"); in vc4_hdmi_audio_init()
2215 if (mai_data->reg != VC4_HD) { in vc4_hdmi_audio_init()
2217 return -EINVAL; in vc4_hdmi_audio_init()
2227 index = of_property_match_string(dev->of_node, "reg-names", "hd"); in vc4_hdmi_audio_init()
2232 addr = of_get_address(dev->of_node, index, NULL, NULL); in vc4_hdmi_audio_init()
2234 return -EINVAL; in vc4_hdmi_audio_init()
2236 vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + mai_data->offset; in vc4_hdmi_audio_init()
2237 vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; in vc4_hdmi_audio_init()
2238 vc4_hdmi->audio.dma_data.maxburst = 2; in vc4_hdmi_audio_init()
2241 * NOTE: Strictly speaking, we should probably use a DRM-managed in vc4_hdmi_audio_init()
2246 * when registering, even when using non-device-managed in vc4_hdmi_audio_init()
2249 * If we call snd_soc_unregister_component() in a DRM-managed in vc4_hdmi_audio_init()
2250 * action, the device-managed actions have already been executed in vc4_hdmi_audio_init()
2253 * Using device-managed hooks here probably leaves us open to a in vc4_hdmi_audio_init()
2260 * Then, the vc4_hdmi structure is DRM-managed and thus only in vc4_hdmi_audio_init()
2277 dai_link->cpus = &vc4_hdmi->audio.cpu; in vc4_hdmi_audio_init()
2278 dai_link->codecs = &vc4_hdmi->audio.codec; in vc4_hdmi_audio_init()
2279 dai_link->platforms = &vc4_hdmi->audio.platform; in vc4_hdmi_audio_init()
2281 dai_link->num_cpus = 1; in vc4_hdmi_audio_init()
2282 dai_link->num_codecs = 1; in vc4_hdmi_audio_init()
2283 dai_link->num_platforms = 1; in vc4_hdmi_audio_init()
2285 dai_link->name = "MAI"; in vc4_hdmi_audio_init()
2286 dai_link->stream_name = "MAI PCM"; in vc4_hdmi_audio_init()
2287 dai_link->codecs->dai_name = "i2s-hifi"; in vc4_hdmi_audio_init()
2288 dai_link->cpus->dai_name = dev_name(dev); in vc4_hdmi_audio_init()
2289 dai_link->codecs->name = dev_name(&vc4_hdmi->connector.hdmi_audio.codec_pdev->dev); in vc4_hdmi_audio_init()
2290 dai_link->platforms->name = dev_name(dev); in vc4_hdmi_audio_init()
2292 card->dai_link = dai_link; in vc4_hdmi_audio_init()
2293 card->num_links = 1; in vc4_hdmi_audio_init()
2294 card->name = vc4_hdmi->variant->card_name; in vc4_hdmi_audio_init()
2295 card->driver_name = "vc4-hdmi"; in vc4_hdmi_audio_init()
2296 card->dev = dev; in vc4_hdmi_audio_init()
2297 card->owner = THIS_MODULE; in vc4_hdmi_audio_init()
2301 * stores a pointer to the snd card object in dev->driver_data. This in vc4_hdmi_audio_init()
2302 * means we cannot use it for something else. The hdmi back-pointer is in vc4_hdmi_audio_init()
2303 * now stored in card->drvdata and should be retrieved with in vc4_hdmi_audio_init()
2318 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_hpd_irq_thread() local
2319 struct drm_device *dev = connector->dev; in vc4_hdmi_hpd_irq_thread()
2321 if (dev && dev->registered) in vc4_hdmi_hpd_irq_thread()
2322 drm_connector_helper_hpd_irq_event(connector); in vc4_hdmi_hpd_irq_thread()
2329 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_hotplug_init() local
2330 struct platform_device *pdev = vc4_hdmi->pdev; in vc4_hdmi_hotplug_init()
2333 if (vc4_hdmi->variant->external_irq_controller) { in vc4_hdmi_hotplug_init()
2334 unsigned int hpd_con = platform_get_irq_byname(pdev, "hpd-connected"); in vc4_hdmi_hotplug_init()
2335 unsigned int hpd_rm = platform_get_irq_byname(pdev, "hpd-removed"); in vc4_hdmi_hotplug_init()
2337 ret = devm_request_threaded_irq(&pdev->dev, hpd_con, in vc4_hdmi_hotplug_init()
2340 "vc4 hdmi hpd connected", vc4_hdmi); in vc4_hdmi_hotplug_init()
2344 ret = devm_request_threaded_irq(&pdev->dev, hpd_rm, in vc4_hdmi_hotplug_init()
2347 "vc4 hdmi hpd disconnected", vc4_hdmi); in vc4_hdmi_hotplug_init()
2351 connector->polled = DRM_CONNECTOR_POLL_HPD; in vc4_hdmi_hotplug_init()
2362 if (vc4_hdmi->cec_rx_msg.len) in vc4_cec_irq_handler_rx_thread()
2363 cec_received_msg(vc4_hdmi->cec_adap, in vc4_cec_irq_handler_rx_thread()
2364 &vc4_hdmi->cec_rx_msg); in vc4_cec_irq_handler_rx_thread()
2373 if (vc4_hdmi->cec_tx_ok) { in vc4_cec_irq_handler_tx_thread()
2374 cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_OK, in vc4_cec_irq_handler_tx_thread()
2381 cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_NACK, in vc4_cec_irq_handler_tx_thread()
2392 if (vc4_hdmi->cec_irq_was_rx) in vc4_cec_irq_handler_thread()
2402 struct drm_device *dev = vc4_hdmi->connector.dev; in vc4_cec_read_msg()
2403 struct cec_msg *msg = &vc4_hdmi->cec_rx_msg; in vc4_cec_read_msg()
2406 lockdep_assert_held(&vc4_hdmi->hw_lock); in vc4_cec_read_msg()
2408 msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >> in vc4_cec_read_msg()
2411 if (msg->len > 16) { in vc4_cec_read_msg()
2412 drm_err(dev, "Attempting to read too much data (%d)\n", msg->len); in vc4_cec_read_msg()
2416 for (i = 0; i < msg->len; i += 4) { in vc4_cec_read_msg()
2419 msg->msg[i] = val & 0xff; in vc4_cec_read_msg()
2420 msg->msg[i + 1] = (val >> 8) & 0xff; in vc4_cec_read_msg()
2421 msg->msg[i + 2] = (val >> 16) & 0xff; in vc4_cec_read_msg()
2422 msg->msg[i + 3] = (val >> 24) & 0xff; in vc4_cec_read_msg()
2441 lockdep_assert_held(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler_tx_bare_locked()
2444 vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD; in vc4_cec_irq_handler_tx_bare_locked()
2456 spin_lock(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler_tx_bare()
2458 spin_unlock(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler_tx_bare()
2467 lockdep_assert_held(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler_rx_bare_locked()
2480 vc4_hdmi->cec_rx_msg.len = 0; in vc4_cec_irq_handler_rx_bare_locked()
2497 spin_lock(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler_rx_bare()
2499 spin_unlock(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler_rx_bare()
2525 spin_lock(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler()
2527 vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT; in vc4_cec_irq_handler()
2528 if (vc4_hdmi->cec_irq_was_rx) in vc4_cec_irq_handler()
2534 spin_unlock(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler()
2542 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_cec_enable()
2558 ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); in vc4_hdmi_cec_enable()
2564 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_cec_enable()
2566 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_enable()
2595 if (!vc4_hdmi->variant->external_irq_controller) in vc4_hdmi_cec_enable()
2598 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_enable()
2600 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_cec_enable()
2609 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_cec_disable()
2621 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_cec_disable()
2623 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_disable()
2625 if (!vc4_hdmi->variant->external_irq_controller) in vc4_hdmi_cec_disable()
2631 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_disable()
2633 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_cec_disable()
2635 pm_runtime_put(&vc4_hdmi->pdev->dev); in vc4_hdmi_cec_disable()
2653 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_cec_adap_log_addr()
2665 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_cec_adap_log_addr()
2666 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_adap_log_addr()
2670 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_adap_log_addr()
2671 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_cec_adap_log_addr()
2682 struct drm_device *dev = vc4_hdmi->connector.dev; in vc4_hdmi_cec_adap_transmit()
2689 return -ENODEV; in vc4_hdmi_cec_adap_transmit()
2691 if (msg->len > 16) { in vc4_hdmi_cec_adap_transmit()
2692 drm_err(dev, "Attempting to transmit too much data (%d)\n", msg->len); in vc4_hdmi_cec_adap_transmit()
2694 return -ENOMEM; in vc4_hdmi_cec_adap_transmit()
2697 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_cec_adap_transmit()
2699 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_adap_transmit()
2701 for (i = 0; i < msg->len; i += 4) in vc4_hdmi_cec_adap_transmit()
2703 (msg->msg[i]) | in vc4_hdmi_cec_adap_transmit()
2704 (msg->msg[i + 1] << 8) | in vc4_hdmi_cec_adap_transmit()
2705 (msg->msg[i + 2] << 16) | in vc4_hdmi_cec_adap_transmit()
2706 (msg->msg[i + 3] << 24)); in vc4_hdmi_cec_adap_transmit()
2712 val |= (msg->len - 1) << VC4_HDMI_CEC_MESSAGE_LENGTH_SHIFT; in vc4_hdmi_cec_adap_transmit()
2717 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_adap_transmit()
2718 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_cec_adap_transmit()
2734 cec_unregister_adapter(vc4_hdmi->cec_adap); in vc4_hdmi_cec_release()
2735 vc4_hdmi->cec_adap = NULL; in vc4_hdmi_cec_release()
2741 struct platform_device *pdev = vc4_hdmi->pdev; in vc4_hdmi_cec_init()
2742 struct device *dev = &pdev->dev; in vc4_hdmi_cec_init()
2745 if (!of_property_present(dev->of_node, "interrupts")) { in vc4_hdmi_cec_init()
2750 vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops, in vc4_hdmi_cec_init()
2752 vc4_hdmi->variant->card_name, in vc4_hdmi_cec_init()
2755 ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap); in vc4_hdmi_cec_init()
2759 cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector); in vc4_hdmi_cec_init()
2760 cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info); in vc4_hdmi_cec_init()
2762 if (vc4_hdmi->variant->external_irq_controller) { in vc4_hdmi_cec_init()
2763 ret = devm_request_threaded_irq(dev, platform_get_irq_byname(pdev, "cec-rx"), in vc4_hdmi_cec_init()
2766 "vc4 hdmi cec rx", vc4_hdmi); in vc4_hdmi_cec_init()
2770 ret = devm_request_threaded_irq(dev, platform_get_irq_byname(pdev, "cec-tx"), in vc4_hdmi_cec_init()
2773 "vc4 hdmi cec tx", vc4_hdmi); in vc4_hdmi_cec_init()
2780 "vc4 hdmi cec", vc4_hdmi); in vc4_hdmi_cec_init()
2785 ret = cec_register_adapter(vc4_hdmi->cec_adap, &pdev->dev); in vc4_hdmi_cec_init()
2790 * NOTE: Strictly speaking, we should probably use a DRM-managed in vc4_hdmi_cec_init()
2798 * By the time the device-managed hook is executed, we will give in vc4_hdmi_cec_init()
2807 * used to be our HDMI controller. If we get a CEC call at that in vc4_hdmi_cec_init()
2808 * moment, we could end up with a use-after-free. Fortunately, in vc4_hdmi_cec_init()
2819 cec_delete_adapter(vc4_hdmi->cec_adap); in vc4_hdmi_cec_init()
2842 const struct vc4_hdmi_variant *variant = vc4_hdmi->variant; in vc4_hdmi_build_regset()
2848 regs = kcalloc(variant->num_registers, sizeof(*regs), in vc4_hdmi_build_regset()
2851 return -ENOMEM; in vc4_hdmi_build_regset()
2853 for (i = 0; i < variant->num_registers; i++) { in vc4_hdmi_build_regset()
2854 const struct vc4_hdmi_register *field = &variant->registers[i]; in vc4_hdmi_build_regset()
2856 if (field->reg != reg) in vc4_hdmi_build_regset()
2859 regs[count].name = field->name; in vc4_hdmi_build_regset()
2860 regs[count].offset = field->offset; in vc4_hdmi_build_regset()
2866 return -ENOMEM; in vc4_hdmi_build_regset()
2868 regset->base = __vc4_hdmi_get_field_base(vc4_hdmi, reg); in vc4_hdmi_build_regset()
2869 regset->regs = new_regs; in vc4_hdmi_build_regset()
2870 regset->nregs = count; in vc4_hdmi_build_regset()
2882 struct platform_device *pdev = vc4_hdmi->pdev; in vc4_hdmi_init_resources()
2883 struct device *dev = &pdev->dev; in vc4_hdmi_init_resources()
2886 vc4_hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0); in vc4_hdmi_init_resources()
2887 if (IS_ERR(vc4_hdmi->hdmicore_regs)) in vc4_hdmi_init_resources()
2888 return PTR_ERR(vc4_hdmi->hdmicore_regs); in vc4_hdmi_init_resources()
2890 vc4_hdmi->hd_regs = vc4_ioremap_regs(pdev, 1); in vc4_hdmi_init_resources()
2891 if (IS_ERR(vc4_hdmi->hd_regs)) in vc4_hdmi_init_resources()
2892 return PTR_ERR(vc4_hdmi->hd_regs); in vc4_hdmi_init_resources()
2894 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD); in vc4_hdmi_init_resources()
2898 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI); in vc4_hdmi_init_resources()
2902 vc4_hdmi->pixel_clock = devm_clk_get(dev, "pixel"); in vc4_hdmi_init_resources()
2903 if (IS_ERR(vc4_hdmi->pixel_clock)) { in vc4_hdmi_init_resources()
2904 ret = PTR_ERR(vc4_hdmi->pixel_clock); in vc4_hdmi_init_resources()
2905 if (ret != -EPROBE_DEFER) in vc4_hdmi_init_resources()
2910 vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi"); in vc4_hdmi_init_resources()
2911 if (IS_ERR(vc4_hdmi->hsm_clock)) { in vc4_hdmi_init_resources()
2912 drm_err(drm, "Failed to get HDMI state machine clock\n"); in vc4_hdmi_init_resources()
2913 return PTR_ERR(vc4_hdmi->hsm_clock); in vc4_hdmi_init_resources()
2915 vc4_hdmi->audio_clock = vc4_hdmi->hsm_clock; in vc4_hdmi_init_resources()
2916 vc4_hdmi->cec_clock = vc4_hdmi->hsm_clock; in vc4_hdmi_init_resources()
2924 struct platform_device *pdev = vc4_hdmi->pdev; in vc5_hdmi_init_resources()
2925 struct device *dev = &pdev->dev; in vc5_hdmi_init_resources()
2929 vc4_hdmi->hdmicore_regs = devm_platform_ioremap_resource_byname(pdev, in vc5_hdmi_init_resources()
2930 "hdmi"); in vc5_hdmi_init_resources()
2931 if (IS_ERR(vc4_hdmi->hdmicore_regs)) in vc5_hdmi_init_resources()
2932 return PTR_ERR(vc4_hdmi->hdmicore_regs); in vc5_hdmi_init_resources()
2934 /* This is shared between both HDMI controllers. Cannot in vc5_hdmi_init_resources()
2941 return -ENODEV; in vc5_hdmi_init_resources()
2943 vc4_hdmi->hd_regs = devm_ioremap(dev, res->start, resource_size(res)); in vc5_hdmi_init_resources()
2944 if (!vc4_hdmi->hd_regs) in vc5_hdmi_init_resources()
2945 return -ENOMEM; in vc5_hdmi_init_resources()
2947 vc4_hdmi->cec_regs = devm_platform_ioremap_resource_byname(pdev, in vc5_hdmi_init_resources()
2949 if (IS_ERR(vc4_hdmi->cec_regs)) in vc5_hdmi_init_resources()
2950 return PTR_ERR(vc4_hdmi->cec_regs); in vc5_hdmi_init_resources()
2952 vc4_hdmi->csc_regs = devm_platform_ioremap_resource_byname(pdev, in vc5_hdmi_init_resources()
2954 if (IS_ERR(vc4_hdmi->csc_regs)) in vc5_hdmi_init_resources()
2955 return PTR_ERR(vc4_hdmi->csc_regs); in vc5_hdmi_init_resources()
2957 vc4_hdmi->dvp_regs = devm_platform_ioremap_resource_byname(pdev, in vc5_hdmi_init_resources()
2959 if (IS_ERR(vc4_hdmi->dvp_regs)) in vc5_hdmi_init_resources()
2960 return PTR_ERR(vc4_hdmi->dvp_regs); in vc5_hdmi_init_resources()
2962 vc4_hdmi->phy_regs = devm_platform_ioremap_resource_byname(pdev, in vc5_hdmi_init_resources()
2965 if (IS_ERR(vc4_hdmi->phy_regs)) in vc5_hdmi_init_resources()
2966 return PTR_ERR(vc4_hdmi->phy_regs); in vc5_hdmi_init_resources()
2968 vc4_hdmi->ram_regs = devm_platform_ioremap_resource_byname(pdev, in vc5_hdmi_init_resources()
2970 if (IS_ERR(vc4_hdmi->ram_regs)) in vc5_hdmi_init_resources()
2971 return PTR_ERR(vc4_hdmi->ram_regs); in vc5_hdmi_init_resources()
2973 vc4_hdmi->rm_regs = devm_platform_ioremap_resource_byname(pdev, "rm"); in vc5_hdmi_init_resources()
2974 if (IS_ERR(vc4_hdmi->rm_regs)) in vc5_hdmi_init_resources()
2975 return PTR_ERR(vc4_hdmi->rm_regs); in vc5_hdmi_init_resources()
2977 vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi"); in vc5_hdmi_init_resources()
2978 if (IS_ERR(vc4_hdmi->hsm_clock)) { in vc5_hdmi_init_resources()
2979 drm_err(drm, "Failed to get HDMI state machine clock\n"); in vc5_hdmi_init_resources()
2980 return PTR_ERR(vc4_hdmi->hsm_clock); in vc5_hdmi_init_resources()
2983 vc4_hdmi->pixel_bvb_clock = devm_clk_get(dev, "bvb"); in vc5_hdmi_init_resources()
2984 if (IS_ERR(vc4_hdmi->pixel_bvb_clock)) { in vc5_hdmi_init_resources()
2986 return PTR_ERR(vc4_hdmi->pixel_bvb_clock); in vc5_hdmi_init_resources()
2989 vc4_hdmi->audio_clock = devm_clk_get(dev, "audio"); in vc5_hdmi_init_resources()
2990 if (IS_ERR(vc4_hdmi->audio_clock)) { in vc5_hdmi_init_resources()
2992 return PTR_ERR(vc4_hdmi->audio_clock); in vc5_hdmi_init_resources()
2995 vc4_hdmi->cec_clock = devm_clk_get(dev, "cec"); in vc5_hdmi_init_resources()
2996 if (IS_ERR(vc4_hdmi->cec_clock)) { in vc5_hdmi_init_resources()
2998 return PTR_ERR(vc4_hdmi->cec_clock); in vc5_hdmi_init_resources()
3001 vc4_hdmi->reset = devm_reset_control_get(dev, NULL); in vc5_hdmi_init_resources()
3002 if (IS_ERR(vc4_hdmi->reset)) { in vc5_hdmi_init_resources()
3003 drm_err(drm, "Failed to get HDMI reset line\n"); in vc5_hdmi_init_resources()
3004 return PTR_ERR(vc4_hdmi->reset); in vc5_hdmi_init_resources()
3007 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI); in vc5_hdmi_init_resources()
3011 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD); in vc5_hdmi_init_resources()
3015 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->cec_regset, VC5_CEC); in vc5_hdmi_init_resources()
3019 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->csc_regset, VC5_CSC); in vc5_hdmi_init_resources()
3023 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->dvp_regset, VC5_DVP); in vc5_hdmi_init_resources()
3027 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->phy_regset, VC5_PHY); in vc5_hdmi_init_resources()
3031 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->ram_regset, VC5_RAM); in vc5_hdmi_init_resources()
3035 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->rm_regset, VC5_RM); in vc5_hdmi_init_resources()
3046 clk_disable_unprepare(vc4_hdmi->audio_clock); in vc4_hdmi_runtime_suspend()
3047 clk_disable_unprepare(vc4_hdmi->hsm_clock); in vc4_hdmi_runtime_suspend()
3060 ret = clk_prepare_enable(vc4_hdmi->hsm_clock); in vc4_hdmi_runtime_resume()
3065 * Whenever the RaspberryPi boots without an HDMI monitor in vc4_hdmi_runtime_resume()
3073 rate = clk_get_rate(vc4_hdmi->hsm_clock); in vc4_hdmi_runtime_resume()
3075 ret = -EINVAL; in vc4_hdmi_runtime_resume()
3079 ret = clk_prepare_enable(vc4_hdmi->audio_clock); in vc4_hdmi_runtime_resume()
3083 if (vc4_hdmi->variant->reset) in vc4_hdmi_runtime_resume()
3084 vc4_hdmi->variant->reset(vc4_hdmi); in vc4_hdmi_runtime_resume()
3087 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_runtime_resume()
3092 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_runtime_resume()
3096 if (!vc4_hdmi->variant->external_irq_controller) { in vc4_hdmi_runtime_resume()
3097 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_runtime_resume()
3099 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_runtime_resume()
3106 clk_disable_unprepare(vc4_hdmi->hsm_clock); in vc4_hdmi_runtime_resume()
3114 put_device(&vc4_hdmi->ddc->dev); in vc4_hdmi_put_ddc_device()
3129 return -ENOMEM; in vc4_hdmi_bind()
3131 ret = drmm_mutex_init(drm, &vc4_hdmi->mutex); in vc4_hdmi_bind()
3135 spin_lock_init(&vc4_hdmi->hw_lock); in vc4_hdmi_bind()
3136 INIT_DELAYED_WORK(&vc4_hdmi->scrambling_work, vc4_hdmi_scrambling_wq); in vc4_hdmi_bind()
3139 encoder = &vc4_hdmi->encoder.base; in vc4_hdmi_bind()
3140 vc4_hdmi->encoder.type = variant->encoder_type; in vc4_hdmi_bind()
3141 vc4_hdmi->encoder.pre_crtc_configure = vc4_hdmi_encoder_pre_crtc_configure; in vc4_hdmi_bind()
3142 vc4_hdmi->encoder.pre_crtc_enable = vc4_hdmi_encoder_pre_crtc_enable; in vc4_hdmi_bind()
3143 vc4_hdmi->encoder.post_crtc_enable = vc4_hdmi_encoder_post_crtc_enable; in vc4_hdmi_bind()
3144 vc4_hdmi->encoder.post_crtc_disable = vc4_hdmi_encoder_post_crtc_disable; in vc4_hdmi_bind()
3145 vc4_hdmi->encoder.post_crtc_powerdown = vc4_hdmi_encoder_post_crtc_powerdown; in vc4_hdmi_bind()
3146 vc4_hdmi->pdev = pdev; in vc4_hdmi_bind()
3147 vc4_hdmi->variant = variant; in vc4_hdmi_bind()
3155 if (variant->max_pixel_clock > HDMI_14_MAX_TMDS_CLK) in vc4_hdmi_bind()
3156 vc4_hdmi->scdc_enabled = true; in vc4_hdmi_bind()
3158 ret = variant->init_resources(drm, vc4_hdmi); in vc4_hdmi_bind()
3162 ddc_node = of_parse_phandle(dev->of_node, "ddc", 0); in vc4_hdmi_bind()
3165 return -ENODEV; in vc4_hdmi_bind()
3168 vc4_hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node); in vc4_hdmi_bind()
3170 if (!vc4_hdmi->ddc) { in vc4_hdmi_bind()
3172 return -EPROBE_DEFER; in vc4_hdmi_bind()
3180 * we'll use the HDMI core's register. in vc4_hdmi_bind()
3182 vc4_hdmi->hpd_gpio = devm_gpiod_get_optional(dev, "hpd", GPIOD_IN); in vc4_hdmi_bind()
3183 if (IS_ERR(vc4_hdmi->hpd_gpio)) { in vc4_hdmi_bind()
3184 return PTR_ERR(vc4_hdmi->hpd_gpio); in vc4_hdmi_bind()
3187 vc4_hdmi->disable_wifi_frequencies = in vc4_hdmi_bind()
3188 of_property_read_bool(dev->of_node, "wifi-2.4ghz-coexistence"); in vc4_hdmi_bind()
3202 if ((of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi0") || in vc4_hdmi_bind()
3203 of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi1") || in vc4_hdmi_bind()
3204 of_device_is_compatible(dev->of_node, "brcm,bcm2712-hdmi0") || in vc4_hdmi_bind()
3205 of_device_is_compatible(dev->of_node, "brcm,bcm2712-hdmi1")) && in vc4_hdmi_bind()
3207 clk_prepare_enable(vc4_hdmi->pixel_clock); in vc4_hdmi_bind()
3208 clk_prepare_enable(vc4_hdmi->hsm_clock); in vc4_hdmi_bind()
3209 clk_prepare_enable(vc4_hdmi->pixel_bvb_clock); in vc4_hdmi_bind()
3253 return component_add(&pdev->dev, &vc4_hdmi_ops); in vc4_hdmi_dev_probe()
3258 component_del(&pdev->dev, &vc4_hdmi_ops); in vc4_hdmi_dev_remove()
3264 .card_name = "vc4-hdmi",
3284 .card_name = "vc4-hdmi-0",
3313 .card_name = "vc4-hdmi-1",
3342 .card_name = "vc4-hdmi-0",
3369 .card_name = "vc4-hdmi-1",
3394 { .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant },
3395 { .compatible = "brcm,bcm2711-hdmi0", .data = &bcm2711_hdmi0_variant },
3396 { .compatible = "brcm,bcm2711-hdmi1", .data = &bcm2711_hdmi1_variant },
3397 { .compatible = "brcm,bcm2712-hdmi0", .data = &bcm2712_hdmi0_variant },
3398 { .compatible = "brcm,bcm2712-hdmi1", .data = &bcm2712_hdmi1_variant },