Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  * Copyright (C) STMicroelectronics SA 2017
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  * Authors: Philippe Cornu <philippe.cornu@st.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  *          Yannick Fertre <yannick.fertre@st.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  *          Fabien Dessenne <fabien.dessenne@st.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  *          Mickael Reulier <mickael.reulier@st.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12) #include <linux/component.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <linux/of_graph.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) #include <linux/pinctrl/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include <linux/reset.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include <drm/drm_atomic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #include <drm/drm_atomic_helper.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) #include <drm/drm_bridge.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) #include <drm/drm_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) #include <drm/drm_fb_cma_helper.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) #include <drm/drm_fourcc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) #include <drm/drm_gem_cma_helper.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) #include <drm/drm_gem_framebuffer_helper.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) #include <drm/drm_of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) #include <drm/drm_plane_helper.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) #include <drm/drm_probe_helper.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) #include <drm/drm_vblank.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) #include <video/videomode.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) #include "ltdc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) #define NB_CRTC 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) #define CRTC_MASK GENMASK(NB_CRTC - 1, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) #define MAX_IRQ 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) #define HWVER_10200 0x010200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) #define HWVER_10300 0x010300
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) #define HWVER_20101 0x020101
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50)  * The address of some registers depends on the HW version: such registers have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51)  * an extra offset specified with reg_ofs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) #define REG_OFS_NONE	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) #define REG_OFS_4	4		/* Insertion of "Layer Conf. 2" reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) #define REG_OFS		(ldev->caps.reg_ofs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) #define LAY_OFS		0x80		/* Register Offset between 2 layers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) /* Global register offsets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) #define LTDC_IDR	0x0000		/* IDentification */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) #define LTDC_LCR	0x0004		/* Layer Count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) #define LTDC_SSCR	0x0008		/* Synchronization Size Configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) #define LTDC_BPCR	0x000C		/* Back Porch Configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) #define LTDC_AWCR	0x0010		/* Active Width Configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) #define LTDC_TWCR	0x0014		/* Total Width Configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) #define LTDC_GCR	0x0018		/* Global Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) #define LTDC_GC1R	0x001C		/* Global Configuration 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) #define LTDC_GC2R	0x0020		/* Global Configuration 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) #define LTDC_SRCR	0x0024		/* Shadow Reload Configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) #define LTDC_GACR	0x0028		/* GAmma Correction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) #define LTDC_BCCR	0x002C		/* Background Color Configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) #define LTDC_IER	0x0034		/* Interrupt Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) #define LTDC_ISR	0x0038		/* Interrupt Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) #define LTDC_ICR	0x003C		/* Interrupt Clear */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) #define LTDC_LIPCR	0x0040		/* Line Interrupt Position Conf. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) #define LTDC_CPSR	0x0044		/* Current Position Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) #define LTDC_CDSR	0x0048		/* Current Display Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) /* Layer register offsets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) #define LTDC_L1LC1R	(0x80)		/* L1 Layer Configuration 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) #define LTDC_L1LC2R	(0x84)		/* L1 Layer Configuration 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) #define LTDC_L1CR	(0x84 + REG_OFS)/* L1 Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) #define LTDC_L1WHPCR	(0x88 + REG_OFS)/* L1 Window Hor Position Config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) #define LTDC_L1WVPCR	(0x8C + REG_OFS)/* L1 Window Vert Position Config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) #define LTDC_L1CKCR	(0x90 + REG_OFS)/* L1 Color Keying Configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) #define LTDC_L1PFCR	(0x94 + REG_OFS)/* L1 Pixel Format Configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) #define LTDC_L1CACR	(0x98 + REG_OFS)/* L1 Constant Alpha Config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) #define LTDC_L1DCCR	(0x9C + REG_OFS)/* L1 Default Color Configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) #define LTDC_L1BFCR	(0xA0 + REG_OFS)/* L1 Blend Factors Configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) #define LTDC_L1FBBCR	(0xA4 + REG_OFS)/* L1 FrameBuffer Bus Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) #define LTDC_L1AFBCR	(0xA8 + REG_OFS)/* L1 AuxFB Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) #define LTDC_L1CFBAR	(0xAC + REG_OFS)/* L1 Color FrameBuffer Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) #define LTDC_L1CFBLR	(0xB0 + REG_OFS)/* L1 Color FrameBuffer Length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) #define LTDC_L1CFBLNR	(0xB4 + REG_OFS)/* L1 Color FrameBuffer Line Nb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) #define LTDC_L1AFBAR	(0xB8 + REG_OFS)/* L1 AuxFB Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) #define LTDC_L1AFBLR	(0xBC + REG_OFS)/* L1 AuxFB Length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) #define LTDC_L1AFBLNR	(0xC0 + REG_OFS)/* L1 AuxFB Line Number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) #define LTDC_L1CLUTWR	(0xC4 + REG_OFS)/* L1 CLUT Write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) #define LTDC_L1YS1R	(0xE0 + REG_OFS)/* L1 YCbCr Scale 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) #define LTDC_L1YS2R	(0xE4 + REG_OFS)/* L1 YCbCr Scale 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) /* Bit definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) #define SSCR_VSH	GENMASK(10, 0)	/* Vertical Synchronization Height */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) #define SSCR_HSW	GENMASK(27, 16)	/* Horizontal Synchronization Width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) #define BPCR_AVBP	GENMASK(10, 0)	/* Accumulated Vertical Back Porch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) #define BPCR_AHBP	GENMASK(27, 16)	/* Accumulated Horizontal Back Porch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) #define AWCR_AAH	GENMASK(10, 0)	/* Accumulated Active Height */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) #define AWCR_AAW	GENMASK(27, 16)	/* Accumulated Active Width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) #define TWCR_TOTALH	GENMASK(10, 0)	/* TOTAL Height */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) #define TWCR_TOTALW	GENMASK(27, 16)	/* TOTAL Width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) #define GCR_LTDCEN	BIT(0)		/* LTDC ENable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) #define GCR_DEN		BIT(16)		/* Dither ENable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) #define GCR_PCPOL	BIT(28)		/* Pixel Clock POLarity-Inverted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) #define GCR_DEPOL	BIT(29)		/* Data Enable POLarity-High */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) #define GCR_VSPOL	BIT(30)		/* Vertical Synchro POLarity-High */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) #define GCR_HSPOL	BIT(31)		/* Horizontal Synchro POLarity-High */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) #define GC1R_WBCH	GENMASK(3, 0)	/* Width of Blue CHannel output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) #define GC1R_WGCH	GENMASK(7, 4)	/* Width of Green Channel output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) #define GC1R_WRCH	GENMASK(11, 8)	/* Width of Red Channel output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) #define GC1R_PBEN	BIT(12)		/* Precise Blending ENable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) #define GC1R_DT		GENMASK(15, 14)	/* Dithering Technique */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) #define GC1R_GCT	GENMASK(19, 17)	/* Gamma Correction Technique */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) #define GC1R_SHREN	BIT(21)		/* SHadow Registers ENabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) #define GC1R_BCP	BIT(22)		/* Background Colour Programmable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) #define GC1R_BBEN	BIT(23)		/* Background Blending ENabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) #define GC1R_LNIP	BIT(24)		/* Line Number IRQ Position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) #define GC1R_TP		BIT(25)		/* Timing Programmable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) #define GC1R_IPP	BIT(26)		/* IRQ Polarity Programmable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) #define GC1R_SPP	BIT(27)		/* Sync Polarity Programmable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) #define GC1R_DWP	BIT(28)		/* Dither Width Programmable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) #define GC1R_STREN	BIT(29)		/* STatus Registers ENabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) #define GC1R_BMEN	BIT(31)		/* Blind Mode ENabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) #define GC2R_EDCA	BIT(0)		/* External Display Control Ability  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) #define GC2R_STSAEN	BIT(1)		/* Slave Timing Sync Ability ENabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) #define GC2R_DVAEN	BIT(2)		/* Dual-View Ability ENabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) #define GC2R_DPAEN	BIT(3)		/* Dual-Port Ability ENabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) #define GC2R_BW		GENMASK(6, 4)	/* Bus Width (log2 of nb of bytes) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) #define GC2R_EDCEN	BIT(7)		/* External Display Control ENabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) #define SRCR_IMR	BIT(0)		/* IMmediate Reload */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) #define SRCR_VBR	BIT(1)		/* Vertical Blanking Reload */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) #define BCCR_BCBLACK	0x00		/* Background Color BLACK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) #define BCCR_BCBLUE	GENMASK(7, 0)	/* Background Color BLUE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) #define BCCR_BCGREEN	GENMASK(15, 8)	/* Background Color GREEN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) #define BCCR_BCRED	GENMASK(23, 16)	/* Background Color RED */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) #define BCCR_BCWHITE	GENMASK(23, 0)	/* Background Color WHITE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) #define IER_LIE		BIT(0)		/* Line Interrupt Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) #define IER_FUIE	BIT(1)		/* Fifo Underrun Interrupt Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) #define IER_TERRIE	BIT(2)		/* Transfer ERRor Interrupt Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) #define IER_RRIE	BIT(3)		/* Register Reload Interrupt enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) #define CPSR_CYPOS	GENMASK(15, 0)	/* Current Y position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) #define ISR_LIF		BIT(0)		/* Line Interrupt Flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) #define ISR_FUIF	BIT(1)		/* Fifo Underrun Interrupt Flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) #define ISR_TERRIF	BIT(2)		/* Transfer ERRor Interrupt Flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) #define ISR_RRIF	BIT(3)		/* Register Reload Interrupt Flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) #define LXCR_LEN	BIT(0)		/* Layer ENable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) #define LXCR_COLKEN	BIT(1)		/* Color Keying Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) #define LXCR_CLUTEN	BIT(4)		/* Color Look-Up Table ENable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) #define LXWHPCR_WHSTPOS	GENMASK(11, 0)	/* Window Horizontal StarT POSition */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) #define LXWHPCR_WHSPPOS	GENMASK(27, 16)	/* Window Horizontal StoP POSition */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) #define LXWVPCR_WVSTPOS	GENMASK(10, 0)	/* Window Vertical StarT POSition */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) #define LXWVPCR_WVSPPOS	GENMASK(26, 16)	/* Window Vertical StoP POSition */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) #define LXPFCR_PF	GENMASK(2, 0)	/* Pixel Format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) #define LXCACR_CONSTA	GENMASK(7, 0)	/* CONSTant Alpha */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) #define LXBFCR_BF2	GENMASK(2, 0)	/* Blending Factor 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) #define LXBFCR_BF1	GENMASK(10, 8)	/* Blending Factor 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) #define LXCFBLR_CFBLL	GENMASK(12, 0)	/* Color Frame Buffer Line Length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) #define LXCFBLR_CFBP	GENMASK(28, 16)	/* Color Frame Buffer Pitch in bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) #define LXCFBLNR_CFBLN	GENMASK(10, 0)	/* Color Frame Buffer Line Number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) #define CLUT_SIZE	256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) #define CONSTA_MAX	0xFF		/* CONSTant Alpha MAX= 1.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) #define BF1_PAXCA	0x600		/* Pixel Alpha x Constant Alpha */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) #define BF1_CA		0x400		/* Constant Alpha */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) #define BF2_1PAXCA	0x007		/* 1 - (Pixel Alpha x Constant Alpha) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) #define BF2_1CA		0x005		/* 1 - Constant Alpha */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) #define NB_PF		8		/* Max nb of HW pixel format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) enum ltdc_pix_fmt {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 	PF_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 	/* RGB formats */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 	PF_ARGB8888,		/* ARGB [32 bits] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 	PF_RGBA8888,		/* RGBA [32 bits] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 	PF_RGB888,		/* RGB [24 bits] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 	PF_RGB565,		/* RGB [16 bits] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 	PF_ARGB1555,		/* ARGB A:1 bit RGB:15 bits [16 bits] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 	PF_ARGB4444,		/* ARGB A:4 bits R/G/B: 4 bits each [16 bits] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 	/* Indexed formats */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 	PF_L8,			/* Indexed 8 bits [8 bits] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 	PF_AL44,		/* Alpha:4 bits + indexed 4 bits [8 bits] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 	PF_AL88			/* Alpha:8 bits + indexed 8 bits [16 bits] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) /* The index gives the encoding of the pixel format for an HW version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) static const enum ltdc_pix_fmt ltdc_pix_fmt_a0[NB_PF] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 	PF_ARGB8888,		/* 0x00 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 	PF_RGB888,		/* 0x01 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 	PF_RGB565,		/* 0x02 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 	PF_ARGB1555,		/* 0x03 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 	PF_ARGB4444,		/* 0x04 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 	PF_L8,			/* 0x05 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 	PF_AL44,		/* 0x06 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 	PF_AL88			/* 0x07 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) static const enum ltdc_pix_fmt ltdc_pix_fmt_a1[NB_PF] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 	PF_ARGB8888,		/* 0x00 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 	PF_RGB888,		/* 0x01 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 	PF_RGB565,		/* 0x02 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 	PF_RGBA8888,		/* 0x03 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 	PF_AL44,		/* 0x04 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 	PF_L8,			/* 0x05 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 	PF_ARGB1555,		/* 0x06 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 	PF_ARGB4444		/* 0x07 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) static const u64 ltdc_format_modifiers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 	DRM_FORMAT_MOD_LINEAR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 	DRM_FORMAT_MOD_INVALID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) static inline u32 reg_read(void __iomem *base, u32 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 	return readl_relaxed(base + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) static inline void reg_write(void __iomem *base, u32 reg, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 	writel_relaxed(val, base + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) static inline void reg_set(void __iomem *base, u32 reg, u32 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 	reg_write(base, reg, reg_read(base, reg) | mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) static inline void reg_clear(void __iomem *base, u32 reg, u32 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 	reg_write(base, reg, reg_read(base, reg) & ~mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) static inline void reg_update_bits(void __iomem *base, u32 reg, u32 mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 				   u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 	reg_write(base, reg, (reg_read(base, reg) & ~mask) | val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) static inline struct ltdc_device *crtc_to_ltdc(struct drm_crtc *crtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 	return (struct ltdc_device *)crtc->dev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) static inline struct ltdc_device *plane_to_ltdc(struct drm_plane *plane)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 	return (struct ltdc_device *)plane->dev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) static inline struct ltdc_device *encoder_to_ltdc(struct drm_encoder *enc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 	return (struct ltdc_device *)enc->dev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) static inline enum ltdc_pix_fmt to_ltdc_pixelformat(u32 drm_fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 	enum ltdc_pix_fmt pf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 	switch (drm_fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 	case DRM_FORMAT_ARGB8888:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 	case DRM_FORMAT_XRGB8888:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 		pf = PF_ARGB8888;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 	case DRM_FORMAT_RGBA8888:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 	case DRM_FORMAT_RGBX8888:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 		pf = PF_RGBA8888;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 	case DRM_FORMAT_RGB888:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 		pf = PF_RGB888;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 	case DRM_FORMAT_RGB565:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 		pf = PF_RGB565;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 	case DRM_FORMAT_ARGB1555:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 	case DRM_FORMAT_XRGB1555:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 		pf = PF_ARGB1555;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 	case DRM_FORMAT_ARGB4444:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 	case DRM_FORMAT_XRGB4444:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 		pf = PF_ARGB4444;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 	case DRM_FORMAT_C8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 		pf = PF_L8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 		pf = PF_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 		/* Note: There are no DRM_FORMAT for AL44 and AL88 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 	return pf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) static inline u32 to_drm_pixelformat(enum ltdc_pix_fmt pf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 	switch (pf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 	case PF_ARGB8888:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 		return DRM_FORMAT_ARGB8888;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 	case PF_RGBA8888:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 		return DRM_FORMAT_RGBA8888;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 	case PF_RGB888:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 		return DRM_FORMAT_RGB888;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 	case PF_RGB565:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 		return DRM_FORMAT_RGB565;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 	case PF_ARGB1555:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 		return DRM_FORMAT_ARGB1555;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 	case PF_ARGB4444:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 		return DRM_FORMAT_ARGB4444;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 	case PF_L8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 		return DRM_FORMAT_C8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 	case PF_AL44:		/* No DRM support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 	case PF_AL88:		/* No DRM support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 	case PF_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) static inline u32 get_pixelformat_without_alpha(u32 drm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 	switch (drm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 	case DRM_FORMAT_ARGB4444:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 		return DRM_FORMAT_XRGB4444;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 	case DRM_FORMAT_RGBA4444:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 		return DRM_FORMAT_RGBX4444;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 	case DRM_FORMAT_ARGB1555:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 		return DRM_FORMAT_XRGB1555;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 	case DRM_FORMAT_RGBA5551:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 		return DRM_FORMAT_RGBX5551;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 	case DRM_FORMAT_ARGB8888:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 		return DRM_FORMAT_XRGB8888;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 	case DRM_FORMAT_RGBA8888:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 		return DRM_FORMAT_RGBX8888;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) static irqreturn_t ltdc_irq_thread(int irq, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 	struct drm_device *ddev = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 	struct ltdc_device *ldev = ddev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 	struct drm_crtc *crtc = drm_crtc_from_index(ddev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 	/* Line IRQ : trigger the vblank event */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 	if (ldev->irq_status & ISR_LIF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 		drm_crtc_handle_vblank(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 	/* Save FIFO Underrun & Transfer Error status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 	mutex_lock(&ldev->err_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 	if (ldev->irq_status & ISR_FUIF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 		ldev->error_status |= ISR_FUIF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 	if (ldev->irq_status & ISR_TERRIF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 		ldev->error_status |= ISR_TERRIF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 	mutex_unlock(&ldev->err_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 	return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) static irqreturn_t ltdc_irq(int irq, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 	struct drm_device *ddev = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 	struct ltdc_device *ldev = ddev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 	/* Read & Clear the interrupt status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 	ldev->irq_status = reg_read(ldev->regs, LTDC_ISR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 	reg_write(ldev->regs, LTDC_ICR, ldev->irq_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 	return IRQ_WAKE_THREAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400)  * DRM_CRTC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) static void ltdc_crtc_update_clut(struct drm_crtc *crtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 	struct ltdc_device *ldev = crtc_to_ltdc(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 	struct drm_color_lut *lut;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 	if (!crtc->state->color_mgmt_changed || !crtc->state->gamma_lut)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 	lut = (struct drm_color_lut *)crtc->state->gamma_lut->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 	for (i = 0; i < CLUT_SIZE; i++, lut++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 		val = ((lut->red << 8) & 0xff0000) | (lut->green & 0xff00) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 			(lut->blue >> 8) | (i << 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 		reg_write(ldev->regs, LTDC_L1CLUTWR, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) static void ltdc_crtc_atomic_enable(struct drm_crtc *crtc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 				    struct drm_crtc_state *old_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 	struct ltdc_device *ldev = crtc_to_ltdc(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 	struct drm_device *ddev = crtc->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 	DRM_DEBUG_DRIVER("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 	pm_runtime_get_sync(ddev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 	/* Sets the background color value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 	reg_write(ldev->regs, LTDC_BCCR, BCCR_BCBLACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 	/* Enable IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 	reg_set(ldev->regs, LTDC_IER, IER_RRIE | IER_FUIE | IER_TERRIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 	/* Commit shadow registers = update planes at next vblank */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 	reg_set(ldev->regs, LTDC_SRCR, SRCR_VBR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 	drm_crtc_vblank_on(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) static void ltdc_crtc_atomic_disable(struct drm_crtc *crtc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 				     struct drm_crtc_state *old_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 	struct ltdc_device *ldev = crtc_to_ltdc(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 	struct drm_device *ddev = crtc->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 	DRM_DEBUG_DRIVER("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 	drm_crtc_vblank_off(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 	/* disable IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 	reg_clear(ldev->regs, LTDC_IER, IER_RRIE | IER_FUIE | IER_TERRIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 	/* immediately commit disable of layers before switching off LTDC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 	reg_set(ldev->regs, LTDC_SRCR, SRCR_IMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 	pm_runtime_put_sync(ddev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) #define CLK_TOLERANCE_HZ 50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) static enum drm_mode_status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) ltdc_crtc_mode_valid(struct drm_crtc *crtc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 		     const struct drm_display_mode *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 	struct ltdc_device *ldev = crtc_to_ltdc(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 	int target = mode->clock * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 	int target_min = target - CLK_TOLERANCE_HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 	int target_max = target + CLK_TOLERANCE_HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 	int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 	result = clk_round_rate(ldev->pixel_clk, target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 	DRM_DEBUG_DRIVER("clk rate target %d, available %d\n", target, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 	/* Filter modes according to the max frequency supported by the pads */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 	if (result > ldev->caps.pad_max_freq_hz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 		return MODE_CLOCK_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 	 * Accept all "preferred" modes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 	 * - this is important for panels because panel clock tolerances are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 	 *   bigger than hdmi ones and there is no reason to not accept them
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 	 *   (the fps may vary a little but it is not a problem).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 	 * - the hdmi preferred mode will be accepted too, but userland will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 	 *   be able to use others hdmi "valid" modes if necessary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 	if (mode->type & DRM_MODE_TYPE_PREFERRED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 		return MODE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 	 * Filter modes according to the clock value, particularly useful for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 	 * hdmi modes that require precise pixel clocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 	if (result < target_min || result > target_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 		return MODE_CLOCK_RANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 	return MODE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) static bool ltdc_crtc_mode_fixup(struct drm_crtc *crtc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 				 const struct drm_display_mode *mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 				 struct drm_display_mode *adjusted_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 	struct ltdc_device *ldev = crtc_to_ltdc(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 	int rate = mode->clock * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 	if (clk_set_rate(ldev->pixel_clk, rate) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 		DRM_ERROR("Cannot set rate (%dHz) for pixel clk\n", rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 	adjusted_mode->clock = clk_get_rate(ldev->pixel_clk) / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 	DRM_DEBUG_DRIVER("requested clock %dkHz, adjusted clock %dkHz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 			 mode->clock, adjusted_mode->clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 	return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 	struct ltdc_device *ldev = crtc_to_ltdc(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 	struct drm_device *ddev = crtc->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 	struct drm_connector_list_iter iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 	struct drm_connector *connector = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 	struct drm_encoder *encoder = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 	struct drm_bridge *bridge = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 	struct videomode vm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 	u32 hsync, vsync, accum_hbp, accum_vbp, accum_act_w, accum_act_h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 	u32 total_width, total_height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 	u32 bus_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 	/* get encoder from crtc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 	drm_for_each_encoder(encoder, ddev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 		if (encoder->crtc == crtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 	if (encoder) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 		/* get bridge from encoder */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 		list_for_each_entry(bridge, &encoder->bridge_chain, chain_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 			if (bridge->encoder == encoder)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 		/* Get the connector from encoder */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 		drm_connector_list_iter_begin(ddev, &iter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 		drm_for_each_connector_iter(connector, &iter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 			if (connector->encoder == encoder)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 		drm_connector_list_iter_end(&iter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 	if (bridge && bridge->timings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 		bus_flags = bridge->timings->input_bus_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 	else if (connector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 		bus_flags = connector->display_info.bus_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 	if (!pm_runtime_active(ddev->dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 		ret = pm_runtime_get_sync(ddev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 			DRM_ERROR("Failed to set mode, cannot get sync\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 	drm_display_mode_to_videomode(mode, &vm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 	DRM_DEBUG_DRIVER("CRTC:%d mode:%s\n", crtc->base.id, mode->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 	DRM_DEBUG_DRIVER("Video mode: %dx%d", vm.hactive, vm.vactive);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 	DRM_DEBUG_DRIVER(" hfp %d hbp %d hsl %d vfp %d vbp %d vsl %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 			 vm.hfront_porch, vm.hback_porch, vm.hsync_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 			 vm.vfront_porch, vm.vback_porch, vm.vsync_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 	/* Convert video timings to ltdc timings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 	hsync = vm.hsync_len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 	vsync = vm.vsync_len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 	accum_hbp = hsync + vm.hback_porch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 	accum_vbp = vsync + vm.vback_porch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 	accum_act_w = accum_hbp + vm.hactive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 	accum_act_h = accum_vbp + vm.vactive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 	total_width = accum_act_w + vm.hfront_porch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 	total_height = accum_act_h + vm.vfront_porch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 	/* Configures the HS, VS, DE and PC polarities. Default Active Low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 	val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 	if (vm.flags & DISPLAY_FLAGS_HSYNC_HIGH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 		val |= GCR_HSPOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 	if (vm.flags & DISPLAY_FLAGS_VSYNC_HIGH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 		val |= GCR_VSPOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 	if (bus_flags & DRM_BUS_FLAG_DE_LOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 		val |= GCR_DEPOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 	if (bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 		val |= GCR_PCPOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 	reg_update_bits(ldev->regs, LTDC_GCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 			GCR_HSPOL | GCR_VSPOL | GCR_DEPOL | GCR_PCPOL, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 	/* Set Synchronization size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 	val = (hsync << 16) | vsync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 	reg_update_bits(ldev->regs, LTDC_SSCR, SSCR_VSH | SSCR_HSW, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 	/* Set Accumulated Back porch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 	val = (accum_hbp << 16) | accum_vbp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 	reg_update_bits(ldev->regs, LTDC_BPCR, BPCR_AVBP | BPCR_AHBP, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 	/* Set Accumulated Active Width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 	val = (accum_act_w << 16) | accum_act_h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 	reg_update_bits(ldev->regs, LTDC_AWCR, AWCR_AAW | AWCR_AAH, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 	/* Set total width & height */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 	val = (total_width << 16) | total_height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 	reg_update_bits(ldev->regs, LTDC_TWCR, TWCR_TOTALH | TWCR_TOTALW, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 	reg_write(ldev->regs, LTDC_LIPCR, (accum_act_h + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) static void ltdc_crtc_atomic_flush(struct drm_crtc *crtc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 				   struct drm_crtc_state *old_crtc_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 	struct ltdc_device *ldev = crtc_to_ltdc(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 	struct drm_device *ddev = crtc->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 	struct drm_pending_vblank_event *event = crtc->state->event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 	DRM_DEBUG_ATOMIC("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 	ltdc_crtc_update_clut(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 	/* Commit shadow registers = update planes at next vblank */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 	reg_set(ldev->regs, LTDC_SRCR, SRCR_VBR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 	if (event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 		crtc->state->event = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 		spin_lock_irq(&ddev->event_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 		if (drm_crtc_vblank_get(crtc) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 			drm_crtc_arm_vblank_event(crtc, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 			drm_crtc_send_vblank_event(crtc, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 		spin_unlock_irq(&ddev->event_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) static bool ltdc_crtc_get_scanout_position(struct drm_crtc *crtc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 					   bool in_vblank_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 					   int *vpos, int *hpos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 					   ktime_t *stime, ktime_t *etime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 					   const struct drm_display_mode *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 	struct drm_device *ddev = crtc->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 	struct ltdc_device *ldev = ddev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 	int line, vactive_start, vactive_end, vtotal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 	if (stime)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 		*stime = ktime_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 	/* The active area starts after vsync + front porch and ends
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 	 * at vsync + front porc + display size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 	 * The total height also include back porch.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 	 * We have 3 possible cases to handle:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 	 * - line < vactive_start: vpos = line - vactive_start and will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 	 * negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 	 * - vactive_start < line < vactive_end: vpos = line - vactive_start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 	 * and will be positive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 	 * - line > vactive_end: vpos = line - vtotal - vactive_start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 	 * and will negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 	 * Computation for the two first cases are identical so we can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 	 * simplify the code and only test if line > vactive_end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 	if (pm_runtime_active(ddev->dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 		line = reg_read(ldev->regs, LTDC_CPSR) & CPSR_CYPOS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 		vactive_start = reg_read(ldev->regs, LTDC_BPCR) & BPCR_AVBP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 		vactive_end = reg_read(ldev->regs, LTDC_AWCR) & AWCR_AAH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 		vtotal = reg_read(ldev->regs, LTDC_TWCR) & TWCR_TOTALH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 		if (line > vactive_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 			*vpos = line - vtotal - vactive_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 			*vpos = line - vactive_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 		*vpos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 	*hpos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 	if (etime)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 		*etime = ktime_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 	return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) static const struct drm_crtc_helper_funcs ltdc_crtc_helper_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 	.mode_valid = ltdc_crtc_mode_valid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 	.mode_fixup = ltdc_crtc_mode_fixup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 	.mode_set_nofb = ltdc_crtc_mode_set_nofb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 	.atomic_flush = ltdc_crtc_atomic_flush,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 	.atomic_enable = ltdc_crtc_atomic_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 	.atomic_disable = ltdc_crtc_atomic_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 	.get_scanout_position = ltdc_crtc_get_scanout_position,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) static int ltdc_crtc_enable_vblank(struct drm_crtc *crtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 	struct ltdc_device *ldev = crtc_to_ltdc(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 	struct drm_crtc_state *state = crtc->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 	DRM_DEBUG_DRIVER("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 	if (state->enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 		reg_set(ldev->regs, LTDC_IER, IER_LIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 		return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) static void ltdc_crtc_disable_vblank(struct drm_crtc *crtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	struct ltdc_device *ldev = crtc_to_ltdc(crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 	DRM_DEBUG_DRIVER("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 	reg_clear(ldev->regs, LTDC_IER, IER_LIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) static const struct drm_crtc_funcs ltdc_crtc_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 	.destroy = drm_crtc_cleanup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 	.set_config = drm_atomic_helper_set_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 	.page_flip = drm_atomic_helper_page_flip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 	.reset = drm_atomic_helper_crtc_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 	.enable_vblank = ltdc_crtc_enable_vblank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 	.disable_vblank = ltdc_crtc_disable_vblank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 	.get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 	.gamma_set = drm_atomic_helper_legacy_gamma_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749)  * DRM_PLANE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) static int ltdc_plane_atomic_check(struct drm_plane *plane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 				   struct drm_plane_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 	struct drm_framebuffer *fb = state->fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 	u32 src_w, src_h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 	DRM_DEBUG_DRIVER("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 	if (!fb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 	/* convert src_ from 16:16 format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 	src_w = state->src_w >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 	src_h = state->src_h >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 	/* Reject scaling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 	if (src_w != state->crtc_w || src_h != state->crtc_h) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 		DRM_ERROR("Scaling is not supported");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) static void ltdc_plane_atomic_update(struct drm_plane *plane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 				     struct drm_plane_state *oldstate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 	struct ltdc_device *ldev = plane_to_ltdc(plane);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 	struct drm_plane_state *state = plane->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 	struct drm_framebuffer *fb = state->fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 	u32 lofs = plane->index * LAY_OFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 	u32 x0 = state->crtc_x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 	u32 x1 = state->crtc_x + state->crtc_w - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 	u32 y0 = state->crtc_y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 	u32 y1 = state->crtc_y + state->crtc_h - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 	u32 src_x, src_y, src_w, src_h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 	u32 val, pitch_in_bytes, line_length, paddr, ahbp, avbp, bpcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 	enum ltdc_pix_fmt pf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 	if (!state->crtc || !fb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 		DRM_DEBUG_DRIVER("fb or crtc NULL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	/* convert src_ from 16:16 format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 	src_x = state->src_x >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 	src_y = state->src_y >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 	src_w = state->src_w >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 	src_h = state->src_h >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 	DRM_DEBUG_DRIVER("plane:%d fb:%d (%dx%d)@(%d,%d) -> (%dx%d)@(%d,%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 			 plane->base.id, fb->base.id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 			 src_w, src_h, src_x, src_y,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 			 state->crtc_w, state->crtc_h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 			 state->crtc_x, state->crtc_y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 	bpcr = reg_read(ldev->regs, LTDC_BPCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 	ahbp = (bpcr & BPCR_AHBP) >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 	avbp = bpcr & BPCR_AVBP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 	/* Configures the horizontal start and stop position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 	val = ((x1 + 1 + ahbp) << 16) + (x0 + 1 + ahbp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 	reg_update_bits(ldev->regs, LTDC_L1WHPCR + lofs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 			LXWHPCR_WHSTPOS | LXWHPCR_WHSPPOS, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 	/* Configures the vertical start and stop position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 	val = ((y1 + 1 + avbp) << 16) + (y0 + 1 + avbp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 	reg_update_bits(ldev->regs, LTDC_L1WVPCR + lofs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 			LXWVPCR_WVSTPOS | LXWVPCR_WVSPPOS, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 	/* Specifies the pixel format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 	pf = to_ltdc_pixelformat(fb->format->format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 	for (val = 0; val < NB_PF; val++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 		if (ldev->caps.pix_fmt_hw[val] == pf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 	if (val == NB_PF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 		DRM_ERROR("Pixel format %.4s not supported\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 			  (char *)&fb->format->format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 		val = 0;	/* set by default ARGB 32 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 	reg_update_bits(ldev->regs, LTDC_L1PFCR + lofs, LXPFCR_PF, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 	/* Configures the color frame buffer pitch in bytes & line length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 	pitch_in_bytes = fb->pitches[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 	line_length = fb->format->cpp[0] *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 		      (x1 - x0 + 1) + (ldev->caps.bus_width >> 3) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 	val = ((pitch_in_bytes << 16) | line_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 	reg_update_bits(ldev->regs, LTDC_L1CFBLR + lofs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 			LXCFBLR_CFBLL | LXCFBLR_CFBP, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 	/* Specifies the constant alpha value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 	val = CONSTA_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 	reg_update_bits(ldev->regs, LTDC_L1CACR + lofs, LXCACR_CONSTA, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 	/* Specifies the blending factors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 	val = BF1_PAXCA | BF2_1PAXCA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 	if (!fb->format->has_alpha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 		val = BF1_CA | BF2_1CA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 	/* Manage hw-specific capabilities */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 	if (ldev->caps.non_alpha_only_l1 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 	    plane->type != DRM_PLANE_TYPE_PRIMARY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 		val = BF1_PAXCA | BF2_1PAXCA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 	reg_update_bits(ldev->regs, LTDC_L1BFCR + lofs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 			LXBFCR_BF2 | LXBFCR_BF1, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 	/* Configures the frame buffer line number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 	val = y1 - y0 + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 	reg_update_bits(ldev->regs, LTDC_L1CFBLNR + lofs, LXCFBLNR_CFBLN, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 	/* Sets the FB address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 	paddr = (u32)drm_fb_cma_get_gem_addr(fb, state, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 	DRM_DEBUG_DRIVER("fb: phys 0x%08x", paddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 	reg_write(ldev->regs, LTDC_L1CFBAR + lofs, paddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 	/* Enable layer and CLUT if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 	val = fb->format->format == DRM_FORMAT_C8 ? LXCR_CLUTEN : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 	val |= LXCR_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 	reg_update_bits(ldev->regs, LTDC_L1CR + lofs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 			LXCR_LEN | LXCR_CLUTEN, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 	ldev->plane_fpsi[plane->index].counter++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 	mutex_lock(&ldev->err_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 	if (ldev->error_status & ISR_FUIF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 		DRM_WARN("ltdc fifo underrun: please verify display mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 		ldev->error_status &= ~ISR_FUIF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 	if (ldev->error_status & ISR_TERRIF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 		DRM_WARN("ltdc transfer error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 		ldev->error_status &= ~ISR_TERRIF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 	mutex_unlock(&ldev->err_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) static void ltdc_plane_atomic_disable(struct drm_plane *plane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 				      struct drm_plane_state *oldstate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 	struct ltdc_device *ldev = plane_to_ltdc(plane);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 	u32 lofs = plane->index * LAY_OFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 	/* disable layer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 	reg_clear(ldev->regs, LTDC_L1CR + lofs, LXCR_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 	DRM_DEBUG_DRIVER("CRTC:%d plane:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 			 oldstate->crtc->base.id, plane->base.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) static void ltdc_plane_atomic_print_state(struct drm_printer *p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 					  const struct drm_plane_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 	struct drm_plane *plane = state->plane;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 	struct ltdc_device *ldev = plane_to_ltdc(plane);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 	struct fps_info *fpsi = &ldev->plane_fpsi[plane->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	int ms_since_last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 	ktime_t now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 	now = ktime_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 	ms_since_last = ktime_to_ms(ktime_sub(now, fpsi->last_timestamp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 	drm_printf(p, "\tuser_updates=%dfps\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 		   DIV_ROUND_CLOSEST(fpsi->counter * 1000, ms_since_last));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 	fpsi->last_timestamp = now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 	fpsi->counter = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) static bool ltdc_plane_format_mod_supported(struct drm_plane *plane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 					    u32 format,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 					    u64 modifier)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 	if (modifier == DRM_FORMAT_MOD_LINEAR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) static const struct drm_plane_funcs ltdc_plane_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 	.update_plane = drm_atomic_helper_update_plane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 	.disable_plane = drm_atomic_helper_disable_plane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 	.destroy = drm_plane_cleanup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 	.reset = drm_atomic_helper_plane_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 	.atomic_print_state = ltdc_plane_atomic_print_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 	.format_mod_supported = ltdc_plane_format_mod_supported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) static const struct drm_plane_helper_funcs ltdc_plane_helper_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 	.prepare_fb = drm_gem_fb_prepare_fb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 	.atomic_check = ltdc_plane_atomic_check,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 	.atomic_update = ltdc_plane_atomic_update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 	.atomic_disable = ltdc_plane_atomic_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) static struct drm_plane *ltdc_plane_create(struct drm_device *ddev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 					   enum drm_plane_type type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 	unsigned long possible_crtcs = CRTC_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 	struct ltdc_device *ldev = ddev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 	struct device *dev = ddev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 	struct drm_plane *plane;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 	unsigned int i, nb_fmt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 	u32 formats[NB_PF * 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 	u32 drm_fmt, drm_fmt_no_alpha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 	const u64 *modifiers = ltdc_format_modifiers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 	/* Get supported pixel formats */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 	for (i = 0; i < NB_PF; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 		drm_fmt = to_drm_pixelformat(ldev->caps.pix_fmt_hw[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 		if (!drm_fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 		formats[nb_fmt++] = drm_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 		/* Add the no-alpha related format if any & supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 		drm_fmt_no_alpha = get_pixelformat_without_alpha(drm_fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 		if (!drm_fmt_no_alpha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 		/* Manage hw-specific capabilities */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 		if (ldev->caps.non_alpha_only_l1 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 		    type != DRM_PLANE_TYPE_PRIMARY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 		formats[nb_fmt++] = drm_fmt_no_alpha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 	plane = devm_kzalloc(dev, sizeof(*plane), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 	if (!plane)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 	ret = drm_universal_plane_init(ddev, plane, possible_crtcs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 				       &ltdc_plane_funcs, formats, nb_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 				       modifiers, type, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 	drm_plane_helper_add(plane, &ltdc_plane_helper_funcs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	DRM_DEBUG_DRIVER("plane:%d created\n", plane->base.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 	return plane;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) static void ltdc_plane_destroy_all(struct drm_device *ddev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	struct drm_plane *plane, *plane_temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 	list_for_each_entry_safe(plane, plane_temp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 				 &ddev->mode_config.plane_list, head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 		drm_plane_cleanup(plane);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 	struct ltdc_device *ldev = ddev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 	struct drm_plane *primary, *overlay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 	primary = ltdc_plane_create(ddev, DRM_PLANE_TYPE_PRIMARY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 	if (!primary) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 		DRM_ERROR("Can not create primary plane\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 	ret = drm_crtc_init_with_planes(ddev, crtc, primary, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 					&ltdc_crtc_funcs, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 		DRM_ERROR("Can not initialize CRTC\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 		goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 	drm_crtc_helper_add(crtc, &ltdc_crtc_helper_funcs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 	drm_mode_crtc_set_gamma_size(crtc, CLUT_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 	drm_crtc_enable_color_mgmt(crtc, 0, false, CLUT_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 	DRM_DEBUG_DRIVER("CRTC:%d created\n", crtc->base.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 	/* Add planes. Note : the first layer is used by primary plane */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 	for (i = 1; i < ldev->caps.nb_layers; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 		overlay = ltdc_plane_create(ddev, DRM_PLANE_TYPE_OVERLAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 		if (!overlay) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 			ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 			DRM_ERROR("Can not create overlay plane %d\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 			goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) cleanup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 	ltdc_plane_destroy_all(ddev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)  * DRM_ENCODER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) static const struct drm_encoder_funcs ltdc_encoder_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 	.destroy = drm_encoder_cleanup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) static void ltdc_encoder_disable(struct drm_encoder *encoder)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 	struct drm_device *ddev = encoder->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 	struct ltdc_device *ldev = ddev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 	DRM_DEBUG_DRIVER("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 	/* Disable LTDC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 	reg_clear(ldev->regs, LTDC_GCR, GCR_LTDCEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 	/* Set to sleep state the pinctrl whatever type of encoder */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 	pinctrl_pm_select_sleep_state(ddev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) static void ltdc_encoder_enable(struct drm_encoder *encoder)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 	struct drm_device *ddev = encoder->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 	struct ltdc_device *ldev = ddev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 	DRM_DEBUG_DRIVER("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 	/* Enable LTDC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 	reg_set(ldev->regs, LTDC_GCR, GCR_LTDCEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) static void ltdc_encoder_mode_set(struct drm_encoder *encoder,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 				  struct drm_display_mode *mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 				  struct drm_display_mode *adjusted_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 	struct drm_device *ddev = encoder->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 	DRM_DEBUG_DRIVER("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 	 * Set to default state the pinctrl only with DPI type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 	 * Others types like DSI, don't need pinctrl due to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 	 * internal bridge (the signals do not come out of the chipset).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 	if (encoder->encoder_type == DRM_MODE_ENCODER_DPI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 		pinctrl_pm_select_default_state(ddev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) static const struct drm_encoder_helper_funcs ltdc_encoder_helper_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 	.disable = ltdc_encoder_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 	.enable = ltdc_encoder_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 	.mode_set = ltdc_encoder_mode_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) static int ltdc_encoder_init(struct drm_device *ddev, struct drm_bridge *bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 	struct drm_encoder *encoder;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 	encoder = devm_kzalloc(ddev->dev, sizeof(*encoder), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 	if (!encoder)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 	encoder->possible_crtcs = CRTC_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 	encoder->possible_clones = 0;	/* No cloning support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 	drm_encoder_init(ddev, encoder, &ltdc_encoder_funcs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 			 DRM_MODE_ENCODER_DPI, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 	drm_encoder_helper_add(encoder, &ltdc_encoder_helper_funcs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 	ret = drm_bridge_attach(encoder, bridge, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 		drm_encoder_cleanup(encoder);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 	DRM_DEBUG_DRIVER("Bridge encoder:%d created\n", encoder->base.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) static int ltdc_get_caps(struct drm_device *ddev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 	struct ltdc_device *ldev = ddev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 	u32 bus_width_log2, lcr, gc2r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 	 * at least 1 layer must be managed & the number of layers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 	 * must not exceed LTDC_MAX_LAYER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 	lcr = reg_read(ldev->regs, LTDC_LCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 	ldev->caps.nb_layers = clamp((int)lcr, 1, LTDC_MAX_LAYER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 	/* set data bus width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 	gc2r = reg_read(ldev->regs, LTDC_GC2R);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) 	bus_width_log2 = (gc2r & GC2R_BW) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 	ldev->caps.bus_width = 8 << bus_width_log2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 	ldev->caps.hw_version = reg_read(ldev->regs, LTDC_IDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 	switch (ldev->caps.hw_version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 	case HWVER_10200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 	case HWVER_10300:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 		ldev->caps.reg_ofs = REG_OFS_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 		ldev->caps.pix_fmt_hw = ltdc_pix_fmt_a0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 		 * Hw older versions support non-alpha color formats derived
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 		 * from native alpha color formats only on the primary layer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 		 * For instance, RG16 native format without alpha works fine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 		 * on 2nd layer but XR24 (derived color format from AR24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 		 * does not work on 2nd layer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 		ldev->caps.non_alpha_only_l1 = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 		ldev->caps.pad_max_freq_hz = 90000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 		if (ldev->caps.hw_version == HWVER_10200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 			ldev->caps.pad_max_freq_hz = 65000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 		ldev->caps.nb_irq = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 	case HWVER_20101:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 		ldev->caps.reg_ofs = REG_OFS_4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 		ldev->caps.pix_fmt_hw = ltdc_pix_fmt_a1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 		ldev->caps.non_alpha_only_l1 = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 		ldev->caps.pad_max_freq_hz = 150000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 		ldev->caps.nb_irq = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) void ltdc_suspend(struct drm_device *ddev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 	struct ltdc_device *ldev = ddev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 	DRM_DEBUG_DRIVER("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 	clk_disable_unprepare(ldev->pixel_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) int ltdc_resume(struct drm_device *ddev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 	struct ltdc_device *ldev = ddev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 	DRM_DEBUG_DRIVER("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 	ret = clk_prepare_enable(ldev->pixel_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 		DRM_ERROR("failed to enable pixel clock (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) int ltdc_load(struct drm_device *ddev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) 	struct platform_device *pdev = to_platform_device(ddev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) 	struct ltdc_device *ldev = ddev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 	struct device *dev = ddev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) 	struct device_node *np = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 	struct drm_bridge *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 	struct drm_panel *panel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 	struct drm_crtc *crtc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 	struct reset_control *rstc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 	struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 	int irq, i, nb_endpoints;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 	int ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 	DRM_DEBUG_DRIVER("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 	/* Get number of endpoints */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) 	nb_endpoints = of_graph_get_endpoint_count(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) 	if (!nb_endpoints)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 	ldev->pixel_clk = devm_clk_get(dev, "lcd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 	if (IS_ERR(ldev->pixel_clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 		if (PTR_ERR(ldev->pixel_clk) != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 			DRM_ERROR("Unable to get lcd clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 		return PTR_ERR(ldev->pixel_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 	if (clk_prepare_enable(ldev->pixel_clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 		DRM_ERROR("Unable to prepare pixel clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 	/* Get endpoints if any */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 	for (i = 0; i < nb_endpoints; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 		ret = drm_of_find_panel_or_bridge(np, 0, i, &panel, &bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 		 * If at least one endpoint is -ENODEV, continue probing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 		 * else if at least one endpoint returned an error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 		 * (ie -EPROBE_DEFER) then stop probing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 		if (ret == -ENODEV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 		else if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) 			goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) 		if (panel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) 			bridge = drm_panel_bridge_add_typed(panel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) 							    DRM_MODE_CONNECTOR_DPI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) 			if (IS_ERR(bridge)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) 				DRM_ERROR("panel-bridge endpoint %d\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) 				ret = PTR_ERR(bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) 				goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) 		if (bridge) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) 			ret = ltdc_encoder_init(ddev, bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) 			if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) 				DRM_ERROR("init encoder endpoint %d\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) 				goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) 	rstc = devm_reset_control_get_exclusive(dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) 	mutex_init(&ldev->err_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) 	if (!IS_ERR(rstc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) 		reset_control_assert(rstc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) 		usleep_range(10, 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) 		reset_control_deassert(rstc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) 	ldev->regs = devm_ioremap_resource(dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) 	if (IS_ERR(ldev->regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) 		DRM_ERROR("Unable to get ltdc registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) 		ret = PTR_ERR(ldev->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) 	/* Disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) 	reg_clear(ldev->regs, LTDC_IER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) 		  IER_LIE | IER_RRIE | IER_FUIE | IER_TERRIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) 	ret = ltdc_get_caps(ddev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) 		DRM_ERROR("hardware identifier (0x%08x) not supported!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) 			  ldev->caps.hw_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) 	DRM_DEBUG_DRIVER("ltdc hw version 0x%08x\n", ldev->caps.hw_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) 	for (i = 0; i < ldev->caps.nb_irq; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) 		irq = platform_get_irq(pdev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) 		if (irq < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) 			ret = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) 			goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 		ret = devm_request_threaded_irq(dev, irq, ltdc_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 						ltdc_irq_thread, IRQF_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) 						dev_name(dev), ddev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 			DRM_ERROR("Failed to register LTDC interrupt\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 			goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) 	crtc = devm_kzalloc(dev, sizeof(*crtc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) 	if (!crtc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) 		DRM_ERROR("Failed to allocate crtc\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 		ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 	ddev->mode_config.allow_fb_modifiers = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) 	ret = ltdc_crtc_init(ddev, crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) 		DRM_ERROR("Failed to init crtc\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) 	ret = drm_vblank_init(ddev, NB_CRTC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) 		DRM_ERROR("Failed calling drm_vblank_init()\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) 	/* Allow usage of vblank without having to call drm_irq_install */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) 	ddev->irq_enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) 	clk_disable_unprepare(ldev->pixel_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) 	pinctrl_pm_select_sleep_state(ddev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) 	pm_runtime_enable(ddev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) 	for (i = 0; i < nb_endpoints; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) 		drm_of_panel_bridge_remove(ddev->dev->of_node, 0, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) 	clk_disable_unprepare(ldev->pixel_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) void ltdc_unload(struct drm_device *ddev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) 	struct device *dev = ddev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) 	int nb_endpoints, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) 	DRM_DEBUG_DRIVER("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) 	nb_endpoints = of_graph_get_endpoint_count(dev->of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) 	for (i = 0; i < nb_endpoints; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) 		drm_of_panel_bridge_remove(ddev->dev->of_node, 0, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) 	pm_runtime_disable(ddev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) MODULE_AUTHOR("Philippe Cornu <philippe.cornu@st.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) MODULE_AUTHOR("Yannick Fertre <yannick.fertre@st.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) MODULE_AUTHOR("Fabien Dessenne <fabien.dessenne@st.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) MODULE_AUTHOR("Mickael Reulier <mickael.reulier@st.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) MODULE_DESCRIPTION("STMicroelectronics ST DRM LTDC driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) MODULE_LICENSE("GPL v2");