Lines Matching +full:display +full:- +full:controller
1 // SPDX-License-Identifier: GPL-2.0
3 * ZynqMP Display Controller Driver
5 * Copyright (C) 2017 - 2020 Xilinx, Inc.
8 * - Hyun Woo Kwon <[email protected]>
9 * - Laurent Pinchart <[email protected]>
19 #include <linux/dma-mapping.h>
21 #include <linux/media-bus-format.h>
34 * --------
36 * The display controller part of ZynqMP DP subsystem, made of the Audio/Video
39 * +------------------------------------------------------------+
40 * +--------+ | +----------------+ +-----------+ |
41 * | DPDMA | --->| | --> | Video | Video +-------------+ |
42 * | 4x vid | | | | | Rendering | -+--> | | | +------+
43 * | 2x aud | | | Audio/Video | --> | Pipeline | | | DisplayPort |---> | PHY0 |
44 * +--------+ | | Buffer Manager | +-----------+ | | Source | | +------+
45 * | | and STC | +-----------+ | | Controller | | +------+
46 * Live Video --->| | --> | Audio | Audio | |---> | PHY1 |
47 * | | | | Mixer | --+-> | | | +------+
48 * Live Audio --->| | --> | | || +-------------+ |
49 * | +----------------+ +-----------+ || |
50 * +---------------------------------------||-------------------+
55 * Only non-live input from the DPDMA and output to the DisplayPort Source
56 * Controller are currently supported. Interface with the programmable logic
59 * The display controller code creates planes for the DPDMA video and graphics
69 * enum zynqmp_dpsub_layer_mode - Layer mode
70 * @ZYNQMP_DPSUB_LAYER_NONLIVE: non-live (memory) mode
79 * struct zynqmp_disp_format - Display subsystem format information
95 * struct zynqmp_disp_layer_dma - DMA channel for one data plane of a layer
107 * struct zynqmp_disp_layer_info - Static layer information
119 * struct zynqmp_disp_layer - Display layer
141 * struct zynqmp_disp - Display controller
143 * @dpsub: Display subsystem
158 /* -----------------------------------------------------------------------------
405 return readl(disp->avbuf + reg); in zynqmp_disp_avbuf_read()
410 writel(val, disp->avbuf + reg); in zynqmp_disp_avbuf_write()
415 return layer->id == ZYNQMP_DPSUB_LAYER_VID; in zynqmp_disp_layer_is_video()
419 * zynqmp_disp_avbuf_set_format - Set the input format for a layer
420 * @disp: Display controller
433 layer->disp_fmt = fmt; in zynqmp_disp_avbuf_set_format()
434 if (layer->mode == ZYNQMP_DPSUB_LAYER_NONLIVE) { in zynqmp_disp_avbuf_set_format()
440 val |= fmt->buf_fmt; in zynqmp_disp_avbuf_set_format()
446 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
461 * @disp: Display controller
488 * zynqmp_disp_avbuf_enable_channels - Enable buffer channels
489 * @disp: Display controller
516 * zynqmp_disp_avbuf_disable_channels - Disable buffer channels
517 * @disp: Display controller
531 * zynqmp_disp_avbuf_enable_audio - Enable audio
532 * @disp: Display controller
534 * Enable all audio buffers with a non-live (memory) source.
548 * zynqmp_disp_avbuf_disable_audio - Disable audio
549 * @disp: Display controller
565 * zynqmp_disp_avbuf_enable_video - Enable a video layer
566 * @disp: Display controller
579 if (layer->mode == ZYNQMP_DPSUB_LAYER_NONLIVE) in zynqmp_disp_avbuf_enable_video()
586 if (layer->mode == ZYNQMP_DPSUB_LAYER_NONLIVE) in zynqmp_disp_avbuf_enable_video()
595 * zynqmp_disp_avbuf_disable_video - Disable a video layer
596 * @disp: Display controller
618 * zynqmp_disp_avbuf_enable - Enable the video pipe
619 * @disp: Display controller
621 * De-assert the video pipe reset.
629 * zynqmp_disp_avbuf_disable - Disable the video pipe
630 * @disp: Display controller
640 /* -----------------------------------------------------------------------------
646 writel(val, disp->blend + reg); in zynqmp_disp_blend_write()
652 * Hardcode RGB <-> YUV conversion to full-range SDTV for now.
691 * zynqmp_disp_blend_set_output_format - Set the output format of the blender
692 * @disp: Display controller
734 * zynqmp_disp_blend_set_bg_color - Set the background color
735 * @disp: Display controller
753 * zynqmp_disp_blend_set_global_alpha - Configure global alpha blending
754 * @disp: Display controller
767 * zynqmp_disp_blend_layer_set_csc - Configure colorspace conversion for layer
768 * @disp: Display controller
786 if (layer->disp_fmt->swap) { in zynqmp_disp_blend_layer_set_csc()
787 if (layer->drm_fmt->is_yuv) { in zynqmp_disp_blend_layer_set_csc()
819 * zynqmp_disp_blend_layer_enable - Enable a layer
820 * @disp: Display controller
830 val = (layer->drm_fmt->is_yuv ? in zynqmp_disp_blend_layer_enable()
832 (layer->drm_fmt->hsub > 1 ? in zynqmp_disp_blend_layer_enable()
836 ZYNQMP_DISP_V_BLEND_LAYER_CONTROL(layer->id), in zynqmp_disp_blend_layer_enable()
839 if (layer->drm_fmt->is_yuv) { in zynqmp_disp_blend_layer_enable()
851 * zynqmp_disp_blend_layer_disable - Disable a layer
852 * @disp: Display controller
859 ZYNQMP_DISP_V_BLEND_LAYER_CONTROL(layer->id), in zynqmp_disp_blend_layer_disable()
866 /* -----------------------------------------------------------------------------
867 * ZynqMP Display Layer & DRM Plane
871 * zynqmp_disp_layer_find_format - Find format information for a DRM format
875 * Search display subsystem format information corresponding to the given DRM
887 for (i = 0; i < layer->info->num_formats; i++) { in zynqmp_disp_layer_find_format()
888 if (layer->info->formats[i].drm_fmt == drm_fmt) in zynqmp_disp_layer_find_format()
889 return &layer->info->formats[i]; in zynqmp_disp_layer_find_format()
896 * zynqmp_disp_layer_find_live_format - Find format information for given
901 * Search display subsystem format information corresponding to the given media
913 for (i = 0; i < layer->info->num_formats; i++) in zynqmp_disp_layer_find_live_format()
914 if (layer->info->formats[i].bus_fmt == media_bus_format) in zynqmp_disp_layer_find_live_format()
915 return &layer->info->formats[i]; in zynqmp_disp_layer_find_live_format()
921 * zynqmp_disp_layer_drm_formats - Return the DRM formats supported by the layer
940 if (WARN_ON(layer->mode != ZYNQMP_DPSUB_LAYER_NONLIVE)) { in zynqmp_disp_layer_drm_formats()
945 formats = kcalloc(layer->info->num_formats, sizeof(*formats), in zynqmp_disp_layer_drm_formats()
952 for (i = 0; i < layer->info->num_formats; ++i) in zynqmp_disp_layer_drm_formats()
953 formats[i] = layer->info->formats[i].drm_fmt; in zynqmp_disp_layer_drm_formats()
955 *num_formats = layer->info->num_formats; in zynqmp_disp_layer_drm_formats()
960 * zynqmp_disp_live_layer_formats - Return the media bus formats supported by
977 if (WARN_ON(layer->mode != ZYNQMP_DPSUB_LAYER_LIVE)) { in zynqmp_disp_live_layer_formats()
982 formats = kcalloc(layer->info->num_formats, sizeof(*formats), in zynqmp_disp_live_layer_formats()
989 for (i = 0; i < layer->info->num_formats; ++i) in zynqmp_disp_live_layer_formats()
990 formats[i] = layer->info->formats[i].bus_fmt; in zynqmp_disp_live_layer_formats()
992 *num_formats = layer->info->num_formats; in zynqmp_disp_live_layer_formats()
997 * zynqmp_disp_layer_enable - Enable a layer
1005 zynqmp_disp_avbuf_enable_video(layer->disp, layer); in zynqmp_disp_layer_enable()
1006 zynqmp_disp_blend_layer_enable(layer->disp, layer); in zynqmp_disp_layer_enable()
1010 * zynqmp_disp_layer_disable - Disable the layer
1020 if (layer->mode == ZYNQMP_DPSUB_LAYER_NONLIVE) { in zynqmp_disp_layer_disable()
1021 for (i = 0; i < layer->drm_fmt->num_planes; i++) in zynqmp_disp_layer_disable()
1022 dmaengine_terminate_sync(layer->dmas[i].chan); in zynqmp_disp_layer_disable()
1025 zynqmp_disp_avbuf_disable_video(layer->disp, layer); in zynqmp_disp_layer_disable()
1026 zynqmp_disp_blend_layer_disable(layer->disp, layer); in zynqmp_disp_layer_disable()
1030 * zynqmp_disp_layer_set_format - Set the layer format
1044 if (WARN_ON(layer->mode != ZYNQMP_DPSUB_LAYER_NONLIVE)) in zynqmp_disp_layer_set_format()
1047 layer->disp_fmt = zynqmp_disp_layer_find_format(layer, info->format); in zynqmp_disp_layer_set_format()
1048 if (WARN_ON(!layer->disp_fmt)) in zynqmp_disp_layer_set_format()
1050 layer->drm_fmt = info; in zynqmp_disp_layer_set_format()
1052 zynqmp_disp_avbuf_set_format(layer->disp, layer, layer->disp_fmt); in zynqmp_disp_layer_set_format()
1058 for (i = 0; i < info->num_planes; i++) { in zynqmp_disp_layer_set_format()
1059 struct zynqmp_disp_layer_dma *dma = &layer->dmas[i]; in zynqmp_disp_layer_set_format()
1069 dmaengine_slave_config(dma->chan, &config); in zynqmp_disp_layer_set_format()
1074 * zynqmp_disp_layer_set_live_format - Set the live video layer format
1078 * NOTE: This function should not be used to set format for non-live video
1081 * Set the display format for the live @layer. The layer must be disabled.
1086 if (WARN_ON(layer->mode != ZYNQMP_DPSUB_LAYER_LIVE)) in zynqmp_disp_layer_set_live_format()
1089 layer->disp_fmt = zynqmp_disp_layer_find_live_format(layer, in zynqmp_disp_layer_set_live_format()
1091 if (WARN_ON(!layer->disp_fmt)) in zynqmp_disp_layer_set_live_format()
1094 zynqmp_disp_avbuf_set_format(layer->disp, layer, layer->disp_fmt); in zynqmp_disp_layer_set_live_format()
1096 layer->drm_fmt = drm_format_info(layer->disp_fmt->drm_fmt); in zynqmp_disp_layer_set_live_format()
1100 * zynqmp_disp_layer_update - Update the layer framebuffer
1112 const struct drm_format_info *info = layer->drm_fmt; in zynqmp_disp_layer_update()
1115 if (layer->mode == ZYNQMP_DPSUB_LAYER_LIVE) in zynqmp_disp_layer_update()
1118 for (i = 0; i < info->num_planes; i++) { in zynqmp_disp_layer_update()
1119 unsigned int width = state->crtc_w / (i ? info->hsub : 1); in zynqmp_disp_layer_update()
1120 unsigned int height = state->crtc_h / (i ? info->vsub : 1); in zynqmp_disp_layer_update()
1121 struct zynqmp_disp_layer_dma *dma = &layer->dmas[i]; in zynqmp_disp_layer_update()
1125 dma_addr = drm_fb_dma_get_gem_addr(state->fb, state, i); in zynqmp_disp_layer_update()
1127 dma->xt.numf = height; in zynqmp_disp_layer_update()
1128 dma->sgl.size = width * info->cpp[i]; in zynqmp_disp_layer_update()
1129 dma->sgl.icg = state->fb->pitches[i] - dma->sgl.size; in zynqmp_disp_layer_update()
1130 dma->xt.src_start = dma_addr; in zynqmp_disp_layer_update()
1131 dma->xt.frame_size = 1; in zynqmp_disp_layer_update()
1132 dma->xt.dir = DMA_MEM_TO_DEV; in zynqmp_disp_layer_update()
1133 dma->xt.src_sgl = true; in zynqmp_disp_layer_update()
1134 dma->xt.dst_sgl = false; in zynqmp_disp_layer_update()
1136 desc = dmaengine_prep_interleaved_dma(dma->chan, &dma->xt, in zynqmp_disp_layer_update()
1141 dev_err(layer->disp->dev, in zynqmp_disp_layer_update()
1143 return -ENOMEM; in zynqmp_disp_layer_update()
1147 dma_async_issue_pending(dma->chan); in zynqmp_disp_layer_update()
1154 * zynqmp_disp_layer_release_dma - Release DMA channels for a layer
1155 * @disp: Display controller
1165 if (!layer->info) in zynqmp_disp_layer_release_dma()
1168 for (i = 0; i < layer->info->num_channels; i++) { in zynqmp_disp_layer_release_dma()
1169 struct zynqmp_disp_layer_dma *dma = &layer->dmas[i]; in zynqmp_disp_layer_release_dma()
1171 if (!dma->chan) in zynqmp_disp_layer_release_dma()
1175 dmaengine_terminate_sync(dma->chan); in zynqmp_disp_layer_release_dma()
1176 dma_release_channel(dma->chan); in zynqmp_disp_layer_release_dma()
1181 * zynqmp_disp_destroy_layers - Destroy all layers
1182 * @disp: Display controller
1188 for (i = 0; i < ARRAY_SIZE(disp->layers); i++) in zynqmp_disp_destroy_layers()
1189 zynqmp_disp_layer_release_dma(disp, &disp->layers[i]); in zynqmp_disp_destroy_layers()
1193 * zynqmp_disp_layer_request_dma - Request DMA channels for a layer
1194 * @disp: Display controller
1208 for (i = 0; i < layer->info->num_channels; i++) { in zynqmp_disp_layer_request_dma()
1209 struct zynqmp_disp_layer_dma *dma = &layer->dmas[i]; in zynqmp_disp_layer_request_dma()
1213 "%s%u", dma_names[layer->id], i); in zynqmp_disp_layer_request_dma()
1214 dma->chan = dma_request_chan(disp->dev, dma_channel_name); in zynqmp_disp_layer_request_dma()
1215 if (IS_ERR(dma->chan)) { in zynqmp_disp_layer_request_dma()
1216 ret = dev_err_probe(disp->dev, PTR_ERR(dma->chan), in zynqmp_disp_layer_request_dma()
1218 dma->chan = NULL; in zynqmp_disp_layer_request_dma()
1227 * zynqmp_disp_create_layers - Create and initialize all layers
1228 * @disp: Display controller
1255 for (i = 0; i < ARRAY_SIZE(disp->layers); i++) { in zynqmp_disp_create_layers()
1256 struct zynqmp_disp_layer *layer = &disp->layers[i]; in zynqmp_disp_create_layers()
1258 layer->id = i; in zynqmp_disp_create_layers()
1259 layer->disp = disp; in zynqmp_disp_create_layers()
1261 * For now assume dpsub works in either live or non-live mode for both layers. in zynqmp_disp_create_layers()
1264 if (disp->dpsub->dma_enabled) { in zynqmp_disp_create_layers()
1265 layer->mode = ZYNQMP_DPSUB_LAYER_NONLIVE; in zynqmp_disp_create_layers()
1266 layer->info = &layer_info[i]; in zynqmp_disp_create_layers()
1268 layer->mode = ZYNQMP_DPSUB_LAYER_LIVE; in zynqmp_disp_create_layers()
1269 layer->info = &live_layer_info; in zynqmp_disp_create_layers()
1276 disp->dpsub->layers[i] = layer; in zynqmp_disp_create_layers()
1286 /* -----------------------------------------------------------------------------
1287 * ZynqMP Display
1291 * zynqmp_disp_enable - Enable the display controller
1292 * @disp: Display controller
1301 zynqmp_disp_avbuf_set_clocks_sources(disp, disp->dpsub->vid_clk_from_ps, in zynqmp_disp_enable()
1302 disp->dpsub->aud_clk_from_ps, in zynqmp_disp_enable()
1303 disp->dpsub->vid_clk_from_ps); in zynqmp_disp_enable()
1309 * zynqmp_disp_disable - Disable the display controller
1310 * @disp: Display controller
1320 * zynqmp_disp_setup_clock - Configure the display controller pixel clock rate
1321 * @disp: Display controller
1333 ret = clk_set_rate(disp->dpsub->vid_clk, mode_clock); in zynqmp_disp_setup_clock()
1335 dev_err(disp->dev, "failed to set the video clock\n"); in zynqmp_disp_setup_clock()
1339 rate = clk_get_rate(disp->dpsub->vid_clk); in zynqmp_disp_setup_clock()
1340 diff = rate - mode_clock; in zynqmp_disp_setup_clock()
1342 dev_info(disp->dev, in zynqmp_disp_setup_clock()
1346 dev_dbg(disp->dev, in zynqmp_disp_setup_clock()
1353 /* -----------------------------------------------------------------------------
1359 struct platform_device *pdev = to_platform_device(dpsub->dev); in zynqmp_disp_probe()
1365 return -ENOMEM; in zynqmp_disp_probe()
1367 disp->dev = &pdev->dev; in zynqmp_disp_probe()
1368 disp->dpsub = dpsub; in zynqmp_disp_probe()
1370 disp->blend = devm_platform_ioremap_resource_byname(pdev, "blend"); in zynqmp_disp_probe()
1371 if (IS_ERR(disp->blend)) { in zynqmp_disp_probe()
1372 ret = PTR_ERR(disp->blend); in zynqmp_disp_probe()
1376 disp->avbuf = devm_platform_ioremap_resource_byname(pdev, "av_buf"); in zynqmp_disp_probe()
1377 if (IS_ERR(disp->avbuf)) { in zynqmp_disp_probe()
1378 ret = PTR_ERR(disp->avbuf); in zynqmp_disp_probe()
1386 if (disp->dpsub->dma_enabled) { in zynqmp_disp_probe()
1389 layer = &disp->layers[ZYNQMP_DPSUB_LAYER_VID]; in zynqmp_disp_probe()
1390 dpsub->dma_align = 1 << layer->dmas[0].chan->device->copy_align; in zynqmp_disp_probe()
1393 dpsub->disp = disp; in zynqmp_disp_probe()
1404 struct zynqmp_disp *disp = dpsub->disp; in zynqmp_disp_remove()