Lines Matching +full:dp +full:- +full:phy0
1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (C) 2017 - 2020 Xilinx, Inc.
8 * - Hyun Woo Kwon <hyun.kwon@xilinx.com>
9 * - Laurent Pinchart <laurent.pinchart@ideasonboard.com>
27 #include <linux/dma-mapping.h>
42 * --------
44 * The display controller part of ZynqMP DP subsystem, made of the Audio/Video
47 * +------------------------------------------------------------+
48 * +--------+ | +----------------+ +-----------+ |
49 * | DPDMA | --->| | --> | Video | Video +-------------+ |
50 * | 4x vid | | | | | Rendering | -+--> | | | +------+
51 * | 2x aud | | | Audio/Video | --> | Pipeline | | | DisplayPort |---> | PHY0 |
52 * +--------+ | | Buffer Manager | +-----------+ | | Source | | +------+
53 * | | and STC | +-----------+ | | Controller | | +------+
54 * Live Video --->| | --> | Audio | Audio | |---> | PHY1 |
55 * | | | | Mixer | --+-> | | | +------+
56 * Live Audio --->| | --> | | || +-------------+ |
57 * | +----------------+ +-----------+ || |
58 * +---------------------------------------||-------------------+
63 * Only non-live input from the DPDMA and output to the DisplayPort Source
78 * struct zynqmp_disp_format - Display subsystem format information
94 * enum zynqmp_disp_layer_id - Layer identifier
104 * enum zynqmp_disp_layer_mode - Layer mode
105 * @ZYNQMP_DISP_LAYER_NONLIVE: non-live (memory) mode
114 * struct zynqmp_disp_layer_dma - DMA channel for one data plane of a layer
126 * struct zynqmp_disp_layer_info - Static layer information
138 * struct zynqmp_disp_layer - Display layer (DRM plane)
162 * struct zynqmp_disp - Display controller
204 /* -----------------------------------------------------------------------------
410 return readl(disp->avbuf.base + reg); in zynqmp_disp_avbuf_read()
415 writel(val, disp->avbuf.base + reg); in zynqmp_disp_avbuf_write()
420 return layer->id == ZYNQMP_DISP_LAYER_GFX; in zynqmp_disp_layer_is_gfx()
425 return layer->id == ZYNQMP_DISP_LAYER_VID; in zynqmp_disp_layer_is_video()
429 * zynqmp_disp_avbuf_set_format - Set the input format for a layer
447 val |= fmt->buf_fmt; in zynqmp_disp_avbuf_set_format()
455 zynqmp_disp_avbuf_write(disp, reg, fmt->sf[i]); in zynqmp_disp_avbuf_set_format()
460 * zynqmp_disp_avbuf_set_clocks_sources - Set the clocks sources
488 * zynqmp_disp_avbuf_enable_channels - Enable buffer channels
516 * zynqmp_disp_avbuf_disable_channels - Disable buffer channels
531 * zynqmp_disp_avbuf_enable_audio - Enable audio
534 * Enable all audio buffers with a non-live (memory) source.
548 * zynqmp_disp_avbuf_disable_audio - Disable audio
565 * zynqmp_disp_avbuf_enable_video - Enable a video layer
597 * zynqmp_disp_avbuf_disable_video - Disable a video layer
620 * zynqmp_disp_avbuf_enable - Enable the video pipe
623 * De-assert the video pipe reset.
631 * zynqmp_disp_avbuf_disable - Disable the video pipe
642 /* -----------------------------------------------------------------------------
648 writel(val, disp->blend.base + reg); in zynqmp_disp_blend_write()
654 * Hardcode RGB <-> YUV conversion to full-range SDTV for now.
693 * zynqmp_disp_blend_set_output_format - Set the output format of the blender
736 * zynqmp_disp_blend_set_bg_color - Set the background color
755 * zynqmp_disp_blend_set_global_alpha - Configure global alpha blending
769 * zynqmp_disp_blend_layer_set_csc - Configure colorspace conversion for layer
788 if (layer->disp_fmt->swap) { in zynqmp_disp_blend_layer_set_csc()
789 if (layer->drm_fmt->is_yuv) { in zynqmp_disp_blend_layer_set_csc()
821 * zynqmp_disp_blend_layer_enable - Enable a layer
832 val = (layer->drm_fmt->is_yuv ? in zynqmp_disp_blend_layer_enable()
834 (layer->drm_fmt->hsub > 1 ? in zynqmp_disp_blend_layer_enable()
838 ZYNQMP_DISP_V_BLEND_LAYER_CONTROL(layer->id), in zynqmp_disp_blend_layer_enable()
841 if (layer->drm_fmt->is_yuv) { in zynqmp_disp_blend_layer_enable()
853 * zynqmp_disp_blend_layer_disable - Disable a layer
861 ZYNQMP_DISP_V_BLEND_LAYER_CONTROL(layer->id), in zynqmp_disp_blend_layer_disable()
868 /* -----------------------------------------------------------------------------
874 writel(val, disp->audio.base + reg); in zynqmp_disp_audio_write()
878 * zynqmp_disp_audio_enable - Enable the audio mixer
881 * Enable the audio mixer by de-asserting the soft reset. The audio state is set to
886 /* Clear the audio soft reset register as it's an non-reset flop. */ in zynqmp_disp_audio_enable()
893 * zynqmp_disp_audio_disable - Disable the audio mixer
907 disp->audio.clk = devm_clk_get(disp->dev, "dp_live_audio_aclk"); in zynqmp_disp_audio_init()
908 if (!IS_ERR(disp->audio.clk)) { in zynqmp_disp_audio_init()
909 disp->audio.clk_from_ps = false; in zynqmp_disp_audio_init()
914 disp->audio.clk = devm_clk_get(disp->dev, "dp_aud_clk"); in zynqmp_disp_audio_init()
915 if (!IS_ERR(disp->audio.clk)) { in zynqmp_disp_audio_init()
916 disp->audio.clk_from_ps = true; in zynqmp_disp_audio_init()
920 dev_err(disp->dev, "audio disabled due to missing clock\n"); in zynqmp_disp_audio_init()
923 /* -----------------------------------------------------------------------------
928 * zynqmp_disp_handle_vblank - Handle the vblank event
932 * CRTC object. This will be called by the DP vblank interrupt handler.
936 struct drm_crtc *crtc = &disp->crtc; in zynqmp_disp_handle_vblank()
942 * zynqmp_disp_audio_enabled - If the audio is enabled
951 return !!disp->audio.clk; in zynqmp_disp_audio_enabled()
955 * zynqmp_disp_get_audio_clk_rate - Get the current audio clock rate
964 return clk_get_rate(disp->audio.clk); in zynqmp_disp_get_audio_clk_rate()
968 * zynqmp_disp_get_crtc_mask - Return the CRTC bit mask
975 return drm_crtc_mask(&disp->crtc); in zynqmp_disp_get_crtc_mask()
978 /* -----------------------------------------------------------------------------
983 * zynqmp_disp_layer_find_format - Find format information for a DRM format
999 for (i = 0; i < layer->info->num_formats; i++) { in zynqmp_disp_layer_find_format()
1000 if (layer->info->formats[i].drm_fmt == drm_fmt) in zynqmp_disp_layer_find_format()
1001 return &layer->info->formats[i]; in zynqmp_disp_layer_find_format()
1008 * zynqmp_disp_layer_enable - Enable a layer
1016 zynqmp_disp_avbuf_enable_video(layer->disp, layer, in zynqmp_disp_layer_enable()
1018 zynqmp_disp_blend_layer_enable(layer->disp, layer); in zynqmp_disp_layer_enable()
1020 layer->mode = ZYNQMP_DISP_LAYER_NONLIVE; in zynqmp_disp_layer_enable()
1024 * zynqmp_disp_layer_disable - Disable the layer
1034 for (i = 0; i < layer->drm_fmt->num_planes; i++) in zynqmp_disp_layer_disable()
1035 dmaengine_terminate_sync(layer->dmas[i].chan); in zynqmp_disp_layer_disable()
1037 zynqmp_disp_avbuf_disable_video(layer->disp, layer); in zynqmp_disp_layer_disable()
1038 zynqmp_disp_blend_layer_disable(layer->disp, layer); in zynqmp_disp_layer_disable()
1042 * zynqmp_disp_layer_set_format - Set the layer format
1046 * Set the format for @layer based on @state->fb->format. The layer must be
1052 const struct drm_format_info *info = state->fb->format; in zynqmp_disp_layer_set_format()
1055 layer->disp_fmt = zynqmp_disp_layer_find_format(layer, info->format); in zynqmp_disp_layer_set_format()
1056 layer->drm_fmt = info; in zynqmp_disp_layer_set_format()
1058 zynqmp_disp_avbuf_set_format(layer->disp, layer, layer->disp_fmt); in zynqmp_disp_layer_set_format()
1064 for (i = 0; i < info->num_planes; i++) { in zynqmp_disp_layer_set_format()
1065 struct zynqmp_disp_layer_dma *dma = &layer->dmas[i]; in zynqmp_disp_layer_set_format()
1071 dmaengine_slave_config(dma->chan, &config); in zynqmp_disp_layer_set_format()
1076 * zynqmp_disp_layer_update - Update the layer framebuffer
1088 const struct drm_format_info *info = layer->drm_fmt; in zynqmp_disp_layer_update()
1091 for (i = 0; i < layer->drm_fmt->num_planes; i++) { in zynqmp_disp_layer_update()
1092 unsigned int width = state->crtc_w / (i ? info->hsub : 1); in zynqmp_disp_layer_update()
1093 unsigned int height = state->crtc_h / (i ? info->vsub : 1); in zynqmp_disp_layer_update()
1094 struct zynqmp_disp_layer_dma *dma = &layer->dmas[i]; in zynqmp_disp_layer_update()
1098 paddr = drm_fb_cma_get_gem_addr(state->fb, state, i); in zynqmp_disp_layer_update()
1100 dma->xt.numf = height; in zynqmp_disp_layer_update()
1101 dma->sgl.size = width * info->cpp[i]; in zynqmp_disp_layer_update()
1102 dma->sgl.icg = state->fb->pitches[i] - dma->sgl.size; in zynqmp_disp_layer_update()
1103 dma->xt.src_start = paddr; in zynqmp_disp_layer_update()
1104 dma->xt.frame_size = 1; in zynqmp_disp_layer_update()
1105 dma->xt.dir = DMA_MEM_TO_DEV; in zynqmp_disp_layer_update()
1106 dma->xt.src_sgl = true; in zynqmp_disp_layer_update()
1107 dma->xt.dst_sgl = false; in zynqmp_disp_layer_update()
1109 desc = dmaengine_prep_interleaved_dma(dma->chan, &dma->xt, in zynqmp_disp_layer_update()
1114 dev_err(layer->disp->dev, in zynqmp_disp_layer_update()
1116 return -ENOMEM; in zynqmp_disp_layer_update()
1120 dma_async_issue_pending(dma->chan); in zynqmp_disp_layer_update()
1139 if (!new_plane_state->crtc) in zynqmp_disp_plane_atomic_check()
1142 crtc_state = drm_atomic_get_crtc_state(state, new_plane_state->crtc); in zynqmp_disp_plane_atomic_check()
1161 if (!old_state->fb) in zynqmp_disp_plane_atomic_disable()
1167 zynqmp_disp_blend_set_global_alpha(layer->disp, false, in zynqmp_disp_plane_atomic_disable()
1168 plane->state->alpha >> 8); in zynqmp_disp_plane_atomic_disable()
1180 if (!old_state->fb || in zynqmp_disp_plane_atomic_update()
1181 old_state->fb->format->format != new_state->fb->format->format) in zynqmp_disp_plane_atomic_update()
1190 if (old_state->fb) in zynqmp_disp_plane_atomic_update()
1199 zynqmp_disp_blend_set_global_alpha(layer->disp, true, in zynqmp_disp_plane_atomic_update()
1200 plane->state->alpha >> 8); in zynqmp_disp_plane_atomic_update()
1202 /* Enable or re-enable the plane is the format has changed. */ in zynqmp_disp_plane_atomic_update()
1228 struct zynqmp_disp_layer *layer = &disp->layers[i]; in zynqmp_disp_create_planes()
1232 drm_formats = drmm_kcalloc(disp->drm, sizeof(*drm_formats), in zynqmp_disp_create_planes()
1233 layer->info->num_formats, in zynqmp_disp_create_planes()
1236 return -ENOMEM; in zynqmp_disp_create_planes()
1238 for (j = 0; j < layer->info->num_formats; ++j) in zynqmp_disp_create_planes()
1239 drm_formats[j] = layer->info->formats[j].drm_fmt; in zynqmp_disp_create_planes()
1244 ret = drm_universal_plane_init(disp->drm, &layer->plane, 0, in zynqmp_disp_create_planes()
1247 layer->info->num_formats, in zynqmp_disp_create_planes()
1252 drm_plane_helper_add(&layer->plane, in zynqmp_disp_create_planes()
1255 drm_plane_create_zpos_immutable_property(&layer->plane, i); in zynqmp_disp_create_planes()
1257 drm_plane_create_alpha_property(&layer->plane); in zynqmp_disp_create_planes()
1264 * zynqmp_disp_layer_release_dma - Release DMA channels for a layer
1275 if (!layer->info) in zynqmp_disp_layer_release_dma()
1278 for (i = 0; i < layer->info->num_channels; i++) { in zynqmp_disp_layer_release_dma()
1279 struct zynqmp_disp_layer_dma *dma = &layer->dmas[i]; in zynqmp_disp_layer_release_dma()
1281 if (!dma->chan) in zynqmp_disp_layer_release_dma()
1285 dmaengine_terminate_sync(dma->chan); in zynqmp_disp_layer_release_dma()
1286 dma_release_channel(dma->chan); in zynqmp_disp_layer_release_dma()
1291 * zynqmp_disp_destroy_layers - Destroy all layers
1299 zynqmp_disp_layer_release_dma(disp, &disp->layers[i]); in zynqmp_disp_destroy_layers()
1303 * zynqmp_disp_layer_request_dma - Request DMA channels for a layer
1318 for (i = 0; i < layer->info->num_channels; i++) { in zynqmp_disp_layer_request_dma()
1319 struct zynqmp_disp_layer_dma *dma = &layer->dmas[i]; in zynqmp_disp_layer_request_dma()
1323 "%s%u", dma_names[layer->id], i); in zynqmp_disp_layer_request_dma()
1324 dma->chan = dma_request_chan(disp->dev, dma_channel_name); in zynqmp_disp_layer_request_dma()
1325 if (IS_ERR(dma->chan)) { in zynqmp_disp_layer_request_dma()
1326 dev_err(disp->dev, "failed to request dma channel\n"); in zynqmp_disp_layer_request_dma()
1327 ret = PTR_ERR(dma->chan); in zynqmp_disp_layer_request_dma()
1328 dma->chan = NULL; in zynqmp_disp_layer_request_dma()
1337 * zynqmp_disp_create_layers - Create and initialize all layers
1361 struct zynqmp_disp_layer *layer = &disp->layers[i]; in zynqmp_disp_create_layers()
1363 layer->id = i; in zynqmp_disp_create_layers()
1364 layer->disp = disp; in zynqmp_disp_create_layers()
1365 layer->info = &layer_info[i]; in zynqmp_disp_create_layers()
1379 /* -----------------------------------------------------------------------------
1384 * zynqmp_disp_enable - Enable the display controller
1391 zynqmp_disp_avbuf_set_clocks_sources(disp, disp->pclk_from_ps, in zynqmp_disp_enable()
1392 disp->audio.clk_from_ps, true); in zynqmp_disp_enable()
1400 * zynqmp_disp_disable - Disable the display controller
1421 unsigned long mode_clock = adjusted_mode->clock * 1000; in zynqmp_disp_crtc_setup_clock()
1426 ret = clk_set_rate(disp->pclk, mode_clock); in zynqmp_disp_crtc_setup_clock()
1428 dev_err(disp->dev, "failed to set a pixel clock\n"); in zynqmp_disp_crtc_setup_clock()
1432 rate = clk_get_rate(disp->pclk); in zynqmp_disp_crtc_setup_clock()
1433 diff = rate - mode_clock; in zynqmp_disp_crtc_setup_clock()
1435 dev_info(disp->dev, in zynqmp_disp_crtc_setup_clock()
1439 dev_dbg(disp->dev, in zynqmp_disp_crtc_setup_clock()
1451 struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; in zynqmp_disp_crtc_atomic_enable()
1454 pm_runtime_get_sync(disp->dev); in zynqmp_disp_crtc_atomic_enable()
1458 ret = clk_prepare_enable(disp->pclk); in zynqmp_disp_crtc_atomic_enable()
1460 dev_err(disp->dev, "failed to enable a pixel clock\n"); in zynqmp_disp_crtc_atomic_enable()
1461 pm_runtime_put_sync(disp->dev); in zynqmp_disp_crtc_atomic_enable()
1471 vrefresh = (adjusted_mode->clock * 1000) / in zynqmp_disp_crtc_atomic_enable()
1472 (adjusted_mode->vtotal * adjusted_mode->htotal); in zynqmp_disp_crtc_atomic_enable()
1488 old_plane_state = drm_atomic_get_old_plane_state(state, crtc->primary); in zynqmp_disp_crtc_atomic_disable()
1490 zynqmp_disp_plane_atomic_disable(crtc->primary, state); in zynqmp_disp_crtc_atomic_disable()
1494 drm_crtc_vblank_off(&disp->crtc); in zynqmp_disp_crtc_atomic_disable()
1496 spin_lock_irq(&crtc->dev->event_lock); in zynqmp_disp_crtc_atomic_disable()
1497 if (crtc->state->event) { in zynqmp_disp_crtc_atomic_disable()
1498 drm_crtc_send_vblank_event(crtc, crtc->state->event); in zynqmp_disp_crtc_atomic_disable()
1499 crtc->state->event = NULL; in zynqmp_disp_crtc_atomic_disable()
1501 spin_unlock_irq(&crtc->dev->event_lock); in zynqmp_disp_crtc_atomic_disable()
1503 clk_disable_unprepare(disp->pclk); in zynqmp_disp_crtc_atomic_disable()
1504 pm_runtime_put_sync(disp->dev); in zynqmp_disp_crtc_atomic_disable()
1524 if (crtc->state->event) { in zynqmp_disp_crtc_atomic_flush()
1528 event = crtc->state->event; in zynqmp_disp_crtc_atomic_flush()
1529 crtc->state->event = NULL; in zynqmp_disp_crtc_atomic_flush()
1531 event->pipe = drm_crtc_index(crtc); in zynqmp_disp_crtc_atomic_flush()
1535 spin_lock_irq(&crtc->dev->event_lock); in zynqmp_disp_crtc_atomic_flush()
1537 spin_unlock_irq(&crtc->dev->event_lock); in zynqmp_disp_crtc_atomic_flush()
1553 zynqmp_dp_enable_vblank(disp->dpsub->dp); in zynqmp_disp_crtc_enable_vblank()
1562 zynqmp_dp_disable_vblank(disp->dpsub->dp); in zynqmp_disp_crtc_disable_vblank()
1578 struct drm_plane *plane = &disp->layers[ZYNQMP_DISP_LAYER_GFX].plane; in zynqmp_disp_create_crtc()
1581 ret = drm_crtc_init_with_planes(disp->drm, &disp->crtc, plane, in zynqmp_disp_create_crtc()
1586 drm_crtc_helper_add(&disp->crtc, &zynqmp_disp_crtc_helper_funcs); in zynqmp_disp_create_crtc()
1589 drm_crtc_vblank_off(&disp->crtc); in zynqmp_disp_create_crtc()
1596 u32 possible_crtcs = drm_crtc_mask(&disp->crtc); in zynqmp_disp_map_crtc_to_plane()
1600 disp->layers[i].plane.possible_crtcs = possible_crtcs; in zynqmp_disp_map_crtc_to_plane()
1603 /* -----------------------------------------------------------------------------
1609 struct zynqmp_disp *disp = dpsub->disp; in zynqmp_disp_drm_init()
1627 struct platform_device *pdev = to_platform_device(dpsub->dev); in zynqmp_disp_probe()
1635 return -ENOMEM; in zynqmp_disp_probe()
1637 disp->dev = &pdev->dev; in zynqmp_disp_probe()
1638 disp->dpsub = dpsub; in zynqmp_disp_probe()
1639 disp->drm = drm; in zynqmp_disp_probe()
1641 dpsub->disp = disp; in zynqmp_disp_probe()
1644 disp->blend.base = devm_ioremap_resource(disp->dev, res); in zynqmp_disp_probe()
1645 if (IS_ERR(disp->blend.base)) in zynqmp_disp_probe()
1646 return PTR_ERR(disp->blend.base); in zynqmp_disp_probe()
1649 disp->avbuf.base = devm_ioremap_resource(disp->dev, res); in zynqmp_disp_probe()
1650 if (IS_ERR(disp->avbuf.base)) in zynqmp_disp_probe()
1651 return PTR_ERR(disp->avbuf.base); in zynqmp_disp_probe()
1654 disp->audio.base = devm_ioremap_resource(disp->dev, res); in zynqmp_disp_probe()
1655 if (IS_ERR(disp->audio.base)) in zynqmp_disp_probe()
1656 return PTR_ERR(disp->audio.base); in zynqmp_disp_probe()
1659 disp->pclk = devm_clk_get(disp->dev, "dp_live_video_in_clk"); in zynqmp_disp_probe()
1660 if (!IS_ERR(disp->pclk)) in zynqmp_disp_probe()
1661 disp->pclk_from_ps = false; in zynqmp_disp_probe()
1662 else if (PTR_ERR(disp->pclk) == -EPROBE_DEFER) in zynqmp_disp_probe()
1663 return PTR_ERR(disp->pclk); in zynqmp_disp_probe()
1666 if (IS_ERR_OR_NULL(disp->pclk)) { in zynqmp_disp_probe()
1667 disp->pclk = devm_clk_get(disp->dev, "dp_vtc_pixel_clk_in"); in zynqmp_disp_probe()
1668 if (IS_ERR(disp->pclk)) { in zynqmp_disp_probe()
1669 dev_err(disp->dev, "failed to init any video clock\n"); in zynqmp_disp_probe()
1670 return PTR_ERR(disp->pclk); in zynqmp_disp_probe()
1672 disp->pclk_from_ps = true; in zynqmp_disp_probe()
1681 layer = &disp->layers[ZYNQMP_DISP_LAYER_VID]; in zynqmp_disp_probe()
1682 dpsub->dma_align = 1 << layer->dmas[0].chan->device->copy_align; in zynqmp_disp_probe()
1689 struct zynqmp_disp *disp = dpsub->disp; in zynqmp_disp_remove()