^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) <dc_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, <dc_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) <dc_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, <dc_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, <dc_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, <dc_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");