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
87 struct drm_info_node *node = (struct drm_info_node *)m->private; in vc4_hdmi_debugfs_regs()
88 struct vc4_hdmi *vc4_hdmi = node->info_ent->data; in vc4_hdmi_debugfs_regs()
91 drm_print_regset32(&p, &vc4_hdmi->hdmi_regset); in vc4_hdmi_debugfs_regs()
92 drm_print_regset32(&p, &vc4_hdmi->hd_regset); in vc4_hdmi_debugfs_regs()
114 reset_control_reset(vc4_hdmi->reset); in vc5_hdmi_reset()
123 vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) in vc4_hdmi_connector_detect() argument
125 struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); in vc4_hdmi_connector_detect()
127 if (vc4_hdmi->hpd_gpio) { in vc4_hdmi_connector_detect()
128 if (gpio_get_value_cansleep(vc4_hdmi->hpd_gpio) ^ in vc4_hdmi_connector_detect()
129 vc4_hdmi->hpd_active_low) in vc4_hdmi_connector_detect()
131 cec_phys_addr_invalidate(vc4_hdmi->cec_adap); in vc4_hdmi_connector_detect()
135 if (drm_probe_ddc(vc4_hdmi->ddc)) in vc4_hdmi_connector_detect()
140 cec_phys_addr_invalidate(vc4_hdmi->cec_adap); in vc4_hdmi_connector_detect()
144 static void vc4_hdmi_connector_destroy(struct drm_connector *connector) in vc4_hdmi_connector_destroy() argument
146 drm_connector_unregister(connector); in vc4_hdmi_connector_destroy()
147 drm_connector_cleanup(connector); in vc4_hdmi_connector_destroy()
150 static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) in vc4_hdmi_connector_get_modes() argument
152 struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); in vc4_hdmi_connector_get_modes()
153 struct vc4_hdmi_encoder *vc4_encoder = &vc4_hdmi->encoder; in vc4_hdmi_connector_get_modes()
157 edid = drm_get_edid(connector, vc4_hdmi->ddc); in vc4_hdmi_connector_get_modes()
158 cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid); in vc4_hdmi_connector_get_modes()
160 return -ENODEV; in vc4_hdmi_connector_get_modes()
162 vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid); in vc4_hdmi_connector_get_modes()
164 drm_connector_update_edid_property(connector, edid); in vc4_hdmi_connector_get_modes()
165 ret = drm_add_edid_modes(connector, edid); in vc4_hdmi_connector_get_modes()
171 static void vc4_hdmi_connector_reset(struct drm_connector *connector) in vc4_hdmi_connector_reset() argument
173 drm_atomic_helper_connector_reset(connector); in vc4_hdmi_connector_reset()
174 drm_atomic_helper_connector_tv_reset(connector); in vc4_hdmi_connector_reset()
193 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_connector_init() local
194 struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; in vc4_hdmi_connector_init()
197 drm_connector_init_with_ddc(dev, connector, in vc4_hdmi_connector_init()
200 vc4_hdmi->ddc); in vc4_hdmi_connector_init()
201 drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs); in vc4_hdmi_connector_init()
203 /* Create and attach TV margin props to this connector. */ in vc4_hdmi_connector_init()
208 drm_connector_attach_tv_margin_properties(connector); in vc4_hdmi_connector_init()
210 connector->polled = (DRM_CONNECTOR_POLL_CONNECT | in vc4_hdmi_connector_init()
213 connector->interlace_allowed = 1; in vc4_hdmi_connector_init()
214 connector->doublescan_allowed = 0; in vc4_hdmi_connector_init()
216 drm_connector_attach_encoder(connector, encoder); in vc4_hdmi_connector_init()
225 u32 packet_id = type - 0x80; in vc4_hdmi_stop_packet()
238 u32 packet_id = frame->any.type - 0x80; in vc4_hdmi_write_infoframe()
240 &vc4_hdmi->variant->registers[HDMI_RAM_PACKET_START]; in vc4_hdmi_write_infoframe()
241 u32 packet_reg = ram_packet_start->offset + VC4_HDMI_PACKET_STRIDE * packet_id; in vc4_hdmi_write_infoframe()
243 ram_packet_start->reg); in vc4_hdmi_write_infoframe()
256 ret = vc4_hdmi_stop_packet(encoder, frame->any.type); in vc4_hdmi_write_infoframe()
289 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_set_avi_infoframe() local
290 struct drm_connector_state *cstate = connector->state; in vc4_hdmi_set_avi_infoframe()
291 struct drm_crtc *crtc = encoder->crtc; in vc4_hdmi_set_avi_infoframe()
292 const struct drm_display_mode *mode = &crtc->state->adjusted_mode; in vc4_hdmi_set_avi_infoframe()
297 connector, mode); in vc4_hdmi_set_avi_infoframe()
304 connector, mode, in vc4_hdmi_set_avi_infoframe()
305 vc4_encoder->limited_rgb_range ? in vc4_hdmi_set_avi_infoframe()
341 frame.audio.channels = vc4_hdmi->audio.channels; in vc4_hdmi_set_audio_infoframe()
356 if (vc4_hdmi->audio.streaming) in vc4_hdmi_set_infoframes()
378 if (vc4_hdmi->variant->phy_disable) in vc4_hdmi_encoder_post_crtc_powerdown()
379 vc4_hdmi->variant->phy_disable(vc4_hdmi); in vc4_hdmi_encoder_post_crtc_powerdown()
384 clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock); in vc4_hdmi_encoder_post_crtc_powerdown()
385 clk_disable_unprepare(vc4_hdmi->hsm_clock); in vc4_hdmi_encoder_post_crtc_powerdown()
386 clk_disable_unprepare(vc4_hdmi->pixel_clock); in vc4_hdmi_encoder_post_crtc_powerdown()
388 ret = pm_runtime_put(&vc4_hdmi->pdev->dev); in vc4_hdmi_encoder_post_crtc_powerdown()
407 * Apply a colorspace conversion to squash 0-255 down in vc4_hdmi_csc_setup()
408 * to 16-235. The matrix here is: in vc4_hdmi_csc_setup()
441 * Apply a colorspace conversion to squash 0-255 down in vc5_hdmi_csc_setup()
442 * to 16-235. The matrix here is: in vc5_hdmi_csc_setup()
474 bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; in vc4_hdmi_set_timings()
475 bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; in vc4_hdmi_set_timings()
476 bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; in vc4_hdmi_set_timings()
477 u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1; in vc4_hdmi_set_timings()
478 u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, in vc4_hdmi_set_timings()
480 VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, in vc4_hdmi_set_timings()
482 VC4_SET_FIELD(mode->crtc_vdisplay, VC4_HDMI_VERTA_VAL)); in vc4_hdmi_set_timings()
484 VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, in vc4_hdmi_set_timings()
487 VC4_SET_FIELD(mode->crtc_vtotal - in vc4_hdmi_set_timings()
488 mode->crtc_vsync_end - in vc4_hdmi_set_timings()
495 VC4_SET_FIELD(mode->hdisplay * pixel_rep, in vc4_hdmi_set_timings()
499 VC4_SET_FIELD((mode->htotal - in vc4_hdmi_set_timings()
500 mode->hsync_end) * pixel_rep, in vc4_hdmi_set_timings()
502 VC4_SET_FIELD((mode->hsync_end - in vc4_hdmi_set_timings()
503 mode->hsync_start) * pixel_rep, in vc4_hdmi_set_timings()
505 VC4_SET_FIELD((mode->hsync_start - in vc4_hdmi_set_timings()
506 mode->hdisplay) * pixel_rep, in vc4_hdmi_set_timings()
518 bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; in vc5_hdmi_set_timings()
519 bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; in vc5_hdmi_set_timings()
520 bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; in vc5_hdmi_set_timings()
521 u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1; in vc5_hdmi_set_timings()
522 u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, in vc5_hdmi_set_timings()
524 VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, in vc5_hdmi_set_timings()
526 VC4_SET_FIELD(mode->crtc_vdisplay, VC5_HDMI_VERTA_VAL)); in vc5_hdmi_set_timings()
528 VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, in vc5_hdmi_set_timings()
531 VC4_SET_FIELD(mode->crtc_vtotal - in vc5_hdmi_set_timings()
532 mode->crtc_vsync_end - in vc5_hdmi_set_timings()
540 VC4_SET_FIELD(mode->hdisplay * pixel_rep, in vc5_hdmi_set_timings()
542 VC4_SET_FIELD((mode->hsync_start - in vc5_hdmi_set_timings()
543 mode->hdisplay) * pixel_rep, in vc5_hdmi_set_timings()
547 VC4_SET_FIELD((mode->htotal - in vc5_hdmi_set_timings()
548 mode->hsync_end) * pixel_rep, in vc5_hdmi_set_timings()
550 VC4_SET_FIELD((mode->hsync_end - in vc5_hdmi_set_timings()
551 mode->hsync_start) * pixel_rep, in vc5_hdmi_set_timings()
589 struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; in vc4_hdmi_encoder_pre_crtc_configure()
594 ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev); in vc4_hdmi_encoder_pre_crtc_configure()
600 pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1); in vc4_hdmi_encoder_pre_crtc_configure()
601 ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate); in vc4_hdmi_encoder_pre_crtc_configure()
607 ret = clk_prepare_enable(vc4_hdmi->pixel_clock); in vc4_hdmi_encoder_pre_crtc_configure()
614 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must in vc4_hdmi_encoder_pre_crtc_configure()
616 * simulation. Otherwise, exact value is unimportant for HDMI in vc4_hdmi_encoder_pre_crtc_configure()
623 * both clocks. Which, for RPi0-3 implies a maximum pixel clock of in vc4_hdmi_encoder_pre_crtc_configure()
630 ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate); in vc4_hdmi_encoder_pre_crtc_configure()
636 ret = clk_prepare_enable(vc4_hdmi->hsm_clock); in vc4_hdmi_encoder_pre_crtc_configure()
639 clk_disable_unprepare(vc4_hdmi->pixel_clock); in vc4_hdmi_encoder_pre_crtc_configure()
647 ret = clk_set_min_rate(vc4_hdmi->pixel_bvb_clock, in vc4_hdmi_encoder_pre_crtc_configure()
651 clk_disable_unprepare(vc4_hdmi->hsm_clock); in vc4_hdmi_encoder_pre_crtc_configure()
652 clk_disable_unprepare(vc4_hdmi->pixel_clock); in vc4_hdmi_encoder_pre_crtc_configure()
656 ret = clk_prepare_enable(vc4_hdmi->pixel_bvb_clock); in vc4_hdmi_encoder_pre_crtc_configure()
659 clk_disable_unprepare(vc4_hdmi->hsm_clock); in vc4_hdmi_encoder_pre_crtc_configure()
660 clk_disable_unprepare(vc4_hdmi->pixel_clock); in vc4_hdmi_encoder_pre_crtc_configure()
664 if (vc4_hdmi->variant->reset) in vc4_hdmi_encoder_pre_crtc_configure()
665 vc4_hdmi->variant->reset(vc4_hdmi); in vc4_hdmi_encoder_pre_crtc_configure()
667 if (vc4_hdmi->variant->phy_init) in vc4_hdmi_encoder_pre_crtc_configure()
668 vc4_hdmi->variant->phy_init(vc4_hdmi, mode); in vc4_hdmi_encoder_pre_crtc_configure()
675 if (vc4_hdmi->variant->set_timings) in vc4_hdmi_encoder_pre_crtc_configure()
676 vc4_hdmi->variant->set_timings(vc4_hdmi, mode); in vc4_hdmi_encoder_pre_crtc_configure()
681 struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; in vc4_hdmi_encoder_pre_crtc_enable()
685 if (vc4_encoder->hdmi_monitor && in vc4_hdmi_encoder_pre_crtc_enable()
687 if (vc4_hdmi->variant->csc_setup) in vc4_hdmi_encoder_pre_crtc_enable()
688 vc4_hdmi->variant->csc_setup(vc4_hdmi, true); in vc4_hdmi_encoder_pre_crtc_enable()
690 vc4_encoder->limited_rgb_range = true; in vc4_hdmi_encoder_pre_crtc_enable()
692 if (vc4_hdmi->variant->csc_setup) in vc4_hdmi_encoder_pre_crtc_enable()
693 vc4_hdmi->variant->csc_setup(vc4_hdmi, false); in vc4_hdmi_encoder_pre_crtc_enable()
695 vc4_encoder->limited_rgb_range = false; in vc4_hdmi_encoder_pre_crtc_enable()
703 struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; in vc4_hdmi_encoder_post_crtc_enable()
706 bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; in vc4_hdmi_encoder_post_crtc_enable()
707 bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; in vc4_hdmi_encoder_post_crtc_enable()
720 if (vc4_encoder->hdmi_monitor) { in vc4_hdmi_encoder_post_crtc_enable()
743 if (vc4_encoder->hdmi_monitor) { in vc4_hdmi_encoder_post_crtc_enable()
770 struct drm_display_mode *mode = &crtc_state->adjusted_mode; in vc4_hdmi_encoder_atomic_check()
772 unsigned long long pixel_rate = mode->clock * 1000; in vc4_hdmi_encoder_atomic_check()
775 if (vc4_hdmi->variant->unsupported_odd_h_timings && in vc4_hdmi_encoder_atomic_check()
776 ((mode->hdisplay % 2) || (mode->hsync_start % 2) || in vc4_hdmi_encoder_atomic_check()
777 (mode->hsync_end % 2) || (mode->htotal % 2))) in vc4_hdmi_encoder_atomic_check()
778 return -EINVAL; in vc4_hdmi_encoder_atomic_check()
787 if (vc4_hdmi->disable_wifi_frequencies && in vc4_hdmi_encoder_atomic_check()
790 mode->clock = 238560; in vc4_hdmi_encoder_atomic_check()
791 pixel_rate = mode->clock * 1000; in vc4_hdmi_encoder_atomic_check()
794 if (pixel_rate > vc4_hdmi->variant->max_pixel_clock) in vc4_hdmi_encoder_atomic_check()
795 return -EINVAL; in vc4_hdmi_encoder_atomic_check()
806 if (vc4_hdmi->variant->unsupported_odd_h_timings && in vc4_hdmi_encoder_mode_valid()
807 ((mode->hdisplay % 2) || (mode->hsync_start % 2) || in vc4_hdmi_encoder_mode_valid()
808 (mode->hsync_end % 2) || (mode->htotal % 2))) in vc4_hdmi_encoder_mode_valid()
811 if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock) in vc4_hdmi_encoder_mode_valid()
848 /* HDMI audio codec callbacks */
851 u32 hsm_clock = clk_get_rate(vc4_hdmi->audio_clock); in vc4_hdmi_audio_set_mai_clock()
854 rational_best_approximation(hsm_clock, vc4_hdmi->audio.samplerate, in vc4_hdmi_audio_set_mai_clock()
863 VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M)); in vc4_hdmi_audio_set_mai_clock()
868 struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; in vc4_hdmi_set_n_cts()
869 struct drm_crtc *crtc = encoder->crtc; in vc4_hdmi_set_n_cts()
870 const struct drm_display_mode *mode = &crtc->state->adjusted_mode; in vc4_hdmi_set_n_cts()
871 u32 samplerate = vc4_hdmi->audio.samplerate; in vc4_hdmi_set_n_cts()
876 tmp = (u64)(mode->clock * 1000) * n; in vc4_hdmi_set_n_cts()
904 struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; in vc4_hdmi_audio_startup()
905 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_audio_startup() local
908 if (vc4_hdmi->audio.substream && vc4_hdmi->audio.substream != substream) in vc4_hdmi_audio_startup()
909 return -EINVAL; in vc4_hdmi_audio_startup()
911 vc4_hdmi->audio.substream = substream; in vc4_hdmi_audio_startup()
914 * If the HDMI encoder hasn't probed, or the encoder is in vc4_hdmi_audio_startup()
917 if (!encoder->crtc || !(HDMI_READ(HDMI_RAM_PACKET_CONFIG) & in vc4_hdmi_audio_startup()
919 return -ENODEV; in vc4_hdmi_audio_startup()
921 ret = snd_pcm_hw_constraint_eld(substream->runtime, connector->eld); in vc4_hdmi_audio_startup()
935 struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; in vc4_hdmi_audio_reset()
936 struct device *dev = &vc4_hdmi->pdev->dev; in vc4_hdmi_audio_reset()
939 vc4_hdmi->audio.streaming = false; in vc4_hdmi_audio_reset()
954 if (substream != vc4_hdmi->audio.substream) in vc4_hdmi_audio_shutdown()
959 vc4_hdmi->audio.substream = NULL; in vc4_hdmi_audio_shutdown()
962 /* HDMI audio codec callbacks */
968 struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; in vc4_hdmi_audio_hw_params()
969 struct device *dev = &vc4_hdmi->pdev->dev; in vc4_hdmi_audio_hw_params()
973 if (substream != vc4_hdmi->audio.substream) in vc4_hdmi_audio_hw_params()
974 return -EINVAL; in vc4_hdmi_audio_hw_params()
980 vc4_hdmi->audio.channels = params_channels(params); in vc4_hdmi_audio_hw_params()
981 vc4_hdmi->audio.samplerate = params_rate(params); in vc4_hdmi_audio_hw_params()
992 /* The B frame identifier should match the value used by alsa-lib (8) */ in vc4_hdmi_audio_hw_params()
998 channel_mask = GENMASK(vc4_hdmi->audio.channels - 1, 0); in vc4_hdmi_audio_hw_params()
1003 if (vc4_hdmi->audio.samplerate > 96000) { in vc4_hdmi_audio_hw_params()
1007 } else if (vc4_hdmi->audio.samplerate > 48000) { in vc4_hdmi_audio_hw_params()
1023 channel_map = vc4_hdmi->variant->channel_map(vc4_hdmi, channel_mask); in vc4_hdmi_audio_hw_params()
1040 vc4_hdmi->audio.streaming = true; in vc4_hdmi_audio_trigger()
1042 if (vc4_hdmi->variant->phy_rng_enable) in vc4_hdmi_audio_trigger()
1043 vc4_hdmi->variant->phy_rng_enable(vc4_hdmi); in vc4_hdmi_audio_trigger()
1046 VC4_SET_FIELD(vc4_hdmi->audio.channels, in vc4_hdmi_audio_trigger()
1056 if (vc4_hdmi->variant->phy_rng_disable) in vc4_hdmi_audio_trigger()
1057 vc4_hdmi->variant->phy_rng_disable(vc4_hdmi); in vc4_hdmi_audio_trigger()
1059 vc4_hdmi->audio.streaming = false; in vc4_hdmi_audio_trigger()
1082 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_audio_eld_ctl_info() local
1084 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; in vc4_hdmi_audio_eld_ctl_info()
1085 uinfo->count = sizeof(connector->eld); in vc4_hdmi_audio_eld_ctl_info()
1095 struct drm_connector *connector = &vc4_hdmi->connector; in vc4_hdmi_audio_eld_ctl_get() local
1097 memcpy(ucontrol->value.bytes.data, connector->eld, in vc4_hdmi_audio_eld_ctl_get()
1098 sizeof(connector->eld)); in vc4_hdmi_audio_eld_ctl_get()
1123 .name = "vc4-hdmi-codec-dai-component",
1145 .name = "vc4-hdmi-hifi",
1159 .name = "vc4-hdmi-cpu-dai-component",
1166 snd_soc_dai_init_dma_data(dai, &vc4_hdmi->audio.dma_data, NULL); in vc4_hdmi_audio_cpu_dai_probe()
1172 .name = "vc4-hdmi-cpu-dai",
1188 .chan_names[SNDRV_PCM_STREAM_PLAYBACK] = "audio-rx",
1195 &vc4_hdmi->variant->registers[HDMI_MAI_DATA]; in vc4_hdmi_audio_init()
1196 struct snd_soc_dai_link *dai_link = &vc4_hdmi->audio.link; in vc4_hdmi_audio_init()
1197 struct snd_soc_card *card = &vc4_hdmi->audio.card; in vc4_hdmi_audio_init()
1198 struct device *dev = &vc4_hdmi->pdev->dev; in vc4_hdmi_audio_init()
1203 if (!of_find_property(dev->of_node, "dmas", NULL)) { in vc4_hdmi_audio_init()
1205 "'dmas' DT property is missing, no HDMI audio\n"); in vc4_hdmi_audio_init()
1209 if (mai_data->reg != VC4_HD) { in vc4_hdmi_audio_init()
1211 return -EINVAL; in vc4_hdmi_audio_init()
1221 index = of_property_match_string(dev->of_node, "reg-names", "hd"); in vc4_hdmi_audio_init()
1226 addr = of_get_address(dev->of_node, index, NULL, NULL); in vc4_hdmi_audio_init()
1228 vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + mai_data->offset; in vc4_hdmi_audio_init()
1229 vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; in vc4_hdmi_audio_init()
1230 vc4_hdmi->audio.dma_data.maxburst = 2; in vc4_hdmi_audio_init()
1253 dai_link->cpus = &vc4_hdmi->audio.cpu; in vc4_hdmi_audio_init()
1254 dai_link->codecs = &vc4_hdmi->audio.codec; in vc4_hdmi_audio_init()
1255 dai_link->platforms = &vc4_hdmi->audio.platform; in vc4_hdmi_audio_init()
1257 dai_link->num_cpus = 1; in vc4_hdmi_audio_init()
1258 dai_link->num_codecs = 1; in vc4_hdmi_audio_init()
1259 dai_link->num_platforms = 1; in vc4_hdmi_audio_init()
1261 dai_link->name = "MAI"; in vc4_hdmi_audio_init()
1262 dai_link->stream_name = "MAI PCM"; in vc4_hdmi_audio_init()
1263 dai_link->codecs->dai_name = vc4_hdmi_audio_codec_dai_drv.name; in vc4_hdmi_audio_init()
1264 dai_link->cpus->dai_name = dev_name(dev); in vc4_hdmi_audio_init()
1265 dai_link->codecs->name = dev_name(dev); in vc4_hdmi_audio_init()
1266 dai_link->platforms->name = dev_name(dev); in vc4_hdmi_audio_init()
1268 card->dai_link = dai_link; in vc4_hdmi_audio_init()
1269 card->num_links = 1; in vc4_hdmi_audio_init()
1270 card->name = vc4_hdmi->variant->card_name; in vc4_hdmi_audio_init()
1271 card->dev = dev; in vc4_hdmi_audio_init()
1272 card->owner = THIS_MODULE; in vc4_hdmi_audio_init()
1276 * stores a pointer to the snd card object in dev->driver_data. This in vc4_hdmi_audio_init()
1277 * means we cannot use it for something else. The hdmi back-pointer is in vc4_hdmi_audio_init()
1278 * now stored in card->drvdata and should be retrieved with in vc4_hdmi_audio_init()
1295 if (vc4_hdmi->cec_irq_was_rx) { in vc4_cec_irq_handler_thread()
1296 if (vc4_hdmi->cec_rx_msg.len) in vc4_cec_irq_handler_thread()
1297 cec_received_msg(vc4_hdmi->cec_adap, in vc4_cec_irq_handler_thread()
1298 &vc4_hdmi->cec_rx_msg); in vc4_cec_irq_handler_thread()
1299 } else if (vc4_hdmi->cec_tx_ok) { in vc4_cec_irq_handler_thread()
1300 cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_OK, in vc4_cec_irq_handler_thread()
1307 cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_NACK, in vc4_cec_irq_handler_thread()
1315 struct cec_msg *msg = &vc4_hdmi->cec_rx_msg; in vc4_cec_read_msg()
1318 msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >> in vc4_cec_read_msg()
1320 for (i = 0; i < msg->len; i += 4) { in vc4_cec_read_msg()
1323 msg->msg[i] = val & 0xff; in vc4_cec_read_msg()
1324 msg->msg[i + 1] = (val >> 8) & 0xff; in vc4_cec_read_msg()
1325 msg->msg[i + 2] = (val >> 16) & 0xff; in vc4_cec_read_msg()
1326 msg->msg[i + 3] = (val >> 24) & 0xff; in vc4_cec_read_msg()
1338 vc4_hdmi->cec_rx_msg.len = 0; in vc4_cec_irq_handler()
1341 vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT; in vc4_cec_irq_handler()
1342 if (vc4_hdmi->cec_irq_was_rx) { in vc4_cec_irq_handler()
1348 vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD; in vc4_cec_irq_handler()
1417 for (i = 0; i < msg->len; i += 4) in vc4_hdmi_cec_adap_transmit()
1419 (msg->msg[i]) | in vc4_hdmi_cec_adap_transmit()
1420 (msg->msg[i + 1] << 8) | in vc4_hdmi_cec_adap_transmit()
1421 (msg->msg[i + 2] << 16) | in vc4_hdmi_cec_adap_transmit()
1422 (msg->msg[i + 3] << 24)); in vc4_hdmi_cec_adap_transmit()
1428 val |= (msg->len - 1) << VC4_HDMI_CEC_MESSAGE_LENGTH_SHIFT; in vc4_hdmi_cec_adap_transmit()
1444 struct platform_device *pdev = vc4_hdmi->pdev; in vc4_hdmi_cec_init()
1448 if (!vc4_hdmi->variant->cec_available) in vc4_hdmi_cec_init()
1451 vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops, in vc4_hdmi_cec_init()
1455 ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap); in vc4_hdmi_cec_init()
1459 cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector); in vc4_hdmi_cec_init()
1460 cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info); in vc4_hdmi_cec_init()
1473 ret = devm_request_threaded_irq(&pdev->dev, platform_get_irq(pdev, 0), in vc4_hdmi_cec_init()
1476 "vc4 hdmi cec", vc4_hdmi); in vc4_hdmi_cec_init()
1480 ret = cec_register_adapter(vc4_hdmi->cec_adap, &pdev->dev); in vc4_hdmi_cec_init()
1487 cec_delete_adapter(vc4_hdmi->cec_adap); in vc4_hdmi_cec_init()
1494 cec_unregister_adapter(vc4_hdmi->cec_adap); in vc4_hdmi_cec_exit()
1510 const struct vc4_hdmi_variant *variant = vc4_hdmi->variant; in vc4_hdmi_build_regset()
1515 regs = kcalloc(variant->num_registers, sizeof(*regs), in vc4_hdmi_build_regset()
1518 return -ENOMEM; in vc4_hdmi_build_regset()
1520 for (i = 0; i < variant->num_registers; i++) { in vc4_hdmi_build_regset()
1521 const struct vc4_hdmi_register *field = &variant->registers[i]; in vc4_hdmi_build_regset()
1523 if (field->reg != reg) in vc4_hdmi_build_regset()
1526 regs[count].name = field->name; in vc4_hdmi_build_regset()
1527 regs[count].offset = field->offset; in vc4_hdmi_build_regset()
1533 return -ENOMEM; in vc4_hdmi_build_regset()
1535 regset->base = __vc4_hdmi_get_field_base(vc4_hdmi, reg); in vc4_hdmi_build_regset()
1536 regset->regs = new_regs; in vc4_hdmi_build_regset()
1537 regset->nregs = count; in vc4_hdmi_build_regset()
1544 struct platform_device *pdev = vc4_hdmi->pdev; in vc4_hdmi_init_resources()
1545 struct device *dev = &pdev->dev; in vc4_hdmi_init_resources()
1548 vc4_hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0); in vc4_hdmi_init_resources()
1549 if (IS_ERR(vc4_hdmi->hdmicore_regs)) in vc4_hdmi_init_resources()
1550 return PTR_ERR(vc4_hdmi->hdmicore_regs); in vc4_hdmi_init_resources()
1552 vc4_hdmi->hd_regs = vc4_ioremap_regs(pdev, 1); in vc4_hdmi_init_resources()
1553 if (IS_ERR(vc4_hdmi->hd_regs)) in vc4_hdmi_init_resources()
1554 return PTR_ERR(vc4_hdmi->hd_regs); in vc4_hdmi_init_resources()
1556 ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD); in vc4_hdmi_init_resources()
1560 ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI); in vc4_hdmi_init_resources()
1564 vc4_hdmi->pixel_clock = devm_clk_get(dev, "pixel"); in vc4_hdmi_init_resources()
1565 if (IS_ERR(vc4_hdmi->pixel_clock)) { in vc4_hdmi_init_resources()
1566 ret = PTR_ERR(vc4_hdmi->pixel_clock); in vc4_hdmi_init_resources()
1567 if (ret != -EPROBE_DEFER) in vc4_hdmi_init_resources()
1572 vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi"); in vc4_hdmi_init_resources()
1573 if (IS_ERR(vc4_hdmi->hsm_clock)) { in vc4_hdmi_init_resources()
1574 DRM_ERROR("Failed to get HDMI state machine clock\n"); in vc4_hdmi_init_resources()
1575 return PTR_ERR(vc4_hdmi->hsm_clock); in vc4_hdmi_init_resources()
1577 vc4_hdmi->audio_clock = vc4_hdmi->hsm_clock; in vc4_hdmi_init_resources()
1584 struct platform_device *pdev = vc4_hdmi->pdev; in vc5_hdmi_init_resources()
1585 struct device *dev = &pdev->dev; in vc5_hdmi_init_resources()
1588 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi"); in vc5_hdmi_init_resources()
1590 return -ENODEV; in vc5_hdmi_init_resources()
1592 vc4_hdmi->hdmicore_regs = devm_ioremap(dev, res->start, in vc5_hdmi_init_resources()
1594 if (!vc4_hdmi->hdmicore_regs) in vc5_hdmi_init_resources()
1595 return -ENOMEM; in vc5_hdmi_init_resources()
1599 return -ENODEV; in vc5_hdmi_init_resources()
1601 vc4_hdmi->hd_regs = devm_ioremap(dev, res->start, resource_size(res)); in vc5_hdmi_init_resources()
1602 if (!vc4_hdmi->hd_regs) in vc5_hdmi_init_resources()
1603 return -ENOMEM; in vc5_hdmi_init_resources()
1607 return -ENODEV; in vc5_hdmi_init_resources()
1609 vc4_hdmi->cec_regs = devm_ioremap(dev, res->start, resource_size(res)); in vc5_hdmi_init_resources()
1610 if (!vc4_hdmi->cec_regs) in vc5_hdmi_init_resources()
1611 return -ENOMEM; in vc5_hdmi_init_resources()
1615 return -ENODEV; in vc5_hdmi_init_resources()
1617 vc4_hdmi->csc_regs = devm_ioremap(dev, res->start, resource_size(res)); in vc5_hdmi_init_resources()
1618 if (!vc4_hdmi->csc_regs) in vc5_hdmi_init_resources()
1619 return -ENOMEM; in vc5_hdmi_init_resources()
1623 return -ENODEV; in vc5_hdmi_init_resources()
1625 vc4_hdmi->dvp_regs = devm_ioremap(dev, res->start, resource_size(res)); in vc5_hdmi_init_resources()
1626 if (!vc4_hdmi->dvp_regs) in vc5_hdmi_init_resources()
1627 return -ENOMEM; in vc5_hdmi_init_resources()
1631 return -ENODEV; in vc5_hdmi_init_resources()
1633 vc4_hdmi->phy_regs = devm_ioremap(dev, res->start, resource_size(res)); in vc5_hdmi_init_resources()
1634 if (!vc4_hdmi->phy_regs) in vc5_hdmi_init_resources()
1635 return -ENOMEM; in vc5_hdmi_init_resources()
1639 return -ENODEV; in vc5_hdmi_init_resources()
1641 vc4_hdmi->ram_regs = devm_ioremap(dev, res->start, resource_size(res)); in vc5_hdmi_init_resources()
1642 if (!vc4_hdmi->ram_regs) in vc5_hdmi_init_resources()
1643 return -ENOMEM; in vc5_hdmi_init_resources()
1647 return -ENODEV; in vc5_hdmi_init_resources()
1649 vc4_hdmi->rm_regs = devm_ioremap(dev, res->start, resource_size(res)); in vc5_hdmi_init_resources()
1650 if (!vc4_hdmi->rm_regs) in vc5_hdmi_init_resources()
1651 return -ENOMEM; in vc5_hdmi_init_resources()
1653 vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi"); in vc5_hdmi_init_resources()
1654 if (IS_ERR(vc4_hdmi->hsm_clock)) { in vc5_hdmi_init_resources()
1655 DRM_ERROR("Failed to get HDMI state machine clock\n"); in vc5_hdmi_init_resources()
1656 return PTR_ERR(vc4_hdmi->hsm_clock); in vc5_hdmi_init_resources()
1659 vc4_hdmi->pixel_bvb_clock = devm_clk_get(dev, "bvb"); in vc5_hdmi_init_resources()
1660 if (IS_ERR(vc4_hdmi->pixel_bvb_clock)) { in vc5_hdmi_init_resources()
1662 return PTR_ERR(vc4_hdmi->pixel_bvb_clock); in vc5_hdmi_init_resources()
1665 vc4_hdmi->audio_clock = devm_clk_get(dev, "audio"); in vc5_hdmi_init_resources()
1666 if (IS_ERR(vc4_hdmi->audio_clock)) { in vc5_hdmi_init_resources()
1668 return PTR_ERR(vc4_hdmi->audio_clock); in vc5_hdmi_init_resources()
1671 vc4_hdmi->reset = devm_reset_control_get(dev, NULL); in vc5_hdmi_init_resources()
1672 if (IS_ERR(vc4_hdmi->reset)) { in vc5_hdmi_init_resources()
1673 DRM_ERROR("Failed to get HDMI reset line\n"); in vc5_hdmi_init_resources()
1674 return PTR_ERR(vc4_hdmi->reset); in vc5_hdmi_init_resources()
1693 return -ENOMEM; in vc4_hdmi_bind()
1696 encoder = &vc4_hdmi->encoder.base.base; in vc4_hdmi_bind()
1697 vc4_hdmi->encoder.base.type = variant->encoder_type; in vc4_hdmi_bind()
1698 vc4_hdmi->encoder.base.pre_crtc_configure = vc4_hdmi_encoder_pre_crtc_configure; in vc4_hdmi_bind()
1699 vc4_hdmi->encoder.base.pre_crtc_enable = vc4_hdmi_encoder_pre_crtc_enable; in vc4_hdmi_bind()
1700 vc4_hdmi->encoder.base.post_crtc_enable = vc4_hdmi_encoder_post_crtc_enable; in vc4_hdmi_bind()
1701 vc4_hdmi->encoder.base.post_crtc_disable = vc4_hdmi_encoder_post_crtc_disable; in vc4_hdmi_bind()
1702 vc4_hdmi->encoder.base.post_crtc_powerdown = vc4_hdmi_encoder_post_crtc_powerdown; in vc4_hdmi_bind()
1703 vc4_hdmi->pdev = pdev; in vc4_hdmi_bind()
1704 vc4_hdmi->variant = variant; in vc4_hdmi_bind()
1706 ret = variant->init_resources(vc4_hdmi); in vc4_hdmi_bind()
1710 ddc_node = of_parse_phandle(dev->of_node, "ddc", 0); in vc4_hdmi_bind()
1713 return -ENODEV; in vc4_hdmi_bind()
1716 vc4_hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node); in vc4_hdmi_bind()
1718 if (!vc4_hdmi->ddc) { in vc4_hdmi_bind()
1720 return -EPROBE_DEFER; in vc4_hdmi_bind()
1724 * we'll use the HDMI core's register. in vc4_hdmi_bind()
1726 if (of_find_property(dev->of_node, "hpd-gpios", &value)) { in vc4_hdmi_bind()
1729 vc4_hdmi->hpd_gpio = of_get_named_gpio_flags(dev->of_node, in vc4_hdmi_bind()
1730 "hpd-gpios", 0, in vc4_hdmi_bind()
1732 if (vc4_hdmi->hpd_gpio < 0) { in vc4_hdmi_bind()
1733 ret = vc4_hdmi->hpd_gpio; in vc4_hdmi_bind()
1737 vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW; in vc4_hdmi_bind()
1740 vc4_hdmi->disable_wifi_frequencies = in vc4_hdmi_bind()
1741 of_property_read_bool(dev->of_node, "wifi-2.4ghz-coexistence"); in vc4_hdmi_bind()
1760 vc4_debugfs_add_file(drm, variant->debugfs_name, in vc4_hdmi_bind()
1769 vc4_hdmi_connector_destroy(&vc4_hdmi->connector); in vc4_hdmi_bind()
1774 put_device(&vc4_hdmi->ddc->dev); in vc4_hdmi_bind()
1805 kfree(vc4_hdmi->hdmi_regset.regs); in vc4_hdmi_unbind()
1806 kfree(vc4_hdmi->hd_regset.regs); in vc4_hdmi_unbind()
1809 vc4_hdmi_connector_destroy(&vc4_hdmi->connector); in vc4_hdmi_unbind()
1810 drm_encoder_cleanup(&vc4_hdmi->encoder.base.base); in vc4_hdmi_unbind()
1814 put_device(&vc4_hdmi->ddc->dev); in vc4_hdmi_unbind()
1824 return component_add(&pdev->dev, &vc4_hdmi_ops); in vc4_hdmi_dev_probe()
1829 component_del(&pdev->dev, &vc4_hdmi_ops); in vc4_hdmi_dev_remove()
1836 .card_name = "vc4-hdmi",
1856 .card_name = "vc4-hdmi-0",
1882 .card_name = "vc4-hdmi-1",
1906 { .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant },
1907 { .compatible = "brcm,bcm2711-hdmi0", .data = &bcm2711_hdmi0_variant },
1908 { .compatible = "brcm,bcm2711-hdmi1", .data = &bcm2711_hdmi1_variant },