cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

meson_crtc.c (23746B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (C) 2016 BayLibre, SAS
      4 * Author: Neil Armstrong <narmstrong@baylibre.com>
      5 * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
      6 * Copyright (C) 2014 Endless Mobile
      7 *
      8 * Written by:
      9 *     Jasper St. Pierre <jstpierre@mecheye.net>
     10 */
     11
     12#include <linux/bitfield.h>
     13#include <linux/soc/amlogic/meson-canvas.h>
     14
     15#include <drm/drm_atomic_helper.h>
     16#include <drm/drm_device.h>
     17#include <drm/drm_print.h>
     18#include <drm/drm_probe_helper.h>
     19#include <drm/drm_vblank.h>
     20
     21#include "meson_crtc.h"
     22#include "meson_plane.h"
     23#include "meson_registers.h"
     24#include "meson_venc.h"
     25#include "meson_viu.h"
     26#include "meson_rdma.h"
     27#include "meson_vpp.h"
     28#include "meson_osd_afbcd.h"
     29
     30#define MESON_G12A_VIU_OFFSET	0x5ec0
     31
     32/* CRTC definition */
     33
     34struct meson_crtc {
     35	struct drm_crtc base;
     36	struct drm_pending_vblank_event *event;
     37	struct meson_drm *priv;
     38	void (*enable_osd1)(struct meson_drm *priv);
     39	void (*enable_vd1)(struct meson_drm *priv);
     40	void (*enable_osd1_afbc)(struct meson_drm *priv);
     41	void (*disable_osd1_afbc)(struct meson_drm *priv);
     42	unsigned int viu_offset;
     43	bool vsync_forced;
     44	bool vsync_disabled;
     45};
     46#define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
     47
     48/* CRTC */
     49
     50static int meson_crtc_enable_vblank(struct drm_crtc *crtc)
     51{
     52	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
     53	struct meson_drm *priv = meson_crtc->priv;
     54
     55	meson_crtc->vsync_disabled = false;
     56	meson_venc_enable_vsync(priv);
     57
     58	return 0;
     59}
     60
     61static void meson_crtc_disable_vblank(struct drm_crtc *crtc)
     62{
     63	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
     64	struct meson_drm *priv = meson_crtc->priv;
     65
     66	if (!meson_crtc->vsync_forced) {
     67		meson_crtc->vsync_disabled = true;
     68		meson_venc_disable_vsync(priv);
     69	}
     70}
     71
     72static const struct drm_crtc_funcs meson_crtc_funcs = {
     73	.atomic_destroy_state	= drm_atomic_helper_crtc_destroy_state,
     74	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
     75	.destroy		= drm_crtc_cleanup,
     76	.page_flip		= drm_atomic_helper_page_flip,
     77	.reset			= drm_atomic_helper_crtc_reset,
     78	.set_config             = drm_atomic_helper_set_config,
     79	.enable_vblank		= meson_crtc_enable_vblank,
     80	.disable_vblank		= meson_crtc_disable_vblank,
     81
     82};
     83
     84static void meson_g12a_crtc_atomic_enable(struct drm_crtc *crtc,
     85					  struct drm_atomic_state *state)
     86{
     87	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
     88	struct drm_crtc_state *crtc_state = crtc->state;
     89	struct meson_drm *priv = meson_crtc->priv;
     90
     91	DRM_DEBUG_DRIVER("\n");
     92
     93	if (!crtc_state) {
     94		DRM_ERROR("Invalid crtc_state\n");
     95		return;
     96	}
     97
     98	/* VD1 Preblend vertical start/end */
     99	writel(FIELD_PREP(GENMASK(11, 0), 2303),
    100	       priv->io_base + _REG(VPP_PREBLEND_VD1_V_START_END));
    101
    102	/* Setup Blender */
    103	writel(crtc_state->mode.hdisplay |
    104	       crtc_state->mode.vdisplay << 16,
    105	       priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
    106
    107	writel_relaxed(0 << 16 |
    108			(crtc_state->mode.hdisplay - 1),
    109			priv->io_base + _REG(VPP_OSD1_BLD_H_SCOPE));
    110	writel_relaxed(0 << 16 |
    111			(crtc_state->mode.vdisplay - 1),
    112			priv->io_base + _REG(VPP_OSD1_BLD_V_SCOPE));
    113	writel_relaxed(crtc_state->mode.hdisplay << 16 |
    114			crtc_state->mode.vdisplay,
    115			priv->io_base + _REG(VPP_OUT_H_V_SIZE));
    116
    117	drm_crtc_vblank_on(crtc);
    118}
    119
    120static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
    121				     struct drm_atomic_state *state)
    122{
    123	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
    124	struct drm_crtc_state *crtc_state = crtc->state;
    125	struct meson_drm *priv = meson_crtc->priv;
    126
    127	DRM_DEBUG_DRIVER("\n");
    128
    129	if (!crtc_state) {
    130		DRM_ERROR("Invalid crtc_state\n");
    131		return;
    132	}
    133
    134	/* Enable VPP Postblend */
    135	writel(crtc_state->mode.hdisplay,
    136	       priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
    137
    138	/* VD1 Preblend vertical start/end */
    139	writel(FIELD_PREP(GENMASK(11, 0), 2303),
    140			priv->io_base + _REG(VPP_PREBLEND_VD1_V_START_END));
    141
    142	writel_bits_relaxed(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE,
    143			    priv->io_base + _REG(VPP_MISC));
    144
    145	drm_crtc_vblank_on(crtc);
    146}
    147
    148static void meson_g12a_crtc_atomic_disable(struct drm_crtc *crtc,
    149					   struct drm_atomic_state *state)
    150{
    151	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
    152	struct meson_drm *priv = meson_crtc->priv;
    153
    154	DRM_DEBUG_DRIVER("\n");
    155
    156	drm_crtc_vblank_off(crtc);
    157
    158	priv->viu.osd1_enabled = false;
    159	priv->viu.osd1_commit = false;
    160
    161	priv->viu.vd1_enabled = false;
    162	priv->viu.vd1_commit = false;
    163
    164	if (crtc->state->event && !crtc->state->active) {
    165		spin_lock_irq(&crtc->dev->event_lock);
    166		drm_crtc_send_vblank_event(crtc, crtc->state->event);
    167		spin_unlock_irq(&crtc->dev->event_lock);
    168
    169		crtc->state->event = NULL;
    170	}
    171}
    172
    173static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
    174				      struct drm_atomic_state *state)
    175{
    176	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
    177	struct meson_drm *priv = meson_crtc->priv;
    178
    179	DRM_DEBUG_DRIVER("\n");
    180
    181	drm_crtc_vblank_off(crtc);
    182
    183	priv->viu.osd1_enabled = false;
    184	priv->viu.osd1_commit = false;
    185
    186	priv->viu.vd1_enabled = false;
    187	priv->viu.vd1_commit = false;
    188
    189	/* Disable VPP Postblend */
    190	writel_bits_relaxed(VPP_OSD1_POSTBLEND | VPP_VD1_POSTBLEND |
    191			    VPP_VD1_PREBLEND | VPP_POSTBLEND_ENABLE, 0,
    192			    priv->io_base + _REG(VPP_MISC));
    193
    194	if (crtc->state->event && !crtc->state->active) {
    195		spin_lock_irq(&crtc->dev->event_lock);
    196		drm_crtc_send_vblank_event(crtc, crtc->state->event);
    197		spin_unlock_irq(&crtc->dev->event_lock);
    198
    199		crtc->state->event = NULL;
    200	}
    201}
    202
    203static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
    204				    struct drm_atomic_state *state)
    205{
    206	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
    207	unsigned long flags;
    208
    209	if (crtc->state->event) {
    210		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
    211
    212		spin_lock_irqsave(&crtc->dev->event_lock, flags);
    213		meson_crtc->event = crtc->state->event;
    214		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
    215		crtc->state->event = NULL;
    216	}
    217}
    218
    219static void meson_crtc_atomic_flush(struct drm_crtc *crtc,
    220				    struct drm_atomic_state *state)
    221{
    222	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
    223	struct meson_drm *priv = meson_crtc->priv;
    224
    225	priv->viu.osd1_commit = true;
    226	priv->viu.vd1_commit = true;
    227}
    228
    229static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs = {
    230	.atomic_begin	= meson_crtc_atomic_begin,
    231	.atomic_flush	= meson_crtc_atomic_flush,
    232	.atomic_enable	= meson_crtc_atomic_enable,
    233	.atomic_disable	= meson_crtc_atomic_disable,
    234};
    235
    236static const struct drm_crtc_helper_funcs meson_g12a_crtc_helper_funcs = {
    237	.atomic_begin	= meson_crtc_atomic_begin,
    238	.atomic_flush	= meson_crtc_atomic_flush,
    239	.atomic_enable	= meson_g12a_crtc_atomic_enable,
    240	.atomic_disable	= meson_g12a_crtc_atomic_disable,
    241};
    242
    243static void meson_crtc_enable_osd1(struct meson_drm *priv)
    244{
    245	writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
    246			    priv->io_base + _REG(VPP_MISC));
    247}
    248
    249static void meson_crtc_g12a_enable_osd1_afbc(struct meson_drm *priv)
    250{
    251	writel_relaxed(priv->viu.osd1_blk2_cfg4,
    252		       priv->io_base + _REG(VIU_OSD1_BLK2_CFG_W4));
    253
    254	writel_bits_relaxed(OSD_MEM_LINEAR_ADDR, OSD_MEM_LINEAR_ADDR,
    255			    priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
    256
    257	writel_relaxed(priv->viu.osd1_blk1_cfg4,
    258		       priv->io_base + _REG(VIU_OSD1_BLK1_CFG_W4));
    259
    260	meson_viu_g12a_enable_osd1_afbc(priv);
    261
    262	writel_bits_relaxed(OSD_MEM_LINEAR_ADDR, OSD_MEM_LINEAR_ADDR,
    263			    priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
    264
    265	writel_bits_relaxed(OSD_MALI_SRC_EN, OSD_MALI_SRC_EN,
    266			    priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W0));
    267}
    268
    269static void meson_g12a_crtc_enable_osd1(struct meson_drm *priv)
    270{
    271	writel_relaxed(priv->viu.osd_blend_din0_scope_h,
    272		       priv->io_base +
    273		       _REG(VIU_OSD_BLEND_DIN0_SCOPE_H));
    274	writel_relaxed(priv->viu.osd_blend_din0_scope_v,
    275		       priv->io_base +
    276		       _REG(VIU_OSD_BLEND_DIN0_SCOPE_V));
    277	writel_relaxed(priv->viu.osb_blend0_size,
    278		       priv->io_base +
    279		       _REG(VIU_OSD_BLEND_BLEND0_SIZE));
    280	writel_relaxed(priv->viu.osb_blend1_size,
    281		       priv->io_base +
    282		       _REG(VIU_OSD_BLEND_BLEND1_SIZE));
    283	writel_bits_relaxed(3 << 8, 3 << 8,
    284			    priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
    285}
    286
    287static void meson_crtc_enable_vd1(struct meson_drm *priv)
    288{
    289	writel_bits_relaxed(VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
    290			    VPP_COLOR_MNG_ENABLE,
    291			    VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
    292			    VPP_COLOR_MNG_ENABLE,
    293			    priv->io_base + _REG(VPP_MISC));
    294
    295	writel_bits_relaxed(VIU_CTRL0_AFBC_TO_VD1,
    296			    priv->viu.vd1_afbc ? VIU_CTRL0_AFBC_TO_VD1 : 0,
    297			    priv->io_base + _REG(VIU_MISC_CTRL0));
    298}
    299
    300static void meson_g12a_crtc_enable_vd1(struct meson_drm *priv)
    301{
    302	writel_relaxed(VD_BLEND_PREBLD_SRC_VD1 |
    303		       VD_BLEND_PREBLD_PREMULT_EN |
    304		       VD_BLEND_POSTBLD_SRC_VD1 |
    305		       VD_BLEND_POSTBLD_PREMULT_EN,
    306		       priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
    307
    308	writel_relaxed(priv->viu.vd1_afbc ?
    309		       (VD1_AXI_SEL_AFBC | AFBC_VD1_SEL) : 0,
    310		       priv->io_base + _REG(VD1_AFBCD0_MISC_CTRL));
    311}
    312
    313void meson_crtc_irq(struct meson_drm *priv)
    314{
    315	struct meson_crtc *meson_crtc = to_meson_crtc(priv->crtc);
    316	unsigned long flags;
    317
    318	/* Update the OSD registers */
    319	if (priv->viu.osd1_enabled && priv->viu.osd1_commit) {
    320		writel_relaxed(priv->viu.osd1_ctrl_stat,
    321				priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
    322		writel_relaxed(priv->viu.osd1_ctrl_stat2,
    323				priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
    324		writel_relaxed(priv->viu.osd1_blk0_cfg[0],
    325				priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W0));
    326		writel_relaxed(priv->viu.osd1_blk0_cfg[1],
    327				priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W1));
    328		writel_relaxed(priv->viu.osd1_blk0_cfg[2],
    329				priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W2));
    330		writel_relaxed(priv->viu.osd1_blk0_cfg[3],
    331				priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W3));
    332		writel_relaxed(priv->viu.osd1_blk0_cfg[4],
    333				priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W4));
    334
    335		if (priv->viu.osd1_afbcd) {
    336			if (meson_crtc->enable_osd1_afbc)
    337				meson_crtc->enable_osd1_afbc(priv);
    338		} else {
    339			if (meson_crtc->disable_osd1_afbc)
    340				meson_crtc->disable_osd1_afbc(priv);
    341			if (priv->afbcd.ops) {
    342				priv->afbcd.ops->reset(priv);
    343				priv->afbcd.ops->disable(priv);
    344			}
    345			meson_crtc->vsync_forced = false;
    346		}
    347
    348		writel_relaxed(priv->viu.osd_sc_ctrl0,
    349				priv->io_base + _REG(VPP_OSD_SC_CTRL0));
    350		writel_relaxed(priv->viu.osd_sc_i_wh_m1,
    351				priv->io_base + _REG(VPP_OSD_SCI_WH_M1));
    352		writel_relaxed(priv->viu.osd_sc_o_h_start_end,
    353				priv->io_base + _REG(VPP_OSD_SCO_H_START_END));
    354		writel_relaxed(priv->viu.osd_sc_o_v_start_end,
    355				priv->io_base + _REG(VPP_OSD_SCO_V_START_END));
    356		writel_relaxed(priv->viu.osd_sc_v_ini_phase,
    357				priv->io_base + _REG(VPP_OSD_VSC_INI_PHASE));
    358		writel_relaxed(priv->viu.osd_sc_v_phase_step,
    359				priv->io_base + _REG(VPP_OSD_VSC_PHASE_STEP));
    360		writel_relaxed(priv->viu.osd_sc_h_ini_phase,
    361				priv->io_base + _REG(VPP_OSD_HSC_INI_PHASE));
    362		writel_relaxed(priv->viu.osd_sc_h_phase_step,
    363				priv->io_base + _REG(VPP_OSD_HSC_PHASE_STEP));
    364		writel_relaxed(priv->viu.osd_sc_h_ctrl0,
    365				priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
    366		writel_relaxed(priv->viu.osd_sc_v_ctrl0,
    367				priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
    368
    369		if (!priv->viu.osd1_afbcd)
    370			meson_canvas_config(priv->canvas, priv->canvas_id_osd1,
    371					    priv->viu.osd1_addr,
    372					    priv->viu.osd1_stride,
    373					    priv->viu.osd1_height,
    374					    MESON_CANVAS_WRAP_NONE,
    375					    MESON_CANVAS_BLKMODE_LINEAR, 0);
    376
    377		/* Enable OSD1 */
    378		if (meson_crtc->enable_osd1)
    379			meson_crtc->enable_osd1(priv);
    380
    381		if (priv->viu.osd1_afbcd) {
    382			priv->afbcd.ops->reset(priv);
    383			priv->afbcd.ops->setup(priv);
    384			priv->afbcd.ops->enable(priv);
    385			meson_crtc->vsync_forced = true;
    386		}
    387
    388		priv->viu.osd1_commit = false;
    389	}
    390
    391	/* Update the VD1 registers */
    392	if (priv->viu.vd1_enabled && priv->viu.vd1_commit) {
    393
    394		if (priv->viu.vd1_afbc) {
    395			writel_relaxed(priv->viu.vd1_afbc_head_addr,
    396				       priv->io_base +
    397				       _REG(AFBC_HEAD_BADDR));
    398			writel_relaxed(priv->viu.vd1_afbc_body_addr,
    399				       priv->io_base +
    400				       _REG(AFBC_BODY_BADDR));
    401			writel_relaxed(priv->viu.vd1_afbc_en,
    402				       priv->io_base +
    403				       _REG(AFBC_ENABLE));
    404			writel_relaxed(priv->viu.vd1_afbc_mode,
    405				       priv->io_base +
    406				       _REG(AFBC_MODE));
    407			writel_relaxed(priv->viu.vd1_afbc_size_in,
    408				       priv->io_base +
    409				       _REG(AFBC_SIZE_IN));
    410			writel_relaxed(priv->viu.vd1_afbc_dec_def_color,
    411				       priv->io_base +
    412				       _REG(AFBC_DEC_DEF_COLOR));
    413			writel_relaxed(priv->viu.vd1_afbc_conv_ctrl,
    414				       priv->io_base +
    415				       _REG(AFBC_CONV_CTRL));
    416			writel_relaxed(priv->viu.vd1_afbc_size_out,
    417				       priv->io_base +
    418				       _REG(AFBC_SIZE_OUT));
    419			writel_relaxed(priv->viu.vd1_afbc_vd_cfmt_ctrl,
    420				       priv->io_base +
    421				       _REG(AFBC_VD_CFMT_CTRL));
    422			writel_relaxed(priv->viu.vd1_afbc_vd_cfmt_w,
    423				       priv->io_base +
    424				       _REG(AFBC_VD_CFMT_W));
    425			writel_relaxed(priv->viu.vd1_afbc_mif_hor_scope,
    426				       priv->io_base +
    427				       _REG(AFBC_MIF_HOR_SCOPE));
    428			writel_relaxed(priv->viu.vd1_afbc_mif_ver_scope,
    429				       priv->io_base +
    430				       _REG(AFBC_MIF_VER_SCOPE));
    431			writel_relaxed(priv->viu.vd1_afbc_pixel_hor_scope,
    432				       priv->io_base+
    433				       _REG(AFBC_PIXEL_HOR_SCOPE));
    434			writel_relaxed(priv->viu.vd1_afbc_pixel_ver_scope,
    435				       priv->io_base +
    436				       _REG(AFBC_PIXEL_VER_SCOPE));
    437			writel_relaxed(priv->viu.vd1_afbc_vd_cfmt_h,
    438				       priv->io_base +
    439				       _REG(AFBC_VD_CFMT_H));
    440		} else {
    441			switch (priv->viu.vd1_planes) {
    442			case 3:
    443				meson_canvas_config(priv->canvas,
    444						    priv->canvas_id_vd1_2,
    445						    priv->viu.vd1_addr2,
    446						    priv->viu.vd1_stride2,
    447						    priv->viu.vd1_height2,
    448						    MESON_CANVAS_WRAP_NONE,
    449						    MESON_CANVAS_BLKMODE_LINEAR,
    450						    MESON_CANVAS_ENDIAN_SWAP64);
    451				fallthrough;
    452			case 2:
    453				meson_canvas_config(priv->canvas,
    454						    priv->canvas_id_vd1_1,
    455						    priv->viu.vd1_addr1,
    456						    priv->viu.vd1_stride1,
    457						    priv->viu.vd1_height1,
    458						    MESON_CANVAS_WRAP_NONE,
    459						    MESON_CANVAS_BLKMODE_LINEAR,
    460						    MESON_CANVAS_ENDIAN_SWAP64);
    461				fallthrough;
    462			case 1:
    463				meson_canvas_config(priv->canvas,
    464						    priv->canvas_id_vd1_0,
    465						    priv->viu.vd1_addr0,
    466						    priv->viu.vd1_stride0,
    467						    priv->viu.vd1_height0,
    468						    MESON_CANVAS_WRAP_NONE,
    469						    MESON_CANVAS_BLKMODE_LINEAR,
    470						    MESON_CANVAS_ENDIAN_SWAP64);
    471			}
    472
    473			writel_relaxed(0, priv->io_base + _REG(AFBC_ENABLE));
    474		}
    475
    476		writel_relaxed(priv->viu.vd1_if0_gen_reg,
    477				priv->io_base + meson_crtc->viu_offset +
    478				_REG(VD1_IF0_GEN_REG));
    479		writel_relaxed(priv->viu.vd1_if0_gen_reg,
    480				priv->io_base + meson_crtc->viu_offset +
    481				_REG(VD2_IF0_GEN_REG));
    482		writel_relaxed(priv->viu.vd1_if0_gen_reg2,
    483				priv->io_base + meson_crtc->viu_offset +
    484				_REG(VD1_IF0_GEN_REG2));
    485		writel_relaxed(priv->viu.viu_vd1_fmt_ctrl,
    486				priv->io_base + meson_crtc->viu_offset +
    487				_REG(VIU_VD1_FMT_CTRL));
    488		writel_relaxed(priv->viu.viu_vd1_fmt_ctrl,
    489				priv->io_base + meson_crtc->viu_offset +
    490				_REG(VIU_VD2_FMT_CTRL));
    491		writel_relaxed(priv->viu.viu_vd1_fmt_w,
    492				priv->io_base + meson_crtc->viu_offset +
    493				_REG(VIU_VD1_FMT_W));
    494		writel_relaxed(priv->viu.viu_vd1_fmt_w,
    495				priv->io_base + meson_crtc->viu_offset +
    496				_REG(VIU_VD2_FMT_W));
    497		writel_relaxed(priv->viu.vd1_if0_canvas0,
    498				priv->io_base + meson_crtc->viu_offset +
    499				_REG(VD1_IF0_CANVAS0));
    500		writel_relaxed(priv->viu.vd1_if0_canvas0,
    501				priv->io_base + meson_crtc->viu_offset +
    502				_REG(VD1_IF0_CANVAS1));
    503		writel_relaxed(priv->viu.vd1_if0_canvas0,
    504				priv->io_base + meson_crtc->viu_offset +
    505				_REG(VD2_IF0_CANVAS0));
    506		writel_relaxed(priv->viu.vd1_if0_canvas0,
    507				priv->io_base + meson_crtc->viu_offset +
    508				_REG(VD2_IF0_CANVAS1));
    509		writel_relaxed(priv->viu.vd1_if0_luma_x0,
    510				priv->io_base + meson_crtc->viu_offset +
    511				_REG(VD1_IF0_LUMA_X0));
    512		writel_relaxed(priv->viu.vd1_if0_luma_x0,
    513				priv->io_base + meson_crtc->viu_offset +
    514				_REG(VD1_IF0_LUMA_X1));
    515		writel_relaxed(priv->viu.vd1_if0_luma_x0,
    516				priv->io_base + meson_crtc->viu_offset +
    517				_REG(VD2_IF0_LUMA_X0));
    518		writel_relaxed(priv->viu.vd1_if0_luma_x0,
    519				priv->io_base + meson_crtc->viu_offset +
    520				_REG(VD2_IF0_LUMA_X1));
    521		writel_relaxed(priv->viu.vd1_if0_luma_y0,
    522				priv->io_base + meson_crtc->viu_offset +
    523				_REG(VD1_IF0_LUMA_Y0));
    524		writel_relaxed(priv->viu.vd1_if0_luma_y0,
    525				priv->io_base + meson_crtc->viu_offset +
    526				_REG(VD1_IF0_LUMA_Y1));
    527		writel_relaxed(priv->viu.vd1_if0_luma_y0,
    528				priv->io_base + meson_crtc->viu_offset +
    529				_REG(VD2_IF0_LUMA_Y0));
    530		writel_relaxed(priv->viu.vd1_if0_luma_y0,
    531				priv->io_base + meson_crtc->viu_offset +
    532				_REG(VD2_IF0_LUMA_Y1));
    533		writel_relaxed(priv->viu.vd1_if0_chroma_x0,
    534				priv->io_base + meson_crtc->viu_offset +
    535				_REG(VD1_IF0_CHROMA_X0));
    536		writel_relaxed(priv->viu.vd1_if0_chroma_x0,
    537				priv->io_base + meson_crtc->viu_offset +
    538				_REG(VD1_IF0_CHROMA_X1));
    539		writel_relaxed(priv->viu.vd1_if0_chroma_x0,
    540				priv->io_base + meson_crtc->viu_offset +
    541				_REG(VD2_IF0_CHROMA_X0));
    542		writel_relaxed(priv->viu.vd1_if0_chroma_x0,
    543				priv->io_base + meson_crtc->viu_offset +
    544				_REG(VD2_IF0_CHROMA_X1));
    545		writel_relaxed(priv->viu.vd1_if0_chroma_y0,
    546				priv->io_base + meson_crtc->viu_offset +
    547				_REG(VD1_IF0_CHROMA_Y0));
    548		writel_relaxed(priv->viu.vd1_if0_chroma_y0,
    549				priv->io_base + meson_crtc->viu_offset +
    550				_REG(VD1_IF0_CHROMA_Y1));
    551		writel_relaxed(priv->viu.vd1_if0_chroma_y0,
    552				priv->io_base + meson_crtc->viu_offset +
    553				_REG(VD2_IF0_CHROMA_Y0));
    554		writel_relaxed(priv->viu.vd1_if0_chroma_y0,
    555				priv->io_base + meson_crtc->viu_offset +
    556				_REG(VD2_IF0_CHROMA_Y1));
    557		writel_relaxed(priv->viu.vd1_if0_repeat_loop,
    558				priv->io_base + meson_crtc->viu_offset +
    559				_REG(VD1_IF0_RPT_LOOP));
    560		writel_relaxed(priv->viu.vd1_if0_repeat_loop,
    561				priv->io_base + meson_crtc->viu_offset +
    562				_REG(VD2_IF0_RPT_LOOP));
    563		writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
    564				priv->io_base + meson_crtc->viu_offset +
    565				_REG(VD1_IF0_LUMA0_RPT_PAT));
    566		writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
    567				priv->io_base + meson_crtc->viu_offset +
    568				_REG(VD2_IF0_LUMA0_RPT_PAT));
    569		writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
    570				priv->io_base + meson_crtc->viu_offset +
    571				_REG(VD1_IF0_LUMA1_RPT_PAT));
    572		writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
    573				priv->io_base + meson_crtc->viu_offset +
    574				_REG(VD2_IF0_LUMA1_RPT_PAT));
    575		writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
    576				priv->io_base + meson_crtc->viu_offset +
    577				_REG(VD1_IF0_CHROMA0_RPT_PAT));
    578		writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
    579				priv->io_base + meson_crtc->viu_offset +
    580				_REG(VD2_IF0_CHROMA0_RPT_PAT));
    581		writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
    582				priv->io_base + meson_crtc->viu_offset +
    583				_REG(VD1_IF0_CHROMA1_RPT_PAT));
    584		writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
    585				priv->io_base + meson_crtc->viu_offset +
    586				_REG(VD2_IF0_CHROMA1_RPT_PAT));
    587		writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
    588				_REG(VD1_IF0_LUMA_PSEL));
    589		writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
    590				_REG(VD1_IF0_CHROMA_PSEL));
    591		writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
    592				_REG(VD2_IF0_LUMA_PSEL));
    593		writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
    594				_REG(VD2_IF0_CHROMA_PSEL));
    595		writel_relaxed(priv->viu.vd1_range_map_y,
    596				priv->io_base + meson_crtc->viu_offset +
    597				_REG(VD1_IF0_RANGE_MAP_Y));
    598		writel_relaxed(priv->viu.vd1_range_map_cb,
    599				priv->io_base + meson_crtc->viu_offset +
    600				_REG(VD1_IF0_RANGE_MAP_CB));
    601		writel_relaxed(priv->viu.vd1_range_map_cr,
    602				priv->io_base + meson_crtc->viu_offset +
    603				_REG(VD1_IF0_RANGE_MAP_CR));
    604		writel_relaxed(VPP_VSC_BANK_LENGTH(4) |
    605			       VPP_HSC_BANK_LENGTH(4) |
    606			       VPP_SC_VD_EN_ENABLE |
    607			       VPP_SC_TOP_EN_ENABLE |
    608			       VPP_SC_HSC_EN_ENABLE |
    609			       VPP_SC_VSC_EN_ENABLE,
    610				priv->io_base + _REG(VPP_SC_MISC));
    611		writel_relaxed(priv->viu.vpp_pic_in_height,
    612				priv->io_base + _REG(VPP_PIC_IN_HEIGHT));
    613		writel_relaxed(priv->viu.vpp_postblend_vd1_h_start_end,
    614			priv->io_base + _REG(VPP_POSTBLEND_VD1_H_START_END));
    615		writel_relaxed(priv->viu.vpp_blend_vd2_h_start_end,
    616			priv->io_base + _REG(VPP_BLEND_VD2_H_START_END));
    617		writel_relaxed(priv->viu.vpp_postblend_vd1_v_start_end,
    618			priv->io_base + _REG(VPP_POSTBLEND_VD1_V_START_END));
    619		writel_relaxed(priv->viu.vpp_blend_vd2_v_start_end,
    620			priv->io_base + _REG(VPP_BLEND_VD2_V_START_END));
    621		writel_relaxed(priv->viu.vpp_hsc_region12_startp,
    622				priv->io_base + _REG(VPP_HSC_REGION12_STARTP));
    623		writel_relaxed(priv->viu.vpp_hsc_region34_startp,
    624				priv->io_base + _REG(VPP_HSC_REGION34_STARTP));
    625		writel_relaxed(priv->viu.vpp_hsc_region4_endp,
    626				priv->io_base + _REG(VPP_HSC_REGION4_ENDP));
    627		writel_relaxed(priv->viu.vpp_hsc_start_phase_step,
    628				priv->io_base + _REG(VPP_HSC_START_PHASE_STEP));
    629		writel_relaxed(priv->viu.vpp_hsc_region1_phase_slope,
    630			priv->io_base + _REG(VPP_HSC_REGION1_PHASE_SLOPE));
    631		writel_relaxed(priv->viu.vpp_hsc_region3_phase_slope,
    632			priv->io_base + _REG(VPP_HSC_REGION3_PHASE_SLOPE));
    633		writel_relaxed(priv->viu.vpp_line_in_length,
    634				priv->io_base + _REG(VPP_LINE_IN_LENGTH));
    635		writel_relaxed(priv->viu.vpp_preblend_h_size,
    636				priv->io_base + _REG(VPP_PREBLEND_H_SIZE));
    637		writel_relaxed(priv->viu.vpp_vsc_region12_startp,
    638				priv->io_base + _REG(VPP_VSC_REGION12_STARTP));
    639		writel_relaxed(priv->viu.vpp_vsc_region34_startp,
    640				priv->io_base + _REG(VPP_VSC_REGION34_STARTP));
    641		writel_relaxed(priv->viu.vpp_vsc_region4_endp,
    642				priv->io_base + _REG(VPP_VSC_REGION4_ENDP));
    643		writel_relaxed(priv->viu.vpp_vsc_start_phase_step,
    644				priv->io_base + _REG(VPP_VSC_START_PHASE_STEP));
    645		writel_relaxed(priv->viu.vpp_vsc_ini_phase,
    646				priv->io_base + _REG(VPP_VSC_INI_PHASE));
    647		writel_relaxed(priv->viu.vpp_vsc_phase_ctrl,
    648				priv->io_base + _REG(VPP_VSC_PHASE_CTRL));
    649		writel_relaxed(priv->viu.vpp_hsc_phase_ctrl,
    650				priv->io_base + _REG(VPP_HSC_PHASE_CTRL));
    651		writel_relaxed(0x42, priv->io_base + _REG(VPP_SCALE_COEF_IDX));
    652
    653		/* Enable VD1 */
    654		if (meson_crtc->enable_vd1)
    655			meson_crtc->enable_vd1(priv);
    656
    657		priv->viu.vd1_commit = false;
    658	}
    659
    660	if (meson_crtc->vsync_disabled)
    661		return;
    662
    663	drm_crtc_handle_vblank(priv->crtc);
    664
    665	spin_lock_irqsave(&priv->drm->event_lock, flags);
    666	if (meson_crtc->event) {
    667		drm_crtc_send_vblank_event(priv->crtc, meson_crtc->event);
    668		drm_crtc_vblank_put(priv->crtc);
    669		meson_crtc->event = NULL;
    670	}
    671	spin_unlock_irqrestore(&priv->drm->event_lock, flags);
    672}
    673
    674int meson_crtc_create(struct meson_drm *priv)
    675{
    676	struct meson_crtc *meson_crtc;
    677	struct drm_crtc *crtc;
    678	int ret;
    679
    680	meson_crtc = devm_kzalloc(priv->drm->dev, sizeof(*meson_crtc),
    681				  GFP_KERNEL);
    682	if (!meson_crtc)
    683		return -ENOMEM;
    684
    685	meson_crtc->priv = priv;
    686	crtc = &meson_crtc->base;
    687	ret = drm_crtc_init_with_planes(priv->drm, crtc,
    688					priv->primary_plane, NULL,
    689					&meson_crtc_funcs, "meson_crtc");
    690	if (ret) {
    691		dev_err(priv->drm->dev, "Failed to init CRTC\n");
    692		return ret;
    693	}
    694
    695	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
    696		meson_crtc->enable_osd1 = meson_g12a_crtc_enable_osd1;
    697		meson_crtc->enable_vd1 = meson_g12a_crtc_enable_vd1;
    698		meson_crtc->viu_offset = MESON_G12A_VIU_OFFSET;
    699		meson_crtc->enable_osd1_afbc =
    700					meson_crtc_g12a_enable_osd1_afbc;
    701		meson_crtc->disable_osd1_afbc =
    702					meson_viu_g12a_disable_osd1_afbc;
    703		drm_crtc_helper_add(crtc, &meson_g12a_crtc_helper_funcs);
    704	} else {
    705		meson_crtc->enable_osd1 = meson_crtc_enable_osd1;
    706		meson_crtc->enable_vd1 = meson_crtc_enable_vd1;
    707		if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM)) {
    708			meson_crtc->enable_osd1_afbc =
    709					meson_viu_gxm_enable_osd1_afbc;
    710			meson_crtc->disable_osd1_afbc =
    711					meson_viu_gxm_disable_osd1_afbc;
    712		}
    713		drm_crtc_helper_add(crtc, &meson_crtc_helper_funcs);
    714	}
    715
    716	priv->crtc = crtc;
    717
    718	return 0;
    719}