Lines Matching +full:bcm2835 +full:- +full:v3d
1 // SPDX-License-Identifier: GPL-2.0-only
27 * output-specific clock. Since the encoders also directly consume
49 #define CRTC_WRITE(offset, val) writel(val, vc4_crtc->regs + (offset))
50 #define CRTC_READ(offset) readl(vc4_crtc->regs + (offset))
72 /* Top/base are supposed to be 4-pixel aligned, but the in vc4_crtc_get_cob_allocation()
79 return top - base + 4; in vc4_crtc_get_cob_allocation()
88 struct drm_device *dev = crtc->dev; in vc4_crtc_get_scanout_position()
91 struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state); in vc4_crtc_get_scanout_position()
108 val = HVS_READ(SCALER_DISPSTATX(vc4_crtc_state->assigned_channel)); in vc4_crtc_get_scanout_position()
120 if (mode->flags & DRM_MODE_FLAG_INTERLACE) { in vc4_crtc_get_scanout_position()
125 *hpos += mode->crtc_htotal / 2; in vc4_crtc_get_scanout_position()
128 cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc_state->assigned_channel); in vc4_crtc_get_scanout_position()
129 /* This is the offset we need for translating hvs -> pv scanout pos. */ in vc4_crtc_get_scanout_position()
130 fifo_lines = cob_size / mode->crtc_hdisplay; in vc4_crtc_get_scanout_position()
145 * incrementing vpos. Therefore we choose HVS read position - in vc4_crtc_get_scanout_position()
149 *vpos -= fifo_lines + 1; in vc4_crtc_get_scanout_position()
157 * fifo with new lines from the top-most lines of the new framebuffers. in vc4_crtc_get_scanout_position()
163 vblank_lines = mode->vtotal - mode->vdisplay; in vc4_crtc_get_scanout_position()
175 *vpos = -vblank_lines; in vc4_crtc_get_scanout_position()
178 *stime = vc4_crtc->t_vblank; in vc4_crtc_get_scanout_position()
180 *etime = vc4_crtc->t_vblank; in vc4_crtc_get_scanout_position()
213 struct vc4_dev *vc4 = to_vc4_dev(vc4_crtc->base.dev); in vc4_get_fifo_full_level()
214 u32 fifo_len_bytes = pv_data->fifo_depth; in vc4_get_fifo_full_level()
229 return fifo_len_bytes - 2 * HVS_FIFO_LATENCY_PIX; in vc4_get_fifo_full_level()
231 return fifo_len_bytes - 14; in vc4_get_fifo_full_level()
239 if (crtc_data->hvs_output == 5) in vc4_get_fifo_full_level()
255 if (!vc4->hvs->hvs5) in vc4_get_fifo_full_level()
256 return fifo_len_bytes - 3 * HVS_FIFO_LATENCY_PIX - 1; in vc4_get_fifo_full_level()
258 return fifo_len_bytes - 3 * HVS_FIFO_LATENCY_PIX; in vc4_get_fifo_full_level()
290 drm_connector_list_iter_begin(crtc->dev, &conn_iter); in vc4_get_crtc_encoder()
297 if (conn_state->crtc == crtc) { in vc4_get_crtc_encoder()
299 return connector->encoder; in vc4_get_crtc_encoder()
318 struct drm_device *dev = crtc->dev; in vc4_crtc_config_pv()
325 struct drm_crtc_state *crtc_state = crtc->state; in vc4_crtc_config_pv()
326 struct drm_display_mode *mode = &crtc_state->adjusted_mode; in vc4_crtc_config_pv()
327 bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE; in vc4_crtc_config_pv()
328 u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1; in vc4_crtc_config_pv()
329 bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 || in vc4_crtc_config_pv()
330 vc4_encoder->type == VC4_ENCODER_TYPE_DSI1); in vc4_crtc_config_pv()
332 u8 ppc = pv_data->pixels_per_clock; in vc4_crtc_config_pv()
336 struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev); in vc4_crtc_config_pv()
337 dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs before:\n", in vc4_crtc_config_pv()
339 drm_print_regset32(&p, &vc4_crtc->regset); in vc4_crtc_config_pv()
345 VC4_SET_FIELD((mode->htotal - mode->hsync_end) * pixel_rep / ppc, in vc4_crtc_config_pv()
347 VC4_SET_FIELD((mode->hsync_end - mode->hsync_start) * pixel_rep / ppc, in vc4_crtc_config_pv()
351 VC4_SET_FIELD((mode->hsync_start - mode->hdisplay) * pixel_rep / ppc, in vc4_crtc_config_pv()
353 VC4_SET_FIELD(mode->hdisplay * pixel_rep / ppc, in vc4_crtc_config_pv()
357 VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, in vc4_crtc_config_pv()
359 VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, in vc4_crtc_config_pv()
362 VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, in vc4_crtc_config_pv()
364 VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE)); in vc4_crtc_config_pv()
368 VC4_SET_FIELD(mode->crtc_vtotal - in vc4_crtc_config_pv()
369 mode->crtc_vsync_end - 1, in vc4_crtc_config_pv()
371 VC4_SET_FIELD(mode->crtc_vsync_end - in vc4_crtc_config_pv()
372 mode->crtc_vsync_start, in vc4_crtc_config_pv()
375 VC4_SET_FIELD(mode->crtc_vsync_start - in vc4_crtc_config_pv()
376 mode->crtc_vdisplay, in vc4_crtc_config_pv()
378 VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE)); in vc4_crtc_config_pv()
389 VC4_SET_FIELD(mode->htotal * pixel_rep / 2, in vc4_crtc_config_pv()
399 CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep); in vc4_crtc_config_pv()
401 if (vc4->hvs->hvs5) in vc4_crtc_config_pv()
409 VC4_SET_FIELD(pixel_rep - 1, PV_CONTROL_PIXEL_REP) | in vc4_crtc_config_pv()
413 VC4_SET_FIELD(vc4_encoder->clock_select, in vc4_crtc_config_pv()
417 struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev); in vc4_crtc_config_pv()
418 dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs after:\n", in vc4_crtc_config_pv()
420 drm_print_regset32(&p, &vc4_crtc->regset); in vc4_crtc_config_pv()
439 struct drm_device *dev = crtc->dev; in vc4_crtc_disable()
465 if (vc4_encoder && vc4_encoder->post_crtc_disable) in vc4_crtc_disable()
466 vc4_encoder->post_crtc_disable(encoder, state); in vc4_crtc_disable()
471 if (vc4_encoder && vc4_encoder->post_crtc_powerdown) in vc4_crtc_disable()
472 vc4_encoder->post_crtc_powerdown(encoder, state); in vc4_crtc_disable()
482 drm_for_each_encoder(encoder, crtc->dev) { in vc4_crtc_get_encoder_by_type()
485 if (vc4_encoder->type == type) in vc4_crtc_get_encoder_by_type()
494 struct drm_device *drm = crtc->dev; in vc4_crtc_disable_at_boot()
502 if (!(of_device_is_compatible(vc4_crtc->pdev->dev.of_node, in vc4_crtc_disable_at_boot()
503 "brcm,bcm2711-pixelvalve2") || in vc4_crtc_disable_at_boot()
504 of_device_is_compatible(vc4_crtc->pdev->dev.of_node, in vc4_crtc_disable_at_boot()
505 "brcm,bcm2711-pixelvalve4"))) in vc4_crtc_disable_at_boot()
514 channel = vc4_hvs_get_fifo_from_output(drm, vc4_crtc->data->hvs_output); in vc4_crtc_disable_at_boot()
523 encoder_type = pv_data->encoder_types[encoder_sel]; in vc4_crtc_disable_at_boot()
539 struct drm_device *dev = crtc->dev; in vc4_crtc_atomic_disable()
546 vc4_crtc_disable(crtc, encoder, state, old_vc4_state->assigned_channel); in vc4_crtc_atomic_disable()
552 if (crtc->state->event) { in vc4_crtc_atomic_disable()
555 spin_lock_irqsave(&dev->event_lock, flags); in vc4_crtc_atomic_disable()
556 drm_crtc_send_vblank_event(crtc, crtc->state->event); in vc4_crtc_atomic_disable()
557 crtc->state->event = NULL; in vc4_crtc_atomic_disable()
558 spin_unlock_irqrestore(&dev->event_lock, flags); in vc4_crtc_atomic_disable()
565 struct drm_device *dev = crtc->dev; in vc4_crtc_atomic_enable()
580 if (vc4_encoder->pre_crtc_configure) in vc4_crtc_atomic_enable()
581 vc4_encoder->pre_crtc_configure(encoder, state); in vc4_crtc_atomic_enable()
587 if (vc4_encoder->pre_crtc_enable) in vc4_crtc_atomic_enable()
588 vc4_encoder->pre_crtc_enable(encoder, state); in vc4_crtc_atomic_enable()
596 if (vc4_encoder->post_crtc_enable) in vc4_crtc_atomic_enable()
597 vc4_encoder->post_crtc_enable(encoder, state); in vc4_crtc_atomic_enable()
604 if (mode->flags & DRM_MODE_FLAG_DBLSCAN) { in vc4_crtc_mode_valid()
606 crtc->base.id); in vc4_crtc_mode_valid()
622 *left = vc4_state->margins.left; in vc4_crtc_get_margins()
623 *right = vc4_state->margins.right; in vc4_crtc_get_margins()
624 *top = vc4_state->margins.top; in vc4_crtc_get_margins()
625 *bottom = vc4_state->margins.bottom; in vc4_crtc_get_margins()
632 for_each_new_connector_in_state(state->state, conn, conn_state, i) { in vc4_crtc_get_margins()
633 if (conn_state->crtc != state->crtc) in vc4_crtc_get_margins()
636 *left = conn_state->tv.margins.left; in vc4_crtc_get_margins()
637 *right = conn_state->tv.margins.right; in vc4_crtc_get_margins()
638 *top = conn_state->tv.margins.top; in vc4_crtc_get_margins()
639 *bottom = conn_state->tv.margins.bottom; in vc4_crtc_get_margins()
660 if (conn_state->crtc != crtc) in vc4_crtc_atomic_check()
663 vc4_state->margins.left = conn_state->tv.margins.left; in vc4_crtc_atomic_check()
664 vc4_state->margins.right = conn_state->tv.margins.right; in vc4_crtc_atomic_check()
665 vc4_state->margins.top = conn_state->tv.margins.top; in vc4_crtc_atomic_check()
666 vc4_state->margins.bottom = conn_state->tv.margins.bottom; in vc4_crtc_atomic_check()
691 struct drm_crtc *crtc = &vc4_crtc->base; in vc4_crtc_handle_page_flip()
692 struct drm_device *dev = crtc->dev; in vc4_crtc_handle_page_flip()
694 struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); in vc4_crtc_handle_page_flip()
695 u32 chan = vc4_state->assigned_channel; in vc4_crtc_handle_page_flip()
698 spin_lock_irqsave(&dev->event_lock, flags); in vc4_crtc_handle_page_flip()
699 if (vc4_crtc->event && in vc4_crtc_handle_page_flip()
700 (vc4_state->mm.start == HVS_READ(SCALER_DISPLACTX(chan)) || in vc4_crtc_handle_page_flip()
701 vc4_state->feed_txp)) { in vc4_crtc_handle_page_flip()
702 drm_crtc_send_vblank_event(crtc, vc4_crtc->event); in vc4_crtc_handle_page_flip()
703 vc4_crtc->event = NULL; in vc4_crtc_handle_page_flip()
714 spin_unlock_irqrestore(&dev->event_lock, flags); in vc4_crtc_handle_page_flip()
719 crtc->t_vblank = ktime_get(); in vc4_crtc_handle_vblank()
720 drm_crtc_handle_vblank(&crtc->base); in vc4_crtc_handle_vblank()
748 /* Called when the V3D execution for the BO being flipped to is done, so that
756 struct drm_crtc *crtc = flip_state->crtc; in vc4_async_page_flip_complete()
757 struct drm_device *dev = crtc->dev; in vc4_async_page_flip_complete()
758 struct drm_plane *plane = crtc->primary; in vc4_async_page_flip_complete()
760 vc4_plane_async_set_fb(plane, flip_state->fb); in vc4_async_page_flip_complete()
761 if (flip_state->event) { in vc4_async_page_flip_complete()
764 spin_lock_irqsave(&dev->event_lock, flags); in vc4_async_page_flip_complete()
765 drm_crtc_send_vblank_event(crtc, flip_state->event); in vc4_async_page_flip_complete()
766 spin_unlock_irqrestore(&dev->event_lock, flags); in vc4_async_page_flip_complete()
770 drm_framebuffer_put(flip_state->fb); in vc4_async_page_flip_complete()
774 * FIXME: we should move to generic async-page-flip when it's in vc4_async_page_flip_complete()
775 * available, so that we can get rid of this hand-made cleanup_fb() in vc4_async_page_flip_complete()
778 if (flip_state->old_fb) { in vc4_async_page_flip_complete()
782 cma_bo = drm_fb_cma_get_gem_obj(flip_state->old_fb, 0); in vc4_async_page_flip_complete()
783 bo = to_vc4_bo(&cma_bo->base); in vc4_async_page_flip_complete()
785 drm_framebuffer_put(flip_state->old_fb); in vc4_async_page_flip_complete()
791 /* Implements async (non-vblank-synced) page flips.
795 * when V3D is done with the BO being flipped to.
802 struct drm_device *dev = crtc->dev; in vc4_async_page_flip()
803 struct drm_plane *plane = crtc->primary; in vc4_async_page_flip()
807 struct vc4_bo *bo = to_vc4_bo(&cma_bo->base); in vc4_async_page_flip()
811 * plane is later updated through the non-async path. in vc4_async_page_flip()
812 * FIXME: we should move to generic async-page-flip when it's in vc4_async_page_flip()
813 * available, so that we can get rid of this hand-made prepare_fb() in vc4_async_page_flip()
823 return -ENOMEM; in vc4_async_page_flip()
827 flip_state->fb = fb; in vc4_async_page_flip()
828 flip_state->crtc = crtc; in vc4_async_page_flip()
829 flip_state->event = event; in vc4_async_page_flip()
835 * FIXME: we should move to generic async-page-flip when it's in vc4_async_page_flip()
836 * available, so that we can get rid of this hand-made cleanup_fb() in vc4_async_page_flip()
839 flip_state->old_fb = plane->state->fb; in vc4_async_page_flip()
840 if (flip_state->old_fb) in vc4_async_page_flip()
841 drm_framebuffer_get(flip_state->old_fb); in vc4_async_page_flip()
849 drm_atomic_set_fb_for_plane(plane->state, fb); in vc4_async_page_flip()
851 vc4_queue_seqno_cb(dev, &flip_state->cb, bo->seqno, in vc4_async_page_flip()
878 old_vc4_state = to_vc4_crtc_state(crtc->state); in vc4_crtc_duplicate_state()
879 vc4_state->feed_txp = old_vc4_state->feed_txp; in vc4_crtc_duplicate_state()
880 vc4_state->margins = old_vc4_state->margins; in vc4_crtc_duplicate_state()
881 vc4_state->assigned_channel = old_vc4_state->assigned_channel; in vc4_crtc_duplicate_state()
883 __drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base); in vc4_crtc_duplicate_state()
884 return &vc4_state->base; in vc4_crtc_duplicate_state()
890 struct vc4_dev *vc4 = to_vc4_dev(crtc->dev); in vc4_crtc_destroy_state()
893 if (drm_mm_node_allocated(&vc4_state->mm)) { in vc4_crtc_destroy_state()
896 spin_lock_irqsave(&vc4->hvs->mm_lock, flags); in vc4_crtc_destroy_state()
897 drm_mm_remove_node(&vc4_state->mm); in vc4_crtc_destroy_state()
898 spin_unlock_irqrestore(&vc4->hvs->mm_lock, flags); in vc4_crtc_destroy_state()
909 if (crtc->state) in vc4_crtc_reset()
910 vc4_crtc_destroy_state(crtc, crtc->state); in vc4_crtc_reset()
914 crtc->state = NULL; in vc4_crtc_reset()
918 vc4_crtc_state->assigned_channel = VC4_HVS_CHANNEL_DISABLED; in vc4_crtc_reset()
919 __drm_atomic_helper_crtc_reset(crtc, &vc4_crtc_state->base); in vc4_crtc_reset()
1056 { .compatible = "brcm,bcm2835-pixelvalve0", .data = &bcm2835_pv0_data },
1057 { .compatible = "brcm,bcm2835-pixelvalve1", .data = &bcm2835_pv1_data },
1058 { .compatible = "brcm,bcm2835-pixelvalve2", .data = &bcm2835_pv2_data },
1059 { .compatible = "brcm,bcm2711-pixelvalve0", .data = &bcm2711_pv0_data },
1060 { .compatible = "brcm,bcm2711-pixelvalve1", .data = &bcm2711_pv1_data },
1061 { .compatible = "brcm,bcm2711-pixelvalve2", .data = &bcm2711_pv2_data },
1062 { .compatible = "brcm,bcm2711-pixelvalve3", .data = &bcm2711_pv3_data },
1063 { .compatible = "brcm,bcm2711-pixelvalve4", .data = &bcm2711_pv4_data },
1072 const enum vc4_encoder_type *encoder_types = pv_data->encoder_types; in vc4_set_crtc_possible_masks()
1079 if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL) in vc4_set_crtc_possible_masks()
1083 for (i = 0; i < ARRAY_SIZE(pv_data->encoder_types); i++) { in vc4_set_crtc_possible_masks()
1084 if (vc4_encoder->type == encoder_types[i]) { in vc4_set_crtc_possible_masks()
1085 vc4_encoder->clock_select = i; in vc4_set_crtc_possible_masks()
1086 encoder->possible_crtcs |= drm_crtc_mask(crtc); in vc4_set_crtc_possible_masks()
1098 struct drm_crtc *crtc = &vc4_crtc->base; in vc4_crtc_init()
1110 dev_err(drm->dev, "failed to construct primary plane\n"); in vc4_crtc_init()
1118 if (!vc4->hvs->hvs5) { in vc4_crtc_init()
1119 drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r)); in vc4_crtc_init()
1121 drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size); in vc4_crtc_init()
1126 drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size); in vc4_crtc_init()
1129 for (i = 0; i < crtc->gamma_size; i++) { in vc4_crtc_init()
1130 vc4_crtc->lut_r[i] = i; in vc4_crtc_init()
1131 vc4_crtc->lut_g[i] = i; in vc4_crtc_init()
1132 vc4_crtc->lut_b[i] = i; in vc4_crtc_init()
1150 return -ENOMEM; in vc4_crtc_bind()
1151 crtc = &vc4_crtc->base; in vc4_crtc_bind()
1155 return -ENODEV; in vc4_crtc_bind()
1156 vc4_crtc->data = &pv_data->base; in vc4_crtc_bind()
1157 vc4_crtc->pdev = pdev; in vc4_crtc_bind()
1159 vc4_crtc->regs = vc4_ioremap_regs(pdev, 0); in vc4_crtc_bind()
1160 if (IS_ERR(vc4_crtc->regs)) in vc4_crtc_bind()
1161 return PTR_ERR(vc4_crtc->regs); in vc4_crtc_bind()
1163 vc4_crtc->regset.base = vc4_crtc->regs; in vc4_crtc_bind()
1164 vc4_crtc->regset.regs = crtc_regs; in vc4_crtc_bind()
1165 vc4_crtc->regset.nregs = ARRAY_SIZE(crtc_regs); in vc4_crtc_bind()
1184 vc4_debugfs_add_regset32(drm, pv_data->debugfs_name, in vc4_crtc_bind()
1185 &vc4_crtc->regset); in vc4_crtc_bind()
1191 &drm->mode_config.plane_list, head) { in vc4_crtc_bind()
1192 if (destroy_plane->possible_crtcs == drm_crtc_mask(crtc)) in vc4_crtc_bind()
1193 destroy_plane->funcs->destroy(destroy_plane); in vc4_crtc_bind()
1205 vc4_crtc_destroy(&vc4_crtc->base); in vc4_crtc_unbind()
1219 return component_add(&pdev->dev, &vc4_crtc_ops); in vc4_crtc_dev_probe()
1224 component_del(&pdev->dev, &vc4_crtc_ops); in vc4_crtc_dev_remove()