Lines Matching +full:bcm2711 +full:- +full:hdmi +full:- +full:i2c

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
43 #include <linux/i2c.h>
50 #include <sound/hdmi-codec.h>
130 struct drm_display_info *display = &vc4_hdmi->connector.display_info; in vc4_hdmi_supports_scrambling()
132 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_supports_scrambling()
134 if (!display->is_hdmi) in vc4_hdmi_supports_scrambling()
137 if (!display->hdmi.scdc.supported || in vc4_hdmi_supports_scrambling()
138 !display->hdmi.scdc.scrambling.supported) in vc4_hdmi_supports_scrambling()
156 struct drm_display_info *display = &vc4_hdmi->connector.display_info; in vc4_hdmi_is_full_range_rgb()
158 return !display->is_hdmi || in vc4_hdmi_is_full_range_rgb()
164 struct drm_info_node *node = (struct drm_info_node *)m->private; in vc4_hdmi_debugfs_regs()
165 struct vc4_hdmi *vc4_hdmi = node->info_ent->data; in vc4_hdmi_debugfs_regs()
166 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_debugfs_regs()
171 return -ENODEV; in vc4_hdmi_debugfs_regs()
173 drm_print_regset32(&p, &vc4_hdmi->hdmi_regset); in vc4_hdmi_debugfs_regs()
174 drm_print_regset32(&p, &vc4_hdmi->hd_regset); in vc4_hdmi_debugfs_regs()
175 drm_print_regset32(&p, &vc4_hdmi->cec_regset); in vc4_hdmi_debugfs_regs()
176 drm_print_regset32(&p, &vc4_hdmi->csc_regset); in vc4_hdmi_debugfs_regs()
177 drm_print_regset32(&p, &vc4_hdmi->dvp_regset); in vc4_hdmi_debugfs_regs()
178 drm_print_regset32(&p, &vc4_hdmi->phy_regset); in vc4_hdmi_debugfs_regs()
179 drm_print_regset32(&p, &vc4_hdmi->ram_regset); in vc4_hdmi_debugfs_regs()
180 drm_print_regset32(&p, &vc4_hdmi->rm_regset); in vc4_hdmi_debugfs_regs()
189 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_reset()
195 * connector->dev pointer might not be initialised yet. in vc4_hdmi_reset()
200 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_reset()
214 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_reset()
222 struct drm_device *drm = vc4_hdmi->connector.dev; in vc5_hdmi_reset()
228 * connector->dev pointer might not be initialised yet. in vc5_hdmi_reset()
233 reset_control_reset(vc4_hdmi->reset); in vc5_hdmi_reset()
235 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_reset()
242 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_reset()
251 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_cec_update_clk_div()
267 cec_rate = clk_get_rate(vc4_hdmi->cec_clock); in vc4_hdmi_cec_update_clk_div()
269 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_update_clk_div()
282 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_update_clk_div()
298 state = drm_atomic_state_alloc(crtc->dev); in reset_pipe()
300 return -ENOMEM; in reset_pipe()
302 state->acquire_ctx = ctx; in reset_pipe()
310 crtc_state->connectors_changed = true; in reset_pipe()
322 struct drm_device *drm = connector->dev; in vc4_hdmi_reset_link()
324 struct drm_encoder *encoder = &vc4_hdmi->encoder.base; in vc4_hdmi_reset_link()
335 ret = drm_modeset_lock(&drm->mode_config.connection_mutex, ctx); in vc4_hdmi_reset_link()
339 conn_state = connector->state; in vc4_hdmi_reset_link()
340 crtc = conn_state->crtc; in vc4_hdmi_reset_link()
344 ret = drm_modeset_lock(&crtc->mutex, ctx); in vc4_hdmi_reset_link()
348 crtc_state = crtc->state; in vc4_hdmi_reset_link()
349 if (!crtc_state->active) in vc4_hdmi_reset_link()
352 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_reset_link()
355 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_reset_link()
359 scrambling_needed = vc4_hdmi_mode_needs_scrambling(&vc4_hdmi->saved_adjusted_mode, in vc4_hdmi_reset_link()
360 vc4_hdmi->output_bpc, in vc4_hdmi_reset_link()
361 vc4_hdmi->output_format); in vc4_hdmi_reset_link()
363 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_reset_link()
367 if (conn_state->commit && in vc4_hdmi_reset_link()
368 !try_wait_for_completion(&conn_state->commit->hw_done)) { in vc4_hdmi_reset_link()
369 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_reset_link()
373 ret = drm_scdc_readb(connector->ddc, SCDC_TMDS_CONFIG, &config); in vc4_hdmi_reset_link()
376 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_reset_link()
381 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_reset_link()
385 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_reset_link()
388 * HDMI 2.0 says that one should not send scrambled data in vc4_hdmi_reset_link()
403 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_handle_hotplug()
408 * vc4_hdmi->mutex held, but doing so results in reentrancy in vc4_hdmi_handle_hotplug()
422 cec_phys_addr_invalidate(vc4_hdmi->cec_adap); in vc4_hdmi_handle_hotplug()
426 edid = drm_get_edid(connector, vc4_hdmi->ddc); in vc4_hdmi_handle_hotplug()
430 cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid); in vc4_hdmi_handle_hotplug()
444 * NOTE: This function should really take vc4_hdmi->mutex, but in vc4_hdmi_connector_detect_ctx()
454 WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev)); in vc4_hdmi_connector_detect_ctx()
456 if (vc4_hdmi->hpd_gpio) { in vc4_hdmi_connector_detect_ctx()
457 if (gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio)) in vc4_hdmi_connector_detect_ctx()
460 if (vc4_hdmi->variant->hp_detect && in vc4_hdmi_connector_detect_ctx()
461 vc4_hdmi->variant->hp_detect(vc4_hdmi)) in vc4_hdmi_connector_detect_ctx()
466 pm_runtime_put(&vc4_hdmi->pdev->dev); in vc4_hdmi_connector_detect_ctx()
478 * NOTE: This function should really take vc4_hdmi->mutex, but in vc4_hdmi_connector_get_modes()
488 edid = drm_get_edid(connector, vc4_hdmi->ddc); in vc4_hdmi_connector_get_modes()
489 cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid); in vc4_hdmi_connector_get_modes()
491 return -ENODEV; in vc4_hdmi_connector_get_modes()
497 if (vc4_hdmi->disable_4kp60) { in vc4_hdmi_connector_get_modes()
498 struct drm_device *drm = connector->dev; in vc4_hdmi_connector_get_modes()
501 list_for_each_entry(mode, &connector->probed_modes, head) { in vc4_hdmi_connector_get_modes()
519 struct drm_crtc *crtc = new_state->crtc; in vc4_hdmi_connector_atomic_check()
524 if (old_state->colorspace != new_state->colorspace || in vc4_hdmi_connector_atomic_check()
532 crtc_state->mode_changed = true; in vc4_hdmi_connector_atomic_check()
541 conn_state_to_vc4_hdmi_conn_state(connector->state); in vc4_hdmi_connector_reset()
545 if (connector->state) in vc4_hdmi_connector_reset()
546 __drm_atomic_helper_connector_destroy_state(connector->state); in vc4_hdmi_connector_reset()
549 __drm_atomic_helper_connector_reset(connector, &new_state->base); in vc4_hdmi_connector_reset()
554 new_state->base.max_bpc = 8; in vc4_hdmi_connector_reset()
555 new_state->base.max_requested_bpc = 8; in vc4_hdmi_connector_reset()
556 new_state->output_format = VC4_HDMI_OUTPUT_RGB; in vc4_hdmi_connector_reset()
563 struct drm_connector_state *conn_state = connector->state; in vc4_hdmi_connector_duplicate_state()
571 new_state->tmds_char_rate = vc4_state->tmds_char_rate; in vc4_hdmi_connector_duplicate_state()
572 new_state->output_bpc = vc4_state->output_bpc; in vc4_hdmi_connector_duplicate_state()
573 new_state->output_format = vc4_state->output_format; in vc4_hdmi_connector_duplicate_state()
574 __drm_atomic_helper_connector_duplicate_state(connector, &new_state->base); in vc4_hdmi_connector_duplicate_state()
576 return &new_state->base; in vc4_hdmi_connector_duplicate_state()
595 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_connector_init()
596 struct drm_encoder *encoder = &vc4_hdmi->encoder.base; in vc4_hdmi_connector_init()
602 vc4_hdmi->ddc); in vc4_hdmi_connector_init()
612 if (connector->funcs->reset) in vc4_hdmi_connector_init()
613 connector->funcs->reset(connector); in vc4_hdmi_connector_init()
628 connector->polled = (DRM_CONNECTOR_POLL_CONNECT | in vc4_hdmi_connector_init()
631 connector->interlace_allowed = 1; in vc4_hdmi_connector_init()
632 connector->doublescan_allowed = 0; in vc4_hdmi_connector_init()
633 connector->stereo_allowed = 1; in vc4_hdmi_connector_init()
635 if (vc4_hdmi->variant->supports_hdr) in vc4_hdmi_connector_init()
648 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_stop_packet()
649 u32 packet_id = type - 0x80; in vc4_hdmi_stop_packet()
655 return -ENODEV; in vc4_hdmi_stop_packet()
657 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_stop_packet()
660 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_stop_packet()
675 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_write_infoframe()
676 u32 packet_id = frame->any.type - 0x80; in vc4_hdmi_write_infoframe()
678 &vc4_hdmi->variant->registers[HDMI_RAM_PACKET_START]; in vc4_hdmi_write_infoframe()
679 u32 packet_reg = ram_packet_start->offset + VC4_HDMI_PACKET_STRIDE * packet_id; in vc4_hdmi_write_infoframe()
680 u32 packet_reg_next = ram_packet_start->offset + in vc4_hdmi_write_infoframe()
683 ram_packet_start->reg); in vc4_hdmi_write_infoframe()
701 ret = vc4_hdmi_stop_packet(encoder, frame->any.type, true); in vc4_hdmi_write_infoframe()
707 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_write_infoframe()
726 * infoframe and triggers a checksum error on hdmi analyser in vc4_hdmi_write_infoframe()
734 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_write_infoframe()
750 frame->colorspace = HDMI_COLORSPACE_RGB; in vc4_hdmi_avi_infoframe_colorspace()
754 frame->colorspace = HDMI_COLORSPACE_YUV420; in vc4_hdmi_avi_infoframe_colorspace()
758 frame->colorspace = HDMI_COLORSPACE_YUV422; in vc4_hdmi_avi_infoframe_colorspace()
762 frame->colorspace = HDMI_COLORSPACE_YUV444; in vc4_hdmi_avi_infoframe_colorspace()
773 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_set_avi_infoframe()
774 struct drm_connector_state *cstate = connector->state; in vc4_hdmi_set_avi_infoframe()
777 const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; in vc4_hdmi_set_avi_infoframe()
781 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_set_avi_infoframe()
796 vc4_hdmi_avi_infoframe_colorspace(&frame.avi, vc4_state->output_format); in vc4_hdmi_set_avi_infoframe()
821 struct hdmi_audio_infoframe *audio = &vc4_hdmi->audio.infoframe; in vc4_hdmi_set_audio_infoframe()
826 if (vc4_hdmi->packet_ram_enabled) in vc4_hdmi_set_audio_infoframe()
833 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_set_hdr_infoframe()
834 struct drm_connector_state *conn_state = connector->state; in vc4_hdmi_set_hdr_infoframe()
837 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_set_hdr_infoframe()
839 if (!vc4_hdmi->variant->supports_hdr) in vc4_hdmi_set_hdr_infoframe()
842 if (!conn_state->hdr_output_metadata) in vc4_hdmi_set_hdr_infoframe()
855 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_set_infoframes()
863 if (vc4_hdmi->audio.streaming) in vc4_hdmi_set_infoframes()
874 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_enable_scrambling()
875 const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; in vc4_hdmi_enable_scrambling()
879 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_enable_scrambling()
885 vc4_hdmi->output_bpc, in vc4_hdmi_enable_scrambling()
886 vc4_hdmi->output_format)) in vc4_hdmi_enable_scrambling()
892 drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, true); in vc4_hdmi_enable_scrambling()
893 drm_scdc_set_scrambling(vc4_hdmi->ddc, true); in vc4_hdmi_enable_scrambling()
895 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_enable_scrambling()
898 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_enable_scrambling()
902 vc4_hdmi->scdc_enabled = true; in vc4_hdmi_enable_scrambling()
904 queue_delayed_work(system_wq, &vc4_hdmi->scrambling_work, in vc4_hdmi_enable_scrambling()
911 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_disable_scrambling()
915 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_disable_scrambling()
917 if (!vc4_hdmi->scdc_enabled) in vc4_hdmi_disable_scrambling()
920 vc4_hdmi->scdc_enabled = false; in vc4_hdmi_disable_scrambling()
922 if (delayed_work_pending(&vc4_hdmi->scrambling_work)) in vc4_hdmi_disable_scrambling()
923 cancel_delayed_work_sync(&vc4_hdmi->scrambling_work); in vc4_hdmi_disable_scrambling()
928 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_disable_scrambling()
931 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_disable_scrambling()
933 drm_scdc_set_scrambling(vc4_hdmi->ddc, false); in vc4_hdmi_disable_scrambling()
934 drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, false); in vc4_hdmi_disable_scrambling()
945 if (drm_scdc_get_scrambling_status(vc4_hdmi->ddc)) in vc4_hdmi_scrambling_wq()
948 drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, true); in vc4_hdmi_scrambling_wq()
949 drm_scdc_set_scrambling(vc4_hdmi->ddc, true); in vc4_hdmi_scrambling_wq()
951 queue_delayed_work(system_wq, &vc4_hdmi->scrambling_work, in vc4_hdmi_scrambling_wq()
959 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_encoder_post_crtc_disable()
963 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_post_crtc_disable()
965 vc4_hdmi->packet_ram_enabled = false; in vc4_hdmi_encoder_post_crtc_disable()
970 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_disable()
976 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_disable()
980 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_disable()
983 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_disable()
990 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_post_crtc_disable()
997 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_encoder_post_crtc_powerdown()
1002 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_post_crtc_powerdown()
1007 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_powerdown()
1010 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_powerdown()
1012 if (vc4_hdmi->variant->phy_disable) in vc4_hdmi_encoder_post_crtc_powerdown()
1013 vc4_hdmi->variant->phy_disable(vc4_hdmi); in vc4_hdmi_encoder_post_crtc_powerdown()
1015 clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock); in vc4_hdmi_encoder_post_crtc_powerdown()
1016 clk_disable_unprepare(vc4_hdmi->pixel_clock); in vc4_hdmi_encoder_post_crtc_powerdown()
1018 ret = pm_runtime_put(&vc4_hdmi->pdev->dev); in vc4_hdmi_encoder_post_crtc_powerdown()
1025 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_post_crtc_powerdown()
1032 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_csc_setup()
1040 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_csc_setup()
1048 * Apply a colorspace conversion to squash 0-255 down in vc4_hdmi_csc_setup()
1049 * to 16-235. The matrix here is: in vc4_hdmi_csc_setup()
1072 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_csc_setup()
1095 * squash 0-255 down to 16-235. The matrix here is:
1115 * [ -0.100268 -0.337232 0.437500 128 ]
1116 * [ 0.437500 -0.397386 -0.040114 128 ]
1130 * [ -0.100268 -0.337232 0.437500 128 ]
1131 * [ 0.437500 -0.397386 -0.040114 128 ]
1145 lockdep_assert_held(&vc4_hdmi->hw_lock); in vc5_hdmi_set_csc_coeffs()
1159 struct drm_device *drm = vc4_hdmi->connector.dev; in vc5_hdmi_csc_setup()
1173 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_csc_setup()
1175 switch (vc4_state->output_format) { in vc5_hdmi_csc_setup()
1213 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_csc_setup()
1222 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_set_timings()
1223 bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; in vc4_hdmi_set_timings()
1224 bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; in vc4_hdmi_set_timings()
1225 bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; in vc4_hdmi_set_timings()
1226 u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1; in vc4_hdmi_set_timings()
1227 u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, in vc4_hdmi_set_timings()
1229 VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, in vc4_hdmi_set_timings()
1231 VC4_SET_FIELD(mode->crtc_vdisplay, VC4_HDMI_VERTA_VAL)); in vc4_hdmi_set_timings()
1233 VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end + in vc4_hdmi_set_timings()
1237 VC4_SET_FIELD(mode->crtc_vtotal - in vc4_hdmi_set_timings()
1238 mode->crtc_vsync_end, in vc4_hdmi_set_timings()
1247 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_set_timings()
1252 VC4_SET_FIELD(mode->hdisplay * pixel_rep, in vc4_hdmi_set_timings()
1256 VC4_SET_FIELD((mode->htotal - in vc4_hdmi_set_timings()
1257 mode->hsync_end) * pixel_rep, in vc4_hdmi_set_timings()
1259 VC4_SET_FIELD((mode->hsync_end - in vc4_hdmi_set_timings()
1260 mode->hsync_start) * pixel_rep, in vc4_hdmi_set_timings()
1262 VC4_SET_FIELD((mode->hsync_start - in vc4_hdmi_set_timings()
1263 mode->hdisplay) * pixel_rep, in vc4_hdmi_set_timings()
1274 reg |= VC4_SET_FIELD(pixel_rep - 1, VC4_HDMI_MISC_CONTROL_PIXEL_REP); in vc4_hdmi_set_timings()
1277 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_set_timings()
1286 struct drm_device *drm = vc4_hdmi->connector.dev; in vc5_hdmi_set_timings()
1289 bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; in vc5_hdmi_set_timings()
1290 bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; in vc5_hdmi_set_timings()
1291 bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; in vc5_hdmi_set_timings()
1292 u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1; in vc5_hdmi_set_timings()
1293 u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, in vc5_hdmi_set_timings()
1295 VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, in vc5_hdmi_set_timings()
1297 VC4_SET_FIELD(mode->crtc_vdisplay, VC5_HDMI_VERTA_VAL)); in vc5_hdmi_set_timings()
1298 u32 vertb = (VC4_SET_FIELD(mode->htotal >> (2 - pixel_rep), in vc5_hdmi_set_timings()
1300 VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, in vc5_hdmi_set_timings()
1303 VC4_SET_FIELD(mode->crtc_vtotal - in vc5_hdmi_set_timings()
1304 mode->crtc_vsync_end - interlaced, in vc5_hdmi_set_timings()
1315 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_set_timings()
1320 VC4_SET_FIELD(mode->hdisplay * pixel_rep, in vc5_hdmi_set_timings()
1322 VC4_SET_FIELD((mode->hsync_start - in vc5_hdmi_set_timings()
1323 mode->hdisplay) * pixel_rep, in vc5_hdmi_set_timings()
1327 VC4_SET_FIELD((mode->htotal - in vc5_hdmi_set_timings()
1328 mode->hsync_end) * pixel_rep, in vc5_hdmi_set_timings()
1330 VC4_SET_FIELD((mode->hsync_end - in vc5_hdmi_set_timings()
1331 mode->hsync_start) * pixel_rep, in vc5_hdmi_set_timings()
1340 switch (vc4_state->output_bpc) { in vc5_hdmi_set_timings()
1357 * YCC422 is always 36-bit and not considered deep colour so in vc5_hdmi_set_timings()
1360 if (vc4_state->output_format == VC4_HDMI_OUTPUT_YUV422) { in vc5_hdmi_set_timings()
1384 reg |= VC4_SET_FIELD(pixel_rep - 1, VC5_HDMI_MISC_CONTROL_PIXEL_REP); in vc5_hdmi_set_timings()
1389 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_set_timings()
1396 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_recenter_fifo()
1405 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_recenter_fifo()
1415 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_recenter_fifo()
1419 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_recenter_fifo()
1426 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_recenter_fifo()
1440 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_encoder_pre_crtc_configure()
1441 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_encoder_pre_crtc_configure()
1446 const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; in vc4_hdmi_encoder_pre_crtc_configure()
1447 unsigned long tmds_char_rate = vc4_conn_state->tmds_char_rate; in vc4_hdmi_encoder_pre_crtc_configure()
1453 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_pre_crtc_configure()
1459 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must in vc4_hdmi_encoder_pre_crtc_configure()
1461 * simulation. Otherwise, exact value is unimportant for HDMI in vc4_hdmi_encoder_pre_crtc_configure()
1468 * both clocks. Which, for RPi0-3 implies a maximum pixel clock of in vc4_hdmi_encoder_pre_crtc_configure()
1475 ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate); in vc4_hdmi_encoder_pre_crtc_configure()
1481 ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); in vc4_hdmi_encoder_pre_crtc_configure()
1487 ret = clk_set_rate(vc4_hdmi->pixel_clock, tmds_char_rate); in vc4_hdmi_encoder_pre_crtc_configure()
1493 ret = clk_prepare_enable(vc4_hdmi->pixel_clock); in vc4_hdmi_encoder_pre_crtc_configure()
1509 ret = clk_set_min_rate(vc4_hdmi->pixel_bvb_clock, bvb_rate); in vc4_hdmi_encoder_pre_crtc_configure()
1515 ret = clk_prepare_enable(vc4_hdmi->pixel_bvb_clock); in vc4_hdmi_encoder_pre_crtc_configure()
1521 if (vc4_hdmi->variant->phy_init) in vc4_hdmi_encoder_pre_crtc_configure()
1522 vc4_hdmi->variant->phy_init(vc4_hdmi, vc4_conn_state); in vc4_hdmi_encoder_pre_crtc_configure()
1524 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_pre_crtc_configure()
1531 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_pre_crtc_configure()
1533 if (vc4_hdmi->variant->set_timings) in vc4_hdmi_encoder_pre_crtc_configure()
1534 vc4_hdmi->variant->set_timings(vc4_hdmi, conn_state, mode); in vc4_hdmi_encoder_pre_crtc_configure()
1538 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_pre_crtc_configure()
1543 clk_disable_unprepare(vc4_hdmi->pixel_clock); in vc4_hdmi_encoder_pre_crtc_configure()
1545 pm_runtime_put(&vc4_hdmi->pdev->dev); in vc4_hdmi_encoder_pre_crtc_configure()
1549 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_pre_crtc_configure()
1557 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_encoder_pre_crtc_enable()
1558 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_encoder_pre_crtc_enable()
1559 const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; in vc4_hdmi_encoder_pre_crtc_enable()
1565 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_pre_crtc_enable()
1570 if (vc4_hdmi->variant->csc_setup) in vc4_hdmi_encoder_pre_crtc_enable()
1571 vc4_hdmi->variant->csc_setup(vc4_hdmi, conn_state, mode); in vc4_hdmi_encoder_pre_crtc_enable()
1573 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_pre_crtc_enable()
1575 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_pre_crtc_enable()
1580 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_pre_crtc_enable()
1587 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_encoder_post_crtc_enable()
1588 const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; in vc4_hdmi_encoder_post_crtc_enable()
1589 struct drm_display_info *display = &vc4_hdmi->connector.display_info; in vc4_hdmi_encoder_post_crtc_enable()
1590 bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; in vc4_hdmi_encoder_post_crtc_enable()
1591 bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; in vc4_hdmi_encoder_post_crtc_enable()
1596 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_post_crtc_enable()
1601 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_enable()
1614 if (display->is_hdmi) { in vc4_hdmi_encoder_post_crtc_enable()
1619 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_enable()
1633 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_enable()
1641 if (display->is_hdmi) { in vc4_hdmi_encoder_post_crtc_enable()
1642 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_enable()
1650 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_enable()
1651 vc4_hdmi->packet_ram_enabled = true; in vc4_hdmi_encoder_post_crtc_enable()
1662 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_post_crtc_enable()
1673 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_atomic_mode_set()
1674 drm_mode_copy(&vc4_hdmi->saved_adjusted_mode, in vc4_hdmi_encoder_atomic_mode_set()
1675 &crtc_state->adjusted_mode); in vc4_hdmi_encoder_atomic_mode_set()
1676 vc4_hdmi->output_bpc = vc4_state->output_bpc; in vc4_hdmi_encoder_atomic_mode_set()
1677 vc4_hdmi->output_format = vc4_state->output_format; in vc4_hdmi_encoder_atomic_mode_set()
1678 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_atomic_mode_set()
1687 struct drm_device *dev = vc4_hdmi->connector.dev; in vc4_hdmi_sink_supports_format_bpc()
1695 if (!info->is_hdmi && in vc4_hdmi_sink_supports_format_bpc()
1705 if (!(info->color_formats & DRM_COLOR_FORMAT_RGB444)) in vc4_hdmi_sink_supports_format_bpc()
1708 if (bpc == 10 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30)) { in vc4_hdmi_sink_supports_format_bpc()
1713 if (bpc == 12 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36)) { in vc4_hdmi_sink_supports_format_bpc()
1725 if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) { in vc4_hdmi_sink_supports_format_bpc()
1742 if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR444)) { in vc4_hdmi_sink_supports_format_bpc()
1747 if (bpc == 10 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_30)) { in vc4_hdmi_sink_supports_format_bpc()
1752 if (bpc == 12 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_36)) { in vc4_hdmi_sink_supports_format_bpc()
1769 const struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_encoder_clock_valid()
1770 const struct drm_display_info *info = &connector->display_info; in vc4_hdmi_encoder_clock_valid()
1772 if (clock > vc4_hdmi->variant->max_pixel_clock) in vc4_hdmi_encoder_clock_valid()
1775 if (vc4_hdmi->disable_4kp60 && clock > HDMI_14_MAX_TMDS_CLK) in vc4_hdmi_encoder_clock_valid()
1778 if (info->max_tmds_clock && clock > (info->max_tmds_clock * 1000)) in vc4_hdmi_encoder_clock_valid()
1789 unsigned long long clock = mode->clock * 1000ULL; in vc4_hdmi_encoder_compute_mode_clock()
1791 if (mode->flags & DRM_MODE_FLAG_DBLCLK) in vc4_hdmi_encoder_compute_mode_clock()
1813 return -EINVAL; in vc4_hdmi_encoder_compute_clock()
1815 vc4_state->tmds_char_rate = clock; in vc4_hdmi_encoder_compute_clock()
1826 struct drm_device *dev = vc4_hdmi->connector.dev; in vc4_hdmi_encoder_compute_format()
1827 const struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_encoder_compute_format()
1828 const struct drm_display_info *info = &connector->display_info; in vc4_hdmi_encoder_compute_format()
1840 vc4_state->output_format = format; in vc4_hdmi_encoder_compute_format()
1854 vc4_state->output_format = format; in vc4_hdmi_encoder_compute_format()
1861 return -EINVAL; in vc4_hdmi_encoder_compute_format()
1869 struct drm_device *dev = vc4_hdmi->connector.dev; in vc4_hdmi_encoder_compute_config()
1870 struct drm_connector_state *conn_state = &vc4_state->base; in vc4_hdmi_encoder_compute_config()
1871 unsigned int max_bpc = clamp_t(unsigned int, conn_state->max_bpc, 8, 12); in vc4_hdmi_encoder_compute_config()
1875 for (bpc = max_bpc; bpc >= 8; bpc -= 2) { in vc4_hdmi_encoder_compute_config()
1883 vc4_state->output_bpc = bpc; in vc4_hdmi_encoder_compute_config()
1887 mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode), in vc4_hdmi_encoder_compute_config()
1888 vc4_state->output_bpc, in vc4_hdmi_encoder_compute_config()
1889 vc4_hdmi_output_fmt_str(vc4_state->output_format), in vc4_hdmi_encoder_compute_config()
1890 vc4_state->tmds_char_rate); in vc4_hdmi_encoder_compute_config()
1906 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_encoder_atomic_check()
1908 drm_atomic_get_old_connector_state(conn_state->state, connector); in vc4_hdmi_encoder_atomic_check()
1912 struct drm_display_mode *mode = &crtc_state->adjusted_mode; in vc4_hdmi_encoder_atomic_check()
1913 unsigned long long tmds_char_rate = mode->clock * 1000; in vc4_hdmi_encoder_atomic_check()
1917 if (vc4_hdmi->variant->unsupported_odd_h_timings) { in vc4_hdmi_encoder_atomic_check()
1918 if (mode->flags & DRM_MODE_FLAG_DBLCLK) { in vc4_hdmi_encoder_atomic_check()
1925 if ((mode->hsync_start - mode->hdisplay) & 1) in vc4_hdmi_encoder_atomic_check()
1926 mode->hsync_start--; in vc4_hdmi_encoder_atomic_check()
1927 if ((mode->hsync_end - mode->hsync_start) & 1) in vc4_hdmi_encoder_atomic_check()
1928 mode->hsync_end--; in vc4_hdmi_encoder_atomic_check()
1932 if ((mode->hdisplay % 2) || (mode->hsync_start % 2) || in vc4_hdmi_encoder_atomic_check()
1933 (mode->hsync_end % 2) || (mode->htotal % 2)) in vc4_hdmi_encoder_atomic_check()
1934 return -EINVAL; in vc4_hdmi_encoder_atomic_check()
1944 if (vc4_hdmi->disable_wifi_frequencies && in vc4_hdmi_encoder_atomic_check()
1947 mode->clock = 238560; in vc4_hdmi_encoder_atomic_check()
1948 tmds_char_rate = mode->clock * 1000; in vc4_hdmi_encoder_atomic_check()
1956 if (vc4_state->output_bpc != old_vc4_state->output_bpc || in vc4_hdmi_encoder_atomic_check()
1957 vc4_state->output_format != old_vc4_state->output_format) in vc4_hdmi_encoder_atomic_check()
1958 crtc_state->mode_changed = true; in vc4_hdmi_encoder_atomic_check()
1969 if (vc4_hdmi->variant->unsupported_odd_h_timings && in vc4_hdmi_encoder_mode_valid()
1970 !(mode->flags & DRM_MODE_FLAG_DBLCLK) && in vc4_hdmi_encoder_mode_valid()
1971 ((mode->hdisplay % 2) || (mode->hsync_start % 2) || in vc4_hdmi_encoder_mode_valid()
1972 (mode->hsync_end % 2) || (mode->htotal % 2))) in vc4_hdmi_encoder_mode_valid()
1975 return vc4_hdmi_encoder_clock_valid(vc4_hdmi, mode->clock * 1000); in vc4_hdmi_encoder_mode_valid()
1986 struct drm_device *drm = encoder->dev; in vc4_hdmi_late_register()
1988 const struct vc4_hdmi_variant *variant = vc4_hdmi->variant; in vc4_hdmi_late_register()
1991 ret = vc4_debugfs_add_file(drm->primary, variant->debugfs_name, in vc4_hdmi_late_register()
2030 struct drm_device *drm = vc4_hdmi->connector.dev; in vc5_hdmi_hp_detect()
2038 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_hp_detect()
2040 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_hp_detect()
2047 /* HDMI audio codec callbacks */
2051 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_audio_set_mai_clock()
2060 hsm_clock = clk_get_rate(vc4_hdmi->audio_clock); in vc4_hdmi_audio_set_mai_clock()
2068 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_set_mai_clock()
2071 VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M)); in vc4_hdmi_audio_set_mai_clock()
2072 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_set_mai_clock()
2079 const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; in vc4_hdmi_set_n_cts()
2083 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_set_n_cts()
2084 lockdep_assert_held(&vc4_hdmi->hw_lock); in vc4_hdmi_set_n_cts()
2087 tmp = (u64)(mode->clock * 1000) * n; in vc4_hdmi_set_n_cts()
2113 struct drm_display_info *display = &vc4_hdmi->connector.display_info; in vc4_hdmi_audio_can_stream()
2115 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_audio_can_stream()
2121 if (!display->is_hdmi) in vc4_hdmi_audio_can_stream()
2130 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_audio_startup()
2135 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_audio_startup()
2138 ret = -ENODEV; in vc4_hdmi_audio_startup()
2143 ret = -ENODEV; in vc4_hdmi_audio_startup()
2147 vc4_hdmi->audio.streaming = true; in vc4_hdmi_audio_startup()
2149 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_startup()
2156 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_startup()
2158 if (vc4_hdmi->variant->phy_rng_enable) in vc4_hdmi_audio_startup()
2159 vc4_hdmi->variant->phy_rng_enable(vc4_hdmi); in vc4_hdmi_audio_startup()
2164 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_audio_startup()
2171 struct drm_encoder *encoder = &vc4_hdmi->encoder.base; in vc4_hdmi_audio_reset()
2172 struct device *dev = &vc4_hdmi->pdev->dev; in vc4_hdmi_audio_reset()
2176 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_audio_reset()
2178 vc4_hdmi->audio.streaming = false; in vc4_hdmi_audio_reset()
2183 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_reset()
2189 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_reset()
2195 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_audio_shutdown()
2199 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_audio_shutdown()
2204 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_shutdown()
2211 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_shutdown()
2213 if (vc4_hdmi->variant->phy_rng_disable) in vc4_hdmi_audio_shutdown()
2214 vc4_hdmi->variant->phy_rng_disable(vc4_hdmi); in vc4_hdmi_audio_shutdown()
2216 vc4_hdmi->audio.streaming = false; in vc4_hdmi_audio_shutdown()
2222 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_audio_shutdown()
2263 /* HDMI audio codec callbacks */
2269 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_audio_prepare()
2270 struct drm_encoder *encoder = &vc4_hdmi->encoder.base; in vc4_hdmi_audio_prepare()
2271 unsigned int sample_rate = params->sample_rate; in vc4_hdmi_audio_prepare()
2272 unsigned int channels = params->channels; in vc4_hdmi_audio_prepare()
2282 sample_rate, params->sample_width, channels); in vc4_hdmi_audio_prepare()
2284 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_audio_prepare()
2287 ret = -ENODEV; in vc4_hdmi_audio_prepare()
2292 ret = -EINVAL; in vc4_hdmi_audio_prepare()
2298 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_prepare()
2306 if (params->iec.status[0] & IEC958_AES0_NONAUDIO && in vc4_hdmi_audio_prepare()
2307 params->channels == 8) in vc4_hdmi_audio_prepare()
2317 /* The B frame identifier should match the value used by alsa-lib (8) */ in vc4_hdmi_audio_prepare()
2323 channel_mask = GENMASK(channels - 1, 0); in vc4_hdmi_audio_prepare()
2339 channel_map = vc4_hdmi->variant->channel_map(vc4_hdmi, channel_mask); in vc4_hdmi_audio_prepare()
2345 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_prepare()
2347 memcpy(&vc4_hdmi->audio.infoframe, &params->cea, sizeof(params->cea)); in vc4_hdmi_audio_prepare()
2353 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_audio_prepare()
2359 .name = "vc4-hdmi-cpu-dai-component",
2367 snd_soc_dai_init_dma_data(dai, &vc4_hdmi->audio.dma_data, NULL); in vc4_hdmi_audio_cpu_dai_probe()
2373 .name = "vc4-hdmi-cpu-dai",
2388 .chan_names[SNDRV_PCM_STREAM_PLAYBACK] = "audio-rx",
2396 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_audio_get_eld()
2398 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_audio_get_eld()
2399 memcpy(buf, connector->eld, min(sizeof(connector->eld), len)); in vc4_hdmi_audio_get_eld()
2400 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_audio_get_eld()
2422 platform_device_unregister(vc4_hdmi->audio.codec_pdev); in vc4_hdmi_audio_codec_release()
2423 vc4_hdmi->audio.codec_pdev = NULL; in vc4_hdmi_audio_codec_release()
2429 &vc4_hdmi->variant->registers[HDMI_MAI_DATA]; in vc4_hdmi_audio_init()
2430 struct snd_soc_dai_link *dai_link = &vc4_hdmi->audio.link; in vc4_hdmi_audio_init()
2431 struct snd_soc_card *card = &vc4_hdmi->audio.card; in vc4_hdmi_audio_init()
2432 struct device *dev = &vc4_hdmi->pdev->dev; in vc4_hdmi_audio_init()
2458 if (!of_find_property(dev->of_node, "dmas", &len) || !len) { in vc4_hdmi_audio_init()
2460 "'dmas' DT property is missing or empty, no HDMI audio\n"); in vc4_hdmi_audio_init()
2464 if (mai_data->reg != VC4_HD) { in vc4_hdmi_audio_init()
2466 return -EINVAL; in vc4_hdmi_audio_init()
2476 index = of_property_match_string(dev->of_node, "reg-names", "hd"); in vc4_hdmi_audio_init()
2477 /* Before BCM2711, we don't have a named register range */ in vc4_hdmi_audio_init()
2481 addr = of_get_address(dev->of_node, index, NULL, NULL); in vc4_hdmi_audio_init()
2483 vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + mai_data->offset; in vc4_hdmi_audio_init()
2484 vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; in vc4_hdmi_audio_init()
2485 vc4_hdmi->audio.dma_data.maxburst = 2; in vc4_hdmi_audio_init()
2488 * NOTE: Strictly speaking, we should probably use a DRM-managed in vc4_hdmi_audio_init()
2493 * when registering, even when using non-device-managed in vc4_hdmi_audio_init()
2496 * If we call snd_soc_unregister_component() in a DRM-managed in vc4_hdmi_audio_init()
2497 * action, the device-managed actions have already been executed in vc4_hdmi_audio_init()
2500 * Using device-managed hooks here probably leaves us open to a in vc4_hdmi_audio_init()
2507 * Then, the vc4_hdmi structure is DRM-managed and thus only in vc4_hdmi_audio_init()
2529 dev_err(dev, "Couldn't register the HDMI codec: %ld\n", PTR_ERR(codec_pdev)); in vc4_hdmi_audio_init()
2532 vc4_hdmi->audio.codec_pdev = codec_pdev; in vc4_hdmi_audio_init()
2538 dai_link->cpus = &vc4_hdmi->audio.cpu; in vc4_hdmi_audio_init()
2539 dai_link->codecs = &vc4_hdmi->audio.codec; in vc4_hdmi_audio_init()
2540 dai_link->platforms = &vc4_hdmi->audio.platform; in vc4_hdmi_audio_init()
2542 dai_link->num_cpus = 1; in vc4_hdmi_audio_init()
2543 dai_link->num_codecs = 1; in vc4_hdmi_audio_init()
2544 dai_link->num_platforms = 1; in vc4_hdmi_audio_init()
2546 dai_link->name = "MAI"; in vc4_hdmi_audio_init()
2547 dai_link->stream_name = "MAI PCM"; in vc4_hdmi_audio_init()
2548 dai_link->codecs->dai_name = "i2s-hifi"; in vc4_hdmi_audio_init()
2549 dai_link->cpus->dai_name = dev_name(dev); in vc4_hdmi_audio_init()
2550 dai_link->codecs->name = dev_name(&codec_pdev->dev); in vc4_hdmi_audio_init()
2551 dai_link->platforms->name = dev_name(dev); in vc4_hdmi_audio_init()
2553 card->dai_link = dai_link; in vc4_hdmi_audio_init()
2554 card->num_links = 1; in vc4_hdmi_audio_init()
2555 card->name = vc4_hdmi->variant->card_name; in vc4_hdmi_audio_init()
2556 card->driver_name = "vc4-hdmi"; in vc4_hdmi_audio_init()
2557 card->dev = dev; in vc4_hdmi_audio_init()
2558 card->owner = THIS_MODULE; in vc4_hdmi_audio_init()
2562 * stores a pointer to the snd card object in dev->driver_data. This in vc4_hdmi_audio_init()
2563 * means we cannot use it for something else. The hdmi back-pointer is in vc4_hdmi_audio_init()
2564 * now stored in card->drvdata and should be retrieved with in vc4_hdmi_audio_init()
2579 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_hpd_irq_thread()
2580 struct drm_device *dev = connector->dev; in vc4_hdmi_hpd_irq_thread()
2582 if (dev && dev->registered) in vc4_hdmi_hpd_irq_thread()
2590 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_hotplug_init()
2591 struct platform_device *pdev = vc4_hdmi->pdev; in vc4_hdmi_hotplug_init()
2594 if (vc4_hdmi->variant->external_irq_controller) { in vc4_hdmi_hotplug_init()
2595 unsigned int hpd_con = platform_get_irq_byname(pdev, "hpd-connected"); in vc4_hdmi_hotplug_init()
2596 unsigned int hpd_rm = platform_get_irq_byname(pdev, "hpd-removed"); in vc4_hdmi_hotplug_init()
2598 ret = devm_request_threaded_irq(&pdev->dev, hpd_con, in vc4_hdmi_hotplug_init()
2601 "vc4 hdmi hpd connected", vc4_hdmi); in vc4_hdmi_hotplug_init()
2605 ret = devm_request_threaded_irq(&pdev->dev, hpd_rm, in vc4_hdmi_hotplug_init()
2608 "vc4 hdmi hpd disconnected", vc4_hdmi); in vc4_hdmi_hotplug_init()
2612 connector->polled = DRM_CONNECTOR_POLL_HPD; in vc4_hdmi_hotplug_init()
2623 if (vc4_hdmi->cec_rx_msg.len) in vc4_cec_irq_handler_rx_thread()
2624 cec_received_msg(vc4_hdmi->cec_adap, in vc4_cec_irq_handler_rx_thread()
2625 &vc4_hdmi->cec_rx_msg); in vc4_cec_irq_handler_rx_thread()
2634 if (vc4_hdmi->cec_tx_ok) { in vc4_cec_irq_handler_tx_thread()
2635 cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_OK, in vc4_cec_irq_handler_tx_thread()
2642 cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_NACK, in vc4_cec_irq_handler_tx_thread()
2653 if (vc4_hdmi->cec_irq_was_rx) in vc4_cec_irq_handler_thread()
2663 struct drm_device *dev = vc4_hdmi->connector.dev; in vc4_cec_read_msg()
2664 struct cec_msg *msg = &vc4_hdmi->cec_rx_msg; in vc4_cec_read_msg()
2667 lockdep_assert_held(&vc4_hdmi->hw_lock); in vc4_cec_read_msg()
2669 msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >> in vc4_cec_read_msg()
2672 if (msg->len > 16) { in vc4_cec_read_msg()
2673 drm_err(dev, "Attempting to read too much data (%d)\n", msg->len); in vc4_cec_read_msg()
2677 for (i = 0; i < msg->len; i += 4) { in vc4_cec_read_msg()
2680 msg->msg[i] = val & 0xff; in vc4_cec_read_msg()
2681 msg->msg[i + 1] = (val >> 8) & 0xff; in vc4_cec_read_msg()
2682 msg->msg[i + 2] = (val >> 16) & 0xff; in vc4_cec_read_msg()
2683 msg->msg[i + 3] = (val >> 24) & 0xff; in vc4_cec_read_msg()
2702 lockdep_assert_held(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler_tx_bare_locked()
2705 vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD; in vc4_cec_irq_handler_tx_bare_locked()
2717 spin_lock(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler_tx_bare()
2719 spin_unlock(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler_tx_bare()
2728 lockdep_assert_held(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler_rx_bare_locked()
2741 vc4_hdmi->cec_rx_msg.len = 0; in vc4_cec_irq_handler_rx_bare_locked()
2758 spin_lock(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler_rx_bare()
2760 spin_unlock(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler_rx_bare()
2786 spin_lock(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler()
2788 vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT; in vc4_cec_irq_handler()
2789 if (vc4_hdmi->cec_irq_was_rx) in vc4_cec_irq_handler()
2795 spin_unlock(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler()
2803 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_cec_enable()
2819 ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); in vc4_hdmi_cec_enable()
2825 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_cec_enable()
2827 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_enable()
2856 if (!vc4_hdmi->variant->external_irq_controller) in vc4_hdmi_cec_enable()
2859 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_enable()
2861 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_cec_enable()
2870 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_cec_disable()
2882 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_cec_disable()
2884 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_disable()
2886 if (!vc4_hdmi->variant->external_irq_controller) in vc4_hdmi_cec_disable()
2892 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_disable()
2894 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_cec_disable()
2896 pm_runtime_put(&vc4_hdmi->pdev->dev); in vc4_hdmi_cec_disable()
2914 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_cec_adap_log_addr()
2926 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_cec_adap_log_addr()
2927 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_adap_log_addr()
2931 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_adap_log_addr()
2932 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_cec_adap_log_addr()
2943 struct drm_device *dev = vc4_hdmi->connector.dev; in vc4_hdmi_cec_adap_transmit()
2950 return -ENODEV; in vc4_hdmi_cec_adap_transmit()
2952 if (msg->len > 16) { in vc4_hdmi_cec_adap_transmit()
2953 drm_err(dev, "Attempting to transmit too much data (%d)\n", msg->len); in vc4_hdmi_cec_adap_transmit()
2955 return -ENOMEM; in vc4_hdmi_cec_adap_transmit()
2958 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_cec_adap_transmit()
2960 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_adap_transmit()
2962 for (i = 0; i < msg->len; i += 4) in vc4_hdmi_cec_adap_transmit()
2964 (msg->msg[i]) | in vc4_hdmi_cec_adap_transmit()
2965 (msg->msg[i + 1] << 8) | in vc4_hdmi_cec_adap_transmit()
2966 (msg->msg[i + 2] << 16) | in vc4_hdmi_cec_adap_transmit()
2967 (msg->msg[i + 3] << 24)); in vc4_hdmi_cec_adap_transmit()
2973 val |= (msg->len - 1) << VC4_HDMI_CEC_MESSAGE_LENGTH_SHIFT; in vc4_hdmi_cec_adap_transmit()
2978 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_adap_transmit()
2979 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_cec_adap_transmit()
2995 cec_unregister_adapter(vc4_hdmi->cec_adap); in vc4_hdmi_cec_release()
2996 vc4_hdmi->cec_adap = NULL; in vc4_hdmi_cec_release()
3002 struct platform_device *pdev = vc4_hdmi->pdev; in vc4_hdmi_cec_init()
3003 struct device *dev = &pdev->dev; in vc4_hdmi_cec_init()
3006 if (!of_find_property(dev->of_node, "interrupts", NULL)) { in vc4_hdmi_cec_init()
3011 vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops, in vc4_hdmi_cec_init()
3015 ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap); in vc4_hdmi_cec_init()
3019 cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector); in vc4_hdmi_cec_init()
3020 cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info); in vc4_hdmi_cec_init()
3022 if (vc4_hdmi->variant->external_irq_controller) { in vc4_hdmi_cec_init()
3023 ret = devm_request_threaded_irq(dev, platform_get_irq_byname(pdev, "cec-rx"), in vc4_hdmi_cec_init()
3026 "vc4 hdmi cec rx", vc4_hdmi); in vc4_hdmi_cec_init()
3030 ret = devm_request_threaded_irq(dev, platform_get_irq_byname(pdev, "cec-tx"), in vc4_hdmi_cec_init()
3033 "vc4 hdmi cec tx", vc4_hdmi); in vc4_hdmi_cec_init()
3040 "vc4 hdmi cec", vc4_hdmi); in vc4_hdmi_cec_init()
3045 ret = cec_register_adapter(vc4_hdmi->cec_adap, &pdev->dev); in vc4_hdmi_cec_init()
3050 * NOTE: Strictly speaking, we should probably use a DRM-managed in vc4_hdmi_cec_init()
3058 * By the time the device-managed hook is executed, we will give in vc4_hdmi_cec_init()
3067 * used to be our HDMI controller. If we get a CEC call at that in vc4_hdmi_cec_init()
3068 * moment, we could end up with a use-after-free. Fortunately, in vc4_hdmi_cec_init()
3079 cec_delete_adapter(vc4_hdmi->cec_adap); in vc4_hdmi_cec_init()
3102 const struct vc4_hdmi_variant *variant = vc4_hdmi->variant; in vc4_hdmi_build_regset()
3108 regs = kcalloc(variant->num_registers, sizeof(*regs), in vc4_hdmi_build_regset()
3111 return -ENOMEM; in vc4_hdmi_build_regset()
3113 for (i = 0; i < variant->num_registers; i++) { in vc4_hdmi_build_regset()
3114 const struct vc4_hdmi_register *field = &variant->registers[i]; in vc4_hdmi_build_regset()
3116 if (field->reg != reg) in vc4_hdmi_build_regset()
3119 regs[count].name = field->name; in vc4_hdmi_build_regset()
3120 regs[count].offset = field->offset; in vc4_hdmi_build_regset()
3126 return -ENOMEM; in vc4_hdmi_build_regset()
3128 regset->base = __vc4_hdmi_get_field_base(vc4_hdmi, reg); in vc4_hdmi_build_regset()
3129 regset->regs = new_regs; in vc4_hdmi_build_regset()
3130 regset->nregs = count; in vc4_hdmi_build_regset()
3142 struct platform_device *pdev = vc4_hdmi->pdev; in vc4_hdmi_init_resources()
3143 struct device *dev = &pdev->dev; in vc4_hdmi_init_resources()
3146 vc4_hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0); in vc4_hdmi_init_resources()
3147 if (IS_ERR(vc4_hdmi->hdmicore_regs)) in vc4_hdmi_init_resources()
3148 return PTR_ERR(vc4_hdmi->hdmicore_regs); in vc4_hdmi_init_resources()
3150 vc4_hdmi->hd_regs = vc4_ioremap_regs(pdev, 1); in vc4_hdmi_init_resources()
3151 if (IS_ERR(vc4_hdmi->hd_regs)) in vc4_hdmi_init_resources()
3152 return PTR_ERR(vc4_hdmi->hd_regs); in vc4_hdmi_init_resources()
3154 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD); in vc4_hdmi_init_resources()
3158 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI); in vc4_hdmi_init_resources()
3162 vc4_hdmi->pixel_clock = devm_clk_get(dev, "pixel"); in vc4_hdmi_init_resources()
3163 if (IS_ERR(vc4_hdmi->pixel_clock)) { in vc4_hdmi_init_resources()
3164 ret = PTR_ERR(vc4_hdmi->pixel_clock); in vc4_hdmi_init_resources()
3165 if (ret != -EPROBE_DEFER) in vc4_hdmi_init_resources()
3170 vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi"); in vc4_hdmi_init_resources()
3171 if (IS_ERR(vc4_hdmi->hsm_clock)) { in vc4_hdmi_init_resources()
3172 DRM_ERROR("Failed to get HDMI state machine clock\n"); in vc4_hdmi_init_resources()
3173 return PTR_ERR(vc4_hdmi->hsm_clock); in vc4_hdmi_init_resources()
3176 vc4_hdmi->audio_clock = vc4_hdmi->hsm_clock; in vc4_hdmi_init_resources()
3177 vc4_hdmi->cec_clock = vc4_hdmi->hsm_clock; in vc4_hdmi_init_resources()
3179 vc4_hdmi->hsm_rpm_clock = devm_clk_get(dev, "hdmi"); in vc4_hdmi_init_resources()
3180 if (IS_ERR(vc4_hdmi->hsm_rpm_clock)) { in vc4_hdmi_init_resources()
3181 DRM_ERROR("Failed to get HDMI state machine clock\n"); in vc4_hdmi_init_resources()
3182 return PTR_ERR(vc4_hdmi->hsm_rpm_clock); in vc4_hdmi_init_resources()
3191 struct platform_device *pdev = vc4_hdmi->pdev; in vc5_hdmi_init_resources()
3192 struct device *dev = &pdev->dev; in vc5_hdmi_init_resources()
3196 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi"); in vc5_hdmi_init_resources()
3198 return -ENODEV; in vc5_hdmi_init_resources()
3200 vc4_hdmi->hdmicore_regs = devm_ioremap(dev, res->start, in vc5_hdmi_init_resources()
3202 if (!vc4_hdmi->hdmicore_regs) in vc5_hdmi_init_resources()
3203 return -ENOMEM; in vc5_hdmi_init_resources()
3207 return -ENODEV; in vc5_hdmi_init_resources()
3209 vc4_hdmi->hd_regs = devm_ioremap(dev, res->start, resource_size(res)); in vc5_hdmi_init_resources()
3210 if (!vc4_hdmi->hd_regs) in vc5_hdmi_init_resources()
3211 return -ENOMEM; in vc5_hdmi_init_resources()
3215 return -ENODEV; in vc5_hdmi_init_resources()
3217 vc4_hdmi->cec_regs = devm_ioremap(dev, res->start, resource_size(res)); in vc5_hdmi_init_resources()
3218 if (!vc4_hdmi->cec_regs) in vc5_hdmi_init_resources()
3219 return -ENOMEM; in vc5_hdmi_init_resources()
3223 return -ENODEV; in vc5_hdmi_init_resources()
3225 vc4_hdmi->csc_regs = devm_ioremap(dev, res->start, resource_size(res)); in vc5_hdmi_init_resources()
3226 if (!vc4_hdmi->csc_regs) in vc5_hdmi_init_resources()
3227 return -ENOMEM; in vc5_hdmi_init_resources()
3231 return -ENODEV; in vc5_hdmi_init_resources()
3233 vc4_hdmi->dvp_regs = devm_ioremap(dev, res->start, resource_size(res)); in vc5_hdmi_init_resources()
3234 if (!vc4_hdmi->dvp_regs) in vc5_hdmi_init_resources()
3235 return -ENOMEM; in vc5_hdmi_init_resources()
3239 return -ENODEV; in vc5_hdmi_init_resources()
3241 vc4_hdmi->phy_regs = devm_ioremap(dev, res->start, resource_size(res)); in vc5_hdmi_init_resources()
3242 if (!vc4_hdmi->phy_regs) in vc5_hdmi_init_resources()
3243 return -ENOMEM; in vc5_hdmi_init_resources()
3247 return -ENODEV; in vc5_hdmi_init_resources()
3249 vc4_hdmi->ram_regs = devm_ioremap(dev, res->start, resource_size(res)); in vc5_hdmi_init_resources()
3250 if (!vc4_hdmi->ram_regs) in vc5_hdmi_init_resources()
3251 return -ENOMEM; in vc5_hdmi_init_resources()
3255 return -ENODEV; in vc5_hdmi_init_resources()
3257 vc4_hdmi->rm_regs = devm_ioremap(dev, res->start, resource_size(res)); in vc5_hdmi_init_resources()
3258 if (!vc4_hdmi->rm_regs) in vc5_hdmi_init_resources()
3259 return -ENOMEM; in vc5_hdmi_init_resources()
3261 vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi"); in vc5_hdmi_init_resources()
3262 if (IS_ERR(vc4_hdmi->hsm_clock)) { in vc5_hdmi_init_resources()
3263 DRM_ERROR("Failed to get HDMI state machine clock\n"); in vc5_hdmi_init_resources()
3264 return PTR_ERR(vc4_hdmi->hsm_clock); in vc5_hdmi_init_resources()
3267 vc4_hdmi->hsm_rpm_clock = devm_clk_get(dev, "hdmi"); in vc5_hdmi_init_resources()
3268 if (IS_ERR(vc4_hdmi->hsm_rpm_clock)) { in vc5_hdmi_init_resources()
3269 DRM_ERROR("Failed to get HDMI state machine clock\n"); in vc5_hdmi_init_resources()
3270 return PTR_ERR(vc4_hdmi->hsm_rpm_clock); in vc5_hdmi_init_resources()
3273 vc4_hdmi->pixel_bvb_clock = devm_clk_get(dev, "bvb"); in vc5_hdmi_init_resources()
3274 if (IS_ERR(vc4_hdmi->pixel_bvb_clock)) { in vc5_hdmi_init_resources()
3276 return PTR_ERR(vc4_hdmi->pixel_bvb_clock); in vc5_hdmi_init_resources()
3279 vc4_hdmi->audio_clock = devm_clk_get(dev, "audio"); in vc5_hdmi_init_resources()
3280 if (IS_ERR(vc4_hdmi->audio_clock)) { in vc5_hdmi_init_resources()
3282 return PTR_ERR(vc4_hdmi->audio_clock); in vc5_hdmi_init_resources()
3285 vc4_hdmi->cec_clock = devm_clk_get(dev, "cec"); in vc5_hdmi_init_resources()
3286 if (IS_ERR(vc4_hdmi->cec_clock)) { in vc5_hdmi_init_resources()
3288 return PTR_ERR(vc4_hdmi->cec_clock); in vc5_hdmi_init_resources()
3291 vc4_hdmi->reset = devm_reset_control_get(dev, NULL); in vc5_hdmi_init_resources()
3292 if (IS_ERR(vc4_hdmi->reset)) { in vc5_hdmi_init_resources()
3293 DRM_ERROR("Failed to get HDMI reset line\n"); in vc5_hdmi_init_resources()
3294 return PTR_ERR(vc4_hdmi->reset); in vc5_hdmi_init_resources()
3297 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI); in vc5_hdmi_init_resources()
3301 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD); in vc5_hdmi_init_resources()
3305 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->cec_regset, VC5_CEC); in vc5_hdmi_init_resources()
3309 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->csc_regset, VC5_CSC); in vc5_hdmi_init_resources()
3313 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->dvp_regset, VC5_DVP); in vc5_hdmi_init_resources()
3317 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->phy_regset, VC5_PHY); in vc5_hdmi_init_resources()
3321 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->ram_regset, VC5_RAM); in vc5_hdmi_init_resources()
3325 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->rm_regset, VC5_RM); in vc5_hdmi_init_resources()
3336 clk_disable_unprepare(vc4_hdmi->hsm_rpm_clock); in vc4_hdmi_runtime_suspend()
3350 * The HSM clock is in the HDMI power domain, so we need to set in vc4_hdmi_runtime_resume()
3354 ret = clk_set_min_rate(vc4_hdmi->hsm_rpm_clock, HSM_MIN_CLOCK_FREQ); in vc4_hdmi_runtime_resume()
3358 ret = clk_prepare_enable(vc4_hdmi->hsm_rpm_clock); in vc4_hdmi_runtime_resume()
3363 * Whenever the RaspberryPi boots without an HDMI monitor in vc4_hdmi_runtime_resume()
3371 rate = clk_get_rate(vc4_hdmi->hsm_rpm_clock); in vc4_hdmi_runtime_resume()
3373 ret = -EINVAL; in vc4_hdmi_runtime_resume()
3377 if (vc4_hdmi->variant->reset) in vc4_hdmi_runtime_resume()
3378 vc4_hdmi->variant->reset(vc4_hdmi); in vc4_hdmi_runtime_resume()
3381 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_runtime_resume()
3386 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_runtime_resume()
3390 if (!vc4_hdmi->variant->external_irq_controller) { in vc4_hdmi_runtime_resume()
3391 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_runtime_resume()
3393 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_runtime_resume()
3400 clk_disable_unprepare(vc4_hdmi->hsm_clock); in vc4_hdmi_runtime_resume()
3408 put_device(&vc4_hdmi->ddc->dev); in vc4_hdmi_put_ddc_device()
3423 return -ENOMEM; in vc4_hdmi_bind()
3425 ret = drmm_mutex_init(drm, &vc4_hdmi->mutex); in vc4_hdmi_bind()
3429 spin_lock_init(&vc4_hdmi->hw_lock); in vc4_hdmi_bind()
3430 INIT_DELAYED_WORK(&vc4_hdmi->scrambling_work, vc4_hdmi_scrambling_wq); in vc4_hdmi_bind()
3433 encoder = &vc4_hdmi->encoder.base; in vc4_hdmi_bind()
3434 vc4_hdmi->encoder.type = variant->encoder_type; in vc4_hdmi_bind()
3435 vc4_hdmi->encoder.pre_crtc_configure = vc4_hdmi_encoder_pre_crtc_configure; in vc4_hdmi_bind()
3436 vc4_hdmi->encoder.pre_crtc_enable = vc4_hdmi_encoder_pre_crtc_enable; in vc4_hdmi_bind()
3437 vc4_hdmi->encoder.post_crtc_enable = vc4_hdmi_encoder_post_crtc_enable; in vc4_hdmi_bind()
3438 vc4_hdmi->encoder.post_crtc_disable = vc4_hdmi_encoder_post_crtc_disable; in vc4_hdmi_bind()
3439 vc4_hdmi->encoder.post_crtc_powerdown = vc4_hdmi_encoder_post_crtc_powerdown; in vc4_hdmi_bind()
3440 vc4_hdmi->pdev = pdev; in vc4_hdmi_bind()
3441 vc4_hdmi->variant = variant; in vc4_hdmi_bind()
3449 if (variant->max_pixel_clock > HDMI_14_MAX_TMDS_CLK) in vc4_hdmi_bind()
3450 vc4_hdmi->scdc_enabled = true; in vc4_hdmi_bind()
3452 ret = variant->init_resources(drm, vc4_hdmi); in vc4_hdmi_bind()
3456 ddc_node = of_parse_phandle(dev->of_node, "ddc", 0); in vc4_hdmi_bind()
3459 return -ENODEV; in vc4_hdmi_bind()
3462 vc4_hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node); in vc4_hdmi_bind()
3464 if (!vc4_hdmi->ddc) { in vc4_hdmi_bind()
3465 DRM_DEBUG("Failed to get ddc i2c adapter by node\n"); in vc4_hdmi_bind()
3466 return -EPROBE_DEFER; in vc4_hdmi_bind()
3474 * we'll use the HDMI core's register. in vc4_hdmi_bind()
3476 vc4_hdmi->hpd_gpio = devm_gpiod_get_optional(dev, "hpd", GPIOD_IN); in vc4_hdmi_bind()
3477 if (IS_ERR(vc4_hdmi->hpd_gpio)) { in vc4_hdmi_bind()
3478 return PTR_ERR(vc4_hdmi->hpd_gpio); in vc4_hdmi_bind()
3481 vc4_hdmi->disable_wifi_frequencies = in vc4_hdmi_bind()
3482 of_property_read_bool(dev->of_node, "wifi-2.4ghz-coexistence"); in vc4_hdmi_bind()
3484 if (variant->max_pixel_clock == 600000000) { in vc4_hdmi_bind()
3486 long max_rate = clk_round_rate(vc4->hvs->core_clk, 550000000); in vc4_hdmi_bind()
3489 vc4_hdmi->disable_4kp60 = true; in vc4_hdmi_bind()
3504 if ((of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi0") || in vc4_hdmi_bind()
3505 of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi1")) && in vc4_hdmi_bind()
3507 clk_prepare_enable(vc4_hdmi->pixel_clock); in vc4_hdmi_bind()
3508 clk_prepare_enable(vc4_hdmi->hsm_clock); in vc4_hdmi_bind()
3509 clk_prepare_enable(vc4_hdmi->pixel_bvb_clock); in vc4_hdmi_bind()
3553 return component_add(&pdev->dev, &vc4_hdmi_ops); in vc4_hdmi_dev_probe()
3558 component_del(&pdev->dev, &vc4_hdmi_ops); in vc4_hdmi_dev_remove()
3565 .card_name = "vc4-hdmi",
3585 .card_name = "vc4-hdmi-0",
3614 .card_name = "vc4-hdmi-1",
3641 { .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant },
3642 { .compatible = "brcm,bcm2711-hdmi0", .data = &bcm2711_hdmi0_variant },
3643 { .compatible = "brcm,bcm2711-hdmi1", .data = &bcm2711_hdmi1_variant },