// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) STMicroelectronics SA 2017
*
* Authors: Philippe Cornu <philippe.cornu@st.com>
* Yannick Fertre <yannick.fertre@st.com>
* Fabien Dessenne <fabien.dessenne@st.com>
* Mickael Reulier <mickael.reulier@st.com>
*/
#include <linux/clk.h>
#include <linux/component.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_graph.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_device.h>
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_of.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_vblank.h>
#include <video/videomode.h>
#include "ltdc.h"
#define NB_CRTC 1
#define CRTC_MASK GENMASK(NB_CRTC - 1, 0)
#define MAX_IRQ 4
#define MAX_ENDPOINTS 2
#define HWVER_10200 0x010200
#define HWVER_10300 0x010300
#define HWVER_20101 0x020101
/*
* The address of some registers depends on the HW version: such registers have
* an extra offset specified with reg_ofs.
*/
#define REG_OFS_NONE 0
#define REG_OFS_4 4 /* Insertion of "Layer Conf. 2" reg */
#define REG_OFS (ldev->caps.reg_ofs)
#define LAY_OFS 0x80 /* Register Offset between 2 layers */
/* Global register offsets */
#define LTDC_IDR 0x0000 /* IDentification */
#define LTDC_LCR 0x0004 /* Layer Count */
#define LTDC_SSCR 0x0008 /* Synchronization Size Configuration */
#define LTDC_BPCR 0x000C /* Back Porch Configuration */
#define LTDC_AWCR 0x0010 /* Active Width Configuration */
#define LTDC_TWCR 0x0014 /* Total Width Configuration */
#define LTDC_GCR 0x0018 /* Global Control */
#define LTDC_GC1R 0x001C /* Global Configuration 1 */
#define LTDC_GC2R 0x0020 /* Global Configuration 2 */
#define LTDC_SRCR 0x0024 /* Shadow Reload Configuration */
#define LTDC_GACR 0x0028 /* GAmma Correction */
#define LTDC_BCCR 0x002C /* Background Color Configuration */
#define LTDC_IER 0x0034 /* Interrupt Enable */
#define LTDC_ISR 0x0038 /* Interrupt Status */
#define LTDC_ICR 0x003C /* Interrupt Clear */
#define LTDC_LIPCR 0x0040 /* Line Interrupt Position Conf. */
#define LTDC_CPSR 0x0044 /* Current Position Status */
#define LTDC_CDSR 0x0048 /* Current Display Status */
/* Layer register offsets */
#define LTDC_L1LC1R (0x80) /* L1 Layer Configuration 1 */
#define LTDC_L1LC2R (0x84) /* L1 Layer Configuration 2 */
#define LTDC_L1CR (0x84 + REG_OFS)/* L1 Control */
#define LTDC_L1WHPCR (0x88 + REG_OFS)/* L1 Window Hor Position Config */
#define LTDC_L1WVPCR (0x8C + REG_OFS)/* L1 Window Vert Position Config */
#define LTDC_L1CKCR (0x90 + REG_OFS)/* L1 Color Keying Configuration */
#define LTDC_L1PFCR (0x94 + REG_OFS)/* L1 Pixel Format Configuration */
#define LTDC_L1CACR (0x98 + REG_OFS)/* L1 Constant Alpha Config */
#define LTDC_L1DCCR (0x9C + REG_OFS)/* L1 Default Color Configuration */
#define LTDC_L1BFCR (0xA0 + REG_OFS)/* L1 Blend Factors Configuration */
#define LTDC_L1FBBCR (0xA4 + REG_OFS)/* L1 FrameBuffer Bus Control */
#define LTDC_L1AFBCR (0xA8 + REG_OFS)/* L1 AuxFB Control */
#define LTDC_L1CFBAR (0xAC + REG_OFS)/* L1 Color FrameBuffer Address */
#define LTDC_L1CFBLR (0xB0 + REG_OFS)/* L1 Color FrameBuffer Length */
#define LTDC_L1CFBLNR (0xB4 + REG_OFS)/* L1 Color FrameBuffer Line Nb */
#define LTDC_L1AFBAR (0xB8 + REG_OFS)/* L1 AuxFB Address */
#define LTDC_L1AFBLR (0xBC + REG_OFS)/* L1 AuxFB Length */
#define LTDC_L1AFBLNR (0xC0 + REG_OFS)/* L1 AuxFB Line Number */
#define LTDC_L1CLUTWR (0xC4 + REG_OFS)/* L1 CLUT Write */
#define LTDC_L1YS1R (0xE0 + REG_OFS)/* L1 YCbCr Scale 1 */
#define LTDC_L1YS2R (0xE4 + REG_OFS)/* L1 YCbCr Scale 2 */
/* Bit definitions */
#define SSCR_VSH GENMASK(10, 0) /* Vertical Synchronization Height */
#define SSCR_HSW GENMASK(27, 16) /* Horizontal Synchronization Width */
#define BPCR_AVBP GENMASK(10, 0) /* Accumulated Vertical Back Porch */
#define BPCR_AHBP GENMASK(27, 16) /* Accumulated Horizontal Back Porch */
#define AWCR_AAH GENMASK(10, 0) /* Accumulated Active Height */
#define AWCR_AAW GENMASK(27, 16) /* Accumulated Active Width */
#define TWCR_TOTALH GENMASK(10, 0) /* TOTAL Height */
#define TWCR_TOTALW GENMASK(27, 16) /* TOTAL Width */
#define GCR_LTDCEN BIT(0) /* LTDC ENable */
#define GCR_DEN BIT(16) /* Dither ENable */
#define GCR_PCPOL BIT(28) /* Pixel Clock POLarity-Inverted */
#define GCR_DEPOL BIT(29) /* Data Enable POLarity-High */
#define GCR_VSPOL BIT(30) /* Vertical Synchro POLarity-High */
#define GCR_HSPOL BIT(31) /* Horizontal Synchro POLarity-High */
#define GC1R_WBCH GENMASK(3, 0) /* Width of Blue CHannel output */
#define GC1R_WGCH GENMASK(7, 4) /* Width of Green Channel output */
#define GC1R_WRCH GENMASK(11, 8) /* Width of Red Channel output */
#define GC1R_PBEN BIT(12) /* Precise Blending ENable */
#define GC1R_DT GENMASK(15, 14) /* Dithering Technique */
#define GC1R_GCT GENMASK(19, 17) /* Gamma Correction Technique */
#define GC1R_SHREN BIT(21) /* SHadow Registers ENabled */
#define GC1R_BCP BIT(22) /* Background Colour Programmable */
#define GC1R_BBEN BIT(23) /* Background Blending ENabled */
#define GC1R_LNIP BIT(24) /* Line Number IRQ Position */
#define GC1R_TP BIT(25) /* Timing Programmable */
#define GC1R_IPP BIT(26) /* IRQ Polarity Programmable */
#define GC1R_SPP BIT(27) /* Sync Polarity Programmable */
#define GC1R_DWP BIT(28) /* Dither Width Programmable */
#define GC1R_STREN BIT(29) /* STatus Registers ENabled */
#define GC1R_BMEN BIT(31) /* Blind Mode ENabled */
#define GC2R_EDCA BIT(0) /* External Display Control Ability */