Lines Matching +full:zynqmp +full:- +full:dpsub +full:- +full:1
1 // SPDX-License-Identifier: GPL-2.0
3 * ZynqMP DisplayPort Subsystem - KMS API
5 * Copyright (C) 2017 - 2021 Xilinx, Inc.
8 * - Hyun Woo Kwon <[email protected]>
9 * - Laurent Pinchart <[email protected]>
47 return container_of(drm, struct zynqmp_dpsub_drm, dev)->dpsub; in to_zynqmp_dpsub()
50 /* -----------------------------------------------------------------------------
61 if (!new_plane_state->crtc) in zynqmp_dpsub_plane_atomic_check()
64 crtc_state = drm_atomic_get_crtc_state(state, new_plane_state->crtc); in zynqmp_dpsub_plane_atomic_check()
80 struct zynqmp_dpsub *dpsub = to_zynqmp_dpsub(plane->dev); in zynqmp_dpsub_plane_atomic_disable() local
81 struct zynqmp_disp_layer *layer = dpsub->layers[plane->index]; in zynqmp_dpsub_plane_atomic_disable()
83 if (!old_state->fb) in zynqmp_dpsub_plane_atomic_disable()
88 if (plane->index == ZYNQMP_DPSUB_LAYER_GFX) in zynqmp_dpsub_plane_atomic_disable()
89 zynqmp_disp_blend_set_global_alpha(dpsub->disp, false, in zynqmp_dpsub_plane_atomic_disable()
90 plane->state->alpha >> 8); in zynqmp_dpsub_plane_atomic_disable()
98 struct zynqmp_dpsub *dpsub = to_zynqmp_dpsub(plane->dev); in zynqmp_dpsub_plane_atomic_update() local
99 struct zynqmp_disp_layer *layer = dpsub->layers[plane->index]; in zynqmp_dpsub_plane_atomic_update()
102 if (!old_state->fb || in zynqmp_dpsub_plane_atomic_update()
103 old_state->fb->format->format != new_state->fb->format->format) in zynqmp_dpsub_plane_atomic_update()
112 if (old_state->fb) in zynqmp_dpsub_plane_atomic_update()
115 zynqmp_disp_layer_set_format(layer, new_state->fb->format); in zynqmp_dpsub_plane_atomic_update()
120 if (plane->index == ZYNQMP_DPSUB_LAYER_GFX) in zynqmp_dpsub_plane_atomic_update()
121 zynqmp_disp_blend_set_global_alpha(dpsub->disp, true, in zynqmp_dpsub_plane_atomic_update()
122 plane->state->alpha >> 8); in zynqmp_dpsub_plane_atomic_update()
127 * implicitly after DPSUB reset during display mode change. DRM in zynqmp_dpsub_plane_atomic_update()
148 static int zynqmp_dpsub_create_planes(struct zynqmp_dpsub *dpsub) in zynqmp_dpsub_create_planes() argument
153 for (i = 0; i < ARRAY_SIZE(dpsub->drm->planes); i++) { in zynqmp_dpsub_create_planes()
154 struct zynqmp_disp_layer *layer = dpsub->layers[i]; in zynqmp_dpsub_create_planes()
155 struct drm_plane *plane = &dpsub->drm->planes[i]; in zynqmp_dpsub_create_planes()
162 return -ENOMEM; in zynqmp_dpsub_create_planes()
167 ret = drm_universal_plane_init(&dpsub->drm->dev, plane, 0, in zynqmp_dpsub_create_planes()
185 /* -----------------------------------------------------------------------------
191 return container_of(crtc, struct zynqmp_dpsub_drm, crtc)->dpsub; in crtc_to_dpsub()
197 struct zynqmp_dpsub *dpsub = crtc_to_dpsub(crtc); in zynqmp_dpsub_crtc_atomic_enable() local
198 struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; in zynqmp_dpsub_crtc_atomic_enable()
201 pm_runtime_get_sync(dpsub->dev); in zynqmp_dpsub_crtc_atomic_enable()
203 zynqmp_disp_setup_clock(dpsub->disp, adjusted_mode->clock * 1000); in zynqmp_dpsub_crtc_atomic_enable()
205 ret = clk_prepare_enable(dpsub->vid_clk); in zynqmp_dpsub_crtc_atomic_enable()
207 dev_err(dpsub->dev, "failed to enable a pixel clock\n"); in zynqmp_dpsub_crtc_atomic_enable()
208 pm_runtime_put_sync(dpsub->dev); in zynqmp_dpsub_crtc_atomic_enable()
212 zynqmp_disp_enable(dpsub->disp); in zynqmp_dpsub_crtc_atomic_enable()
215 vrefresh = (adjusted_mode->clock * 1000) / in zynqmp_dpsub_crtc_atomic_enable()
216 (adjusted_mode->vtotal * adjusted_mode->htotal); in zynqmp_dpsub_crtc_atomic_enable()
223 struct zynqmp_dpsub *dpsub = crtc_to_dpsub(crtc); in zynqmp_dpsub_crtc_atomic_disable() local
231 old_plane_state = drm_atomic_get_old_plane_state(state, crtc->primary); in zynqmp_dpsub_crtc_atomic_disable()
233 zynqmp_dpsub_plane_atomic_disable(crtc->primary, state); in zynqmp_dpsub_crtc_atomic_disable()
235 zynqmp_disp_disable(dpsub->disp); in zynqmp_dpsub_crtc_atomic_disable()
239 spin_lock_irq(&crtc->dev->event_lock); in zynqmp_dpsub_crtc_atomic_disable()
240 if (crtc->state->event) { in zynqmp_dpsub_crtc_atomic_disable()
241 drm_crtc_send_vblank_event(crtc, crtc->state->event); in zynqmp_dpsub_crtc_atomic_disable()
242 crtc->state->event = NULL; in zynqmp_dpsub_crtc_atomic_disable()
244 spin_unlock_irq(&crtc->dev->event_lock); in zynqmp_dpsub_crtc_atomic_disable()
246 clk_disable_unprepare(dpsub->vid_clk); in zynqmp_dpsub_crtc_atomic_disable()
247 pm_runtime_put_sync(dpsub->dev); in zynqmp_dpsub_crtc_atomic_disable()
265 if (crtc->state->event) { in zynqmp_dpsub_crtc_atomic_flush()
269 event = crtc->state->event; in zynqmp_dpsub_crtc_atomic_flush()
270 crtc->state->event = NULL; in zynqmp_dpsub_crtc_atomic_flush()
272 event->pipe = drm_crtc_index(crtc); in zynqmp_dpsub_crtc_atomic_flush()
276 spin_lock_irq(&crtc->dev->event_lock); in zynqmp_dpsub_crtc_atomic_flush()
278 spin_unlock_irq(&crtc->dev->event_lock); in zynqmp_dpsub_crtc_atomic_flush()
292 struct zynqmp_dpsub *dpsub = crtc_to_dpsub(crtc); in zynqmp_dpsub_crtc_enable_vblank() local
294 zynqmp_dp_enable_vblank(dpsub->dp); in zynqmp_dpsub_crtc_enable_vblank()
301 struct zynqmp_dpsub *dpsub = crtc_to_dpsub(crtc); in zynqmp_dpsub_crtc_disable_vblank() local
303 zynqmp_dp_disable_vblank(dpsub->dp); in zynqmp_dpsub_crtc_disable_vblank()
317 static int zynqmp_dpsub_create_crtc(struct zynqmp_dpsub *dpsub) in zynqmp_dpsub_create_crtc() argument
319 struct drm_plane *plane = &dpsub->drm->planes[ZYNQMP_DPSUB_LAYER_GFX]; in zynqmp_dpsub_create_crtc()
320 struct drm_crtc *crtc = &dpsub->drm->crtc; in zynqmp_dpsub_create_crtc()
323 ret = drm_crtc_init_with_planes(&dpsub->drm->dev, crtc, plane, in zynqmp_dpsub_create_crtc()
336 static void zynqmp_dpsub_map_crtc_to_plane(struct zynqmp_dpsub *dpsub) in zynqmp_dpsub_map_crtc_to_plane() argument
338 u32 possible_crtcs = drm_crtc_mask(&dpsub->drm->crtc); in zynqmp_dpsub_map_crtc_to_plane()
341 for (i = 0; i < ARRAY_SIZE(dpsub->drm->planes); i++) in zynqmp_dpsub_map_crtc_to_plane()
342 dpsub->drm->planes[i].possible_crtcs = possible_crtcs; in zynqmp_dpsub_map_crtc_to_plane()
346 * zynqmp_dpsub_drm_handle_vblank - Handle the vblank event
347 * @dpsub: DisplayPort subsystem
352 void zynqmp_dpsub_drm_handle_vblank(struct zynqmp_dpsub *dpsub) in zynqmp_dpsub_drm_handle_vblank() argument
354 drm_crtc_handle_vblank(&dpsub->drm->crtc); in zynqmp_dpsub_drm_handle_vblank()
357 /* -----------------------------------------------------------------------------
365 struct zynqmp_dpsub *dpsub = to_zynqmp_dpsub(drm); in zynqmp_dpsub_dumb_create() local
366 unsigned int pitch = DIV_ROUND_UP(args->width * args->bpp, 8); in zynqmp_dpsub_dumb_create()
369 args->pitch = ALIGN(pitch, dpsub->dma_align); in zynqmp_dpsub_dumb_create()
378 struct zynqmp_dpsub *dpsub = to_zynqmp_dpsub(drm); in zynqmp_dpsub_fb_create() local
384 cmd.pitches[i] = ALIGN(cmd.pitches[i], dpsub->dma_align); in zynqmp_dpsub_fb_create()
395 /* -----------------------------------------------------------------------------
410 .name = "zynqmp-dpsub",
412 .major = 1,
416 static int zynqmp_dpsub_kms_init(struct zynqmp_dpsub *dpsub) in zynqmp_dpsub_kms_init() argument
418 struct drm_encoder *encoder = &dpsub->drm->encoder; in zynqmp_dpsub_kms_init()
423 ret = zynqmp_dpsub_create_planes(dpsub); in zynqmp_dpsub_kms_init()
427 ret = zynqmp_dpsub_create_crtc(dpsub); in zynqmp_dpsub_kms_init()
431 zynqmp_dpsub_map_crtc_to_plane(dpsub); in zynqmp_dpsub_kms_init()
434 encoder->possible_crtcs |= drm_crtc_mask(&dpsub->drm->crtc); in zynqmp_dpsub_kms_init()
435 drm_simple_encoder_init(&dpsub->drm->dev, encoder, DRM_MODE_ENCODER_NONE); in zynqmp_dpsub_kms_init()
437 ret = drm_bridge_attach(encoder, dpsub->bridge, NULL, in zynqmp_dpsub_kms_init()
440 dev_err(dpsub->dev, "failed to attach bridge to encoder\n"); in zynqmp_dpsub_kms_init()
445 connector = drm_bridge_connector_init(&dpsub->drm->dev, encoder); in zynqmp_dpsub_kms_init()
447 dev_err(dpsub->dev, "failed to created connector\n"); in zynqmp_dpsub_kms_init()
454 dev_err(dpsub->dev, "failed to attach connector to encoder\n"); in zynqmp_dpsub_kms_init()
469 zynqmp_dpsub_release(dpdrm->dpsub); in zynqmp_dpsub_drm_release()
472 int zynqmp_dpsub_drm_init(struct zynqmp_dpsub *dpsub) in zynqmp_dpsub_drm_init() argument
481 * dpsub->drm will remain NULL, which tells the caller that it must in zynqmp_dpsub_drm_init()
484 dpdrm = devm_drm_dev_alloc(dpsub->dev, &zynqmp_dpsub_drm_driver, in zynqmp_dpsub_drm_init()
489 dpdrm->dpsub = dpsub; in zynqmp_dpsub_drm_init()
490 drm = &dpdrm->dev; in zynqmp_dpsub_drm_init()
496 dpsub->drm = dpdrm; in zynqmp_dpsub_drm_init()
503 drm->mode_config.funcs = &zynqmp_dpsub_mode_config_funcs; in zynqmp_dpsub_drm_init()
504 drm->mode_config.min_width = 0; in zynqmp_dpsub_drm_init()
505 drm->mode_config.min_height = 0; in zynqmp_dpsub_drm_init()
506 drm->mode_config.max_width = ZYNQMP_DISP_MAX_WIDTH; in zynqmp_dpsub_drm_init()
507 drm->mode_config.max_height = ZYNQMP_DISP_MAX_HEIGHT; in zynqmp_dpsub_drm_init()
509 ret = drm_vblank_init(drm, 1); in zynqmp_dpsub_drm_init()
513 ret = zynqmp_dpsub_kms_init(dpsub); in zynqmp_dpsub_drm_init()
536 void zynqmp_dpsub_drm_cleanup(struct zynqmp_dpsub *dpsub) in zynqmp_dpsub_drm_cleanup() argument
538 struct drm_device *drm = &dpsub->drm->dev; in zynqmp_dpsub_drm_cleanup()
542 drm_encoder_cleanup(&dpsub->drm->encoder); in zynqmp_dpsub_drm_cleanup()