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
50 #include <sound/hdmi-codec.h>
133 struct drm_display_info *display = &vc4_hdmi->connector.display_info; in vc4_hdmi_supports_scrambling()
135 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_supports_scrambling()
137 if (!display->is_hdmi) in vc4_hdmi_supports_scrambling()
140 if (!display->hdmi.scdc.supported || in vc4_hdmi_supports_scrambling()
141 !display->hdmi.scdc.scrambling.supported) in vc4_hdmi_supports_scrambling()
159 const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; in vc4_hdmi_is_full_range()
160 struct drm_display_info *display = &vc4_hdmi->connector.display_info; in vc4_hdmi_is_full_range()
162 if (vc4_state->broadcast_rgb == VC4_HDMI_BROADCAST_RGB_LIMITED) in vc4_hdmi_is_full_range()
164 else if (vc4_state->broadcast_rgb == VC4_HDMI_BROADCAST_RGB_FULL) in vc4_hdmi_is_full_range()
167 return !display->is_hdmi || in vc4_hdmi_is_full_range()
173 struct drm_debugfs_entry *entry = m->private; in vc4_hdmi_debugfs_regs()
174 struct vc4_hdmi *vc4_hdmi = entry->file.data; in vc4_hdmi_debugfs_regs()
175 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_debugfs_regs()
180 return -ENODEV; in vc4_hdmi_debugfs_regs()
182 drm_print_regset32(&p, &vc4_hdmi->hdmi_regset); in vc4_hdmi_debugfs_regs()
183 drm_print_regset32(&p, &vc4_hdmi->hd_regset); in vc4_hdmi_debugfs_regs()
184 drm_print_regset32(&p, &vc4_hdmi->cec_regset); in vc4_hdmi_debugfs_regs()
185 drm_print_regset32(&p, &vc4_hdmi->csc_regset); in vc4_hdmi_debugfs_regs()
186 drm_print_regset32(&p, &vc4_hdmi->dvp_regset); in vc4_hdmi_debugfs_regs()
187 drm_print_regset32(&p, &vc4_hdmi->phy_regset); in vc4_hdmi_debugfs_regs()
188 drm_print_regset32(&p, &vc4_hdmi->ram_regset); in vc4_hdmi_debugfs_regs()
189 drm_print_regset32(&p, &vc4_hdmi->rm_regset); in vc4_hdmi_debugfs_regs()
198 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_reset()
204 * connector->dev pointer might not be initialised yet. in vc4_hdmi_reset()
209 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_reset()
223 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_reset()
231 struct drm_device *drm = vc4_hdmi->connector.dev; in vc5_hdmi_reset()
237 * connector->dev pointer might not be initialised yet. in vc5_hdmi_reset()
242 reset_control_reset(vc4_hdmi->reset); in vc5_hdmi_reset()
244 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_reset()
251 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_reset()
260 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_cec_update_clk_div()
270 * connector yet and thus don't have a pointer to the DRM in vc4_hdmi_cec_update_clk_div()
276 cec_rate = clk_get_rate(vc4_hdmi->cec_clock); in vc4_hdmi_cec_update_clk_div()
278 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_update_clk_div()
291 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_update_clk_div()
307 state = drm_atomic_state_alloc(crtc->dev); in reset_pipe()
309 return -ENOMEM; in reset_pipe()
311 state->acquire_ctx = ctx; in reset_pipe()
319 crtc_state->connectors_changed = true; in reset_pipe()
328 static int vc4_hdmi_reset_link(struct drm_connector *connector, in vc4_hdmi_reset_link() argument
340 if (!connector) in vc4_hdmi_reset_link()
343 drm = connector->dev; in vc4_hdmi_reset_link()
344 ret = drm_modeset_lock(&drm->mode_config.connection_mutex, ctx); in vc4_hdmi_reset_link()
348 conn_state = connector->state; in vc4_hdmi_reset_link()
349 crtc = conn_state->crtc; in vc4_hdmi_reset_link()
353 ret = drm_modeset_lock(&crtc->mutex, ctx); in vc4_hdmi_reset_link()
357 crtc_state = crtc->state; in vc4_hdmi_reset_link()
358 if (!crtc_state->active) in vc4_hdmi_reset_link()
361 vc4_hdmi = connector_to_vc4_hdmi(connector); in vc4_hdmi_reset_link()
362 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_reset_link()
365 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_reset_link()
369 scrambling_needed = vc4_hdmi_mode_needs_scrambling(&vc4_hdmi->saved_adjusted_mode, in vc4_hdmi_reset_link()
370 vc4_hdmi->output_bpc, in vc4_hdmi_reset_link()
371 vc4_hdmi->output_format); in vc4_hdmi_reset_link()
373 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_reset_link()
377 if (conn_state->commit && in vc4_hdmi_reset_link()
378 !try_wait_for_completion(&conn_state->commit->hw_done)) { in vc4_hdmi_reset_link()
379 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_reset_link()
383 ret = drm_scdc_readb(connector->ddc, SCDC_TMDS_CONFIG, &config); in vc4_hdmi_reset_link()
386 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_reset_link()
391 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_reset_link()
395 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_reset_link()
398 * HDMI 2.0 says that one should not send scrambled data in vc4_hdmi_reset_link()
413 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_handle_hotplug() local
419 * vc4_hdmi->mutex held, but doing so results in reentrancy in vc4_hdmi_handle_hotplug()
433 cec_phys_addr_invalidate(vc4_hdmi->cec_adap); in vc4_hdmi_handle_hotplug()
437 edid = drm_get_edid(connector, vc4_hdmi->ddc); in vc4_hdmi_handle_hotplug()
441 cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid); in vc4_hdmi_handle_hotplug()
445 ret = vc4_hdmi_reset_link(connector, ctx); in vc4_hdmi_handle_hotplug()
446 if (ret == -EDEADLK) { in vc4_hdmi_handle_hotplug()
455 static int vc4_hdmi_connector_detect_ctx(struct drm_connector *connector, in vc4_hdmi_connector_detect_ctx() argument
459 struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); in vc4_hdmi_connector_detect_ctx()
463 * NOTE: This function should really take vc4_hdmi->mutex, but in vc4_hdmi_connector_detect_ctx()
473 WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev)); in vc4_hdmi_connector_detect_ctx()
475 if (vc4_hdmi->hpd_gpio) { in vc4_hdmi_connector_detect_ctx()
476 if (gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio)) in vc4_hdmi_connector_detect_ctx()
479 if (vc4_hdmi->variant->hp_detect && in vc4_hdmi_connector_detect_ctx()
480 vc4_hdmi->variant->hp_detect(vc4_hdmi)) in vc4_hdmi_connector_detect_ctx()
485 pm_runtime_put(&vc4_hdmi->pdev->dev); in vc4_hdmi_connector_detect_ctx()
490 static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) in vc4_hdmi_connector_get_modes() argument
492 struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); in vc4_hdmi_connector_get_modes()
493 struct vc4_dev *vc4 = to_vc4_dev(connector->dev); in vc4_hdmi_connector_get_modes()
498 * NOTE: This function should really take vc4_hdmi->mutex, but in vc4_hdmi_connector_get_modes()
508 edid = drm_get_edid(connector, vc4_hdmi->ddc); in vc4_hdmi_connector_get_modes()
509 cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid); in vc4_hdmi_connector_get_modes()
511 return -ENODEV; in vc4_hdmi_connector_get_modes()
513 drm_connector_update_edid_property(connector, edid); in vc4_hdmi_connector_get_modes()
514 ret = drm_add_edid_modes(connector, edid); in vc4_hdmi_connector_get_modes()
517 if (!vc4->hvs->vc5_hdmi_enable_hdmi_20) { in vc4_hdmi_connector_get_modes()
518 struct drm_device *drm = connector->dev; in vc4_hdmi_connector_get_modes()
521 list_for_each_entry(mode, &connector->probed_modes, head) { in vc4_hdmi_connector_get_modes()
532 static int vc4_hdmi_connector_atomic_check(struct drm_connector *connector, in vc4_hdmi_connector_atomic_check() argument
536 drm_atomic_get_old_connector_state(state, connector); in vc4_hdmi_connector_atomic_check()
540 drm_atomic_get_new_connector_state(state, connector); in vc4_hdmi_connector_atomic_check()
543 struct drm_crtc *crtc = new_state->crtc; in vc4_hdmi_connector_atomic_check()
548 if (old_state->tv.margins.left != new_state->tv.margins.left || in vc4_hdmi_connector_atomic_check()
549 old_state->tv.margins.right != new_state->tv.margins.right || in vc4_hdmi_connector_atomic_check()
550 old_state->tv.margins.top != new_state->tv.margins.top || in vc4_hdmi_connector_atomic_check()
551 old_state->tv.margins.bottom != new_state->tv.margins.bottom) { in vc4_hdmi_connector_atomic_check()
563 * connector atomic_check is called as part of in vc4_hdmi_connector_atomic_check()
574 if (old_state->colorspace != new_state->colorspace || in vc4_hdmi_connector_atomic_check()
575 old_vc4_state->broadcast_rgb != new_vc4_state->broadcast_rgb || in vc4_hdmi_connector_atomic_check()
583 crtc_state->mode_changed = true; in vc4_hdmi_connector_atomic_check()
589 static int vc4_hdmi_connector_get_property(struct drm_connector *connector, in vc4_hdmi_connector_get_property() argument
594 struct drm_device *drm = connector->dev; in vc4_hdmi_connector_get_property()
596 connector_to_vc4_hdmi(connector); in vc4_hdmi_connector_get_property()
600 if (property == vc4_hdmi->broadcast_rgb_property) { in vc4_hdmi_connector_get_property()
601 *val = vc4_conn_state->broadcast_rgb; in vc4_hdmi_connector_get_property()
604 property->base.id, property->name); in vc4_hdmi_connector_get_property()
605 return -EINVAL; in vc4_hdmi_connector_get_property()
611 static int vc4_hdmi_connector_set_property(struct drm_connector *connector, in vc4_hdmi_connector_set_property() argument
616 struct drm_device *drm = connector->dev; in vc4_hdmi_connector_set_property()
618 connector_to_vc4_hdmi(connector); in vc4_hdmi_connector_set_property()
622 if (property == vc4_hdmi->broadcast_rgb_property) { in vc4_hdmi_connector_set_property()
623 vc4_conn_state->broadcast_rgb = val; in vc4_hdmi_connector_set_property()
628 property->base.id, property->name); in vc4_hdmi_connector_set_property()
629 return -EINVAL; in vc4_hdmi_connector_set_property()
632 static void vc4_hdmi_connector_reset(struct drm_connector *connector) in vc4_hdmi_connector_reset() argument
635 conn_state_to_vc4_hdmi_conn_state(connector->state); in vc4_hdmi_connector_reset()
639 if (connector->state) in vc4_hdmi_connector_reset()
640 __drm_atomic_helper_connector_destroy_state(connector->state); in vc4_hdmi_connector_reset()
643 __drm_atomic_helper_connector_reset(connector, &new_state->base); in vc4_hdmi_connector_reset()
648 new_state->base.max_bpc = 8; in vc4_hdmi_connector_reset()
649 new_state->base.max_requested_bpc = 8; in vc4_hdmi_connector_reset()
650 new_state->output_format = VC4_HDMI_OUTPUT_RGB; in vc4_hdmi_connector_reset()
651 new_state->broadcast_rgb = VC4_HDMI_BROADCAST_RGB_AUTO; in vc4_hdmi_connector_reset()
652 drm_atomic_helper_connector_tv_margins_reset(connector); in vc4_hdmi_connector_reset()
656 vc4_hdmi_connector_duplicate_state(struct drm_connector *connector) in vc4_hdmi_connector_duplicate_state() argument
658 struct drm_connector_state *conn_state = connector->state; in vc4_hdmi_connector_duplicate_state()
666 new_state->tmds_char_rate = vc4_state->tmds_char_rate; in vc4_hdmi_connector_duplicate_state()
667 new_state->output_bpc = vc4_state->output_bpc; in vc4_hdmi_connector_duplicate_state()
668 new_state->output_format = vc4_state->output_format; in vc4_hdmi_connector_duplicate_state()
669 new_state->broadcast_rgb = vc4_state->broadcast_rgb; in vc4_hdmi_connector_duplicate_state()
670 __drm_atomic_helper_connector_duplicate_state(connector, &new_state->base); in vc4_hdmi_connector_duplicate_state()
672 return &new_state->base; in vc4_hdmi_connector_duplicate_state()
675 static void vc4_hdmi_connector_destroy_state(struct drm_connector *connector, in vc4_hdmi_connector_destroy_state() argument
710 struct drm_property *prop = vc4_hdmi->broadcast_rgb_property; in vc4_hdmi_attach_broadcast_rgb_property()
720 vc4_hdmi->broadcast_rgb_property = prop; in vc4_hdmi_attach_broadcast_rgb_property()
723 drm_object_attach_property(&vc4_hdmi->connector.base, prop, in vc4_hdmi_attach_broadcast_rgb_property()
730 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_connector_init() local
731 struct drm_encoder *encoder = &vc4_hdmi->encoder.base; in vc4_hdmi_connector_init()
734 ret = drmm_connector_init(dev, connector, in vc4_hdmi_connector_init()
737 vc4_hdmi->ddc); in vc4_hdmi_connector_init()
741 drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs); in vc4_hdmi_connector_init()
745 * Allocate some default initial connector state with our reset helper. in vc4_hdmi_connector_init()
747 if (connector->funcs->reset) in vc4_hdmi_connector_init()
748 connector->funcs->reset(connector); in vc4_hdmi_connector_init()
750 /* Create and attach TV margin props to this connector. */ in vc4_hdmi_connector_init()
755 ret = drm_mode_create_hdmi_colorspace_property(connector, 0); in vc4_hdmi_connector_init()
759 drm_connector_attach_colorspace_property(connector); in vc4_hdmi_connector_init()
760 drm_connector_attach_tv_margin_properties(connector); in vc4_hdmi_connector_init()
761 drm_connector_attach_max_bpc_property(connector, 8, 12); in vc4_hdmi_connector_init()
763 connector->polled = (DRM_CONNECTOR_POLL_CONNECT | in vc4_hdmi_connector_init()
766 connector->interlace_allowed = 1; in vc4_hdmi_connector_init()
767 connector->doublescan_allowed = 0; in vc4_hdmi_connector_init()
768 connector->stereo_allowed = 1; in vc4_hdmi_connector_init()
770 if (vc4_hdmi->variant->supports_hdr) in vc4_hdmi_connector_init()
771 drm_connector_attach_hdr_output_metadata_property(connector); in vc4_hdmi_connector_init()
775 drm_connector_attach_encoder(connector, encoder); in vc4_hdmi_connector_init()
785 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_stop_packet()
786 u32 packet_id = type - 0x80; in vc4_hdmi_stop_packet()
792 return -ENODEV; in vc4_hdmi_stop_packet()
794 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_stop_packet()
797 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_stop_packet()
812 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_write_infoframe()
813 u32 packet_id = frame->any.type - 0x80; in vc4_hdmi_write_infoframe()
815 &vc4_hdmi->variant->registers[HDMI_RAM_PACKET_START]; in vc4_hdmi_write_infoframe()
816 u32 packet_reg = ram_packet_start->offset + VC4_HDMI_PACKET_STRIDE * packet_id; in vc4_hdmi_write_infoframe()
817 u32 packet_reg_next = ram_packet_start->offset + in vc4_hdmi_write_infoframe()
820 ram_packet_start->reg); in vc4_hdmi_write_infoframe()
838 ret = vc4_hdmi_stop_packet(encoder, frame->any.type, true); in vc4_hdmi_write_infoframe()
844 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_write_infoframe()
863 * infoframe and triggers a checksum error on hdmi analyser in vc4_hdmi_write_infoframe()
871 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_write_infoframe()
887 frame->colorspace = HDMI_COLORSPACE_RGB; in vc4_hdmi_avi_infoframe_colorspace()
891 frame->colorspace = HDMI_COLORSPACE_YUV420; in vc4_hdmi_avi_infoframe_colorspace()
895 frame->colorspace = HDMI_COLORSPACE_YUV422; in vc4_hdmi_avi_infoframe_colorspace()
899 frame->colorspace = HDMI_COLORSPACE_YUV444; in vc4_hdmi_avi_infoframe_colorspace()
910 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_set_avi_infoframe() local
911 struct drm_connector_state *cstate = connector->state; in vc4_hdmi_set_avi_infoframe()
914 const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; in vc4_hdmi_set_avi_infoframe()
918 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_set_avi_infoframe()
921 connector, mode); in vc4_hdmi_set_avi_infoframe()
928 connector, mode, in vc4_hdmi_set_avi_infoframe()
933 vc4_hdmi_avi_infoframe_colorspace(&frame.avi, vc4_state->output_format); in vc4_hdmi_set_avi_infoframe()
958 struct hdmi_audio_infoframe *audio = &vc4_hdmi->audio.infoframe; in vc4_hdmi_set_audio_infoframe()
963 if (vc4_hdmi->packet_ram_enabled) in vc4_hdmi_set_audio_infoframe()
970 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_set_hdr_infoframe() local
971 struct drm_connector_state *conn_state = connector->state; in vc4_hdmi_set_hdr_infoframe()
974 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_set_hdr_infoframe()
976 if (!vc4_hdmi->variant->supports_hdr) in vc4_hdmi_set_hdr_infoframe()
979 if (!conn_state->hdr_output_metadata) in vc4_hdmi_set_hdr_infoframe()
992 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_set_infoframes()
1000 if (vc4_hdmi->audio.streaming) in vc4_hdmi_set_infoframes()
1011 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_enable_scrambling() local
1012 struct drm_device *drm = connector->dev; in vc4_hdmi_enable_scrambling()
1013 const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; in vc4_hdmi_enable_scrambling()
1017 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_enable_scrambling()
1023 vc4_hdmi->output_bpc, in vc4_hdmi_enable_scrambling()
1024 vc4_hdmi->output_format)) in vc4_hdmi_enable_scrambling()
1030 drm_scdc_set_high_tmds_clock_ratio(connector, true); in vc4_hdmi_enable_scrambling()
1031 drm_scdc_set_scrambling(connector, true); in vc4_hdmi_enable_scrambling()
1033 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_enable_scrambling()
1036 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_enable_scrambling()
1040 vc4_hdmi->scdc_enabled = true; in vc4_hdmi_enable_scrambling()
1042 queue_delayed_work(system_wq, &vc4_hdmi->scrambling_work, in vc4_hdmi_enable_scrambling()
1049 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_disable_scrambling() local
1050 struct drm_device *drm = connector->dev; in vc4_hdmi_disable_scrambling()
1054 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_disable_scrambling()
1056 if (!vc4_hdmi->scdc_enabled) in vc4_hdmi_disable_scrambling()
1059 vc4_hdmi->scdc_enabled = false; in vc4_hdmi_disable_scrambling()
1061 if (delayed_work_pending(&vc4_hdmi->scrambling_work)) in vc4_hdmi_disable_scrambling()
1062 cancel_delayed_work_sync(&vc4_hdmi->scrambling_work); in vc4_hdmi_disable_scrambling()
1067 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_disable_scrambling()
1070 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_disable_scrambling()
1072 drm_scdc_set_scrambling(connector, false); in vc4_hdmi_disable_scrambling()
1073 drm_scdc_set_high_tmds_clock_ratio(connector, false); in vc4_hdmi_disable_scrambling()
1083 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_scrambling_wq() local
1085 if (drm_scdc_get_scrambling_status(connector)) in vc4_hdmi_scrambling_wq()
1088 drm_scdc_set_high_tmds_clock_ratio(connector, true); in vc4_hdmi_scrambling_wq()
1089 drm_scdc_set_scrambling(connector, true); in vc4_hdmi_scrambling_wq()
1091 queue_delayed_work(system_wq, &vc4_hdmi->scrambling_work, in vc4_hdmi_scrambling_wq()
1099 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_encoder_post_crtc_disable()
1103 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_post_crtc_disable()
1105 vc4_hdmi->packet_ram_enabled = false; in vc4_hdmi_encoder_post_crtc_disable()
1110 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_disable()
1116 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_disable()
1120 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_disable()
1123 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_disable()
1130 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_post_crtc_disable()
1137 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_encoder_post_crtc_powerdown()
1142 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_post_crtc_powerdown()
1147 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_powerdown()
1150 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_powerdown()
1152 if (vc4_hdmi->variant->phy_disable) in vc4_hdmi_encoder_post_crtc_powerdown()
1153 vc4_hdmi->variant->phy_disable(vc4_hdmi); in vc4_hdmi_encoder_post_crtc_powerdown()
1155 clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock); in vc4_hdmi_encoder_post_crtc_powerdown()
1156 clk_disable_unprepare(vc4_hdmi->pixel_clock); in vc4_hdmi_encoder_post_crtc_powerdown()
1158 ret = pm_runtime_put(&vc4_hdmi->pdev->dev); in vc4_hdmi_encoder_post_crtc_powerdown()
1165 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_post_crtc_powerdown()
1174 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_csc_setup()
1182 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_csc_setup()
1190 * Apply a colorspace conversion to squash 0-255 down in vc4_hdmi_csc_setup()
1191 * to 16-235. The matrix here is: in vc4_hdmi_csc_setup()
1214 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_csc_setup()
1227 * Full range - unity
1243 * colorspace conversion to squash 0-255 down to 16-235.
1267 * [ -0.168736 -0.331264 0.500000 128 ]
1268 * [ 0.500000 -0.418688 -0.081312 128 ]
1278 * [ -0.147644 -0.289856 0.437500 128 ]
1279 * [ 0.437500 -0.366352 -0.071148 128 ]
1298 * [ -0.114572 -0.385428 0.500000 128 ]
1299 * [ 0.500000 -0.454153 -0.045847 128 ]
1310 * [ -0.100268 -0.337232 0.437500 128 ]
1311 * [ 0.437500 -0.397386 -0.040114 128 ]
1330 * [ -0.139630 -0.360370 0.500000 128 ]
1331 * [ 0.500000 -0.459786 -0.040214 128 ]
1341 * [ -0.122176 -0.315324 0.437500 128 ]
1342 * [ 0.437500 -0.402312 -0.035188 128 ]
1353 lockdep_assert_held(&vc4_hdmi->hw_lock); in vc5_hdmi_set_csc_coeffs()
1366 lockdep_assert_held(&vc4_hdmi->hw_lock); in vc5_hdmi_set_csc_coeffs_swap()
1409 struct drm_device *drm = vc4_hdmi->connector.dev; in vc5_hdmi_csc_setup()
1425 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_csc_setup()
1427 switch (vc4_state->output_format) { in vc5_hdmi_csc_setup()
1429 csc = vc5_hdmi_find_yuv_csc_coeffs(vc4_hdmi, state->colorspace, !!lim_range); in vc5_hdmi_csc_setup()
1435 csc = vc5_hdmi_find_yuv_csc_coeffs(vc4_hdmi, state->colorspace, !!lim_range); in vc5_hdmi_csc_setup()
1466 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_csc_setup()
1475 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_set_timings()
1476 bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; in vc4_hdmi_set_timings()
1477 bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; in vc4_hdmi_set_timings()
1478 bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; in vc4_hdmi_set_timings()
1479 u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1; in vc4_hdmi_set_timings()
1480 u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, in vc4_hdmi_set_timings()
1482 VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, in vc4_hdmi_set_timings()
1484 VC4_SET_FIELD(mode->crtc_vdisplay, VC4_HDMI_VERTA_VAL)); in vc4_hdmi_set_timings()
1486 VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end + in vc4_hdmi_set_timings()
1490 VC4_SET_FIELD(mode->crtc_vtotal - in vc4_hdmi_set_timings()
1491 mode->crtc_vsync_end, in vc4_hdmi_set_timings()
1500 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_set_timings()
1505 VC4_SET_FIELD(mode->hdisplay * pixel_rep, in vc4_hdmi_set_timings()
1509 VC4_SET_FIELD((mode->htotal - in vc4_hdmi_set_timings()
1510 mode->hsync_end) * pixel_rep, in vc4_hdmi_set_timings()
1512 VC4_SET_FIELD((mode->hsync_end - in vc4_hdmi_set_timings()
1513 mode->hsync_start) * pixel_rep, in vc4_hdmi_set_timings()
1515 VC4_SET_FIELD((mode->hsync_start - in vc4_hdmi_set_timings()
1516 mode->hdisplay) * pixel_rep, in vc4_hdmi_set_timings()
1527 reg |= VC4_SET_FIELD(pixel_rep - 1, VC4_HDMI_MISC_CONTROL_PIXEL_REP); in vc4_hdmi_set_timings()
1530 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_set_timings()
1539 struct drm_device *drm = vc4_hdmi->connector.dev; in vc5_hdmi_set_timings()
1542 bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; in vc5_hdmi_set_timings()
1543 bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; in vc5_hdmi_set_timings()
1544 bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; in vc5_hdmi_set_timings()
1545 u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1; in vc5_hdmi_set_timings()
1546 u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, in vc5_hdmi_set_timings()
1548 VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, in vc5_hdmi_set_timings()
1550 VC4_SET_FIELD(mode->crtc_vdisplay, VC5_HDMI_VERTA_VAL)); in vc5_hdmi_set_timings()
1551 u32 vertb = (VC4_SET_FIELD(mode->htotal >> (2 - pixel_rep), in vc5_hdmi_set_timings()
1553 VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end + in vc5_hdmi_set_timings()
1557 VC4_SET_FIELD(mode->crtc_vtotal - in vc5_hdmi_set_timings()
1558 mode->crtc_vsync_end, in vc5_hdmi_set_timings()
1568 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_set_timings()
1573 VC4_SET_FIELD(mode->hdisplay * pixel_rep, in vc5_hdmi_set_timings()
1575 VC4_SET_FIELD((mode->hsync_start - in vc5_hdmi_set_timings()
1576 mode->hdisplay) * pixel_rep, in vc5_hdmi_set_timings()
1580 VC4_SET_FIELD((mode->htotal - in vc5_hdmi_set_timings()
1581 mode->hsync_end) * pixel_rep, in vc5_hdmi_set_timings()
1583 VC4_SET_FIELD((mode->hsync_end - in vc5_hdmi_set_timings()
1584 mode->hsync_start) * pixel_rep, in vc5_hdmi_set_timings()
1593 switch (vc4_state->output_bpc) { in vc5_hdmi_set_timings()
1607 * YCC422 is always 36-bit and not considered deep colour so in vc5_hdmi_set_timings()
1610 if (vc4_state->output_format == VC4_HDMI_OUTPUT_YUV422) { in vc5_hdmi_set_timings()
1634 reg |= VC4_SET_FIELD(pixel_rep - 1, VC5_HDMI_MISC_CONTROL_PIXEL_REP); in vc5_hdmi_set_timings()
1639 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_set_timings()
1646 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_recenter_fifo()
1655 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_recenter_fifo()
1665 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_recenter_fifo()
1669 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_recenter_fifo()
1676 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_recenter_fifo()
1690 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_encoder_pre_crtc_configure()
1691 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_encoder_pre_crtc_configure() local
1693 drm_atomic_get_new_connector_state(state, connector); in vc4_hdmi_encoder_pre_crtc_configure()
1696 const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; in vc4_hdmi_encoder_pre_crtc_configure()
1697 unsigned long tmds_char_rate = vc4_conn_state->tmds_char_rate; in vc4_hdmi_encoder_pre_crtc_configure()
1703 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_pre_crtc_configure()
1708 ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); in vc4_hdmi_encoder_pre_crtc_configure()
1715 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must in vc4_hdmi_encoder_pre_crtc_configure()
1717 * simulation. Otherwise, exact value is unimportant for HDMI in vc4_hdmi_encoder_pre_crtc_configure()
1724 * both clocks. Which, for RPi0-3 implies a maximum pixel clock of in vc4_hdmi_encoder_pre_crtc_configure()
1733 ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate); in vc4_hdmi_encoder_pre_crtc_configure()
1739 ret = clk_set_rate(vc4_hdmi->pixel_clock, tmds_char_rate); in vc4_hdmi_encoder_pre_crtc_configure()
1745 ret = clk_prepare_enable(vc4_hdmi->pixel_clock); in vc4_hdmi_encoder_pre_crtc_configure()
1761 ret = clk_set_min_rate(vc4_hdmi->pixel_bvb_clock, bvb_rate); in vc4_hdmi_encoder_pre_crtc_configure()
1767 ret = clk_prepare_enable(vc4_hdmi->pixel_bvb_clock); in vc4_hdmi_encoder_pre_crtc_configure()
1773 if (vc4_hdmi->variant->phy_init) in vc4_hdmi_encoder_pre_crtc_configure()
1774 vc4_hdmi->variant->phy_init(vc4_hdmi, vc4_conn_state); in vc4_hdmi_encoder_pre_crtc_configure()
1776 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_pre_crtc_configure()
1783 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_pre_crtc_configure()
1785 if (vc4_hdmi->variant->set_timings) in vc4_hdmi_encoder_pre_crtc_configure()
1786 vc4_hdmi->variant->set_timings(vc4_hdmi, conn_state, mode); in vc4_hdmi_encoder_pre_crtc_configure()
1790 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_pre_crtc_configure()
1795 clk_disable_unprepare(vc4_hdmi->pixel_clock); in vc4_hdmi_encoder_pre_crtc_configure()
1797 pm_runtime_put(&vc4_hdmi->pdev->dev); in vc4_hdmi_encoder_pre_crtc_configure()
1801 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_pre_crtc_configure()
1809 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_encoder_pre_crtc_enable()
1810 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_encoder_pre_crtc_enable() local
1811 const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; in vc4_hdmi_encoder_pre_crtc_enable()
1813 drm_atomic_get_new_connector_state(state, connector); in vc4_hdmi_encoder_pre_crtc_enable()
1817 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_pre_crtc_enable()
1822 if (vc4_hdmi->variant->csc_setup) in vc4_hdmi_encoder_pre_crtc_enable()
1823 vc4_hdmi->variant->csc_setup(vc4_hdmi, conn_state, mode); in vc4_hdmi_encoder_pre_crtc_enable()
1825 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_pre_crtc_enable()
1827 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_pre_crtc_enable()
1832 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_pre_crtc_enable()
1839 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_encoder_post_crtc_enable()
1840 const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; in vc4_hdmi_encoder_post_crtc_enable()
1841 struct drm_display_info *display = &vc4_hdmi->connector.display_info; in vc4_hdmi_encoder_post_crtc_enable()
1842 bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; in vc4_hdmi_encoder_post_crtc_enable()
1843 bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; in vc4_hdmi_encoder_post_crtc_enable()
1848 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_post_crtc_enable()
1853 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_enable()
1866 if (display->is_hdmi) { in vc4_hdmi_encoder_post_crtc_enable()
1871 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_enable()
1885 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_enable()
1893 if (display->is_hdmi) { in vc4_hdmi_encoder_post_crtc_enable()
1894 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_enable()
1902 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_encoder_post_crtc_enable()
1903 vc4_hdmi->packet_ram_enabled = true; in vc4_hdmi_encoder_post_crtc_enable()
1914 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_post_crtc_enable()
1925 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_atomic_mode_set()
1926 drm_mode_copy(&vc4_hdmi->saved_adjusted_mode, in vc4_hdmi_encoder_atomic_mode_set()
1927 &crtc_state->adjusted_mode); in vc4_hdmi_encoder_atomic_mode_set()
1928 vc4_hdmi->output_bpc = vc4_state->output_bpc; in vc4_hdmi_encoder_atomic_mode_set()
1929 vc4_hdmi->output_format = vc4_state->output_format; in vc4_hdmi_encoder_atomic_mode_set()
1930 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_encoder_atomic_mode_set()
1939 struct drm_device *dev = vc4_hdmi->connector.dev; in vc4_hdmi_sink_supports_format_bpc()
1947 if (!info->is_hdmi && in vc4_hdmi_sink_supports_format_bpc()
1957 if (!(info->color_formats & DRM_COLOR_FORMAT_RGB444)) in vc4_hdmi_sink_supports_format_bpc()
1960 if (bpc == 10 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30)) { in vc4_hdmi_sink_supports_format_bpc()
1965 if (bpc == 12 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36)) { in vc4_hdmi_sink_supports_format_bpc()
1977 if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) { in vc4_hdmi_sink_supports_format_bpc()
1994 if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR444)) { in vc4_hdmi_sink_supports_format_bpc()
1999 if (bpc == 10 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_30)) { in vc4_hdmi_sink_supports_format_bpc()
2004 if (bpc == 12 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_36)) { in vc4_hdmi_sink_supports_format_bpc()
2022 const struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_encoder_clock_valid() local
2023 const struct drm_display_info *info = &connector->display_info; in vc4_hdmi_encoder_clock_valid()
2024 struct vc4_dev *vc4 = to_vc4_dev(connector->dev); in vc4_hdmi_encoder_clock_valid()
2026 if (clock > vc4_hdmi->variant->max_pixel_clock) in vc4_hdmi_encoder_clock_valid()
2029 if (!vc4->hvs->vc5_hdmi_enable_hdmi_20 && clock > HDMI_14_MAX_TMDS_CLK) in vc4_hdmi_encoder_clock_valid()
2033 if (!vc4->hvs->vc5_hdmi_enable_4096by2160 && in vc4_hdmi_encoder_clock_valid()
2034 mode->hdisplay > 3840 && mode->vdisplay >= 2160 && in vc4_hdmi_encoder_clock_valid()
2038 if (info->max_tmds_clock && clock > (info->max_tmds_clock * 1000)) in vc4_hdmi_encoder_clock_valid()
2049 unsigned long long clock = mode->clock * 1000ULL; in vc4_hdmi_encoder_compute_mode_clock()
2051 if (mode->flags & DRM_MODE_FLAG_DBLCLK) in vc4_hdmi_encoder_compute_mode_clock()
2073 return -EINVAL; in vc4_hdmi_encoder_compute_clock()
2075 vc4_state->tmds_char_rate = clock; in vc4_hdmi_encoder_compute_clock()
2086 struct drm_device *dev = vc4_hdmi->connector.dev; in vc4_hdmi_encoder_compute_format()
2087 const struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_encoder_compute_format() local
2088 const struct drm_display_info *info = &connector->display_info; in vc4_hdmi_encoder_compute_format()
2100 vc4_state->output_format = format; in vc4_hdmi_encoder_compute_format()
2114 vc4_state->output_format = format; in vc4_hdmi_encoder_compute_format()
2121 return -EINVAL; in vc4_hdmi_encoder_compute_format()
2129 struct drm_device *dev = vc4_hdmi->connector.dev; in vc4_hdmi_encoder_compute_config()
2130 struct drm_connector_state *conn_state = &vc4_state->base; in vc4_hdmi_encoder_compute_config()
2131 unsigned int max_bpc = clamp_t(unsigned int, conn_state->max_bpc, 8, 12); in vc4_hdmi_encoder_compute_config()
2135 for (bpc = max_bpc; bpc >= 8; bpc -= 2) { in vc4_hdmi_encoder_compute_config()
2143 vc4_state->output_bpc = bpc; in vc4_hdmi_encoder_compute_config()
2147 mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode), in vc4_hdmi_encoder_compute_config()
2148 vc4_state->output_bpc, in vc4_hdmi_encoder_compute_config()
2149 vc4_hdmi_output_fmt_str(vc4_state->output_format), in vc4_hdmi_encoder_compute_config()
2150 vc4_state->tmds_char_rate); in vc4_hdmi_encoder_compute_config()
2166 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_encoder_atomic_check() local
2168 drm_atomic_get_old_connector_state(conn_state->state, connector); in vc4_hdmi_encoder_atomic_check()
2172 struct drm_display_mode *mode = &crtc_state->adjusted_mode; in vc4_hdmi_encoder_atomic_check()
2173 unsigned long long tmds_char_rate = mode->clock * 1000; in vc4_hdmi_encoder_atomic_check()
2177 if (vc4_hdmi->variant->unsupported_odd_h_timings) { in vc4_hdmi_encoder_atomic_check()
2178 if (mode->flags & DRM_MODE_FLAG_DBLCLK) { in vc4_hdmi_encoder_atomic_check()
2185 if ((mode->hsync_start - mode->hdisplay) & 1) in vc4_hdmi_encoder_atomic_check()
2186 mode->hsync_start--; in vc4_hdmi_encoder_atomic_check()
2187 if ((mode->hsync_end - mode->hsync_start) & 1) in vc4_hdmi_encoder_atomic_check()
2188 mode->hsync_end--; in vc4_hdmi_encoder_atomic_check()
2192 if ((mode->hdisplay % 2) || (mode->hsync_start % 2) || in vc4_hdmi_encoder_atomic_check()
2193 (mode->hsync_end % 2) || (mode->htotal % 2)) in vc4_hdmi_encoder_atomic_check()
2194 return -EINVAL; in vc4_hdmi_encoder_atomic_check()
2204 if (vc4_hdmi->disable_wifi_frequencies && in vc4_hdmi_encoder_atomic_check()
2207 mode->clock = 238560; in vc4_hdmi_encoder_atomic_check()
2208 tmds_char_rate = mode->clock * 1000; in vc4_hdmi_encoder_atomic_check()
2216 if (vc4_state->output_bpc != old_vc4_state->output_bpc || in vc4_hdmi_encoder_atomic_check()
2217 vc4_state->output_format != old_vc4_state->output_format) in vc4_hdmi_encoder_atomic_check()
2218 crtc_state->mode_changed = true; in vc4_hdmi_encoder_atomic_check()
2229 if (vc4_hdmi->variant->unsupported_odd_h_timings && in vc4_hdmi_encoder_mode_valid()
2230 !(mode->flags & DRM_MODE_FLAG_DBLCLK) && in vc4_hdmi_encoder_mode_valid()
2231 ((mode->hdisplay % 2) || (mode->hsync_start % 2) || in vc4_hdmi_encoder_mode_valid()
2232 (mode->hsync_end % 2) || (mode->htotal % 2))) in vc4_hdmi_encoder_mode_valid()
2235 return vc4_hdmi_encoder_clock_valid(vc4_hdmi, mode, mode->clock * 1000); in vc4_hdmi_encoder_mode_valid()
2246 struct drm_device *drm = encoder->dev; in vc4_hdmi_late_register()
2248 const struct vc4_hdmi_variant *variant = vc4_hdmi->variant; in vc4_hdmi_late_register()
2250 drm_debugfs_add_file(drm, variant->debugfs_name, in vc4_hdmi_late_register()
2286 struct drm_device *drm = vc4_hdmi->connector.dev; in vc5_hdmi_hp_detect()
2294 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_hp_detect()
2296 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc5_hdmi_hp_detect()
2303 /* HDMI audio codec callbacks */
2307 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_audio_set_mai_clock()
2316 hsm_clock = clk_get_rate(vc4_hdmi->audio_clock); in vc4_hdmi_audio_set_mai_clock()
2324 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_set_mai_clock()
2327 VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M)); in vc4_hdmi_audio_set_mai_clock()
2328 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_set_mai_clock()
2335 const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; in vc4_hdmi_set_n_cts()
2339 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_set_n_cts()
2340 lockdep_assert_held(&vc4_hdmi->hw_lock); in vc4_hdmi_set_n_cts()
2343 tmp = (u64)(mode->clock * 1000) * n; in vc4_hdmi_set_n_cts()
2369 struct drm_display_info *display = &vc4_hdmi->connector.display_info; in vc4_hdmi_audio_can_stream()
2371 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_audio_can_stream()
2377 if (!display->is_hdmi) in vc4_hdmi_audio_can_stream()
2386 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_audio_startup()
2391 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_audio_startup()
2394 ret = -ENODEV; in vc4_hdmi_audio_startup()
2399 ret = -ENODEV; in vc4_hdmi_audio_startup()
2403 vc4_hdmi->audio.streaming = true; in vc4_hdmi_audio_startup()
2405 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_startup()
2412 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_startup()
2414 if (vc4_hdmi->variant->phy_rng_enable) in vc4_hdmi_audio_startup()
2415 vc4_hdmi->variant->phy_rng_enable(vc4_hdmi); in vc4_hdmi_audio_startup()
2420 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_audio_startup()
2427 struct drm_encoder *encoder = &vc4_hdmi->encoder.base; in vc4_hdmi_audio_reset()
2428 struct device *dev = &vc4_hdmi->pdev->dev; in vc4_hdmi_audio_reset()
2432 lockdep_assert_held(&vc4_hdmi->mutex); in vc4_hdmi_audio_reset()
2434 vc4_hdmi->audio.streaming = false; in vc4_hdmi_audio_reset()
2439 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_reset()
2445 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_reset()
2451 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_audio_shutdown()
2455 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_audio_shutdown()
2460 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_shutdown()
2467 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_shutdown()
2469 if (vc4_hdmi->variant->phy_rng_disable) in vc4_hdmi_audio_shutdown()
2470 vc4_hdmi->variant->phy_rng_disable(vc4_hdmi); in vc4_hdmi_audio_shutdown()
2472 vc4_hdmi->audio.streaming = false; in vc4_hdmi_audio_shutdown()
2478 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_audio_shutdown()
2519 /* HDMI audio codec callbacks */
2525 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_audio_prepare()
2526 struct drm_encoder *encoder = &vc4_hdmi->encoder.base; in vc4_hdmi_audio_prepare()
2527 unsigned int sample_rate = params->sample_rate; in vc4_hdmi_audio_prepare()
2528 unsigned int channels = params->channels; in vc4_hdmi_audio_prepare()
2538 sample_rate, params->sample_width, channels); in vc4_hdmi_audio_prepare()
2540 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_audio_prepare()
2543 ret = -ENODEV; in vc4_hdmi_audio_prepare()
2548 ret = -EINVAL; in vc4_hdmi_audio_prepare()
2554 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_prepare()
2562 if (params->iec.status[0] & IEC958_AES0_NONAUDIO && in vc4_hdmi_audio_prepare()
2563 params->channels == 8) in vc4_hdmi_audio_prepare()
2573 /* The B frame identifier should match the value used by alsa-lib (8) */ in vc4_hdmi_audio_prepare()
2579 channel_mask = GENMASK(channels - 1, 0); in vc4_hdmi_audio_prepare()
2595 channel_map = vc4_hdmi->variant->channel_map(vc4_hdmi, channel_mask); in vc4_hdmi_audio_prepare()
2601 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_audio_prepare()
2603 memcpy(&vc4_hdmi->audio.infoframe, ¶ms->cea, sizeof(params->cea)); in vc4_hdmi_audio_prepare()
2609 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_audio_prepare()
2615 .name = "vc4-hdmi-cpu-dai-component",
2623 snd_soc_dai_init_dma_data(dai, &vc4_hdmi->audio.dma_data, NULL); in vc4_hdmi_audio_cpu_dai_probe()
2633 .name = "vc4-hdmi-cpu-dai",
2648 .chan_names[SNDRV_PCM_STREAM_PLAYBACK] = "audio-rx",
2656 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_audio_get_eld() local
2658 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_audio_get_eld()
2659 memcpy(buf, connector->eld, min(sizeof(connector->eld), len)); in vc4_hdmi_audio_get_eld()
2660 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_audio_get_eld()
2682 platform_device_unregister(vc4_hdmi->audio.codec_pdev); in vc4_hdmi_audio_codec_release()
2683 vc4_hdmi->audio.codec_pdev = NULL; in vc4_hdmi_audio_codec_release()
2689 &vc4_hdmi->variant->registers[HDMI_MAI_DATA]; in vc4_hdmi_audio_init()
2690 struct snd_soc_dai_link *dai_link = &vc4_hdmi->audio.link; in vc4_hdmi_audio_init()
2691 struct snd_soc_card *card = &vc4_hdmi->audio.card; in vc4_hdmi_audio_init()
2692 struct device *dev = &vc4_hdmi->pdev->dev; in vc4_hdmi_audio_init()
2718 if (!of_find_property(dev->of_node, "dmas", &len) || !len) { in vc4_hdmi_audio_init()
2720 "'dmas' DT property is missing or empty, no HDMI audio\n"); in vc4_hdmi_audio_init()
2724 if (mai_data->reg != VC4_HD) { in vc4_hdmi_audio_init()
2726 return -EINVAL; in vc4_hdmi_audio_init()
2736 index = of_property_match_string(dev->of_node, "reg-names", "hd"); in vc4_hdmi_audio_init()
2741 addr = of_get_address(dev->of_node, index, NULL, NULL); in vc4_hdmi_audio_init()
2743 vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + mai_data->offset; in vc4_hdmi_audio_init()
2744 vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; in vc4_hdmi_audio_init()
2745 vc4_hdmi->audio.dma_data.maxburst = 2; in vc4_hdmi_audio_init()
2748 * NOTE: Strictly speaking, we should probably use a DRM-managed in vc4_hdmi_audio_init()
2753 * when registering, even when using non-device-managed in vc4_hdmi_audio_init()
2756 * If we call snd_soc_unregister_component() in a DRM-managed in vc4_hdmi_audio_init()
2757 * action, the device-managed actions have already been executed in vc4_hdmi_audio_init()
2760 * Using device-managed hooks here probably leaves us open to a in vc4_hdmi_audio_init()
2767 * Then, the vc4_hdmi structure is DRM-managed and thus only in vc4_hdmi_audio_init()
2789 dev_err(dev, "Couldn't register the HDMI codec: %ld\n", PTR_ERR(codec_pdev)); in vc4_hdmi_audio_init()
2792 vc4_hdmi->audio.codec_pdev = codec_pdev; in vc4_hdmi_audio_init()
2798 dai_link->cpus = &vc4_hdmi->audio.cpu; in vc4_hdmi_audio_init()
2799 dai_link->codecs = &vc4_hdmi->audio.codec; in vc4_hdmi_audio_init()
2800 dai_link->platforms = &vc4_hdmi->audio.platform; in vc4_hdmi_audio_init()
2802 dai_link->num_cpus = 1; in vc4_hdmi_audio_init()
2803 dai_link->num_codecs = 1; in vc4_hdmi_audio_init()
2804 dai_link->num_platforms = 1; in vc4_hdmi_audio_init()
2806 dai_link->name = "MAI"; in vc4_hdmi_audio_init()
2807 dai_link->stream_name = "MAI PCM"; in vc4_hdmi_audio_init()
2808 dai_link->codecs->dai_name = "i2s-hifi"; in vc4_hdmi_audio_init()
2809 dai_link->cpus->dai_name = dev_name(dev); in vc4_hdmi_audio_init()
2810 dai_link->codecs->name = dev_name(&codec_pdev->dev); in vc4_hdmi_audio_init()
2811 dai_link->platforms->name = dev_name(dev); in vc4_hdmi_audio_init()
2813 card->dai_link = dai_link; in vc4_hdmi_audio_init()
2814 card->num_links = 1; in vc4_hdmi_audio_init()
2815 card->name = vc4_hdmi->variant->card_name; in vc4_hdmi_audio_init()
2816 card->driver_name = "vc4-hdmi"; in vc4_hdmi_audio_init()
2817 card->dev = dev; in vc4_hdmi_audio_init()
2818 card->owner = THIS_MODULE; in vc4_hdmi_audio_init()
2822 * stores a pointer to the snd card object in dev->driver_data. This in vc4_hdmi_audio_init()
2823 * means we cannot use it for something else. The hdmi back-pointer is in vc4_hdmi_audio_init()
2824 * now stored in card->drvdata and should be retrieved with in vc4_hdmi_audio_init()
2839 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_hpd_irq_thread() local
2840 struct drm_device *dev = connector->dev; in vc4_hdmi_hpd_irq_thread()
2842 if (dev && dev->registered) in vc4_hdmi_hpd_irq_thread()
2843 drm_connector_helper_hpd_irq_event(connector); in vc4_hdmi_hpd_irq_thread()
2850 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_hotplug_init() local
2851 struct platform_device *pdev = vc4_hdmi->pdev; in vc4_hdmi_hotplug_init()
2854 if (vc4_hdmi->variant->external_irq_controller) { in vc4_hdmi_hotplug_init()
2855 unsigned int hpd_con = platform_get_irq_byname(pdev, "hpd-connected"); in vc4_hdmi_hotplug_init()
2856 unsigned int hpd_rm = platform_get_irq_byname(pdev, "hpd-removed"); in vc4_hdmi_hotplug_init()
2858 ret = devm_request_threaded_irq(&pdev->dev, hpd_con, in vc4_hdmi_hotplug_init()
2861 "vc4 hdmi hpd connected", vc4_hdmi); in vc4_hdmi_hotplug_init()
2865 ret = devm_request_threaded_irq(&pdev->dev, hpd_rm, in vc4_hdmi_hotplug_init()
2868 "vc4 hdmi hpd disconnected", vc4_hdmi); in vc4_hdmi_hotplug_init()
2872 connector->polled = DRM_CONNECTOR_POLL_HPD; in vc4_hdmi_hotplug_init()
2883 if (vc4_hdmi->cec_rx_msg.len) in vc4_cec_irq_handler_rx_thread()
2884 cec_received_msg(vc4_hdmi->cec_adap, in vc4_cec_irq_handler_rx_thread()
2885 &vc4_hdmi->cec_rx_msg); in vc4_cec_irq_handler_rx_thread()
2894 if (vc4_hdmi->cec_tx_ok) { in vc4_cec_irq_handler_tx_thread()
2895 cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_OK, in vc4_cec_irq_handler_tx_thread()
2902 cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_NACK, in vc4_cec_irq_handler_tx_thread()
2913 if (vc4_hdmi->cec_irq_was_rx) in vc4_cec_irq_handler_thread()
2923 struct drm_device *dev = vc4_hdmi->connector.dev; in vc4_cec_read_msg()
2924 struct cec_msg *msg = &vc4_hdmi->cec_rx_msg; in vc4_cec_read_msg()
2927 lockdep_assert_held(&vc4_hdmi->hw_lock); in vc4_cec_read_msg()
2929 msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >> in vc4_cec_read_msg()
2932 if (msg->len > 16) { in vc4_cec_read_msg()
2933 drm_err(dev, "Attempting to read too much data (%d)\n", msg->len); in vc4_cec_read_msg()
2937 for (i = 0; i < msg->len; i += 4) { in vc4_cec_read_msg()
2940 msg->msg[i] = val & 0xff; in vc4_cec_read_msg()
2941 msg->msg[i + 1] = (val >> 8) & 0xff; in vc4_cec_read_msg()
2942 msg->msg[i + 2] = (val >> 16) & 0xff; in vc4_cec_read_msg()
2943 msg->msg[i + 3] = (val >> 24) & 0xff; in vc4_cec_read_msg()
2962 lockdep_assert_held(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler_tx_bare_locked()
2965 vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD; in vc4_cec_irq_handler_tx_bare_locked()
2977 spin_lock(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler_tx_bare()
2979 spin_unlock(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler_tx_bare()
2988 lockdep_assert_held(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler_rx_bare_locked()
3001 vc4_hdmi->cec_rx_msg.len = 0; in vc4_cec_irq_handler_rx_bare_locked()
3018 spin_lock(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler_rx_bare()
3020 spin_unlock(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler_rx_bare()
3046 spin_lock(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler()
3048 vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT; in vc4_cec_irq_handler()
3049 if (vc4_hdmi->cec_irq_was_rx) in vc4_cec_irq_handler()
3055 spin_unlock(&vc4_hdmi->hw_lock); in vc4_cec_irq_handler()
3063 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_cec_enable()
3079 ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); in vc4_hdmi_cec_enable()
3085 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_cec_enable()
3087 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_enable()
3116 if (!vc4_hdmi->variant->external_irq_controller) in vc4_hdmi_cec_enable()
3119 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_enable()
3121 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_cec_enable()
3130 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_cec_disable()
3142 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_cec_disable()
3144 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_disable()
3146 if (!vc4_hdmi->variant->external_irq_controller) in vc4_hdmi_cec_disable()
3152 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_disable()
3154 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_cec_disable()
3156 pm_runtime_put(&vc4_hdmi->pdev->dev); in vc4_hdmi_cec_disable()
3174 struct drm_device *drm = vc4_hdmi->connector.dev; in vc4_hdmi_cec_adap_log_addr()
3186 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_cec_adap_log_addr()
3187 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_adap_log_addr()
3191 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_adap_log_addr()
3192 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_cec_adap_log_addr()
3203 struct drm_device *dev = vc4_hdmi->connector.dev; in vc4_hdmi_cec_adap_transmit()
3210 return -ENODEV; in vc4_hdmi_cec_adap_transmit()
3212 if (msg->len > 16) { in vc4_hdmi_cec_adap_transmit()
3213 drm_err(dev, "Attempting to transmit too much data (%d)\n", msg->len); in vc4_hdmi_cec_adap_transmit()
3215 return -ENOMEM; in vc4_hdmi_cec_adap_transmit()
3218 mutex_lock(&vc4_hdmi->mutex); in vc4_hdmi_cec_adap_transmit()
3220 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_adap_transmit()
3222 for (i = 0; i < msg->len; i += 4) in vc4_hdmi_cec_adap_transmit()
3224 (msg->msg[i]) | in vc4_hdmi_cec_adap_transmit()
3225 (msg->msg[i + 1] << 8) | in vc4_hdmi_cec_adap_transmit()
3226 (msg->msg[i + 2] << 16) | in vc4_hdmi_cec_adap_transmit()
3227 (msg->msg[i + 3] << 24)); in vc4_hdmi_cec_adap_transmit()
3233 val |= (msg->len - 1) << VC4_HDMI_CEC_MESSAGE_LENGTH_SHIFT; in vc4_hdmi_cec_adap_transmit()
3238 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_cec_adap_transmit()
3239 mutex_unlock(&vc4_hdmi->mutex); in vc4_hdmi_cec_adap_transmit()
3255 cec_unregister_adapter(vc4_hdmi->cec_adap); in vc4_hdmi_cec_release()
3256 vc4_hdmi->cec_adap = NULL; in vc4_hdmi_cec_release()
3262 struct platform_device *pdev = vc4_hdmi->pdev; in vc4_hdmi_cec_init()
3263 struct device *dev = &pdev->dev; in vc4_hdmi_cec_init()
3266 if (!of_property_present(dev->of_node, "interrupts")) { in vc4_hdmi_cec_init()
3271 vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops, in vc4_hdmi_cec_init()
3273 vc4_hdmi->variant->card_name, in vc4_hdmi_cec_init()
3276 ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap); in vc4_hdmi_cec_init()
3280 cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector); in vc4_hdmi_cec_init()
3281 cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info); in vc4_hdmi_cec_init()
3283 if (vc4_hdmi->variant->external_irq_controller) { in vc4_hdmi_cec_init()
3284 ret = devm_request_threaded_irq(dev, platform_get_irq_byname(pdev, "cec-rx"), in vc4_hdmi_cec_init()
3287 "vc4 hdmi cec rx", vc4_hdmi); in vc4_hdmi_cec_init()
3291 ret = devm_request_threaded_irq(dev, platform_get_irq_byname(pdev, "cec-tx"), in vc4_hdmi_cec_init()
3294 "vc4 hdmi cec tx", vc4_hdmi); in vc4_hdmi_cec_init()
3301 "vc4 hdmi cec", vc4_hdmi); in vc4_hdmi_cec_init()
3306 ret = cec_register_adapter(vc4_hdmi->cec_adap, &pdev->dev); in vc4_hdmi_cec_init()
3311 * NOTE: Strictly speaking, we should probably use a DRM-managed in vc4_hdmi_cec_init()
3319 * By the time the device-managed hook is executed, we will give in vc4_hdmi_cec_init()
3328 * used to be our HDMI controller. If we get a CEC call at that in vc4_hdmi_cec_init()
3329 * moment, we could end up with a use-after-free. Fortunately, in vc4_hdmi_cec_init()
3340 cec_delete_adapter(vc4_hdmi->cec_adap); in vc4_hdmi_cec_init()
3363 const struct vc4_hdmi_variant *variant = vc4_hdmi->variant; in vc4_hdmi_build_regset()
3369 regs = kcalloc(variant->num_registers, sizeof(*regs), in vc4_hdmi_build_regset()
3372 return -ENOMEM; in vc4_hdmi_build_regset()
3374 for (i = 0; i < variant->num_registers; i++) { in vc4_hdmi_build_regset()
3375 const struct vc4_hdmi_register *field = &variant->registers[i]; in vc4_hdmi_build_regset()
3377 if (field->reg != reg) in vc4_hdmi_build_regset()
3380 regs[count].name = field->name; in vc4_hdmi_build_regset()
3381 regs[count].offset = field->offset; in vc4_hdmi_build_regset()
3387 return -ENOMEM; in vc4_hdmi_build_regset()
3389 regset->base = __vc4_hdmi_get_field_base(vc4_hdmi, reg); in vc4_hdmi_build_regset()
3390 regset->regs = new_regs; in vc4_hdmi_build_regset()
3391 regset->nregs = count; in vc4_hdmi_build_regset()
3403 struct platform_device *pdev = vc4_hdmi->pdev; in vc4_hdmi_init_resources()
3404 struct device *dev = &pdev->dev; in vc4_hdmi_init_resources()
3407 vc4_hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0); in vc4_hdmi_init_resources()
3408 if (IS_ERR(vc4_hdmi->hdmicore_regs)) in vc4_hdmi_init_resources()
3409 return PTR_ERR(vc4_hdmi->hdmicore_regs); in vc4_hdmi_init_resources()
3411 vc4_hdmi->hd_regs = vc4_ioremap_regs(pdev, 1); in vc4_hdmi_init_resources()
3412 if (IS_ERR(vc4_hdmi->hd_regs)) in vc4_hdmi_init_resources()
3413 return PTR_ERR(vc4_hdmi->hd_regs); in vc4_hdmi_init_resources()
3415 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD); in vc4_hdmi_init_resources()
3419 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI); in vc4_hdmi_init_resources()
3423 vc4_hdmi->pixel_clock = devm_clk_get(dev, "pixel"); in vc4_hdmi_init_resources()
3424 if (IS_ERR(vc4_hdmi->pixel_clock)) { in vc4_hdmi_init_resources()
3425 ret = PTR_ERR(vc4_hdmi->pixel_clock); in vc4_hdmi_init_resources()
3426 if (ret != -EPROBE_DEFER) in vc4_hdmi_init_resources()
3431 vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi"); in vc4_hdmi_init_resources()
3432 if (IS_ERR(vc4_hdmi->hsm_clock)) { in vc4_hdmi_init_resources()
3433 DRM_ERROR("Failed to get HDMI state machine clock\n"); in vc4_hdmi_init_resources()
3434 return PTR_ERR(vc4_hdmi->hsm_clock); in vc4_hdmi_init_resources()
3436 vc4_hdmi->audio_clock = vc4_hdmi->hsm_clock; in vc4_hdmi_init_resources()
3437 vc4_hdmi->cec_clock = vc4_hdmi->hsm_clock; in vc4_hdmi_init_resources()
3445 struct platform_device *pdev = vc4_hdmi->pdev; in vc5_hdmi_init_resources()
3446 struct device *dev = &pdev->dev; in vc5_hdmi_init_resources()
3450 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi"); in vc5_hdmi_init_resources()
3452 return -ENODEV; in vc5_hdmi_init_resources()
3454 vc4_hdmi->hdmicore_regs = devm_ioremap(dev, res->start, in vc5_hdmi_init_resources()
3456 if (!vc4_hdmi->hdmicore_regs) in vc5_hdmi_init_resources()
3457 return -ENOMEM; in vc5_hdmi_init_resources()
3461 return -ENODEV; in vc5_hdmi_init_resources()
3463 vc4_hdmi->hd_regs = devm_ioremap(dev, res->start, resource_size(res)); in vc5_hdmi_init_resources()
3464 if (!vc4_hdmi->hd_regs) in vc5_hdmi_init_resources()
3465 return -ENOMEM; in vc5_hdmi_init_resources()
3469 return -ENODEV; in vc5_hdmi_init_resources()
3471 vc4_hdmi->cec_regs = devm_ioremap(dev, res->start, resource_size(res)); in vc5_hdmi_init_resources()
3472 if (!vc4_hdmi->cec_regs) in vc5_hdmi_init_resources()
3473 return -ENOMEM; in vc5_hdmi_init_resources()
3477 return -ENODEV; in vc5_hdmi_init_resources()
3479 vc4_hdmi->csc_regs = devm_ioremap(dev, res->start, resource_size(res)); in vc5_hdmi_init_resources()
3480 if (!vc4_hdmi->csc_regs) in vc5_hdmi_init_resources()
3481 return -ENOMEM; in vc5_hdmi_init_resources()
3485 return -ENODEV; in vc5_hdmi_init_resources()
3487 vc4_hdmi->dvp_regs = devm_ioremap(dev, res->start, resource_size(res)); in vc5_hdmi_init_resources()
3488 if (!vc4_hdmi->dvp_regs) in vc5_hdmi_init_resources()
3489 return -ENOMEM; in vc5_hdmi_init_resources()
3493 return -ENODEV; in vc5_hdmi_init_resources()
3495 vc4_hdmi->phy_regs = devm_ioremap(dev, res->start, resource_size(res)); in vc5_hdmi_init_resources()
3496 if (!vc4_hdmi->phy_regs) in vc5_hdmi_init_resources()
3497 return -ENOMEM; in vc5_hdmi_init_resources()
3501 return -ENODEV; in vc5_hdmi_init_resources()
3503 vc4_hdmi->ram_regs = devm_ioremap(dev, res->start, resource_size(res)); in vc5_hdmi_init_resources()
3504 if (!vc4_hdmi->ram_regs) in vc5_hdmi_init_resources()
3505 return -ENOMEM; in vc5_hdmi_init_resources()
3509 return -ENODEV; in vc5_hdmi_init_resources()
3511 vc4_hdmi->rm_regs = devm_ioremap(dev, res->start, resource_size(res)); in vc5_hdmi_init_resources()
3512 if (!vc4_hdmi->rm_regs) in vc5_hdmi_init_resources()
3513 return -ENOMEM; in vc5_hdmi_init_resources()
3515 vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi"); in vc5_hdmi_init_resources()
3516 if (IS_ERR(vc4_hdmi->hsm_clock)) { in vc5_hdmi_init_resources()
3517 DRM_ERROR("Failed to get HDMI state machine clock\n"); in vc5_hdmi_init_resources()
3518 return PTR_ERR(vc4_hdmi->hsm_clock); in vc5_hdmi_init_resources()
3521 vc4_hdmi->pixel_bvb_clock = devm_clk_get(dev, "bvb"); in vc5_hdmi_init_resources()
3522 if (IS_ERR(vc4_hdmi->pixel_bvb_clock)) { in vc5_hdmi_init_resources()
3524 return PTR_ERR(vc4_hdmi->pixel_bvb_clock); in vc5_hdmi_init_resources()
3527 vc4_hdmi->audio_clock = devm_clk_get(dev, "audio"); in vc5_hdmi_init_resources()
3528 if (IS_ERR(vc4_hdmi->audio_clock)) { in vc5_hdmi_init_resources()
3530 return PTR_ERR(vc4_hdmi->audio_clock); in vc5_hdmi_init_resources()
3533 vc4_hdmi->cec_clock = devm_clk_get(dev, "cec"); in vc5_hdmi_init_resources()
3534 if (IS_ERR(vc4_hdmi->cec_clock)) { in vc5_hdmi_init_resources()
3536 return PTR_ERR(vc4_hdmi->cec_clock); in vc5_hdmi_init_resources()
3539 vc4_hdmi->reset = devm_reset_control_get(dev, NULL); in vc5_hdmi_init_resources()
3540 if (IS_ERR(vc4_hdmi->reset)) { in vc5_hdmi_init_resources()
3541 DRM_ERROR("Failed to get HDMI reset line\n"); in vc5_hdmi_init_resources()
3542 return PTR_ERR(vc4_hdmi->reset); in vc5_hdmi_init_resources()
3545 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI); in vc5_hdmi_init_resources()
3549 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD); in vc5_hdmi_init_resources()
3553 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->cec_regset, VC5_CEC); in vc5_hdmi_init_resources()
3557 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->csc_regset, VC5_CSC); in vc5_hdmi_init_resources()
3561 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->dvp_regset, VC5_DVP); in vc5_hdmi_init_resources()
3565 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->phy_regset, VC5_PHY); in vc5_hdmi_init_resources()
3569 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->ram_regset, VC5_RAM); in vc5_hdmi_init_resources()
3573 ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->rm_regset, VC5_RM); in vc5_hdmi_init_resources()
3584 clk_disable_unprepare(vc4_hdmi->hsm_clock); in vc4_hdmi_runtime_suspend()
3597 ret = clk_prepare_enable(vc4_hdmi->hsm_clock); in vc4_hdmi_runtime_resume()
3602 * Whenever the RaspberryPi boots without an HDMI monitor in vc4_hdmi_runtime_resume()
3610 rate = clk_get_rate(vc4_hdmi->hsm_clock); in vc4_hdmi_runtime_resume()
3612 ret = -EINVAL; in vc4_hdmi_runtime_resume()
3616 if (vc4_hdmi->variant->reset) in vc4_hdmi_runtime_resume()
3617 vc4_hdmi->variant->reset(vc4_hdmi); in vc4_hdmi_runtime_resume()
3620 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_runtime_resume()
3625 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_runtime_resume()
3629 if (!vc4_hdmi->variant->external_irq_controller) { in vc4_hdmi_runtime_resume()
3630 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_runtime_resume()
3632 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); in vc4_hdmi_runtime_resume()
3639 clk_disable_unprepare(vc4_hdmi->hsm_clock); in vc4_hdmi_runtime_resume()
3647 put_device(&vc4_hdmi->ddc->dev); in vc4_hdmi_put_ddc_device()
3662 return -ENOMEM; in vc4_hdmi_bind()
3664 ret = drmm_mutex_init(drm, &vc4_hdmi->mutex); in vc4_hdmi_bind()
3668 spin_lock_init(&vc4_hdmi->hw_lock); in vc4_hdmi_bind()
3669 INIT_DELAYED_WORK(&vc4_hdmi->scrambling_work, vc4_hdmi_scrambling_wq); in vc4_hdmi_bind()
3672 encoder = &vc4_hdmi->encoder.base; in vc4_hdmi_bind()
3673 vc4_hdmi->encoder.type = variant->encoder_type; in vc4_hdmi_bind()
3674 vc4_hdmi->encoder.pre_crtc_configure = vc4_hdmi_encoder_pre_crtc_configure; in vc4_hdmi_bind()
3675 vc4_hdmi->encoder.pre_crtc_enable = vc4_hdmi_encoder_pre_crtc_enable; in vc4_hdmi_bind()
3676 vc4_hdmi->encoder.post_crtc_enable = vc4_hdmi_encoder_post_crtc_enable; in vc4_hdmi_bind()
3677 vc4_hdmi->encoder.post_crtc_disable = vc4_hdmi_encoder_post_crtc_disable; in vc4_hdmi_bind()
3678 vc4_hdmi->encoder.post_crtc_powerdown = vc4_hdmi_encoder_post_crtc_powerdown; in vc4_hdmi_bind()
3679 vc4_hdmi->pdev = pdev; in vc4_hdmi_bind()
3680 vc4_hdmi->variant = variant; in vc4_hdmi_bind()
3688 if (variant->max_pixel_clock > HDMI_14_MAX_TMDS_CLK) in vc4_hdmi_bind()
3689 vc4_hdmi->scdc_enabled = true; in vc4_hdmi_bind()
3691 ret = variant->init_resources(drm, vc4_hdmi); in vc4_hdmi_bind()
3695 ddc_node = of_parse_phandle(dev->of_node, "ddc", 0); in vc4_hdmi_bind()
3698 return -ENODEV; in vc4_hdmi_bind()
3701 vc4_hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node); in vc4_hdmi_bind()
3703 if (!vc4_hdmi->ddc) { in vc4_hdmi_bind()
3705 return -EPROBE_DEFER; in vc4_hdmi_bind()
3713 * we'll use the HDMI core's register. in vc4_hdmi_bind()
3715 vc4_hdmi->hpd_gpio = devm_gpiod_get_optional(dev, "hpd", GPIOD_IN); in vc4_hdmi_bind()
3716 if (IS_ERR(vc4_hdmi->hpd_gpio)) { in vc4_hdmi_bind()
3717 return PTR_ERR(vc4_hdmi->hpd_gpio); in vc4_hdmi_bind()
3720 vc4_hdmi->disable_wifi_frequencies = in vc4_hdmi_bind()
3721 of_property_read_bool(dev->of_node, "wifi-2.4ghz-coexistence"); in vc4_hdmi_bind()
3735 if ((of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi0") || in vc4_hdmi_bind()
3736 of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi1")) && in vc4_hdmi_bind()
3738 clk_prepare_enable(vc4_hdmi->pixel_clock); in vc4_hdmi_bind()
3739 clk_prepare_enable(vc4_hdmi->hsm_clock); in vc4_hdmi_bind()
3740 clk_prepare_enable(vc4_hdmi->pixel_bvb_clock); in vc4_hdmi_bind()
3784 return component_add(&pdev->dev, &vc4_hdmi_ops); in vc4_hdmi_dev_probe()
3789 component_del(&pdev->dev, &vc4_hdmi_ops); in vc4_hdmi_dev_remove()
3795 .card_name = "vc4-hdmi",
3815 .card_name = "vc4-hdmi-0",
3844 .card_name = "vc4-hdmi-1",
3871 { .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant },
3872 { .compatible = "brcm,bcm2711-hdmi0", .data = &bcm2711_hdmi0_variant },
3873 { .compatible = "brcm,bcm2711-hdmi1", .data = &bcm2711_hdmi1_variant },