linux/drivers/gpu/drm/xlnx/zynqmp_disp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * ZynqMP Display Controller Driver
   4 *
   5 *  Copyright (C) 2017 - 2018 Xilinx, Inc.
   6 *
   7 *  Author: Hyun Woo Kwon <hyun.kwon@xilinx.com>
   8 *
   9 * This software is licensed under the terms of the GNU General Public
  10 * License version 2, as published by the Free Software Foundation, and
  11 * may be copied, distributed, and modified under those terms.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 */
  18
  19#include <drm/drmP.h>
  20#include <drm/drm_atomic.h>
  21#include <drm/drm_atomic_helper.h>
  22#include <drm/drm_crtc.h>
  23#include <drm/drm_crtc_helper.h>
  24#include <drm/drm_fb_cma_helper.h>
  25#include <drm/drm_fourcc.h>
  26#include <drm/drm_plane_helper.h>
  27
  28#include <linux/clk.h>
  29#include <linux/device.h>
  30#include <linux/dmaengine.h>
  31#include <linux/interrupt.h>
  32#include <linux/irqreturn.h>
  33#include <linux/list.h>
  34#include <linux/module.h>
  35#include <linux/mutex.h>
  36#include <linux/of.h>
  37#include <linux/of_dma.h>
  38#include <linux/platform_device.h>
  39#include <linux/pm_runtime.h>
  40#include <linux/spinlock.h>
  41#include <linux/uaccess.h>
  42
  43#include "xlnx_bridge.h"
  44#include "xlnx_crtc.h"
  45#include "xlnx_fb.h"
  46#include "zynqmp_disp.h"
  47#include "zynqmp_dp.h"
  48#include "zynqmp_dpsub.h"
  49
  50/*
  51 * Overview
  52 * --------
  53 *
  54 * The display part of ZynqMP DP subsystem. Internally, the device
  55 * is partitioned into 3 blocks: AV buffer manager, Blender, Audio.
  56 * The driver creates the DRM crtc and plane objectes and maps the DRM
  57 * interface into those 3 blocks. In high level, the driver is layered
  58 * in the following way:
  59 *
  60 * zynqmp_disp_crtc & zynqmp_disp_plane
  61 * |->zynqmp_disp
  62 *      |->zynqmp_disp_aud
  63 *      |->zynqmp_disp_blend
  64 *      |->zynqmp_disp_av_buf
  65 *
  66 * The driver APIs are used externally by
  67 * - zynqmp_dpsub: Top level ZynqMP DP subsystem driver
  68 * - zynqmp_dp: ZynqMP DP driver
  69 * - xlnx_crtc: Xilinx DRM specific crtc functions
  70 */
  71
  72/* The default value is ZYNQMP_DISP_AV_BUF_GFX_FMT_RGB565 */
  73static uint zynqmp_disp_gfx_init_fmt;
  74module_param_named(gfx_init_fmt, zynqmp_disp_gfx_init_fmt, uint, 0444);
  75MODULE_PARM_DESC(gfx_init_fmt, "The initial format of the graphics layer\n"
  76                               "\t\t0 = rgb565 (default)\n"
  77                               "\t\t1 = rgb888\n"
  78                               "\t\t2 = argb8888\n");
  79/* These value should be mapped to index of av_buf_gfx_fmts[] */
  80#define ZYNQMP_DISP_AV_BUF_GFX_FMT_RGB565               10
  81#define ZYNQMP_DISP_AV_BUF_GFX_FMT_RGB888               5
  82#define ZYNQMP_DISP_AV_BUF_GFX_FMT_ARGB8888             1
  83static const u32 zynqmp_disp_gfx_init_fmts[] = {
  84        ZYNQMP_DISP_AV_BUF_GFX_FMT_RGB565,
  85        ZYNQMP_DISP_AV_BUF_GFX_FMT_RGB888,
  86        ZYNQMP_DISP_AV_BUF_GFX_FMT_ARGB8888,
  87};
  88
  89/* Blender registers */
  90#define ZYNQMP_DISP_V_BLEND_BG_CLR_0                    0x0
  91#define ZYNQMP_DISP_V_BLEND_BG_CLR_1                    0x4
  92#define ZYNQMP_DISP_V_BLEND_BG_CLR_2                    0x8
  93#define ZYNQMP_DISP_V_BLEND_BG_MAX                      0xfff
  94#define ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA            0xc
  95#define ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MASK       0x1fe
  96#define ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MAX        0xff
  97#define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT              0x14
  98#define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_RGB          0x0
  99#define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YCBCR444     0x1
 100#define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YCBCR422     0x2
 101#define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YONLY        0x3
 102#define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_XVYCC        0x4
 103#define ZYNQMP_DISP_V_BLEND_OUTPUT_EN_DOWNSAMPLE        BIT(4)
 104#define ZYNQMP_DISP_V_BLEND_LAYER_CONTROL               0x18
 105#define ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_EN_US         BIT(0)
 106#define ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_RGB           BIT(1)
 107#define ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_BYPASS        BIT(8)
 108#define ZYNQMP_DISP_V_BLEND_NUM_COEFF                   9
 109#define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF0            0x20
 110#define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF1            0x24
 111#define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF2            0x28
 112#define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF3            0x2c
 113#define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF4            0x30
 114#define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF5            0x34
 115#define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF6            0x38
 116#define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF7            0x3c
 117#define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF8            0x40
 118#define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF0               0x44
 119#define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF1               0x48
 120#define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF2               0x4c
 121#define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF3               0x50
 122#define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF4               0x54
 123#define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF5               0x58
 124#define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF6               0x5c
 125#define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF7               0x60
 126#define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF8               0x64
 127#define ZYNQMP_DISP_V_BLEND_NUM_OFFSET                  3
 128#define ZYNQMP_DISP_V_BLEND_LUMA_IN1CSC_OFFSET          0x68
 129#define ZYNQMP_DISP_V_BLEND_CR_IN1CSC_OFFSET            0x6c
 130#define ZYNQMP_DISP_V_BLEND_CB_IN1CSC_OFFSET            0x70
 131#define ZYNQMP_DISP_V_BLEND_LUMA_OUTCSC_OFFSET          0x74
 132#define ZYNQMP_DISP_V_BLEND_CR_OUTCSC_OFFSET            0x78
 133#define ZYNQMP_DISP_V_BLEND_CB_OUTCSC_OFFSET            0x7c
 134#define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF0               0x80
 135#define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF1               0x84
 136#define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF2               0x88
 137#define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF3               0x8c
 138#define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF4               0x90
 139#define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF5               0x94
 140#define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF6               0x98
 141#define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF7               0x9c
 142#define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF8               0xa0
 143#define ZYNQMP_DISP_V_BLEND_LUMA_IN2CSC_OFFSET          0xa4
 144#define ZYNQMP_DISP_V_BLEND_CR_IN2CSC_OFFSET            0xa8
 145#define ZYNQMP_DISP_V_BLEND_CB_IN2CSC_OFFSET            0xac
 146#define ZYNQMP_DISP_V_BLEND_CHROMA_KEY_ENABLE           0x1d0
 147#define ZYNQMP_DISP_V_BLEND_CHROMA_KEY_COMP1            0x1d4
 148#define ZYNQMP_DISP_V_BLEND_CHROMA_KEY_COMP2            0x1d8
 149#define ZYNQMP_DISP_V_BLEND_CHROMA_KEY_COMP3            0x1dc
 150
 151/* AV buffer manager registers */
 152#define ZYNQMP_DISP_AV_BUF_FMT                          0x0
 153#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_SHIFT             0
 154#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MASK              (0x1f << 0)
 155#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_UYVY              (0 << 0)
 156#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_VYUY              (1 << 0)
 157#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YVYU              (2 << 0)
 158#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUYV              (3 << 0)
 159#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16              (4 << 0)
 160#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV24              (5 << 0)
 161#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI            (6 << 0)
 162#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MONO              (7 << 0)
 163#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI2           (8 << 0)
 164#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUV444            (9 << 0)
 165#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888            (10 << 0)
 166#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGBA8880          (11 << 0)
 167#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888_10         (12 << 0)
 168#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUV444_10         (13 << 0)
 169#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI2_10        (14 << 0)
 170#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_10         (15 << 0)
 171#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_10           (16 << 0)
 172#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV24_10           (17 << 0)
 173#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YONLY_10          (18 << 0)
 174#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_420          (19 << 0)
 175#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420        (20 << 0)
 176#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI2_420       (21 << 0)
 177#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_420_10       (22 << 0)
 178#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420_10     (23 << 0)
 179#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI2_420_10    (24 << 0)
 180#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_SHIFT             8
 181#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_MASK              (0xf << 8)
 182#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA8888          (0 << 8)
 183#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_ABGR8888          (1 << 8)
 184#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB888            (2 << 8)
 185#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_BGR888            (3 << 8)
 186#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA5551          (4 << 8)
 187#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA4444          (5 << 8)
 188#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB565            (6 << 8)
 189#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_8BPP              (7 << 8)
 190#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_4BPP              (8 << 8)
 191#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_2BPP              (9 << 8)
 192#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_1BPP              (10 << 8)
 193#define ZYNQMP_DISP_AV_BUF_NON_LIVE_LATENCY             0x8
 194#define ZYNQMP_DISP_AV_BUF_CHBUF                        0x10
 195#define ZYNQMP_DISP_AV_BUF_CHBUF_EN                     BIT(0)
 196#define ZYNQMP_DISP_AV_BUF_CHBUF_FLUSH                  BIT(1)
 197#define ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_SHIFT        2
 198#define ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_MASK         (0xf << 2)
 199#define ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_MAX          0xf
 200#define ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_AUD_MAX      0x3
 201#define ZYNQMP_DISP_AV_BUF_STATUS                       0x28
 202#define ZYNQMP_DISP_AV_BUF_STC_CTRL                     0x2c
 203#define ZYNQMP_DISP_AV_BUF_STC_CTRL_EN                  BIT(0)
 204#define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_SHIFT         1
 205#define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_EX_VSYNC      0
 206#define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_EX_VID        1
 207#define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_EX_AUD        2
 208#define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_INT_VSYNC     3
 209#define ZYNQMP_DISP_AV_BUF_STC_INIT_VALUE0              0x30
 210#define ZYNQMP_DISP_AV_BUF_STC_INIT_VALUE1              0x34
 211#define ZYNQMP_DISP_AV_BUF_STC_ADJ                      0x38
 212#define ZYNQMP_DISP_AV_BUF_STC_VID_VSYNC_TS0            0x3c
 213#define ZYNQMP_DISP_AV_BUF_STC_VID_VSYNC_TS1            0x40
 214#define ZYNQMP_DISP_AV_BUF_STC_EXT_VSYNC_TS0            0x44
 215#define ZYNQMP_DISP_AV_BUF_STC_EXT_VSYNC_TS1            0x48
 216#define ZYNQMP_DISP_AV_BUF_STC_CUSTOM_EVENT_TS0         0x4c
 217#define ZYNQMP_DISP_AV_BUF_STC_CUSTOM_EVENT_TS1         0x50
 218#define ZYNQMP_DISP_AV_BUF_STC_CUSTOM_EVENT2_TS0        0x54
 219#define ZYNQMP_DISP_AV_BUF_STC_CUSTOM_EVENT2_TS1        0x58
 220#define ZYNQMP_DISP_AV_BUF_STC_SNAPSHOT0                0x60
 221#define ZYNQMP_DISP_AV_BUF_STC_SNAPSHOT1                0x64
 222#define ZYNQMP_DISP_AV_BUF_OUTPUT                       0x70
 223#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_SHIFT            0
 224#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK             (0x3 << 0)
 225#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_LIVE             (0 << 0)
 226#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MEM              (1 << 0)
 227#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_PATTERN          (2 << 0)
 228#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_NONE             (3 << 0)
 229#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_SHIFT            2
 230#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MASK             (0x3 << 2)
 231#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_DISABLE          (0 << 2)
 232#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MEM              (1 << 2)
 233#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_LIVE             (2 << 2)
 234#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_NONE             (3 << 2)
 235#define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_SHIFT            4
 236#define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MASK             (0x3 << 4)
 237#define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_PL               (0 << 4)
 238#define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MEM              (1 << 4)
 239#define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_PATTERN          (2 << 4)
 240#define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_DISABLE          (3 << 4)
 241#define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD2_EN               BIT(6)
 242#define ZYNQMP_DISP_AV_BUF_HCOUNT_VCOUNT_INT0           0x74
 243#define ZYNQMP_DISP_AV_BUF_HCOUNT_VCOUNT_INT1           0x78
 244#define ZYNQMP_DISP_AV_BUF_PATTERN_GEN_SELECT           0x100
 245#define ZYNQMP_DISP_AV_BUF_CLK_SRC                      0x120
 246#define ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_FROM_PS          BIT(0)
 247#define ZYNQMP_DISP_AV_BUF_CLK_SRC_AUD_FROM_PS          BIT(1)
 248#define ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING  BIT(2)
 249#define ZYNQMP_DISP_AV_BUF_SRST_REG                     0x124
 250#define ZYNQMP_DISP_AV_BUF_SRST_REG_VID_RST             BIT(1)
 251#define ZYNQMP_DISP_AV_BUF_AUDIO_CH_CONFIG              0x12c
 252#define ZYNQMP_DISP_AV_BUF_GFX_COMP0_SF                 0x200
 253#define ZYNQMP_DISP_AV_BUF_GFX_COMP1_SF                 0x204
 254#define ZYNQMP_DISP_AV_BUF_GFX_COMP2_SF                 0x208
 255#define ZYNQMP_DISP_AV_BUF_VID_COMP0_SF                 0x20c
 256#define ZYNQMP_DISP_AV_BUF_VID_COMP1_SF                 0x210
 257#define ZYNQMP_DISP_AV_BUF_VID_COMP2_SF                 0x214
 258#define ZYNQMP_DISP_AV_BUF_LIVE_VID_COMP0_SF            0x218
 259#define ZYNQMP_DISP_AV_BUF_LIVE_VID_COMP1_SF            0x21c
 260#define ZYNQMP_DISP_AV_BUF_LIVE_VID_COMP2_SF            0x220
 261#define ZYNQMP_DISP_AV_BUF_LIVE_VID_CONFIG              0x224
 262#define ZYNQMP_DISP_AV_BUF_LIVE_GFX_COMP0_SF            0x228
 263#define ZYNQMP_DISP_AV_BUF_LIVE_GFX_COMP1_SF            0x22c
 264#define ZYNQMP_DISP_AV_BUF_LIVE_GFX_COMP2_SF            0x230
 265#define ZYNQMP_DISP_AV_BUF_LIVE_GFX_CONFIG              0x234
 266#define ZYNQMP_DISP_AV_BUF_4BIT_SF                      0x11111
 267#define ZYNQMP_DISP_AV_BUF_5BIT_SF                      0x10842
 268#define ZYNQMP_DISP_AV_BUF_6BIT_SF                      0x10410
 269#define ZYNQMP_DISP_AV_BUF_8BIT_SF                      0x10101
 270#define ZYNQMP_DISP_AV_BUF_10BIT_SF                     0x10040
 271#define ZYNQMP_DISP_AV_BUF_NULL_SF                      0
 272#define ZYNQMP_DISP_AV_BUF_NUM_SF                       3
 273#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_6            0x0
 274#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8            0x1
 275#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_10           0x2
 276#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_12           0x3
 277#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_MASK         GENMASK(2, 0)
 278#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB          0x0
 279#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV444       0x1
 280#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422       0x2
 281#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YONLY        0x3
 282#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_MASK         GENMASK(5, 4)
 283#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_CB_FIRST         BIT(8)
 284#define ZYNQMP_DISP_AV_BUF_PALETTE_MEMORY               0x400
 285
 286/* Audio registers */
 287#define ZYNQMP_DISP_AUD_MIXER_VOLUME                    0x0
 288#define ZYNQMP_DISP_AUD_MIXER_VOLUME_NO_SCALE           0x20002000
 289#define ZYNQMP_DISP_AUD_MIXER_META_DATA                 0x4
 290#define ZYNQMP_DISP_AUD_CH_STATUS0                      0x8
 291#define ZYNQMP_DISP_AUD_CH_STATUS1                      0xc
 292#define ZYNQMP_DISP_AUD_CH_STATUS2                      0x10
 293#define ZYNQMP_DISP_AUD_CH_STATUS3                      0x14
 294#define ZYNQMP_DISP_AUD_CH_STATUS4                      0x18
 295#define ZYNQMP_DISP_AUD_CH_STATUS5                      0x1c
 296#define ZYNQMP_DISP_AUD_CH_A_DATA0                      0x20
 297#define ZYNQMP_DISP_AUD_CH_A_DATA1                      0x24
 298#define ZYNQMP_DISP_AUD_CH_A_DATA2                      0x28
 299#define ZYNQMP_DISP_AUD_CH_A_DATA3                      0x2c
 300#define ZYNQMP_DISP_AUD_CH_A_DATA4                      0x30
 301#define ZYNQMP_DISP_AUD_CH_A_DATA5                      0x34
 302#define ZYNQMP_DISP_AUD_CH_B_DATA0                      0x38
 303#define ZYNQMP_DISP_AUD_CH_B_DATA1                      0x3c
 304#define ZYNQMP_DISP_AUD_CH_B_DATA2                      0x40
 305#define ZYNQMP_DISP_AUD_CH_B_DATA3                      0x44
 306#define ZYNQMP_DISP_AUD_CH_B_DATA4                      0x48
 307#define ZYNQMP_DISP_AUD_CH_B_DATA5                      0x4c
 308#define ZYNQMP_DISP_AUD_SOFT_RESET                      0xc00
 309#define ZYNQMP_DISP_AUD_SOFT_RESET_AUD_SRST             BIT(0)
 310
 311#define ZYNQMP_DISP_AV_BUF_NUM_VID_GFX_BUFFERS          4
 312#define ZYNQMP_DISP_AV_BUF_NUM_BUFFERS                  6
 313
 314#define ZYNQMP_DISP_NUM_LAYERS                          2
 315#define ZYNQMP_DISP_MAX_NUM_SUB_PLANES                  3
 316/*
 317 * 3840x2160 is advertised max resolution, but almost any resolutions under
 318 * 300Mhz pixel rate would work. Thus put 4096 as maximum width and height.
 319 */
 320#define ZYNQMP_DISP_MAX_WIDTH                           4096
 321#define ZYNQMP_DISP_MAX_HEIGHT                          4096
 322/* 44 bit addressing. This is acutally DPDMA limitation */
 323#define ZYNQMP_DISP_MAX_DMA_BIT                         44
 324
 325/**
 326 * enum zynqmp_disp_layer_type - Layer type (can be used for hw ID)
 327 * @ZYNQMP_DISP_LAYER_VID: Video layer
 328 * @ZYNQMP_DISP_LAYER_GFX: Graphics layer
 329 */
 330enum zynqmp_disp_layer_type {
 331        ZYNQMP_DISP_LAYER_VID,
 332        ZYNQMP_DISP_LAYER_GFX
 333};
 334
 335/**
 336 * enum zynqmp_disp_layer_mode - Layer mode
 337 * @ZYNQMP_DISP_LAYER_NONLIVE: non-live (memory) mode
 338 * @ZYNQMP_DISP_LAYER_LIVE: live (stream) mode
 339 */
 340enum zynqmp_disp_layer_mode {
 341        ZYNQMP_DISP_LAYER_NONLIVE,
 342        ZYNQMP_DISP_LAYER_LIVE
 343};
 344
 345/**
 346 * struct zynqmp_disp_layer_dma - struct for DMA engine
 347 * @chan: DMA channel
 348 * @is_active: flag if the DMA is active
 349 * @xt: Interleaved desc config container
 350 * @sgl: Data chunk for dma_interleaved_template
 351 */
 352struct zynqmp_disp_layer_dma {
 353        struct dma_chan *chan;
 354        bool is_active;
 355        struct dma_interleaved_template xt;
 356        struct data_chunk sgl[1];
 357};
 358
 359/**
 360 * struct zynqmp_disp_layer - Display subsystem layer
 361 * @plane: DRM plane
 362 * @bridge: Xlnx bridge
 363 * @of_node: device node
 364 * @dma: struct for DMA engine
 365 * @num_chan: Number of DMA channel
 366 * @id: Layer ID
 367 * @offset: Layer offset in the register space
 368 * @enabled: flag if enabled
 369 * @fmt: Current format descriptor
 370 * @drm_fmts: Array of supported DRM formats
 371 * @num_fmts: Number of supported DRM formats
 372 * @bus_fmts: Array of supported bus formats
 373 * @num_bus_fmts: Number of supported bus formats
 374 * @w: Width
 375 * @h: Height
 376 * @mode: the operation mode
 377 * @other: other layer
 378 * @disp: back pointer to struct zynqmp_disp
 379 */
 380struct zynqmp_disp_layer {
 381        struct drm_plane plane;
 382        struct xlnx_bridge bridge;
 383        struct device_node *of_node;
 384        struct zynqmp_disp_layer_dma dma[ZYNQMP_DISP_MAX_NUM_SUB_PLANES];
 385        unsigned int num_chan;
 386        enum zynqmp_disp_layer_type id;
 387        u32 offset;
 388        u8 enabled;
 389        const struct zynqmp_disp_fmt *fmt;
 390        u32 *drm_fmts;
 391        unsigned int num_fmts;
 392        u32 *bus_fmts;
 393        unsigned int num_bus_fmts;
 394        u32 w;
 395        u32 h;
 396        enum zynqmp_disp_layer_mode mode;
 397        struct zynqmp_disp_layer *other;
 398        struct zynqmp_disp *disp;
 399};
 400
 401/**
 402 * struct zynqmp_disp_blend - Blender
 403 * @base: Base address offset
 404 */
 405struct zynqmp_disp_blend {
 406        void __iomem *base;
 407};
 408
 409/**
 410 * struct zynqmp_disp_av_buf - AV buffer manager
 411 * @base: Base address offset
 412 */
 413struct zynqmp_disp_av_buf {
 414        void __iomem *base;
 415};
 416
 417/**
 418 * struct zynqmp_disp_aud - Audio
 419 * @base: Base address offset
 420 */
 421struct zynqmp_disp_aud {
 422        void __iomem *base;
 423};
 424
 425/**
 426 * struct zynqmp_disp - Display subsystem
 427 * @xlnx_crtc: Xilinx DRM crtc
 428 * @dev: device structure
 429 * @dpsub: Display subsystem
 430 * @drm: DRM core
 431 * @enabled: flag if enabled
 432 * @blend: Blender block
 433 * @av_buf: AV buffer manager block
 434 * @aud:Audio block
 435 * @layers: layers
 436 * @g_alpha_prop: global alpha property
 437 * @alpha: current global alpha value
 438 * @g_alpha_en_prop: the global alpha enable property
 439 * @alpha_en: flag if the global alpha is enabled
 440 * @color_prop: output color format property
 441 * @color: current output color value
 442 * @bg_c0_prop: 1st component of background color property
 443 * @bg_c0: current value of 1st background color component
 444 * @bg_c1_prop: 2nd component of background color property
 445 * @bg_c1: current value of 2nd background color component
 446 * @bg_c2_prop: 3rd component of background color property
 447 * @bg_c2: current value of 3rd background color component
 448 * @tpg_prop: Test Pattern Generation mode property
 449 * @tpg_on: current TPG mode state
 450 * @event: pending vblank event request
 451 * @_ps_pclk: Pixel clock from PS
 452 * @_pl_pclk: Pixel clock from PL
 453 * @pclk: Pixel clock
 454 * @pclk_en: Flag if the pixel clock is enabled
 455 * @_ps_audclk: Audio clock from PS
 456 * @_pl_audclk: Audio clock from PL
 457 * @audclk: Audio clock
 458 * @audclk_en: Flag if the audio clock is enabled
 459 * @aclk: APB clock
 460 * @aclk_en: Flag if the APB clock is enabled
 461 */
 462struct zynqmp_disp {
 463        struct xlnx_crtc xlnx_crtc;
 464        struct device *dev;
 465        struct zynqmp_dpsub *dpsub;
 466        struct drm_device *drm;
 467        bool enabled;
 468        struct zynqmp_disp_blend blend;
 469        struct zynqmp_disp_av_buf av_buf;
 470        struct zynqmp_disp_aud aud;
 471        struct zynqmp_disp_layer layers[ZYNQMP_DISP_NUM_LAYERS];
 472        struct drm_property *g_alpha_prop;
 473        u32 alpha;
 474        struct drm_property *g_alpha_en_prop;
 475        bool alpha_en;
 476        struct drm_property *color_prop;
 477        unsigned int color;
 478        struct drm_property *bg_c0_prop;
 479        u32 bg_c0;
 480        struct drm_property *bg_c1_prop;
 481        u32 bg_c1;
 482        struct drm_property *bg_c2_prop;
 483        u32 bg_c2;
 484        struct drm_property *tpg_prop;
 485        bool tpg_on;
 486        struct drm_pending_vblank_event *event;
 487        /* Don't operate directly on _ps_ */
 488        struct clk *_ps_pclk;
 489        struct clk *_pl_pclk;
 490        struct clk *pclk;
 491        bool pclk_en;
 492        struct clk *_ps_audclk;
 493        struct clk *_pl_audclk;
 494        struct clk *audclk;
 495        bool audclk_en;
 496        struct clk *aclk;
 497        bool aclk_en;
 498};
 499
 500/**
 501 * struct zynqmp_disp_fmt - Display subsystem format mapping
 502 * @drm_fmt: drm format
 503 * @disp_fmt: Display subsystem format
 504 * @bus_fmt: Bus formats (live formats)
 505 * @rgb: flag for RGB formats
 506 * @swap: flag to swap r & b for rgb formats, and u & v for yuv formats
 507 * @chroma_sub: flag for chroma subsampled formats
 508 * @sf: scaling factors for upto 3 color components
 509 */
 510struct zynqmp_disp_fmt {
 511        u32 drm_fmt;
 512        u32 disp_fmt;
 513        u32 bus_fmt;
 514        bool rgb;
 515        bool swap;
 516        bool chroma_sub;
 517        u32 sf[3];
 518};
 519
 520static void zynqmp_disp_write(void __iomem *base, int offset, u32 val)
 521{
 522        writel(val, base + offset);
 523}
 524
 525static u32 zynqmp_disp_read(void __iomem *base, int offset)
 526{
 527        return readl(base + offset);
 528}
 529
 530static void zynqmp_disp_clr(void __iomem *base, int offset, u32 clr)
 531{
 532        zynqmp_disp_write(base, offset, zynqmp_disp_read(base, offset) & ~clr);
 533}
 534
 535static void zynqmp_disp_set(void __iomem *base, int offset, u32 set)
 536{
 537        zynqmp_disp_write(base, offset, zynqmp_disp_read(base, offset) | set);
 538}
 539
 540/*
 541 * Clock functions
 542 */
 543
 544/**
 545 * zynqmp_disp_clk_enable - Enable the clock if needed
 546 * @clk: clk device
 547 * @flag: flag if the clock is enabled
 548 *
 549 * Enable the clock only if it's not enabled @flag.
 550 *
 551 * Return: value from clk_prepare_enable().
 552 */
 553static int zynqmp_disp_clk_enable(struct clk *clk, bool *flag)
 554{
 555        int ret = 0;
 556
 557        if (!*flag) {
 558                ret = clk_prepare_enable(clk);
 559                if (!ret)
 560                        *flag = true;
 561        }
 562
 563        return ret;
 564}
 565
 566/**
 567 * zynqmp_disp_clk_enable - Enable the clock if needed
 568 * @clk: clk device
 569 * @flag: flag if the clock is enabled
 570 *
 571 * Disable the clock only if it's enabled @flag.
 572 */
 573static void zynqmp_disp_clk_disable(struct clk *clk, bool *flag)
 574{
 575        if (*flag) {
 576                clk_disable_unprepare(clk);
 577                *flag = false;
 578        }
 579}
 580
 581/**
 582 * zynqmp_disp_clk_enable - Enable and disable the clock
 583 * @clk: clk device
 584 * @flag: flag if the clock is enabled
 585 *
 586 * This is to ensure the clock is disabled. The initial hardware state is
 587 * unknown, and this makes sure that the clock is disabled.
 588 *
 589 * Return: value from clk_prepare_enable().
 590 */
 591static int zynqmp_disp_clk_enable_disable(struct clk *clk, bool *flag)
 592{
 593        int ret = 0;
 594
 595        if (!*flag) {
 596                ret = clk_prepare_enable(clk);
 597                clk_disable_unprepare(clk);
 598        }
 599
 600        return ret;
 601}
 602
 603/*
 604 * Blender functions
 605 */
 606
 607/**
 608 * zynqmp_disp_blend_set_output_fmt - Set the output format of the blend
 609 * @blend: blend object
 610 * @fmt: output format
 611 *
 612 * Set the output format to @fmt.
 613 */
 614static void
 615zynqmp_disp_blend_set_output_fmt(struct zynqmp_disp_blend *blend, u32 fmt)
 616{
 617        u16 reset_coeffs[] = { 0x1000, 0x0, 0x0,
 618                               0x0, 0x1000, 0x0,
 619                               0x0, 0x0, 0x1000 };
 620        u32 reset_offsets[] = { 0x0, 0x0, 0x0 };
 621        u16 sdtv_coeffs[] = { 0x4c9, 0x864, 0x1d3,
 622                              0x7d4d, 0x7ab3, 0x800,
 623                              0x800, 0x794d, 0x7eb3 };
 624        u32 full_range_offsets[] = { 0x0, 0x8000000, 0x8000000 };
 625        u16 *coeffs;
 626        u32 *offsets;
 627        u32 offset, i;
 628
 629        zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT, fmt);
 630        if (fmt == ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_RGB) {
 631                coeffs = reset_coeffs;
 632                offsets = reset_offsets;
 633        } else {
 634                /* Hardcode Full-range SDTV values. Can be runtime config */
 635                coeffs = sdtv_coeffs;
 636                offsets = full_range_offsets;
 637        }
 638
 639        offset = ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF0;
 640        for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_COEFF; i++)
 641                zynqmp_disp_write(blend->base, offset + i * 4, coeffs[i]);
 642
 643        offset = ZYNQMP_DISP_V_BLEND_LUMA_OUTCSC_OFFSET;
 644        for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_OFFSET; i++)
 645                zynqmp_disp_write(blend->base, offset + i * 4, offsets[i]);
 646}
 647
 648/**
 649 * zynqmp_disp_blend_layer_coeff - Set the coefficients for @layer
 650 * @blend: blend object
 651 * @layer: layer to set the coefficients for
 652 * @on: if layer is on / off
 653 *
 654 * Depending on the format (rgb / yuv and swap), and the status (on / off),
 655 * this function sets the coefficients for the given layer @layer accordingly.
 656 */
 657static void zynqmp_disp_blend_layer_coeff(struct zynqmp_disp_blend *blend,
 658                                          struct zynqmp_disp_layer *layer,
 659                                          bool on)
 660{
 661        u32 offset, i, s0, s1;
 662        u16 sdtv_coeffs[] = { 0x1000, 0x166f, 0x0,
 663                              0x1000, 0x7483, 0x7a7f,
 664                              0x1000, 0x0, 0x1c5a };
 665        u16 swap_coeffs[] = { 0x1000, 0x0, 0x0,
 666                              0x0, 0x1000, 0x0,
 667                              0x0, 0x0, 0x1000 };
 668        u16 null_coeffs[] = { 0x0, 0x0, 0x0,
 669                              0x0, 0x0, 0x0,
 670                              0x0, 0x0, 0x0 };
 671        u16 *coeffs;
 672        u32 sdtv_offsets[] = { 0x0, 0x1800, 0x1800 };
 673        u32 null_offsets[] = { 0x0, 0x0, 0x0 };
 674        u32 *offsets;
 675
 676        if (layer->id == ZYNQMP_DISP_LAYER_VID)
 677                offset = ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF0;
 678        else
 679                offset = ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF0;
 680
 681        if (!on) {
 682                coeffs = null_coeffs;
 683                offsets = null_offsets;
 684        } else {
 685                if (!layer->fmt->rgb) {
 686                        coeffs = sdtv_coeffs;
 687                        offsets = sdtv_offsets;
 688                        s0 = 1;
 689                        s1 = 2;
 690                } else {
 691                        coeffs = swap_coeffs;
 692                        s0 = 0;
 693                        s1 = 2;
 694
 695                        /* No offset for RGB formats */
 696                        offsets = null_offsets;
 697                }
 698
 699                if (layer->fmt->swap) {
 700                        for (i = 0; i < 3; i++) {
 701                                coeffs[i * 3 + s0] ^= coeffs[i * 3 + s1];
 702                                coeffs[i * 3 + s1] ^= coeffs[i * 3 + s0];
 703                                coeffs[i * 3 + s0] ^= coeffs[i * 3 + s1];
 704                        }
 705                }
 706        }
 707
 708        /* Program coefficients. Can be runtime configurable */
 709        for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_COEFF; i++)
 710                zynqmp_disp_write(blend->base, offset + i * 4, coeffs[i]);
 711
 712        if (layer->id == ZYNQMP_DISP_LAYER_VID)
 713                offset = ZYNQMP_DISP_V_BLEND_LUMA_IN1CSC_OFFSET;
 714        else
 715                offset = ZYNQMP_DISP_V_BLEND_LUMA_IN2CSC_OFFSET;
 716
 717        /* Program offsets. Can be runtime configurable */
 718        for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_OFFSET; i++)
 719                zynqmp_disp_write(blend->base, offset + i * 4, offsets[i]);
 720}
 721
 722/**
 723 * zynqmp_disp_blend_layer_enable - Enable a layer
 724 * @blend: blend object
 725 * @layer: layer to enable
 726 *
 727 * Enable a layer @layer.
 728 */
 729static void zynqmp_disp_blend_layer_enable(struct zynqmp_disp_blend *blend,
 730                                           struct zynqmp_disp_layer *layer)
 731{
 732        u32 reg;
 733
 734        reg = layer->fmt->rgb ? ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_RGB : 0;
 735        reg |= layer->fmt->chroma_sub ?
 736               ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_EN_US : 0;
 737
 738        zynqmp_disp_write(blend->base,
 739                          ZYNQMP_DISP_V_BLEND_LAYER_CONTROL + layer->offset,
 740                          reg);
 741
 742        zynqmp_disp_blend_layer_coeff(blend, layer, true);
 743}
 744
 745/**
 746 * zynqmp_disp_blend_layer_disable - Disable a layer
 747 * @blend: blend object
 748 * @layer: layer to disable
 749 *
 750 * Disable a layer @layer.
 751 */
 752static void zynqmp_disp_blend_layer_disable(struct zynqmp_disp_blend *blend,
 753                                            struct zynqmp_disp_layer *layer)
 754{
 755        zynqmp_disp_write(blend->base,
 756                          ZYNQMP_DISP_V_BLEND_LAYER_CONTROL + layer->offset, 0);
 757
 758        zynqmp_disp_blend_layer_coeff(blend, layer, false);
 759}
 760
 761/**
 762 * zynqmp_disp_blend_set_bg_color - Set the background color
 763 * @blend: blend object
 764 * @c0: color component 0
 765 * @c1: color component 1
 766 * @c2: color component 2
 767 *
 768 * Set the background color.
 769 */
 770static void zynqmp_disp_blend_set_bg_color(struct zynqmp_disp_blend *blend,
 771                                           u32 c0, u32 c1, u32 c2)
 772{
 773        zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_BG_CLR_0, c0);
 774        zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_BG_CLR_1, c1);
 775        zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_BG_CLR_2, c2);
 776}
 777
 778/**
 779 * zynqmp_disp_blend_set_alpha - Set the alpha for blending
 780 * @blend: blend object
 781 * @alpha: alpha value to be used
 782 *
 783 * Set the alpha for blending.
 784 */
 785static void
 786zynqmp_disp_blend_set_alpha(struct zynqmp_disp_blend *blend, u32 alpha)
 787{
 788        u32 reg;
 789
 790        reg = zynqmp_disp_read(blend->base,
 791                               ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA);
 792        reg &= ~ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MASK;
 793        reg |= alpha << 1;
 794        zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA,
 795                          reg);
 796}
 797
 798/**
 799 * zynqmp_disp_blend_enable_alpha - Enable/disable the global alpha
 800 * @blend: blend object
 801 * @enable: flag to enable or disable alpha blending
 802 *
 803 * Enable/disable the global alpha blending based on @enable.
 804 */
 805static void
 806zynqmp_disp_blend_enable_alpha(struct zynqmp_disp_blend *blend, bool enable)
 807{
 808        if (enable)
 809                zynqmp_disp_set(blend->base,
 810                                ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA, BIT(0));
 811        else
 812                zynqmp_disp_clr(blend->base,
 813                                ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA, BIT(0));
 814}
 815
 816/* List of blend output formats */
 817/* The id / order should be aligned with zynqmp_disp_color_enum */
 818static const struct zynqmp_disp_fmt blend_output_fmts[] = {
 819        {
 820                .disp_fmt       = ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_RGB,
 821        }, {
 822                .disp_fmt       = ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YCBCR444,
 823        }, {
 824                .disp_fmt       = ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YCBCR422,
 825        }, {
 826                .disp_fmt       = ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YONLY,
 827        }
 828};
 829
 830/*
 831 * AV buffer manager functions
 832 */
 833
 834/* List of video layer formats */
 835#define ZYNQMP_DISP_AV_BUF_VID_FMT_YUYV 2
 836static const struct zynqmp_disp_fmt av_buf_vid_fmts[] = {
 837        {
 838                .drm_fmt        = DRM_FORMAT_VYUY,
 839                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_VYUY,
 840                .rgb            = false,
 841                .swap           = true,
 842                .chroma_sub     = true,
 843                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 844                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 845                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 846        }, {
 847                .drm_fmt        = DRM_FORMAT_UYVY,
 848                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_VYUY,
 849                .rgb            = false,
 850                .swap           = false,
 851                .chroma_sub     = true,
 852                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 853                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 854                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 855        }, {
 856                .drm_fmt        = DRM_FORMAT_YUYV,
 857                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUYV,
 858                .rgb            = false,
 859                .swap           = false,
 860                .chroma_sub     = true,
 861                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 862                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 863                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 864        }, {
 865                .drm_fmt        = DRM_FORMAT_YVYU,
 866                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUYV,
 867                .rgb            = false,
 868                .swap           = true,
 869                .chroma_sub     = true,
 870                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 871                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 872                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 873        }, {
 874                .drm_fmt        = DRM_FORMAT_YUV422,
 875                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16,
 876                .rgb            = false,
 877                .swap           = false,
 878                .chroma_sub     = true,
 879                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 880                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 881                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 882        }, {
 883                .drm_fmt        = DRM_FORMAT_YVU422,
 884                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16,
 885                .rgb            = false,
 886                .swap           = true,
 887                .chroma_sub     = true,
 888                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 889                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 890                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 891        }, {
 892                .drm_fmt        = DRM_FORMAT_YUV444,
 893                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV24,
 894                .rgb            = false,
 895                .swap           = false,
 896                .chroma_sub     = false,
 897                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 898                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 899                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 900        }, {
 901                .drm_fmt        = DRM_FORMAT_YVU444,
 902                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV24,
 903                .rgb            = false,
 904                .swap           = true,
 905                .chroma_sub     = false,
 906                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 907                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 908                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 909        }, {
 910                .drm_fmt        = DRM_FORMAT_NV16,
 911                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI,
 912                .rgb            = false,
 913                .swap           = false,
 914                .chroma_sub     = true,
 915                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 916                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 917                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 918        }, {
 919                .drm_fmt        = DRM_FORMAT_NV61,
 920                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI,
 921                .rgb            = false,
 922                .swap           = true,
 923                .chroma_sub     = true,
 924                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 925                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 926                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 927        }, {
 928                .drm_fmt        = DRM_FORMAT_BGR888,
 929                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888,
 930                .rgb            = true,
 931                .swap           = false,
 932                .chroma_sub     = false,
 933                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 934                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 935                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 936        }, {
 937                .drm_fmt        = DRM_FORMAT_RGB888,
 938                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888,
 939                .rgb            = true,
 940                .swap           = true,
 941                .chroma_sub     = false,
 942                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 943                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 944                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 945        }, {
 946                .drm_fmt        = DRM_FORMAT_XBGR8888,
 947                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGBA8880,
 948                .rgb            = true,
 949                .swap           = false,
 950                .chroma_sub     = false,
 951                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 952                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 953                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 954        }, {
 955                .drm_fmt        = DRM_FORMAT_XRGB8888,
 956                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGBA8880,
 957                .rgb            = true,
 958                .swap           = true,
 959                .chroma_sub     = false,
 960                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 961                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 962                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 963        }, {
 964                .drm_fmt        = DRM_FORMAT_XBGR2101010,
 965                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888_10,
 966                .rgb            = true,
 967                .swap           = false,
 968                .chroma_sub     = false,
 969                .sf[0]          = ZYNQMP_DISP_AV_BUF_10BIT_SF,
 970                .sf[1]          = ZYNQMP_DISP_AV_BUF_10BIT_SF,
 971                .sf[2]          = ZYNQMP_DISP_AV_BUF_10BIT_SF,
 972        }, {
 973                .drm_fmt        = DRM_FORMAT_XRGB2101010,
 974                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888_10,
 975                .rgb            = true,
 976                .swap           = true,
 977                .chroma_sub     = false,
 978                .sf[0]          = ZYNQMP_DISP_AV_BUF_10BIT_SF,
 979                .sf[1]          = ZYNQMP_DISP_AV_BUF_10BIT_SF,
 980                .sf[2]          = ZYNQMP_DISP_AV_BUF_10BIT_SF,
 981        }, {
 982                .drm_fmt        = DRM_FORMAT_YUV420,
 983                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_420,
 984                .rgb            = false,
 985                .swap           = false,
 986                .chroma_sub     = true,
 987                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 988                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 989                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 990        }, {
 991                .drm_fmt        = DRM_FORMAT_YVU420,
 992                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_420,
 993                .rgb            = false,
 994                .swap           = true,
 995                .chroma_sub     = true,
 996                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 997                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 998                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
 999        }, {
1000                .drm_fmt        = DRM_FORMAT_NV12,
1001                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420,
1002                .rgb            = false,
1003                .swap           = false,
1004                .chroma_sub     = true,
1005                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1006                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1007                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1008        }, {
1009                .drm_fmt        = DRM_FORMAT_NV21,
1010                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420,
1011                .rgb            = false,
1012                .swap           = true,
1013                .chroma_sub     = true,
1014                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1015                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1016                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1017        }, {
1018                .drm_fmt        = DRM_FORMAT_XV15,
1019                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420_10,
1020                .rgb            = false,
1021                .swap           = false,
1022                .chroma_sub     = true,
1023                .sf[0]          = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1024                .sf[1]          = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1025                .sf[2]          = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1026        }, {
1027                .drm_fmt        = DRM_FORMAT_XV20,
1028                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_10,
1029                .rgb            = false,
1030                .swap           = false,
1031                .chroma_sub     = true,
1032                .sf[0]          = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1033                .sf[1]          = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1034                .sf[2]          = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1035        }
1036};
1037
1038/* List of graphics layer formats */
1039static const struct zynqmp_disp_fmt av_buf_gfx_fmts[] = {
1040        {
1041                .drm_fmt        = DRM_FORMAT_ABGR8888,
1042                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA8888,
1043                .rgb            = true,
1044                .swap           = false,
1045                .chroma_sub     = false,
1046                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1047                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1048                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1049        }, {
1050                .drm_fmt        = DRM_FORMAT_ARGB8888,
1051                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA8888,
1052                .rgb            = true,
1053                .swap           = true,
1054                .chroma_sub     = false,
1055                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1056                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1057                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1058        }, {
1059                .drm_fmt        = DRM_FORMAT_RGBA8888,
1060                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_ABGR8888,
1061                .rgb            = true,
1062                .swap           = false,
1063                .chroma_sub     = false,
1064                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1065                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1066                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1067        }, {
1068                .drm_fmt        = DRM_FORMAT_BGRA8888,
1069                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_ABGR8888,
1070                .rgb            = true,
1071                .swap           = true,
1072                .chroma_sub     = false,
1073                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1074                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1075                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1076        }, {
1077                .drm_fmt        = DRM_FORMAT_BGR888,
1078                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB888,
1079                .rgb            = true,
1080                .swap           = false,
1081                .chroma_sub     = false,
1082                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1083                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1084                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1085        }, {
1086                .drm_fmt        = DRM_FORMAT_RGB888,
1087                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_BGR888,
1088                .rgb            = true,
1089                .swap           = false,
1090                .chroma_sub     = false,
1091                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1092                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1093                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1094        }, {
1095                .drm_fmt        = DRM_FORMAT_RGBA5551,
1096                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA5551,
1097                .rgb            = true,
1098                .swap           = false,
1099                .chroma_sub     = false,
1100                .sf[0]          = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1101                .sf[1]          = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1102                .sf[2]          = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1103        }, {
1104                .drm_fmt        = DRM_FORMAT_BGRA5551,
1105                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA5551,
1106                .rgb            = true,
1107                .swap           = true,
1108                .chroma_sub     = false,
1109                .sf[0]          = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1110                .sf[1]          = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1111                .sf[2]          = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1112        }, {
1113                .drm_fmt        = DRM_FORMAT_RGBA4444,
1114                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA4444,
1115                .rgb            = true,
1116                .swap           = false,
1117                .chroma_sub     = false,
1118                .sf[0]          = ZYNQMP_DISP_AV_BUF_4BIT_SF,
1119                .sf[1]          = ZYNQMP_DISP_AV_BUF_4BIT_SF,
1120                .sf[2]          = ZYNQMP_DISP_AV_BUF_4BIT_SF,
1121        }, {
1122                .drm_fmt        = DRM_FORMAT_BGRA4444,
1123                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA4444,
1124                .rgb            = true,
1125                .swap           = true,
1126                .chroma_sub     = false,
1127                .sf[0]          = ZYNQMP_DISP_AV_BUF_4BIT_SF,
1128                .sf[1]          = ZYNQMP_DISP_AV_BUF_4BIT_SF,
1129                .sf[2]          = ZYNQMP_DISP_AV_BUF_4BIT_SF,
1130        }, {
1131                .drm_fmt        = DRM_FORMAT_RGB565,
1132                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB565,
1133                .rgb            = true,
1134                .swap           = false,
1135                .chroma_sub     = false,
1136                .sf[0]          = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1137                .sf[1]          = ZYNQMP_DISP_AV_BUF_6BIT_SF,
1138                .sf[2]          = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1139        }, {
1140                .drm_fmt        = DRM_FORMAT_BGR565,
1141                .disp_fmt       = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB565,
1142                .rgb            = true,
1143                .swap           = true,
1144                .chroma_sub     = false,
1145                .sf[0]          = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1146                .sf[1]          = ZYNQMP_DISP_AV_BUF_6BIT_SF,
1147                .sf[2]          = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1148        }
1149};
1150
1151/* List of live formats */
1152/* Format can be combination of color, bpc, and cb-cr order.
1153 * - Color: RGB / YUV444 / YUV422 / Y only
1154 * - BPC: 6, 8, 10, 12
1155 * - Swap: Cb and Cr swap
1156 * which can be 32 bus formats. Only list the subset of those for now.
1157 */
1158static const struct zynqmp_disp_fmt av_buf_live_fmts[] = {
1159        {
1160                .bus_fmt        = MEDIA_BUS_FMT_RGB666_1X18,
1161                .disp_fmt       = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_6 ||
1162                                  ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB,
1163                .rgb            = true,
1164                .swap           = false,
1165                .chroma_sub     = false,
1166                .sf[0]          = ZYNQMP_DISP_AV_BUF_6BIT_SF,
1167                .sf[1]          = ZYNQMP_DISP_AV_BUF_6BIT_SF,
1168                .sf[2]          = ZYNQMP_DISP_AV_BUF_6BIT_SF,
1169        }, {
1170                .bus_fmt        = MEDIA_BUS_FMT_RBG888_1X24,
1171                .disp_fmt       = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 ||
1172                                  ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB,
1173                .rgb            = true,
1174                .swap           = false,
1175                .chroma_sub     = false,
1176                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1177                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1178                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1179        }, {
1180                .bus_fmt        = MEDIA_BUS_FMT_UYVY8_1X16,
1181                .disp_fmt       = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 ||
1182                                  ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422,
1183                .rgb            = false,
1184                .swap           = false,
1185                .chroma_sub     = true,
1186                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1187                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1188                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1189        }, {
1190                .bus_fmt        = MEDIA_BUS_FMT_VUY8_1X24,
1191                .disp_fmt       = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 ||
1192                                  ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV444,
1193                .rgb            = false,
1194                .swap           = false,
1195                .chroma_sub     = false,
1196                .sf[0]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1197                .sf[1]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1198                .sf[2]          = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1199        }, {
1200                .bus_fmt        = MEDIA_BUS_FMT_UYVY10_1X20,
1201                .disp_fmt       = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_10 ||
1202                                  ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422,
1203                .rgb            = false,
1204                .swap           = false,
1205                .chroma_sub     = true,
1206                .sf[0]          = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1207                .sf[1]          = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1208                .sf[2]          = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1209        }
1210};
1211
1212/**
1213 * zynqmp_disp_av_buf_set_fmt - Set the input formats
1214 * @av_buf: av buffer manager
1215 * @fmt: formats
1216 *
1217 * Set the av buffer manager format to @fmt. @fmt should have valid values
1218 * for both video and graphics layer.
1219 */
1220static void
1221zynqmp_disp_av_buf_set_fmt(struct zynqmp_disp_av_buf *av_buf, u32 fmt)
1222{
1223        zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_FMT, fmt);
1224}
1225
1226/**
1227 * zynqmp_disp_av_buf_get_fmt - Get the input formats
1228 * @av_buf: av buffer manager
1229 *
1230 * Get the input formats (which include video and graphics) of
1231 * av buffer manager.
1232 *
1233 * Return: value of ZYNQMP_DISP_AV_BUF_FMT register.
1234 */
1235static u32
1236zynqmp_disp_av_buf_get_fmt(struct zynqmp_disp_av_buf *av_buf)
1237{
1238        return zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_FMT);
1239}
1240
1241/**
1242 * zynqmp_disp_av_buf_set_live_fmt - Set the live_input format
1243 * @av_buf: av buffer manager
1244 * @fmt: format
1245 * @is_vid: if it's for video layer
1246 *
1247 * Set the live input format to @fmt. @fmt should have valid values.
1248 * @vid will determine if it's for video layer or graphics layer
1249 * @fmt should be a valid hardware value.
1250 */
1251static void zynqmp_disp_av_buf_set_live_fmt(struct zynqmp_disp_av_buf *av_buf,
1252                                            u32 fmt, bool is_vid)
1253{
1254        u32 offset;
1255
1256        if (is_vid)
1257                offset = ZYNQMP_DISP_AV_BUF_LIVE_VID_CONFIG;
1258        else
1259                offset = ZYNQMP_DISP_AV_BUF_LIVE_GFX_CONFIG;
1260
1261        zynqmp_disp_write(av_buf->base, offset, fmt);
1262}
1263
1264/**
1265 * zynqmp_disp_av_buf_set_vid_clock_src - Set the video clock source
1266 * @av_buf: av buffer manager
1267 * @from_ps: flag if the video clock is from ps
1268 *
1269 * Set the video clock source based on @from_ps. It can come from either PS or
1270 * PL.
1271 */
1272static void
1273zynqmp_disp_av_buf_set_vid_clock_src(struct zynqmp_disp_av_buf *av_buf,
1274                                     bool from_ps)
1275{
1276        u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
1277
1278        if (from_ps)
1279                reg |= ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_FROM_PS;
1280        else
1281                reg &= ~ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_FROM_PS;
1282        zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC, reg);
1283}
1284
1285/**
1286 * zynqmp_disp_av_buf_vid_clock_src_is_ps - if ps clock is used
1287 * @av_buf: av buffer manager
1288 *
1289 * Return: if ps clock is used
1290 */
1291static bool
1292zynqmp_disp_av_buf_vid_clock_src_is_ps(struct zynqmp_disp_av_buf *av_buf)
1293{
1294        u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
1295
1296        return !!(reg & ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_FROM_PS);
1297}
1298
1299/**
1300 * zynqmp_disp_av_buf_set_vid_timing_src - Set the video timing source
1301 * @av_buf: av buffer manager
1302 * @internal: flag if the video timing is generated internally
1303 *
1304 * Set the video timing source based on @internal. It can come externally or
1305 * be generated internally.
1306 */
1307static void
1308zynqmp_disp_av_buf_set_vid_timing_src(struct zynqmp_disp_av_buf *av_buf,
1309                                      bool internal)
1310{
1311        u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
1312
1313        if (internal)
1314                reg |= ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING;
1315        else
1316                reg &= ~ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING;
1317        zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC, reg);
1318}
1319
1320/**
1321 * zynqmp_disp_av_buf_vid_timing_src_is_int - if internal timing is used
1322 * @av_buf: av buffer manager
1323 *
1324 * Return: if the internal timing is used
1325 */
1326static bool
1327zynqmp_disp_av_buf_vid_timing_src_is_int(struct zynqmp_disp_av_buf *av_buf)
1328{
1329        u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
1330
1331        return !!(reg & ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING);
1332}
1333
1334/**
1335 * zynqmp_disp_av_buf_set_aud_clock_src - Set the audio clock source
1336 * @av_buf: av buffer manager
1337 * @from_ps: flag if the video clock is from ps
1338 *
1339 * Set the audio clock source based on @from_ps. It can come from either PS or
1340 * PL.
1341 */
1342static void
1343zynqmp_disp_av_buf_set_aud_clock_src(struct zynqmp_disp_av_buf *av_buf,
1344                                     bool from_ps)
1345{
1346        u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
1347
1348        if (from_ps)
1349                reg |= ZYNQMP_DISP_AV_BUF_CLK_SRC_AUD_FROM_PS;
1350        else
1351                reg &= ~ZYNQMP_DISP_AV_BUF_CLK_SRC_AUD_FROM_PS;
1352        zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC, reg);
1353}
1354
1355/**
1356 * zynqmp_disp_av_buf_enable_buf - Enable buffers
1357 * @av_buf: av buffer manager
1358 *
1359 * Enable all (video and audio) buffers.
1360 */
1361static void
1362zynqmp_disp_av_buf_enable_buf(struct zynqmp_disp_av_buf *av_buf)
1363{
1364        u32 reg, i;
1365
1366        reg = ZYNQMP_DISP_AV_BUF_CHBUF_EN;
1367        reg |= ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_MAX <<
1368               ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_SHIFT;
1369
1370        for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_VID_GFX_BUFFERS; i++)
1371                zynqmp_disp_write(av_buf->base,
1372                                  ZYNQMP_DISP_AV_BUF_CHBUF + i * 4, reg);
1373
1374        reg = ZYNQMP_DISP_AV_BUF_CHBUF_EN;
1375        reg |= ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_AUD_MAX <<
1376               ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_SHIFT;
1377
1378        for (; i < ZYNQMP_DISP_AV_BUF_NUM_BUFFERS; i++)
1379                zynqmp_disp_write(av_buf->base,
1380                                  ZYNQMP_DISP_AV_BUF_CHBUF + i * 4, reg);
1381}
1382
1383/**
1384 * zynqmp_disp_av_buf_disable_buf - Disable buffers
1385 * @av_buf: av buffer manager
1386 *
1387 * Disable all (video and audio) buffers.
1388 */
1389static void
1390zynqmp_disp_av_buf_disable_buf(struct zynqmp_disp_av_buf *av_buf)
1391{
1392        u32 reg, i;
1393
1394        reg = ZYNQMP_DISP_AV_BUF_CHBUF_FLUSH & ~ZYNQMP_DISP_AV_BUF_CHBUF_EN;
1395        for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_BUFFERS; i++)
1396                zynqmp_disp_write(av_buf->base,
1397                                  ZYNQMP_DISP_AV_BUF_CHBUF + i * 4, reg);
1398}
1399
1400/**
1401 * zynqmp_disp_av_buf_enable_aud - Enable audio
1402 * @av_buf: av buffer manager
1403 *
1404 * Enable all audio buffers.
1405 */
1406static void
1407zynqmp_disp_av_buf_enable_aud(struct zynqmp_disp_av_buf *av_buf)
1408{
1409        u32 reg;
1410
1411        reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
1412        reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MASK;
1413        reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MEM;
1414        reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD2_EN;
1415        zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
1416}
1417
1418/**
1419 * zynqmp_disp_av_buf_enable - Enable the video pipe
1420 * @av_buf: av buffer manager
1421 *
1422 * De-assert the video pipe reset
1423 */
1424static void
1425zynqmp_disp_av_buf_enable(struct zynqmp_disp_av_buf *av_buf)
1426{
1427        zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_SRST_REG, 0);
1428}
1429
1430/**
1431 * zynqmp_disp_av_buf_disable - Disable the video pipe
1432 * @av_buf: av buffer manager
1433 *
1434 * Assert the video pipe reset
1435 */
1436static void
1437zynqmp_disp_av_buf_disable(struct zynqmp_disp_av_buf *av_buf)
1438{
1439        zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_SRST_REG,
1440                          ZYNQMP_DISP_AV_BUF_SRST_REG_VID_RST);
1441}
1442
1443/**
1444 * zynqmp_disp_av_buf_disable_aud - Disable audio
1445 * @av_buf: av buffer manager
1446 *
1447 * Disable all audio buffers.
1448 */
1449static void
1450zynqmp_disp_av_buf_disable_aud(struct zynqmp_disp_av_buf *av_buf)
1451{
1452        u32 reg;
1453
1454        reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
1455        reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MASK;
1456        reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_DISABLE;
1457        reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_AUD2_EN;
1458        zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
1459}
1460
1461/**
1462 * zynqmp_disp_av_buf_set_tpg - Set TPG mode
1463 * @av_buf: av buffer manager
1464 * @tpg_on: if TPG should be on
1465 *
1466 * Set the TPG mode based on @tpg_on.
1467 */
1468static void zynqmp_disp_av_buf_set_tpg(struct zynqmp_disp_av_buf *av_buf,
1469                                       bool tpg_on)
1470{
1471        u32 reg;
1472
1473        reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
1474        reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK;
1475        if (tpg_on)
1476                reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_PATTERN;
1477        else
1478                reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_PATTERN;
1479        zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
1480}
1481
1482/**
1483 * zynqmp_disp_av_buf_enable_vid - Enable the video layer buffer
1484 * @av_buf: av buffer manager
1485 * @layer: layer to enable
1486 * @mode: operation mode of layer
1487 *
1488 * Enable the video/graphics buffer for @layer.
1489 */
1490static void zynqmp_disp_av_buf_enable_vid(struct zynqmp_disp_av_buf *av_buf,
1491                                          struct zynqmp_disp_layer *layer,
1492                                          enum zynqmp_disp_layer_mode mode)
1493{
1494        u32 reg;
1495
1496        reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
1497        if (layer->id == ZYNQMP_DISP_LAYER_VID) {
1498                reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK;
1499                if (mode == ZYNQMP_DISP_LAYER_NONLIVE)
1500                        reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MEM;
1501                else
1502                        reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_LIVE;
1503        } else {
1504                reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MASK;
1505                reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MEM;
1506                if (mode == ZYNQMP_DISP_LAYER_NONLIVE)
1507                        reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MEM;
1508                else
1509                        reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_LIVE;
1510        }
1511        zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
1512}
1513
1514/**
1515 * zynqmp_disp_av_buf_disable_vid - Disable the video layer buffer
1516 * @av_buf: av buffer manager
1517 * @layer: layer to disable
1518 *
1519 * Disable the video/graphics buffer for @layer.
1520 */
1521static void
1522zynqmp_disp_av_buf_disable_vid(struct zynqmp_disp_av_buf *av_buf,
1523                               struct zynqmp_disp_layer *layer)
1524{
1525        u32 reg;
1526
1527        reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
1528        if (layer->id == ZYNQMP_DISP_LAYER_VID) {
1529                reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK;
1530                reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_NONE;
1531        } else {
1532                reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MASK;
1533                reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_DISABLE;
1534        }
1535        zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
1536}
1537
1538/**
1539 * zynqmp_disp_av_buf_init_sf - Initialize scaling factors
1540 * @av_buf: av buffer manager
1541 * @vid_fmt: video format descriptor
1542 * @gfx_fmt: graphics format descriptor
1543 *
1544 * Initialize scaling factors for both video and graphics layers.
1545 * If the format descriptor is NULL, the function skips the programming.
1546 */
1547static void zynqmp_disp_av_buf_init_sf(struct zynqmp_disp_av_buf *av_buf,
1548                                       const struct zynqmp_disp_fmt *vid_fmt,
1549                                       const struct zynqmp_disp_fmt *gfx_fmt)
1550{
1551        unsigned int i;
1552        u32 offset;
1553
1554        if (gfx_fmt) {
1555                offset = ZYNQMP_DISP_AV_BUF_GFX_COMP0_SF;
1556                for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; i++)
1557                        zynqmp_disp_write(av_buf->base, offset + i * 4,
1558                                          gfx_fmt->sf[i]);
1559        }
1560
1561        if (vid_fmt) {
1562                offset = ZYNQMP_DISP_AV_BUF_VID_COMP0_SF;
1563                for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; i++)
1564                        zynqmp_disp_write(av_buf->base, offset + i * 4,
1565                                          vid_fmt->sf[i]);
1566        }
1567}
1568
1569/**
1570 * zynqmp_disp_av_buf_init_live_sf - Initialize scaling factors for live source
1571 * @av_buf: av buffer manager
1572 * @fmt: format descriptor
1573 * @is_vid: flag if this is for video layer
1574 *
1575 * Initialize scaling factors for live source.
1576 */
1577static void zynqmp_disp_av_buf_init_live_sf(struct zynqmp_disp_av_buf *av_buf,
1578                                            const struct zynqmp_disp_fmt *fmt,
1579                                            bool is_vid)
1580{
1581        unsigned int i;
1582        u32 offset;
1583
1584        if (is_vid)
1585                offset = ZYNQMP_DISP_AV_BUF_LIVE_VID_COMP0_SF;
1586        else
1587                offset = ZYNQMP_DISP_AV_BUF_LIVE_GFX_COMP0_SF;
1588
1589        for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; i++)
1590                zynqmp_disp_write(av_buf->base, offset + i * 4,
1591                                  fmt->sf[i]);
1592}
1593
1594/*
1595 * Audio functions
1596 */
1597
1598/**
1599 * zynqmp_disp_aud_init - Initialize the audio
1600 * @aud: audio
1601 *
1602 * Initialize the audio with default mixer volume. The de-assertion will
1603 * initialize the audio states.
1604 */
1605static void zynqmp_disp_aud_init(struct zynqmp_disp_aud *aud)
1606{
1607        /* Clear the audio soft reset register as it's an non-reset flop */
1608        zynqmp_disp_write(aud->base, ZYNQMP_DISP_AUD_SOFT_RESET, 0);
1609        zynqmp_disp_write(aud->base, ZYNQMP_DISP_AUD_MIXER_VOLUME,
1610                          ZYNQMP_DISP_AUD_MIXER_VOLUME_NO_SCALE);
1611}
1612
1613/**
1614 * zynqmp_disp_aud_deinit - De-initialize the audio
1615 * @aud: audio
1616 *
1617 * Put the audio in reset.
1618 */
1619static void zynqmp_disp_aud_deinit(struct zynqmp_disp_aud *aud)
1620{
1621        zynqmp_disp_set(aud->base, ZYNQMP_DISP_AUD_SOFT_RESET,
1622                        ZYNQMP_DISP_AUD_SOFT_RESET_AUD_SRST);
1623}
1624
1625/*
1626 * ZynqMP Display layer functions
1627 */
1628
1629/**
1630 * zynqmp_disp_layer_check_size - Verify width and height for the layer
1631 * @disp: Display subsystem
1632 * @layer: layer
1633 * @width: width
1634 * @height: height
1635 *
1636 * The Display subsystem has the limitation that both layers should have
1637 * identical size. This function stores width and height of @layer, and verifies
1638 * if the size (width and height) is valid.
1639 *
1640 * Return: 0 on success, or -EINVAL if width or/and height is invalid.
1641 */
1642static int zynqmp_disp_layer_check_size(struct zynqmp_disp *disp,
1643                                        struct zynqmp_disp_layer *layer,
1644                                        u32 width, u32 height)
1645{
1646        struct zynqmp_disp_layer *other = layer->other;
1647
1648        if (other->enabled && (other->w != width || other->h != height)) {
1649                dev_err(disp->dev, "Layer width:height must be %d:%d\n",
1650                        other->w, other->h);
1651                return -EINVAL;
1652        }
1653
1654        layer->w = width;
1655        layer->h = height;
1656
1657        return 0;
1658}
1659
1660/**
1661 * zynqmp_disp_map_fmt - Find the Display subsystem format for given drm format
1662 * @fmts: format table to look up
1663 * @size: size of the table @fmts
1664 * @drm_fmt: DRM format to search
1665 *
1666 * Search a Display subsystem format corresponding to the given DRM format
1667 * @drm_fmt, and return the format descriptor which contains the Display
1668 * subsystem format value.
1669 *
1670 * Return: a Display subsystem format descriptor on success, or NULL.
1671 */
1672static const struct zynqmp_disp_fmt *
1673zynqmp_disp_map_fmt(const struct zynqmp_disp_fmt fmts[],
1674                    unsigned int size, uint32_t drm_fmt)
1675{
1676        unsigned int i;
1677
1678        for (i = 0; i < size; i++)
1679                if (fmts[i].drm_fmt == drm_fmt)
1680                        return &fmts[i];
1681
1682        return NULL;
1683}
1684
1685/**
1686 * zynqmp_disp_set_fmt - Set the format of the layer
1687 * @disp: Display subsystem
1688 * @layer: layer to set the format
1689 * @drm_fmt: DRM format to set
1690 *
1691 * Set the format of the given layer to @drm_fmt.
1692 *
1693 * Return: 0 on success. -EINVAL if @drm_fmt is not supported by the layer.
1694 */
1695static int zynqmp_disp_layer_set_fmt(struct zynqmp_disp *disp,
1696                                     struct zynqmp_disp_layer *layer,
1697                                     uint32_t drm_fmt)
1698{
1699        const struct zynqmp_disp_fmt *fmt;
1700        const struct zynqmp_disp_fmt *vid_fmt = NULL, *gfx_fmt = NULL;
1701        u32 size, fmts, mask;
1702
1703        if (layer->id == ZYNQMP_DISP_LAYER_VID) {
1704                size = ARRAY_SIZE(av_buf_vid_fmts);
1705                mask = ~ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MASK;
1706                fmt = zynqmp_disp_map_fmt(av_buf_vid_fmts, size, drm_fmt);
1707                vid_fmt = fmt;
1708        } else {
1709                size = ARRAY_SIZE(av_buf_gfx_fmts);
1710                mask = ~ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_MASK;
1711                fmt = zynqmp_disp_map_fmt(av_buf_gfx_fmts, size, drm_fmt);
1712                gfx_fmt = fmt;
1713        }
1714
1715        if (!fmt)
1716                return -EINVAL;
1717
1718        fmts = zynqmp_disp_av_buf_get_fmt(&disp->av_buf);
1719        fmts &= mask;
1720        fmts |= fmt->disp_fmt;
1721        zynqmp_disp_av_buf_set_fmt(&disp->av_buf, fmts);
1722        zynqmp_disp_av_buf_init_sf(&disp->av_buf, vid_fmt, gfx_fmt);
1723        layer->fmt = fmt;
1724
1725        return 0;
1726}
1727
1728/**
1729 * zynqmp_disp_map_live_fmt - Find the hardware format for given bus format
1730 * @fmts: format table to look up
1731 * @size: size of the table @fmts
1732 * @bus_fmt: bus format to search
1733 *
1734 * Search a Display subsystem format corresponding to the given bus format
1735 * @bus_fmt, and return the format descriptor which contains the Display
1736 * subsystem format value.
1737 *
1738 * Return: a Display subsystem format descriptor on success, or NULL.
1739 */
1740static const struct zynqmp_disp_fmt *
1741zynqmp_disp_map_live_fmt(const struct zynqmp_disp_fmt fmts[],
1742                         unsigned int size, uint32_t bus_fmt)
1743{
1744        unsigned int i;
1745
1746        for (i = 0; i < size; i++)
1747                if (fmts[i].bus_fmt == bus_fmt)
1748                        return &fmts[i];
1749
1750        return NULL;
1751}
1752
1753/**
1754 * zynqmp_disp_set_live_fmt - Set the live format of the layer
1755 * @disp: Display subsystem
1756 * @layer: layer to set the format
1757 * @bus_fmt: bus format to set
1758 *
1759 * Set the live format of the given layer to @live_fmt.
1760 *
1761 * Return: 0 on success. -EINVAL if @bus_fmt is not supported by the layer.
1762 */
1763static int zynqmp_disp_layer_set_live_fmt(struct zynqmp_disp *disp,
1764                                          struct zynqmp_disp_layer *layer,
1765                                          uint32_t bus_fmt)
1766{
1767        const struct zynqmp_disp_fmt *fmt;
1768        u32 size;
1769        bool is_vid = layer->id == ZYNQMP_DISP_LAYER_VID;
1770
1771        size = ARRAY_SIZE(av_buf_live_fmts);
1772        fmt = zynqmp_disp_map_live_fmt(av_buf_live_fmts, size, bus_fmt);
1773        if (!fmt)
1774                return -EINVAL;
1775
1776        zynqmp_disp_av_buf_set_live_fmt(&disp->av_buf, fmt->disp_fmt, is_vid);
1777        zynqmp_disp_av_buf_init_live_sf(&disp->av_buf, fmt, is_vid);
1778        layer->fmt = fmt;
1779
1780        return 0;
1781}
1782
1783/**
1784 * zynqmp_disp_set_tpg - Enable or disable TPG
1785 * @disp: Display subsystem
1786 * @layer: Video layer
1787 * @tpg_on: flag if TPG needs to be enabled or disabled
1788 *
1789 * Enable / disable the TPG mode on the video layer @layer depending on
1790 * @tpg_on. The video layer should be disabled prior to enable request.
1791 *
1792 * Return: 0 on success. -ENODEV if it's not video layer. -EIO if
1793 * the video layer is enabled.
1794 */
1795static int zynqmp_disp_layer_set_tpg(struct zynqmp_disp *disp,
1796                                     struct zynqmp_disp_layer *layer,
1797                                     bool tpg_on)
1798{
1799        if (layer->id != ZYNQMP_DISP_LAYER_VID) {
1800                dev_err(disp->dev,
1801                        "only the video layer has the tpg mode\n");
1802                return -ENODEV;
1803        }
1804
1805        if (layer->enabled) {
1806                dev_err(disp->dev,
1807                        "the video layer should be disabled for tpg mode\n");
1808                return -EIO;
1809        }
1810
1811        zynqmp_disp_blend_layer_coeff(&disp->blend, layer, tpg_on);
1812        zynqmp_disp_av_buf_set_tpg(&disp->av_buf, tpg_on);
1813        disp->tpg_on = tpg_on;
1814
1815        return 0;
1816}
1817
1818/**
1819 * zynqmp_disp_get_tpg - Get the TPG mode status
1820 * @disp: Display subsystem
1821 * @layer: Video layer
1822 *
1823 * Return if the TPG is enabled or not.
1824 *
1825 * Return: true if TPG is on, otherwise false
1826 */
1827static bool zynqmp_disp_layer_get_tpg(struct zynqmp_disp *disp,
1828                                      struct zynqmp_disp_layer *layer)
1829{
1830        return disp->tpg_on;
1831}
1832
1833/**
1834 * zynqmp_disp_get_fmt - Get the supported DRM formats of the layer
1835 * @disp: Display subsystem
1836 * @layer: layer to get the formats
1837 * @drm_fmts: pointer to array of DRM format strings
1838 * @num_fmts: pointer to number of returned DRM formats
1839 *
1840 * Get the supported DRM formats of the given layer.
1841 */
1842static void zynqmp_disp_layer_get_fmts(struct zynqmp_disp *disp,
1843                                       struct zynqmp_disp_layer *layer,
1844                                       u32 **drm_fmts, unsigned int *num_fmts)
1845{
1846        *drm_fmts = layer->drm_fmts;
1847        *num_fmts = layer->num_fmts;
1848}
1849
1850/**
1851 * zynqmp_disp_layer_enable - Enable the layer
1852 * @disp: Display subsystem
1853 * @layer: layer to esable
1854 * @mode: operation mode
1855 *
1856 * Enable the layer @layer.
1857 *
1858 * Return: 0 on success, otherwise error code.
1859 */
1860static int zynqmp_disp_layer_enable(struct zynqmp_disp *disp,
1861                                    struct zynqmp_disp_layer *layer,
1862                                    enum zynqmp_disp_layer_mode mode)
1863{
1864        struct device *dev = disp->dev;
1865        struct dma_async_tx_descriptor *desc;
1866        enum dma_ctrl_flags flags;
1867        unsigned int i;
1868
1869        if (layer->enabled && layer->mode != mode) {
1870                dev_err(dev, "layer is already enabled in different mode\n");
1871                return -EBUSY;
1872        }
1873
1874        zynqmp_disp_av_buf_enable_vid(&disp->av_buf, layer, mode);
1875        zynqmp_disp_blend_layer_enable(&disp->blend, layer);
1876
1877        layer->enabled = true;
1878        layer->mode = mode;
1879
1880        if (mode == ZYNQMP_DISP_LAYER_LIVE)
1881                return 0;
1882
1883        for (i = 0; i < ZYNQMP_DISP_MAX_NUM_SUB_PLANES; i++) {
1884                struct zynqmp_disp_layer_dma *dma = &layer->dma[i];
1885
1886                if (dma->chan && dma->is_active) {
1887                        flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
1888                        desc = dmaengine_prep_interleaved_dma(dma->chan,
1889                                                              &dma->xt, flags);
1890                        if (!desc) {
1891                                dev_err(dev, "failed to prep DMA descriptor\n");
1892                                return -ENOMEM;
1893                        }
1894
1895                        dmaengine_submit(desc);
1896                        dma_async_issue_pending(dma->chan);
1897                }
1898        }
1899
1900        return 0;
1901}
1902
1903/**
1904 * zynqmp_disp_layer_disable - Disable the layer
1905 * @disp: Display subsystem
1906 * @layer: layer to disable
1907 * @mode: operation mode
1908 *
1909 * Disable the layer @layer.
1910 *
1911 * Return: 0 on success, or -EBUSY if the layer is in different mode.
1912 */
1913static int zynqmp_disp_layer_disable(struct zynqmp_disp *disp,
1914                                     struct zynqmp_disp_layer *layer,
1915                                     enum zynqmp_disp_layer_mode mode)
1916{
1917        struct device *dev = disp->dev;
1918        unsigned int i;
1919
1920        if (layer->mode != mode) {
1921                dev_err(dev, "the layer is operating in different mode\n");
1922                return -EBUSY;
1923        }
1924
1925        for (i = 0; i < ZYNQMP_DISP_MAX_NUM_SUB_PLANES; i++)
1926                if (layer->dma[i].chan && layer->dma[i].is_active)
1927                        dmaengine_terminate_sync(layer->dma[i].chan);
1928
1929        zynqmp_disp_av_buf_disable_vid(&disp->av_buf, layer);
1930        zynqmp_disp_blend_layer_disable(&disp->blend, layer);
1931        layer->enabled = false;
1932
1933        return 0;
1934}
1935
1936/**
1937 * zynqmp_disp_layer_request_dma - Request DMA channels for a layer
1938 * @disp: Display subsystem
1939 * @layer: layer to request DMA channels
1940 * @name: identifier string for layer type
1941 *
1942 * Request DMA engine channels for corresponding layer.
1943 *
1944 * Return: 0 on success, or err value from of_dma_request_slave_channel().
1945 */
1946static int
1947zynqmp_disp_layer_request_dma(struct zynqmp_disp *disp,
1948                              struct zynqmp_disp_layer *layer, const char *name)
1949{
1950        struct zynqmp_disp_layer_dma *dma;
1951        unsigned int i;
1952        int ret;
1953
1954        for (i = 0; i < layer->num_chan; i++) {
1955                char temp[16];
1956
1957                dma = &layer->dma[i];
1958                snprintf(temp, sizeof(temp), "%s%d", name, i);
1959                dma->chan = of_dma_request_slave_channel(layer->of_node,
1960                                                         temp);
1961                if (IS_ERR(dma->chan)) {
1962                        dev_err(disp->dev, "failed to request dma channel\n");
1963                        ret = PTR_ERR(dma->chan);
1964                        dma->chan = NULL;
1965                        return ret;
1966                }
1967        }
1968
1969        return 0;
1970}
1971
1972/**
1973 * zynqmp_disp_layer_release_dma - Release DMA channels for a layer
1974 * @disp: Display subsystem
1975 * @layer: layer to release DMA channels
1976 *
1977 * Release the dma channels associated with @layer.
1978 */
1979static void zynqmp_disp_layer_release_dma(struct zynqmp_disp *disp,
1980                                          struct zynqmp_disp_layer *layer)
1981{
1982        unsigned int i;
1983
1984        for (i = 0; i < layer->num_chan; i++) {
1985                if (layer->dma[i].chan) {
1986                        /* Make sure the channel is terminated before release */
1987                        dmaengine_terminate_all(layer->dma[i].chan);
1988                        dma_release_channel(layer->dma[i].chan);
1989                }
1990        }
1991}
1992
1993/**
1994 * zynqmp_disp_layer_is_live - if any layer is live
1995 * @disp: Display subsystem
1996 *
1997 * Return: true if any layer is live
1998 */
1999static bool zynqmp_disp_layer_is_live(struct zynqmp_disp *disp)
2000{
2001        unsigned int i;
2002
2003        for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
2004                if (disp->layers[i].enabled &&
2005                    disp->layers[i].mode == ZYNQMP_DISP_LAYER_LIVE)
2006                        return true;
2007        }
2008
2009        return false;
2010}
2011
2012/**
2013 * zynqmp_disp_layer_is_enabled - if any layer is enabled
2014 * @disp: Display subsystem
2015 *
2016 * Return: true if any layer is enabled
2017 */
2018static bool zynqmp_disp_layer_is_enabled(struct zynqmp_disp *disp)
2019{
2020        unsigned int i;
2021
2022        for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++)
2023                if (disp->layers[i].enabled)
2024                        return true;
2025
2026        return false;
2027}
2028
2029/**
2030 * zynqmp_disp_layer_destroy - Destroy all layers
2031 * @disp: Display subsystem
2032 *
2033 * Destroy all layers.
2034 */
2035static void zynqmp_disp_layer_destroy(struct zynqmp_disp *disp)
2036{
2037        unsigned int i;
2038
2039        for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
2040                zynqmp_disp_layer_release_dma(disp, &disp->layers[i]);
2041                if (disp->layers[i].of_node)
2042                        of_node_put(disp->layers[i].of_node);
2043        }
2044}
2045
2046/**
2047 * zynqmp_disp_layer_create - Create all layers
2048 * @disp: Display subsystem
2049 *
2050 * Create all layers.
2051 *
2052 * Return: 0 on success, otherwise error code from failed function
2053 */
2054static int zynqmp_disp_layer_create(struct zynqmp_disp *disp)
2055{
2056        struct zynqmp_disp_layer *layer;
2057        unsigned int i;
2058        int num_chans[ZYNQMP_DISP_NUM_LAYERS] = { 3, 1 };
2059        const char * const dma_name[] = { "vid", "gfx" };
2060        int ret;
2061
2062        for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
2063                char temp[16];
2064
2065                layer = &disp->layers[i];
2066                layer->id = i;
2067                layer->offset = i * 4;
2068                layer->other = &disp->layers[!i];
2069                layer->num_chan = num_chans[i];
2070                snprintf(temp, sizeof(temp), "%s-layer", dma_name[i]);
2071                layer->of_node = of_get_child_by_name(disp->dev->of_node, temp);
2072                if (!layer->of_node)
2073                        goto err;
2074                ret = zynqmp_disp_layer_request_dma(disp, layer, dma_name[i]);
2075                if (ret)
2076                        goto err;
2077                layer->disp = disp;
2078        }
2079
2080        return 0;
2081
2082err:
2083        zynqmp_disp_layer_destroy(disp);
2084        return ret;
2085}
2086
2087/*
2088 * ZynqMP Display internal functions
2089 */
2090
2091/*
2092 * Output format enumeration.
2093 * The ID should be aligned with blend_output_fmts.
2094 * The string should be aligned with how zynqmp_dp_set_color() decodes.
2095 */
2096static struct drm_prop_enum_list zynqmp_disp_color_enum[] = {
2097        { 0, "rgb" },
2098        { 1, "ycrcb444" },
2099        { 2, "ycrcb422" },
2100        { 3, "yonly" },
2101};
2102
2103/**
2104 * zynqmp_disp_set_output_fmt - Set the output format
2105 * @disp: Display subsystem
2106 * @id: the format ID. Refer to zynqmp_disp_color_enum[].
2107 *
2108 * This function sets the output format of the display / blender as well as
2109 * the format of DP controller. The @id should be aligned with
2110 * zynqmp_disp_color_enum.
2111 */
2112static void
2113zynqmp_disp_set_output_fmt(struct zynqmp_disp *disp, unsigned int id)
2114{
2115        const struct zynqmp_disp_fmt *fmt = &blend_output_fmts[id];
2116
2117        zynqmp_dp_set_color(disp->dpsub->dp, zynqmp_disp_color_enum[id].name);
2118        zynqmp_disp_blend_set_output_fmt(&disp->blend, fmt->disp_fmt);
2119}
2120
2121/**
2122 * zynqmp_disp_set_bg_color - Set the background color
2123 * @disp: Display subsystem
2124 * @c0: color component 0
2125 * @c1: color component 1
2126 * @c2: color component 2
2127 *
2128 * Set the background color with given color components (@c0, @c1, @c2).
2129 */
2130static void zynqmp_disp_set_bg_color(struct zynqmp_disp *disp,
2131                                     u32 c0, u32 c1, u32 c2)
2132{
2133        zynqmp_disp_blend_set_bg_color(&disp->blend, c0, c1, c2);
2134}
2135
2136/**
2137 * zynqmp_disp_set_alpha - Set the alpha value
2138 * @disp: Display subsystem
2139 * @alpha: alpha value to set
2140 *
2141 * Set the alpha value for blending.
2142 */
2143static void zynqmp_disp_set_alpha(struct zynqmp_disp *disp, u32 alpha)
2144{
2145        disp->alpha = alpha;
2146        zynqmp_disp_blend_set_alpha(&disp->blend, alpha);
2147}
2148
2149/**
2150 * zynqmp_disp_get_alpha - Get the alpha value
2151 * @disp: Display subsystem
2152 *
2153 * Get the alpha value for blending.
2154 *
2155 * Return: current alpha value.
2156 */
2157static u32 zynqmp_disp_get_alpha(struct zynqmp_disp *disp)
2158{
2159        return disp->alpha;
2160}
2161
2162/**
2163 * zynqmp_disp_set_g_alpha - Enable/disable the global alpha blending
2164 * @disp: Display subsystem
2165 * @enable: flag to enable or disable alpha blending
2166 *
2167 * Set the alpha value for blending.
2168 */
2169static void zynqmp_disp_set_g_alpha(struct zynqmp_disp *disp, bool enable)
2170{
2171        disp->alpha_en = enable;
2172        zynqmp_disp_blend_enable_alpha(&disp->blend, enable);
2173}
2174
2175/**
2176 * zynqmp_disp_get_g_alpha - Get the global alpha status
2177 * @disp: Display subsystem
2178 *
2179 * Get the global alpha statue.
2180 *
2181 * Return: true if global alpha is enabled, or false.
2182 */
2183static bool zynqmp_disp_get_g_alpha(struct zynqmp_disp *disp)
2184{
2185        return disp->alpha_en;
2186}
2187
2188/**
2189 * zynqmp_disp_enable - Enable the Display subsystem
2190 * @disp: Display subsystem
2191 *
2192 * Enable the Display subsystem.
2193 */
2194static void zynqmp_disp_enable(struct zynqmp_disp *disp)
2195{
2196        bool live;
2197
2198        if (disp->enabled)
2199                return;
2200
2201        zynqmp_disp_av_buf_enable(&disp->av_buf);
2202        /* Choose clock source based on the DT clock handle */
2203        zynqmp_disp_av_buf_set_vid_clock_src(&disp->av_buf, !!disp->_ps_pclk);
2204        zynqmp_disp_av_buf_set_aud_clock_src(&disp->av_buf, !!disp->_ps_audclk);
2205        live = zynqmp_disp_layer_is_live(disp);
2206        zynqmp_disp_av_buf_set_vid_timing_src(&disp->av_buf, !live);
2207        zynqmp_disp_av_buf_enable_buf(&disp->av_buf);
2208        zynqmp_disp_av_buf_enable_aud(&disp->av_buf);
2209        zynqmp_disp_aud_init(&disp->aud);
2210        disp->enabled = true;
2211}
2212
2213/**
2214 * zynqmp_disp_disable - Disable the Display subsystem
2215 * @disp: Display subsystem
2216 * @force: flag to disable forcefully
2217 *
2218 * Disable the Display subsystem.
2219 */
2220static void zynqmp_disp_disable(struct zynqmp_disp *disp, bool force)
2221{
2222        struct drm_crtc *crtc = &disp->xlnx_crtc.crtc;
2223
2224        if (!force && (!disp->enabled || zynqmp_disp_layer_is_enabled(disp)))
2225                return;
2226
2227        zynqmp_disp_aud_deinit(&disp->aud);
2228        zynqmp_disp_av_buf_disable_aud(&disp->av_buf);
2229        zynqmp_disp_av_buf_disable_buf(&disp->av_buf);
2230        zynqmp_disp_av_buf_disable(&disp->av_buf);
2231
2232        /* Mark the flip is done as crtc is disabled anyway */
2233        if (crtc->state->event) {
2234                complete_all(crtc->state->event->base.completion);
2235                crtc->state->event = NULL;
2236        }
2237
2238        disp->enabled = false;
2239}
2240
2241/**
2242 * zynqmp_disp_init - Initialize the Display subsystem states
2243 * @disp: Display subsystem
2244 *
2245 * Some states are not initialized as desired. For example, the output select
2246 * register resets to the live source. This function is to initialize
2247 * some register states as desired.
2248 */
2249static void zynqmp_disp_init(struct zynqmp_disp *disp)
2250{
2251        struct zynqmp_disp_layer *layer;
2252        unsigned int i;
2253
2254        for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
2255                layer = &disp->layers[i];
2256                zynqmp_disp_av_buf_disable_vid(&disp->av_buf, layer);
2257        }
2258}
2259
2260/*
2261 * ZynqMP Display external functions for zynqmp_dp
2262 */
2263
2264/**
2265 * zynqmp_disp_handle_vblank - Handle the vblank event
2266 * @disp: Display subsystem
2267 *
2268 * This function handles the vblank interrupt, and sends an event to
2269 * CRTC object. This will be called by the DP vblank interrupt handler.
2270 */
2271void zynqmp_disp_handle_vblank(struct zynqmp_disp *disp)
2272{
2273        struct drm_crtc *crtc = &disp->xlnx_crtc.crtc;
2274
2275        drm_crtc_handle_vblank(crtc);
2276}
2277
2278/**
2279 * zynqmp_disp_get_apb_clk_rate - Get the current APB clock rate
2280 * @disp: Display subsystem
2281 *
2282 * Return: the current APB clock rate.
2283 */
2284unsigned int zynqmp_disp_get_apb_clk_rate(struct zynqmp_disp *disp)
2285{
2286        return clk_get_rate(disp->aclk);
2287}
2288
2289/**
2290 * zynqmp_disp_aud_enabled - If the audio is enabled
2291 * @disp: Display subsystem
2292 *
2293 * Return if the audio is enabled depending on the audio clock.
2294 *
2295 * Return: true if audio is enabled, or false.
2296 */
2297bool zynqmp_disp_aud_enabled(struct zynqmp_disp *disp)
2298{
2299        return !!disp->audclk;
2300}
2301
2302/**
2303 * zynqmp_disp_get_aud_clk_rate - Get the current audio clock rate
2304 * @disp: Display subsystem
2305 *
2306 * Return: the current audio clock rate.
2307 */
2308unsigned int zynqmp_disp_get_aud_clk_rate(struct zynqmp_disp *disp)
2309{
2310        if (zynqmp_disp_aud_enabled(disp))
2311                return 0;
2312        return clk_get_rate(disp->aclk);
2313}
2314
2315/**
2316 * zynqmp_disp_get_crtc_mask - Return the CRTC bit mask
2317 * @disp: Display subsystem
2318 *
2319 * Return: the crtc mask of the zyqnmp_disp CRTC.
2320 */
2321uint32_t zynqmp_disp_get_crtc_mask(struct zynqmp_disp *disp)
2322{
2323        return drm_crtc_mask(&disp->xlnx_crtc.crtc);
2324}
2325
2326/*
2327 * Xlnx bridge functions
2328 */
2329
2330static inline struct zynqmp_disp_layer
2331*bridge_to_layer(struct xlnx_bridge *bridge)
2332{
2333        return container_of(bridge, struct zynqmp_disp_layer, bridge);
2334}
2335
2336static int zynqmp_disp_bridge_enable(struct xlnx_bridge *bridge)
2337{
2338        struct zynqmp_disp_layer *layer = bridge_to_layer(bridge);
2339        struct zynqmp_disp *disp = layer->disp;
2340        int ret;
2341
2342        if (!disp->_pl_pclk) {
2343                dev_err(disp->dev, "PL clock is required for live\n");
2344                return -ENODEV;
2345        }
2346
2347        ret = zynqmp_disp_layer_check_size(disp, layer, layer->w, layer->h);
2348        if (ret)
2349                return ret;
2350
2351        zynqmp_disp_set_g_alpha(disp, disp->alpha_en);
2352        zynqmp_disp_set_alpha(disp, disp->alpha);
2353        ret = zynqmp_disp_layer_enable(layer->disp, layer,
2354                                       ZYNQMP_DISP_LAYER_LIVE);
2355        if (ret)
2356                return ret;
2357
2358        if (layer->id == ZYNQMP_DISP_LAYER_GFX && disp->tpg_on) {
2359                layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
2360                zynqmp_disp_layer_set_tpg(disp, layer, disp->tpg_on);
2361        }
2362
2363        if (zynqmp_disp_av_buf_vid_timing_src_is_int(&disp->av_buf) ||
2364            zynqmp_disp_av_buf_vid_clock_src_is_ps(&disp->av_buf)) {
2365                dev_info(disp->dev,
2366                         "Disabling the pipeline to change the clk/timing src");
2367                zynqmp_disp_disable(disp, true);
2368                zynqmp_disp_av_buf_set_vid_clock_src(&disp->av_buf, false);
2369                zynqmp_disp_av_buf_set_vid_timing_src(&disp->av_buf, false);
2370        }
2371
2372        zynqmp_disp_enable(disp);
2373
2374        return 0;
2375}
2376
2377static void zynqmp_disp_bridge_disable(struct xlnx_bridge *bridge)
2378{
2379        struct zynqmp_disp_layer *layer = bridge_to_layer(bridge);
2380        struct zynqmp_disp *disp = layer->disp;
2381
2382        zynqmp_disp_disable(disp, false);
2383
2384        zynqmp_disp_layer_disable(disp, layer, ZYNQMP_DISP_LAYER_LIVE);
2385        if (layer->id == ZYNQMP_DISP_LAYER_VID && disp->tpg_on)
2386                zynqmp_disp_layer_set_tpg(disp, layer, disp->tpg_on);
2387
2388        if (!zynqmp_disp_layer_is_live(disp)) {
2389                dev_info(disp->dev,
2390                         "Disabling the pipeline to change the clk/timing src");
2391                zynqmp_disp_disable(disp, true);
2392                zynqmp_disp_av_buf_set_vid_clock_src(&disp->av_buf, true);
2393                zynqmp_disp_av_buf_set_vid_timing_src(&disp->av_buf, true);
2394                if (zynqmp_disp_layer_is_enabled(disp))
2395                        zynqmp_disp_enable(disp);
2396        }
2397}
2398
2399static int zynqmp_disp_bridge_set_input(struct xlnx_bridge *bridge,
2400                                        u32 width, u32 height, u32 bus_fmt)
2401{
2402        struct zynqmp_disp_layer *layer = bridge_to_layer(bridge);
2403        int ret;
2404
2405        ret = zynqmp_disp_layer_check_size(layer->disp, layer, width, height);
2406        if (ret)
2407                return ret;
2408
2409        ret = zynqmp_disp_layer_set_live_fmt(layer->disp,  layer, bus_fmt);
2410        if (ret)
2411                dev_err(layer->disp->dev, "failed to set live fmt\n");
2412
2413        return ret;
2414}
2415
2416static int zynqmp_disp_bridge_get_input_fmts(struct xlnx_bridge *bridge,
2417                                             const u32 **fmts, u32 *count)
2418{
2419        struct zynqmp_disp_layer *layer = bridge_to_layer(bridge);
2420
2421        *fmts = layer->bus_fmts;
2422        *count = layer->num_bus_fmts;
2423
2424        return 0;
2425}
2426
2427/*
2428 * DRM plane functions
2429 */
2430
2431static inline struct zynqmp_disp_layer *plane_to_layer(struct drm_plane *plane)
2432{
2433        return container_of(plane, struct zynqmp_disp_layer, plane);
2434}
2435
2436static int zynqmp_disp_plane_enable(struct drm_plane *plane)
2437{
2438        struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2439        struct zynqmp_disp *disp = layer->disp;
2440        int ret;
2441
2442        zynqmp_disp_set_g_alpha(disp, disp->alpha_en);
2443        zynqmp_disp_set_alpha(disp, disp->alpha);
2444        ret = zynqmp_disp_layer_enable(layer->disp, layer,
2445                                       ZYNQMP_DISP_LAYER_NONLIVE);
2446        if (ret)
2447                return ret;
2448
2449        if (layer->id == ZYNQMP_DISP_LAYER_GFX && disp->tpg_on) {
2450                layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
2451                zynqmp_disp_layer_set_tpg(disp, layer, disp->tpg_on);
2452        }
2453
2454        return 0;
2455}
2456
2457static int zynqmp_disp_plane_disable(struct drm_plane *plane)
2458{
2459        struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2460        struct zynqmp_disp *disp = layer->disp;
2461
2462        zynqmp_disp_layer_disable(disp, layer, ZYNQMP_DISP_LAYER_NONLIVE);
2463        if (layer->id == ZYNQMP_DISP_LAYER_VID && disp->tpg_on)
2464                zynqmp_disp_layer_set_tpg(disp, layer, disp->tpg_on);
2465
2466        return 0;
2467}
2468
2469static int zynqmp_disp_plane_mode_set(struct drm_plane *plane,
2470                                      struct drm_framebuffer *fb,
2471                                      int crtc_x, int crtc_y,
2472                                      unsigned int crtc_w, unsigned int crtc_h,
2473                                      u32 src_x, u32 src_y,
2474                                      u32 src_w, u32 src_h)
2475{
2476        struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2477        const struct drm_format_info *info = fb->format;
2478        struct drm_format_name_buf format_name;
2479        struct device *dev = layer->disp->dev;
2480        dma_addr_t paddr;
2481        unsigned int i;
2482        int ret;
2483
2484        if (!info) {
2485                dev_err(dev, "No format info found\n");
2486                return -EINVAL;
2487        }
2488
2489        ret = zynqmp_disp_layer_check_size(layer->disp, layer, src_w, src_h);
2490        if (ret)
2491                return ret;
2492
2493        for (i = 0; i < info->num_planes; i++) {
2494                unsigned int width = src_w / (i ? info->hsub : 1);
2495                unsigned int height = src_h / (i ? info->vsub : 1);
2496                int width_bytes;
2497
2498                paddr = drm_fb_cma_get_gem_addr(fb, plane->state, i);
2499                if (!paddr) {
2500                        dev_err(dev, "failed to get a paddr\n");
2501                        return -EINVAL;
2502                }
2503
2504                layer->dma[i].xt.numf = height;
2505                width_bytes = drm_format_plane_width_bytes(info, i, width);
2506                layer->dma[i].sgl[0].size = width_bytes;
2507                layer->dma[i].sgl[0].icg = fb->pitches[i] -
2508                                           layer->dma[i].sgl[0].size;
2509                layer->dma[i].xt.src_start = paddr;
2510                layer->dma[i].xt.frame_size = 1;
2511                layer->dma[i].xt.dir = DMA_MEM_TO_DEV;
2512                layer->dma[i].xt.src_sgl = true;
2513                layer->dma[i].xt.dst_sgl = false;
2514                layer->dma[i].is_active = true;
2515        }
2516
2517        for (; i < ZYNQMP_DISP_MAX_NUM_SUB_PLANES; i++)
2518                layer->dma[i].is_active = false;
2519
2520        ret = zynqmp_disp_layer_set_fmt(layer->disp,  layer, info->format);
2521        if (ret)
2522                dev_err(dev, "failed to set dp_sub layer fmt\n");
2523
2524        return ret;
2525}
2526
2527static void zynqmp_disp_plane_destroy(struct drm_plane *plane)
2528{
2529        struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2530
2531        xlnx_bridge_unregister(&layer->bridge);
2532        drm_plane_cleanup(plane);
2533}
2534
2535static int
2536zynqmp_disp_plane_atomic_set_property(struct drm_plane *plane,
2537                                      struct drm_plane_state *state,
2538                                      struct drm_property *property, u64 val)
2539{
2540        struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2541        struct zynqmp_disp *disp = layer->disp;
2542        int ret = 0;
2543
2544        if (property == disp->g_alpha_prop)
2545                zynqmp_disp_set_alpha(disp, val);
2546        else if (property == disp->g_alpha_en_prop)
2547                zynqmp_disp_set_g_alpha(disp, val);
2548        else if (property == disp->tpg_prop)
2549                ret = zynqmp_disp_layer_set_tpg(disp, layer, val);
2550        else
2551                return -EINVAL;
2552
2553        return ret;
2554}
2555
2556static int
2557zynqmp_disp_plane_atomic_get_property(struct drm_plane *plane,
2558                                      const struct drm_plane_state *state,
2559                                      struct drm_property *property,
2560                                      uint64_t *val)
2561{
2562        struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2563        struct zynqmp_disp *disp = layer->disp;
2564        int ret = 0;
2565
2566        if (property == disp->g_alpha_prop)
2567                *val = zynqmp_disp_get_alpha(disp);
2568        else if (property == disp->g_alpha_en_prop)
2569                *val = zynqmp_disp_get_g_alpha(disp);
2570        else if (property == disp->tpg_prop)
2571                *val = zynqmp_disp_layer_get_tpg(disp, layer);
2572        else
2573                return -EINVAL;
2574
2575        return ret;
2576}
2577
2578static int
2579zynqmp_disp_plane_atomic_update_plane(struct drm_plane *plane,
2580                                      struct drm_crtc *crtc,
2581                                      struct drm_framebuffer *fb,
2582                                      int crtc_x, int crtc_y,
2583                                      unsigned int crtc_w, unsigned int crtc_h,
2584                                      u32 src_x, u32 src_y,
2585                                      u32 src_w, u32 src_h,
2586                                      struct drm_modeset_acquire_ctx *ctx)
2587{
2588        struct drm_atomic_state *state;
2589        struct drm_plane_state *plane_state;
2590        int ret;
2591
2592        state = drm_atomic_state_alloc(plane->dev);
2593        if (!state)
2594                return -ENOMEM;
2595
2596        state->acquire_ctx = ctx;
2597        plane_state = drm_atomic_get_plane_state(state, plane);
2598        if (IS_ERR(plane_state)) {
2599                ret = PTR_ERR(plane_state);
2600                goto fail;
2601        }
2602
2603        ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
2604        if (ret)
2605                goto fail;
2606        drm_atomic_set_fb_for_plane(plane_state, fb);
2607        plane_state->crtc_x = crtc_x;
2608        plane_state->crtc_y = crtc_y;
2609        plane_state->crtc_w = crtc_w;
2610        plane_state->crtc_h = crtc_h;
2611        plane_state->src_x = src_x;
2612        plane_state->src_y = src_y;
2613        plane_state->src_w = src_w;
2614        plane_state->src_h = src_h;
2615
2616        if (plane == crtc->cursor)
2617                state->legacy_cursor_update = true;
2618
2619        /* Do async-update if possible */
2620        state->async_update = !drm_atomic_helper_async_check(plane->dev, state);
2621        ret = drm_atomic_commit(state);
2622fail:
2623        drm_atomic_state_put(state);
2624        return ret;
2625}
2626
2627static struct drm_plane_funcs zynqmp_disp_plane_funcs = {
2628        .update_plane           = zynqmp_disp_plane_atomic_update_plane,
2629        .disable_plane          = drm_atomic_helper_disable_plane,
2630        .atomic_set_property    = zynqmp_disp_plane_atomic_set_property,
2631        .atomic_get_property    = zynqmp_disp_plane_atomic_get_property,
2632        .destroy                = zynqmp_disp_plane_destroy,
2633        .reset                  = drm_atomic_helper_plane_reset,
2634        .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
2635        .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
2636};
2637
2638static void
2639zynqmp_disp_plane_atomic_update(struct drm_plane *plane,
2640                                struct drm_plane_state *old_state)
2641{
2642        int ret;
2643
2644        if (!plane->state->crtc || !plane->state->fb)
2645                return;
2646
2647        if (old_state->fb &&
2648            old_state->fb->format->format != plane->state->fb->format->format)
2649                zynqmp_disp_plane_disable(plane);
2650
2651        ret = zynqmp_disp_plane_mode_set(plane, plane->state->fb,
2652                                         plane->state->crtc_x,
2653                                         plane->state->crtc_y,
2654                                         plane->state->crtc_w,
2655                                         plane->state->crtc_h,
2656                                         plane->state->src_x >> 16,
2657                                         plane->state->src_y >> 16,
2658                                         plane->state->src_w >> 16,
2659                                         plane->state->src_h >> 16);
2660        if (ret)
2661                return;
2662
2663        zynqmp_disp_plane_enable(plane);
2664}
2665
2666static void
2667zynqmp_disp_plane_atomic_disable(struct drm_plane *plane,
2668                                 struct drm_plane_state *old_state)
2669{
2670        zynqmp_disp_plane_disable(plane);
2671}
2672
2673static int zynqmp_disp_plane_atomic_async_check(struct drm_plane *plane,
2674                                                struct drm_plane_state *state)
2675{
2676        return 0;
2677}
2678
2679static void
2680zynqmp_disp_plane_atomic_async_update(struct drm_plane *plane,
2681                                      struct drm_plane_state *new_state)
2682{
2683        struct drm_plane_state *old_state =
2684                drm_atomic_get_old_plane_state(new_state->state, plane);
2685
2686        if (plane->state->fb == new_state->fb)
2687                return;
2688
2689         /* Update the current state with new configurations */
2690        drm_atomic_set_fb_for_plane(plane->state, new_state->fb);
2691        plane->state->crtc = new_state->crtc;
2692        plane->state->crtc_x = new_state->crtc_x;
2693        plane->state->crtc_y = new_state->crtc_y;
2694        plane->state->crtc_w = new_state->crtc_w;
2695        plane->state->crtc_h = new_state->crtc_h;
2696        plane->state->src_x = new_state->src_x;
2697        plane->state->src_y = new_state->src_y;
2698        plane->state->src_w = new_state->src_w;
2699        plane->state->src_h = new_state->src_h;
2700        plane->state->state = new_state->state;
2701
2702        zynqmp_disp_plane_atomic_update(plane, old_state);
2703}
2704
2705static const struct drm_plane_helper_funcs zynqmp_disp_plane_helper_funcs = {
2706        .atomic_update          = zynqmp_disp_plane_atomic_update,
2707        .atomic_disable         = zynqmp_disp_plane_atomic_disable,
2708        .atomic_async_check     = zynqmp_disp_plane_atomic_async_check,
2709        .atomic_async_update    = zynqmp_disp_plane_atomic_async_update,
2710};
2711
2712static int zynqmp_disp_create_plane(struct zynqmp_disp *disp)
2713{
2714        struct zynqmp_disp_layer *layer;
2715        unsigned int i;
2716        u32 *fmts = NULL;
2717        unsigned int num_fmts = 0;
2718        enum drm_plane_type type;
2719        int ret;
2720
2721        /* graphics layer is primary, and video layer is overaly */
2722        type = DRM_PLANE_TYPE_OVERLAY;
2723        for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
2724                layer = &disp->layers[i];
2725                zynqmp_disp_layer_get_fmts(disp, layer, &fmts, &num_fmts);
2726                ret = drm_universal_plane_init(disp->drm, &layer->plane, 0,
2727                                               &zynqmp_disp_plane_funcs, fmts,
2728                                               num_fmts, NULL, type, NULL);
2729                if (ret)
2730                        goto err_plane;
2731                drm_plane_helper_add(&layer->plane,
2732                                     &zynqmp_disp_plane_helper_funcs);
2733                type = DRM_PLANE_TYPE_PRIMARY;
2734        }
2735
2736        for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
2737                layer = &disp->layers[i];
2738                layer->bridge.enable = &zynqmp_disp_bridge_enable;
2739                layer->bridge.disable = &zynqmp_disp_bridge_disable;
2740                layer->bridge.set_input = &zynqmp_disp_bridge_set_input;
2741                layer->bridge.get_input_fmts =
2742                        &zynqmp_disp_bridge_get_input_fmts;
2743                layer->bridge.of_node = layer->of_node;
2744                xlnx_bridge_register(&layer->bridge);
2745        }
2746
2747        /* Attach properties to each layers */
2748        drm_object_attach_property(&layer->plane.base, disp->g_alpha_prop,
2749                                   ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MAX);
2750        disp->alpha = ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MAX;
2751        /* Enable the global alpha as default */
2752        drm_object_attach_property(&layer->plane.base, disp->g_alpha_en_prop,
2753                                   true);
2754        disp->alpha_en = true;
2755
2756        layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
2757        drm_object_attach_property(&layer->plane.base, disp->tpg_prop, false);
2758
2759        return ret;
2760
2761err_plane:
2762        if (i)
2763                drm_plane_cleanup(&disp->layers[0].plane);
2764        return ret;
2765}
2766
2767static void zynqmp_disp_destroy_plane(struct zynqmp_disp *disp)
2768{
2769        unsigned int i;
2770
2771        for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++)
2772                zynqmp_disp_plane_destroy(&disp->layers[i].plane);
2773}
2774
2775/*
2776 * Xlnx crtc functions
2777 */
2778
2779static inline struct zynqmp_disp *xlnx_crtc_to_disp(struct xlnx_crtc *xlnx_crtc)
2780{
2781        return container_of(xlnx_crtc, struct zynqmp_disp, xlnx_crtc);
2782}
2783
2784static int zynqmp_disp_get_max_width(struct xlnx_crtc *xlnx_crtc)
2785{
2786        return ZYNQMP_DISP_MAX_WIDTH;
2787}
2788
2789static int zynqmp_disp_get_max_height(struct xlnx_crtc *xlnx_crtc)
2790{
2791        return ZYNQMP_DISP_MAX_HEIGHT;
2792}
2793
2794static uint32_t zynqmp_disp_get_format(struct xlnx_crtc *xlnx_crtc)
2795{
2796        struct zynqmp_disp *disp = xlnx_crtc_to_disp(xlnx_crtc);
2797
2798        return disp->layers[ZYNQMP_DISP_LAYER_GFX].fmt->drm_fmt;
2799}
2800
2801static unsigned int zynqmp_disp_get_align(struct xlnx_crtc *xlnx_crtc)
2802{
2803        struct zynqmp_disp *disp = xlnx_crtc_to_disp(xlnx_crtc);
2804        struct zynqmp_disp_layer *layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
2805
2806        return 1 << layer->dma->chan->device->copy_align;
2807}
2808
2809static u64 zynqmp_disp_get_dma_mask(struct xlnx_crtc *xlnx_crtc)
2810{
2811        return DMA_BIT_MASK(ZYNQMP_DISP_MAX_DMA_BIT);
2812}
2813
2814/*
2815 * DRM crtc functions
2816 */
2817
2818static inline struct zynqmp_disp *crtc_to_disp(struct drm_crtc *crtc)
2819{
2820        struct xlnx_crtc *xlnx_crtc = to_xlnx_crtc(crtc);
2821
2822        return xlnx_crtc_to_disp(xlnx_crtc);
2823}
2824
2825static int zynqmp_disp_crtc_mode_set(struct drm_crtc *crtc,
2826                                     struct drm_display_mode *mode,
2827                                     struct drm_display_mode *adjusted_mode,
2828                                     int x, int y,
2829                                     struct drm_framebuffer *old_fb)
2830{
2831        struct zynqmp_disp *disp = crtc_to_disp(crtc);
2832        unsigned long rate;
2833        long diff;
2834        int ret;
2835
2836        zynqmp_disp_clk_disable(disp->pclk, &disp->pclk_en);
2837        ret = clk_set_rate(disp->pclk, adjusted_mode->clock * 1000);
2838        if (ret) {
2839                dev_err(disp->dev, "failed to set a pixel clock\n");
2840                return ret;
2841        }
2842
2843        rate = clk_get_rate(disp->pclk);
2844        diff = rate - adjusted_mode->clock * 1000;
2845        if (abs(diff) > (adjusted_mode->clock * 1000) / 20) {
2846                dev_info(disp->dev, "request pixel rate: %d actual rate: %lu\n",
2847                         adjusted_mode->clock, rate);
2848        } else {
2849                dev_dbg(disp->dev, "request pixel rate: %d actual rate: %lu\n",
2850                        adjusted_mode->clock, rate);
2851        }
2852
2853        /* The timing register should be programmed always */
2854        zynqmp_dp_encoder_mode_set_stream(disp->dpsub->dp, adjusted_mode);
2855
2856        return 0;
2857}
2858
2859static void
2860zynqmp_disp_crtc_atomic_enable(struct drm_crtc *crtc,
2861                               struct drm_crtc_state *old_crtc_state)
2862{
2863        struct zynqmp_disp *disp = crtc_to_disp(crtc);
2864        struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
2865        int ret, vrefresh;
2866
2867        zynqmp_disp_crtc_mode_set(crtc, &crtc->state->mode,
2868                                  adjusted_mode, crtc->x, crtc->y, NULL);
2869
2870        pm_runtime_get_sync(disp->dev);
2871        ret = zynqmp_disp_clk_enable(disp->pclk, &disp->pclk_en);
2872        if (ret) {
2873                dev_err(disp->dev, "failed to enable a pixel clock\n");
2874                return;
2875        }
2876        zynqmp_disp_set_output_fmt(disp, disp->color);
2877        zynqmp_disp_set_bg_color(disp, disp->bg_c0, disp->bg_c1, disp->bg_c2);
2878        zynqmp_disp_enable(disp);
2879        /* Delay of 3 vblank intervals for timing gen to be stable */
2880        vrefresh = (adjusted_mode->clock * 1000) /
2881                   (adjusted_mode->vtotal * adjusted_mode->htotal);
2882        msleep(3 * 1000 / vrefresh);
2883}
2884
2885static void
2886zynqmp_disp_crtc_atomic_disable(struct drm_crtc *crtc,
2887                                struct drm_crtc_state *old_crtc_state)
2888{
2889        struct zynqmp_disp *disp = crtc_to_disp(crtc);
2890
2891        zynqmp_disp_clk_disable(disp->pclk, &disp->pclk_en);
2892        zynqmp_disp_plane_disable(crtc->primary);
2893        zynqmp_disp_disable(disp, true);
2894        drm_crtc_vblank_off(crtc);
2895        pm_runtime_put_sync(disp->dev);
2896}
2897
2898static int zynqmp_disp_crtc_atomic_check(struct drm_crtc *crtc,
2899                                         struct drm_crtc_state *state)
2900{
2901        return drm_atomic_add_affected_planes(state->state, crtc);
2902}
2903
2904static void
2905zynqmp_disp_crtc_atomic_begin(struct drm_crtc *crtc,
2906                              struct drm_crtc_state *old_crtc_state)
2907{
2908        drm_crtc_vblank_on(crtc);
2909        /* Don't rely on vblank when disabling crtc */
2910        spin_lock_irq(&crtc->dev->event_lock);
2911        if (crtc->primary->state->fb && crtc->state->event) {
2912                /* Consume the flip_done event from atomic helper */
2913                crtc->state->event->pipe = drm_crtc_index(crtc);
2914                WARN_ON(drm_crtc_vblank_get(crtc) != 0);
2915                drm_crtc_arm_vblank_event(crtc, crtc->state->event);
2916                crtc->state->event = NULL;
2917        }
2918        spin_unlock_irq(&crtc->dev->event_lock);
2919}
2920
2921static struct drm_crtc_helper_funcs zynqmp_disp_crtc_helper_funcs = {
2922        .atomic_enable  = zynqmp_disp_crtc_atomic_enable,
2923        .atomic_disable = zynqmp_disp_crtc_atomic_disable,
2924        .atomic_check   = zynqmp_disp_crtc_atomic_check,
2925        .atomic_begin   = zynqmp_disp_crtc_atomic_begin,
2926};
2927
2928static void zynqmp_disp_crtc_destroy(struct drm_crtc *crtc)
2929{
2930        zynqmp_disp_crtc_atomic_disable(crtc, NULL);
2931        drm_crtc_cleanup(crtc);
2932}
2933
2934static int zynqmp_disp_crtc_enable_vblank(struct drm_crtc *crtc)
2935{
2936        struct zynqmp_disp *disp = crtc_to_disp(crtc);
2937
2938        zynqmp_dp_enable_vblank(disp->dpsub->dp);
2939
2940        return 0;
2941}
2942
2943static void zynqmp_disp_crtc_disable_vblank(struct drm_crtc *crtc)
2944{
2945        struct zynqmp_disp *disp = crtc_to_disp(crtc);
2946
2947        zynqmp_dp_disable_vblank(disp->dpsub->dp);
2948}
2949
2950static int
2951zynqmp_disp_crtc_atomic_set_property(struct drm_crtc *crtc,
2952                                     struct drm_crtc_state *state,
2953                                     struct drm_property *property,
2954                                     uint64_t val)
2955{
2956        struct zynqmp_disp *disp = crtc_to_disp(crtc);
2957
2958        /*
2959         * CRTC prop values are just stored here and applied when CRTC gets
2960         * enabled
2961         */
2962        if (property == disp->color_prop)
2963                disp->color = val;
2964        else if (property == disp->bg_c0_prop)
2965                disp->bg_c0 = val;
2966        else if (property == disp->bg_c1_prop)
2967                disp->bg_c1 = val;
2968        else if (property == disp->bg_c2_prop)
2969                disp->bg_c2 = val;
2970        else
2971                return -EINVAL;
2972
2973        return 0;
2974}
2975
2976static int
2977zynqmp_disp_crtc_atomic_get_property(struct drm_crtc *crtc,
2978                                     const struct drm_crtc_state *state,
2979                                     struct drm_property *property,
2980                                     uint64_t *val)
2981{
2982        struct zynqmp_disp *disp = crtc_to_disp(crtc);
2983
2984        if (property == disp->color_prop)
2985                *val = disp->color;
2986        else if (property == disp->bg_c0_prop)
2987                *val = disp->bg_c0;
2988        else if (property == disp->bg_c1_prop)
2989                *val = disp->bg_c1;
2990        else if (property == disp->bg_c2_prop)
2991                *val = disp->bg_c2;
2992        else
2993                return -EINVAL;
2994
2995        return 0;
2996}
2997
2998static struct drm_crtc_funcs zynqmp_disp_crtc_funcs = {
2999        .destroy                = zynqmp_disp_crtc_destroy,
3000        .set_config             = drm_atomic_helper_set_config,
3001        .page_flip              = drm_atomic_helper_page_flip,
3002        .atomic_set_property    = zynqmp_disp_crtc_atomic_set_property,
3003        .atomic_get_property    = zynqmp_disp_crtc_atomic_get_property,
3004        .reset                  = drm_atomic_helper_crtc_reset,
3005        .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
3006        .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
3007        .enable_vblank          = zynqmp_disp_crtc_enable_vblank,
3008        .disable_vblank         = zynqmp_disp_crtc_disable_vblank,
3009};
3010
3011static void zynqmp_disp_create_crtc(struct zynqmp_disp *disp)
3012{
3013        struct drm_plane *plane = &disp->layers[ZYNQMP_DISP_LAYER_GFX].plane;
3014        struct drm_mode_object *obj = &disp->xlnx_crtc.crtc.base;
3015        int ret;
3016
3017        ret = drm_crtc_init_with_planes(disp->drm, &disp->xlnx_crtc.crtc, plane,
3018                                        NULL, &zynqmp_disp_crtc_funcs, NULL);
3019        drm_crtc_helper_add(&disp->xlnx_crtc.crtc,
3020                            &zynqmp_disp_crtc_helper_funcs);
3021        drm_object_attach_property(obj, disp->color_prop, 0);
3022        zynqmp_dp_set_color(disp->dpsub->dp, zynqmp_disp_color_enum[0].name);
3023        drm_object_attach_property(obj, disp->bg_c0_prop, 0);
3024        drm_object_attach_property(obj, disp->bg_c1_prop, 0);
3025        drm_object_attach_property(obj, disp->bg_c2_prop, 0);
3026
3027        disp->xlnx_crtc.get_max_width = &zynqmp_disp_get_max_width;
3028        disp->xlnx_crtc.get_max_height = &zynqmp_disp_get_max_height;
3029        disp->xlnx_crtc.get_format = &zynqmp_disp_get_format;
3030        disp->xlnx_crtc.get_align = &zynqmp_disp_get_align;
3031        disp->xlnx_crtc.get_dma_mask = &zynqmp_disp_get_dma_mask;
3032        xlnx_crtc_register(disp->drm, &disp->xlnx_crtc);
3033}
3034
3035static void zynqmp_disp_destroy_crtc(struct zynqmp_disp *disp)
3036{
3037        xlnx_crtc_unregister(disp->drm, &disp->xlnx_crtc);
3038        zynqmp_disp_crtc_destroy(&disp->xlnx_crtc.crtc);
3039}
3040
3041static void zynqmp_disp_map_crtc_to_plane(struct zynqmp_disp *disp)
3042{
3043        u32 possible_crtcs = drm_crtc_mask(&disp->xlnx_crtc.crtc);
3044        unsigned int i;
3045
3046        for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++)
3047                disp->layers[i].plane.possible_crtcs = possible_crtcs;
3048}
3049
3050/*
3051 * Component functions
3052 */
3053
3054int zynqmp_disp_bind(struct device *dev, struct device *master, void *data)
3055{
3056        struct zynqmp_dpsub *dpsub = dev_get_drvdata(dev);
3057        struct zynqmp_disp *disp = dpsub->disp;
3058        struct drm_device *drm = data;
3059        int num;
3060        u64 max;
3061        int ret;
3062
3063        disp->drm = drm;
3064
3065        max = ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MAX;
3066        disp->g_alpha_prop = drm_property_create_range(drm, 0, "alpha", 0, max);
3067        disp->g_alpha_en_prop = drm_property_create_bool(drm, 0,
3068                                                         "g_alpha_en");
3069        num = ARRAY_SIZE(zynqmp_disp_color_enum);
3070        disp->color_prop = drm_property_create_enum(drm, 0,
3071                                                    "output_color",
3072                                                    zynqmp_disp_color_enum,
3073                                                    num);
3074        max = ZYNQMP_DISP_V_BLEND_BG_MAX;
3075        disp->bg_c0_prop = drm_property_create_range(drm, 0, "bg_c0", 0, max);
3076        disp->bg_c1_prop = drm_property_create_range(drm, 0, "bg_c1", 0, max);
3077        disp->bg_c2_prop = drm_property_create_range(drm, 0, "bg_c2", 0, max);
3078        disp->tpg_prop = drm_property_create_bool(drm, 0, "tpg");
3079
3080        ret = zynqmp_disp_create_plane(disp);
3081        if (ret)
3082                return ret;
3083        zynqmp_disp_create_crtc(disp);
3084        zynqmp_disp_map_crtc_to_plane(disp);
3085
3086        return 0;
3087}
3088
3089void zynqmp_disp_unbind(struct device *dev, struct device *master, void *data)
3090{
3091        struct zynqmp_dpsub *dpsub = dev_get_drvdata(dev);
3092        struct zynqmp_disp *disp = dpsub->disp;
3093
3094        zynqmp_disp_destroy_crtc(disp);
3095        zynqmp_disp_destroy_plane(disp);
3096        drm_property_destroy(disp->drm, disp->bg_c2_prop);
3097        drm_property_destroy(disp->drm, disp->bg_c1_prop);
3098        drm_property_destroy(disp->drm, disp->bg_c0_prop);
3099        drm_property_destroy(disp->drm, disp->color_prop);
3100        drm_property_destroy(disp->drm, disp->g_alpha_en_prop);
3101        drm_property_destroy(disp->drm, disp->g_alpha_prop);
3102}
3103
3104/*
3105 * Platform initialization functions
3106 */
3107
3108static int zynqmp_disp_enumerate_fmts(struct zynqmp_disp *disp)
3109{
3110        struct zynqmp_disp_layer *layer;
3111        u32 *bus_fmts;
3112        u32 i, size, num_bus_fmts;
3113        u32 gfx_fmt = ZYNQMP_DISP_AV_BUF_GFX_FMT_RGB565;
3114
3115        num_bus_fmts = ARRAY_SIZE(av_buf_live_fmts);
3116        bus_fmts = devm_kzalloc(disp->dev, sizeof(*bus_fmts) * num_bus_fmts,
3117                                GFP_KERNEL);
3118        if (!bus_fmts)
3119                return -ENOMEM;
3120        for (i = 0; i < num_bus_fmts; i++)
3121                bus_fmts[i] = av_buf_live_fmts[i].bus_fmt;
3122
3123        layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
3124        layer->num_bus_fmts = num_bus_fmts;
3125        layer->bus_fmts = bus_fmts;
3126        size = ARRAY_SIZE(av_buf_vid_fmts);
3127        layer->num_fmts = size;
3128        layer->drm_fmts = devm_kzalloc(disp->dev,
3129                                       sizeof(*layer->drm_fmts) * size,
3130                                       GFP_KERNEL);
3131        if (!layer->drm_fmts)
3132                return -ENOMEM;
3133        for (i = 0; i < layer->num_fmts; i++)
3134                layer->drm_fmts[i] = av_buf_vid_fmts[i].drm_fmt;
3135        layer->fmt = &av_buf_vid_fmts[ZYNQMP_DISP_AV_BUF_VID_FMT_YUYV];
3136
3137        layer = &disp->layers[ZYNQMP_DISP_LAYER_GFX];
3138        layer->num_bus_fmts = num_bus_fmts;
3139        layer->bus_fmts = bus_fmts;
3140        size = ARRAY_SIZE(av_buf_gfx_fmts);
3141        layer->num_fmts = size;
3142        layer->drm_fmts = devm_kzalloc(disp->dev,
3143                                       sizeof(*layer->drm_fmts) * size,
3144                                       GFP_KERNEL);
3145        if (!layer->drm_fmts)
3146                return -ENOMEM;
3147
3148        for (i = 0; i < layer->num_fmts; i++)
3149                layer->drm_fmts[i] = av_buf_gfx_fmts[i].drm_fmt;
3150        if (zynqmp_disp_gfx_init_fmt < ARRAY_SIZE(zynqmp_disp_gfx_init_fmts))
3151                gfx_fmt = zynqmp_disp_gfx_init_fmts[zynqmp_disp_gfx_init_fmt];
3152        layer->fmt = &av_buf_gfx_fmts[gfx_fmt];
3153
3154        return 0;
3155}
3156
3157int zynqmp_disp_probe(struct platform_device *pdev)
3158{
3159        struct zynqmp_dpsub *dpsub;
3160        struct zynqmp_disp *disp;
3161        struct resource *res;
3162        int ret;
3163
3164        disp = devm_kzalloc(&pdev->dev, sizeof(*disp), GFP_KERNEL);
3165        if (!disp)
3166                return -ENOMEM;
3167        disp->dev = &pdev->dev;
3168
3169        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "blend");
3170        disp->blend.base = devm_ioremap_resource(&pdev->dev, res);
3171        if (IS_ERR(disp->blend.base))
3172                return PTR_ERR(disp->blend.base);
3173
3174        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "av_buf");
3175        disp->av_buf.base = devm_ioremap_resource(&pdev->dev, res);
3176        if (IS_ERR(disp->av_buf.base))
3177                return PTR_ERR(disp->av_buf.base);
3178
3179        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aud");
3180        disp->aud.base = devm_ioremap_resource(&pdev->dev, res);
3181        if (IS_ERR(disp->aud.base))
3182                return PTR_ERR(disp->aud.base);
3183
3184        dpsub = platform_get_drvdata(pdev);
3185        dpsub->disp = disp;
3186        disp->dpsub = dpsub;
3187
3188        ret = zynqmp_disp_enumerate_fmts(disp);
3189        if (ret)
3190                return ret;
3191
3192        /* Try the live PL video clock */
3193        disp->_pl_pclk = devm_clk_get(disp->dev, "dp_live_video_in_clk");
3194        if (!IS_ERR(disp->_pl_pclk)) {
3195                disp->pclk = disp->_pl_pclk;
3196                ret = zynqmp_disp_clk_enable_disable(disp->pclk,
3197                                                     &disp->pclk_en);
3198                if (ret)
3199                        disp->pclk = NULL;
3200        } else if (PTR_ERR(disp->_pl_pclk) == -EPROBE_DEFER) {
3201                return PTR_ERR(disp->_pl_pclk);
3202        }
3203
3204        /* If the live PL video clock is not valid, fall back to PS clock */
3205        if (!disp->pclk) {
3206                disp->_ps_pclk = devm_clk_get(disp->dev, "dp_vtc_pixel_clk_in");
3207                if (IS_ERR(disp->_ps_pclk)) {
3208                        dev_err(disp->dev, "failed to init any video clock\n");
3209                        return PTR_ERR(disp->_ps_pclk);
3210                }
3211                disp->pclk = disp->_ps_pclk;
3212                ret = zynqmp_disp_clk_enable_disable(disp->pclk,
3213                                                     &disp->pclk_en);
3214                if (ret) {
3215                        dev_err(disp->dev, "failed to init any video clock\n");
3216                        return ret;
3217                }
3218        }
3219
3220        disp->aclk = devm_clk_get(disp->dev, "dp_apb_clk");
3221        if (IS_ERR(disp->aclk))
3222                return PTR_ERR(disp->aclk);
3223        ret = zynqmp_disp_clk_enable(disp->aclk, &disp->aclk_en);
3224        if (ret) {
3225                dev_err(disp->dev, "failed to enable the APB clk\n");
3226                return ret;
3227        }
3228
3229        /* Try the live PL audio clock */
3230        disp->_pl_audclk = devm_clk_get(disp->dev, "dp_live_audio_aclk");
3231        if (!IS_ERR(disp->_pl_audclk)) {
3232                disp->audclk = disp->_pl_audclk;
3233                ret = zynqmp_disp_clk_enable_disable(disp->audclk,
3234                                                     &disp->audclk_en);
3235                if (ret)
3236                        disp->audclk = NULL;
3237        }
3238
3239        /* If the live PL audio clock is not valid, fall back to PS clock */
3240        if (!disp->audclk) {
3241                disp->_ps_audclk = devm_clk_get(disp->dev, "dp_aud_clk");
3242                if (!IS_ERR(disp->_ps_audclk)) {
3243                        disp->audclk = disp->_ps_audclk;
3244                        ret = zynqmp_disp_clk_enable_disable(disp->audclk,
3245                                                             &disp->audclk_en);
3246                        if (ret)
3247                                disp->audclk = NULL;
3248                }
3249
3250                if (!disp->audclk) {
3251                        dev_err(disp->dev,
3252                                "audio is disabled due to clock failure\n");
3253                }
3254        }
3255
3256        ret = zynqmp_disp_layer_create(disp);
3257        if (ret)
3258                goto error_aclk;
3259
3260        zynqmp_disp_init(disp);
3261
3262        return 0;
3263
3264error_aclk:
3265        zynqmp_disp_clk_disable(disp->aclk, &disp->aclk_en);
3266        return ret;
3267}
3268
3269int zynqmp_disp_remove(struct platform_device *pdev)
3270{
3271        struct zynqmp_dpsub *dpsub = platform_get_drvdata(pdev);
3272        struct zynqmp_disp *disp = dpsub->disp;
3273
3274        zynqmp_disp_layer_destroy(disp);
3275        if (disp->audclk)
3276                zynqmp_disp_clk_disable(disp->audclk, &disp->audclk_en);
3277        zynqmp_disp_clk_disable(disp->aclk, &disp->aclk_en);
3278        zynqmp_disp_clk_disable(disp->pclk, &disp->pclk_en);
3279        dpsub->disp = NULL;
3280
3281        return 0;
3282}
3283