Lines Matching +full:zynqmp +full:- +full:dpdma

1 // SPDX-License-Identifier: GPL-2.0
3 * ZynqMP Display Controller Driver
5 * Copyright (C) 2017 - 2020 Xilinx, Inc.
8 * - Hyun Woo Kwon <hyun.kwon@xilinx.com>
9 * - Laurent Pinchart <laurent.pinchart@ideasonboard.com>
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
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
160 /* -----------------------------------------------------------------------------
407 return readl(disp->avbuf + reg); in zynqmp_disp_avbuf_read()
412 writel(val, disp->avbuf + reg); in zynqmp_disp_avbuf_write()
417 return layer->id == ZYNQMP_DPSUB_LAYER_VID; in zynqmp_disp_layer_is_video()
421 * zynqmp_disp_avbuf_set_format - Set the input format for a layer
435 layer->disp_fmt = fmt; in zynqmp_disp_avbuf_set_format()
436 if (layer->mode == ZYNQMP_DPSUB_LAYER_NONLIVE) { in zynqmp_disp_avbuf_set_format()
442 val |= fmt->buf_fmt; in zynqmp_disp_avbuf_set_format()
448 val = fmt->buf_fmt; in zynqmp_disp_avbuf_set_format()
457 zynqmp_disp_avbuf_write(disp, reg, fmt->sf[i]); in zynqmp_disp_avbuf_set_format()
462 * zynqmp_disp_avbuf_set_clocks_sources - Set the clocks sources
490 * zynqmp_disp_avbuf_enable_channels - Enable buffer channels
518 * zynqmp_disp_avbuf_disable_channels - Disable buffer channels
533 * zynqmp_disp_avbuf_enable_audio - Enable audio
536 * Enable all audio buffers with a non-live (memory) source.
550 * zynqmp_disp_avbuf_disable_audio - Disable audio
567 * zynqmp_disp_avbuf_enable_video - Enable a video layer
581 if (layer->mode == ZYNQMP_DPSUB_LAYER_NONLIVE) in zynqmp_disp_avbuf_enable_video()
588 if (layer->mode == ZYNQMP_DPSUB_LAYER_NONLIVE) in zynqmp_disp_avbuf_enable_video()
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 + 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 + 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
904 /* -----------------------------------------------------------------------------
905 * ZynqMP Display Layer & DRM Plane
909 * zynqmp_disp_layer_find_format - Find format information for a DRM format
925 for (i = 0; i < layer->info->num_formats; i++) { in zynqmp_disp_layer_find_format()
926 if (layer->info->formats[i].drm_fmt == drm_fmt) in zynqmp_disp_layer_find_format()
927 return &layer->info->formats[i]; in zynqmp_disp_layer_find_format()
934 * zynqmp_disp_layer_find_live_format - Find format information for given
951 for (i = 0; i < layer->info->num_formats; i++) in zynqmp_disp_layer_find_live_format()
952 if (layer->info->formats[i].bus_fmt == media_bus_format) in zynqmp_disp_layer_find_live_format()
953 return &layer->info->formats[i]; in zynqmp_disp_layer_find_live_format()
959 * zynqmp_disp_layer_drm_formats - Return the DRM formats supported by the layer
978 if (WARN_ON(layer->mode != ZYNQMP_DPSUB_LAYER_NONLIVE)) { in zynqmp_disp_layer_drm_formats()
983 formats = kcalloc(layer->info->num_formats, sizeof(*formats), in zynqmp_disp_layer_drm_formats()
990 for (i = 0; i < layer->info->num_formats; ++i) in zynqmp_disp_layer_drm_formats()
991 formats[i] = layer->info->formats[i].drm_fmt; in zynqmp_disp_layer_drm_formats()
993 *num_formats = layer->info->num_formats; in zynqmp_disp_layer_drm_formats()
998 * zynqmp_disp_live_layer_formats - Return the media bus formats supported by
1015 if (WARN_ON(layer->mode != ZYNQMP_DPSUB_LAYER_LIVE)) { in zynqmp_disp_live_layer_formats()
1020 formats = kcalloc(layer->info->num_formats, sizeof(*formats), in zynqmp_disp_live_layer_formats()
1027 for (i = 0; i < layer->info->num_formats; ++i) in zynqmp_disp_live_layer_formats()
1028 formats[i] = layer->info->formats[i].bus_fmt; in zynqmp_disp_live_layer_formats()
1030 *num_formats = layer->info->num_formats; in zynqmp_disp_live_layer_formats()
1035 * zynqmp_disp_layer_enable - Enable a layer
1043 zynqmp_disp_avbuf_enable_video(layer->disp, layer); in zynqmp_disp_layer_enable()
1044 zynqmp_disp_blend_layer_enable(layer->disp, layer); in zynqmp_disp_layer_enable()
1048 * zynqmp_disp_layer_disable - Disable the layer
1058 if (layer->mode == ZYNQMP_DPSUB_LAYER_NONLIVE) { in zynqmp_disp_layer_disable()
1059 for (i = 0; i < layer->drm_fmt->num_planes; i++) in zynqmp_disp_layer_disable()
1060 dmaengine_terminate_sync(layer->dmas[i].chan); in zynqmp_disp_layer_disable()
1063 zynqmp_disp_avbuf_disable_video(layer->disp, layer); in zynqmp_disp_layer_disable()
1064 zynqmp_disp_blend_layer_disable(layer->disp, layer); in zynqmp_disp_layer_disable()
1068 * zynqmp_disp_layer_set_format - Set the layer format
1082 if (WARN_ON(layer->mode != ZYNQMP_DPSUB_LAYER_NONLIVE)) in zynqmp_disp_layer_set_format()
1085 layer->disp_fmt = zynqmp_disp_layer_find_format(layer, info->format); in zynqmp_disp_layer_set_format()
1086 if (WARN_ON(!layer->disp_fmt)) in zynqmp_disp_layer_set_format()
1088 layer->drm_fmt = info; in zynqmp_disp_layer_set_format()
1090 zynqmp_disp_avbuf_set_format(layer->disp, layer, layer->disp_fmt); in zynqmp_disp_layer_set_format()
1096 for (i = 0; i < info->num_planes; i++) { in zynqmp_disp_layer_set_format()
1097 struct zynqmp_disp_layer_dma *dma = &layer->dmas[i]; in zynqmp_disp_layer_set_format()
1107 dmaengine_slave_config(dma->chan, &config); in zynqmp_disp_layer_set_format()
1112 * zynqmp_disp_layer_set_live_format - Set the live video layer format
1116 * NOTE: This function should not be used to set format for non-live video
1124 if (WARN_ON(layer->mode != ZYNQMP_DPSUB_LAYER_LIVE)) in zynqmp_disp_layer_set_live_format()
1127 layer->disp_fmt = zynqmp_disp_layer_find_live_format(layer, in zynqmp_disp_layer_set_live_format()
1129 if (WARN_ON(!layer->disp_fmt)) in zynqmp_disp_layer_set_live_format()
1132 zynqmp_disp_avbuf_set_format(layer->disp, layer, layer->disp_fmt); in zynqmp_disp_layer_set_live_format()
1134 layer->drm_fmt = drm_format_info(layer->disp_fmt->drm_fmt); in zynqmp_disp_layer_set_live_format()
1138 * zynqmp_disp_layer_update - Update the layer framebuffer
1150 const struct drm_format_info *info = layer->drm_fmt; in zynqmp_disp_layer_update()
1153 if (layer->mode == ZYNQMP_DPSUB_LAYER_LIVE) in zynqmp_disp_layer_update()
1156 for (i = 0; i < info->num_planes; i++) { in zynqmp_disp_layer_update()
1157 unsigned int width = state->crtc_w / (i ? info->hsub : 1); in zynqmp_disp_layer_update()
1158 unsigned int height = state->crtc_h / (i ? info->vsub : 1); in zynqmp_disp_layer_update()
1159 struct zynqmp_disp_layer_dma *dma = &layer->dmas[i]; in zynqmp_disp_layer_update()
1163 dma_addr = drm_fb_dma_get_gem_addr(state->fb, state, i); in zynqmp_disp_layer_update()
1165 dma->xt.numf = height; in zynqmp_disp_layer_update()
1166 dma->sgl.size = width * info->cpp[i]; in zynqmp_disp_layer_update()
1167 dma->sgl.icg = state->fb->pitches[i] - dma->sgl.size; in zynqmp_disp_layer_update()
1168 dma->xt.src_start = dma_addr; in zynqmp_disp_layer_update()
1169 dma->xt.frame_size = 1; in zynqmp_disp_layer_update()
1170 dma->xt.dir = DMA_MEM_TO_DEV; in zynqmp_disp_layer_update()
1171 dma->xt.src_sgl = true; in zynqmp_disp_layer_update()
1172 dma->xt.dst_sgl = false; in zynqmp_disp_layer_update()
1174 desc = dmaengine_prep_interleaved_dma(dma->chan, &dma->xt, in zynqmp_disp_layer_update()
1179 dev_err(layer->disp->dev, in zynqmp_disp_layer_update()
1181 return -ENOMEM; in zynqmp_disp_layer_update()
1185 dma_async_issue_pending(dma->chan); in zynqmp_disp_layer_update()
1192 * zynqmp_disp_layer_release_dma - Release DMA channels for a layer
1203 for (i = 0; i < layer->info->num_channels; i++) { in zynqmp_disp_layer_release_dma()
1204 struct zynqmp_disp_layer_dma *dma = &layer->dmas[i]; in zynqmp_disp_layer_release_dma()
1206 if (!dma->chan) in zynqmp_disp_layer_release_dma()
1210 dmaengine_terminate_sync(dma->chan); in zynqmp_disp_layer_release_dma()
1211 dma_release_channel(dma->chan); in zynqmp_disp_layer_release_dma()
1216 * zynqmp_disp_destroy_layers - Destroy all layers
1223 for (i = 0; i < ARRAY_SIZE(disp->layers); i++) in zynqmp_disp_destroy_layers()
1224 zynqmp_disp_layer_release_dma(disp, &disp->layers[i]); in zynqmp_disp_destroy_layers()
1228 * zynqmp_disp_layer_request_dma - Request DMA channels for a layer
1243 for (i = 0; i < layer->info->num_channels; i++) { in zynqmp_disp_layer_request_dma()
1244 struct zynqmp_disp_layer_dma *dma = &layer->dmas[i]; in zynqmp_disp_layer_request_dma()
1248 "%s%u", dma_names[layer->id], i); in zynqmp_disp_layer_request_dma()
1249 dma->chan = dma_request_chan(disp->dev, dma_channel_name); in zynqmp_disp_layer_request_dma()
1250 if (IS_ERR(dma->chan)) { in zynqmp_disp_layer_request_dma()
1251 ret = dev_err_probe(disp->dev, PTR_ERR(dma->chan), in zynqmp_disp_layer_request_dma()
1253 dma->chan = NULL; in zynqmp_disp_layer_request_dma()
1262 * zynqmp_disp_create_layers - Create and initialize all layers
1290 for (i = 0; i < ARRAY_SIZE(disp->layers); i++) { in zynqmp_disp_create_layers()
1291 struct zynqmp_disp_layer *layer = &disp->layers[i]; in zynqmp_disp_create_layers()
1293 layer->id = i; in zynqmp_disp_create_layers()
1294 layer->disp = disp; in zynqmp_disp_create_layers()
1296 * For now assume dpsub works in either live or non-live mode for both layers. in zynqmp_disp_create_layers()
1299 if (disp->dpsub->dma_enabled) { in zynqmp_disp_create_layers()
1300 layer->mode = ZYNQMP_DPSUB_LAYER_NONLIVE; in zynqmp_disp_create_layers()
1301 layer->info = &layer_info[i]; in zynqmp_disp_create_layers()
1303 layer->mode = ZYNQMP_DPSUB_LAYER_LIVE; in zynqmp_disp_create_layers()
1304 layer->info = &live_layer_info; in zynqmp_disp_create_layers()
1311 disp->dpsub->layers[i] = layer; in zynqmp_disp_create_layers()
1321 /* -----------------------------------------------------------------------------
1322 * ZynqMP Display
1326 * zynqmp_disp_enable - Enable the display controller
1336 zynqmp_disp_avbuf_set_clocks_sources(disp, disp->dpsub->vid_clk_from_ps, in zynqmp_disp_enable()
1337 disp->dpsub->aud_clk_from_ps, in zynqmp_disp_enable()
1338 disp->dpsub->vid_clk_from_ps); in zynqmp_disp_enable()
1346 * zynqmp_disp_disable - Disable the display controller
1359 * zynqmp_disp_setup_clock - Configure the display controller pixel clock rate
1372 ret = clk_set_rate(disp->dpsub->vid_clk, mode_clock); in zynqmp_disp_setup_clock()
1374 dev_err(disp->dev, "failed to set the video clock\n"); in zynqmp_disp_setup_clock()
1378 rate = clk_get_rate(disp->dpsub->vid_clk); in zynqmp_disp_setup_clock()
1379 diff = rate - mode_clock; in zynqmp_disp_setup_clock()
1381 dev_info(disp->dev, in zynqmp_disp_setup_clock()
1385 dev_dbg(disp->dev, in zynqmp_disp_setup_clock()
1392 /* -----------------------------------------------------------------------------
1398 struct platform_device *pdev = to_platform_device(dpsub->dev); in zynqmp_disp_probe()
1404 return -ENOMEM; in zynqmp_disp_probe()
1406 disp->dev = &pdev->dev; in zynqmp_disp_probe()
1407 disp->dpsub = dpsub; in zynqmp_disp_probe()
1409 disp->blend = devm_platform_ioremap_resource_byname(pdev, "blend"); in zynqmp_disp_probe()
1410 if (IS_ERR(disp->blend)) { in zynqmp_disp_probe()
1411 ret = PTR_ERR(disp->blend); in zynqmp_disp_probe()
1415 disp->avbuf = devm_platform_ioremap_resource_byname(pdev, "av_buf"); in zynqmp_disp_probe()
1416 if (IS_ERR(disp->avbuf)) { in zynqmp_disp_probe()
1417 ret = PTR_ERR(disp->avbuf); in zynqmp_disp_probe()
1421 disp->audio = devm_platform_ioremap_resource_byname(pdev, "aud"); in zynqmp_disp_probe()
1422 if (IS_ERR(disp->audio)) { in zynqmp_disp_probe()
1423 ret = PTR_ERR(disp->audio); in zynqmp_disp_probe()
1431 if (disp->dpsub->dma_enabled) { in zynqmp_disp_probe()
1434 layer = &disp->layers[ZYNQMP_DPSUB_LAYER_VID]; in zynqmp_disp_probe()
1435 dpsub->dma_align = 1 << layer->dmas[0].chan->device->copy_align; in zynqmp_disp_probe()
1438 dpsub->disp = disp; in zynqmp_disp_probe()
1449 struct zynqmp_disp *disp = dpsub->disp; in zynqmp_disp_remove()