1/* SPDX-License-Identifier: GPL-2.0-only */ 2/* 3 * Copyright (C) 2013 Red Hat 4 * Author: Rob Clark <robdclark@gmail.com> 5 */ 6 7#ifndef __MDP4_KMS_H__ 8#define __MDP4_KMS_H__ 9 10#include <drm/drm_panel.h> 11 12#include "msm_drv.h" 13#include "msm_kms.h" 14#include "disp/mdp_kms.h" 15#include "mdp4.xml.h" 16 17struct device_node; 18 19struct mdp4_kms { 20 struct mdp_kms base; 21 22 struct drm_device *dev; 23 24 int rev; 25 26 void __iomem *mmio; 27 28 struct regulator *vdd; 29 30 struct clk *clk; 31 struct clk *pclk; 32 struct clk *lut_clk; 33 struct clk *axi_clk; 34 35 struct mdp_irq error_handler; 36 37 bool rpm_enabled; 38 39 /* empty/blank cursor bo to use when cursor is "disabled" */ 40 struct drm_gem_object *blank_cursor_bo; 41 uint64_t blank_cursor_iova; 42}; 43#define to_mdp4_kms(x) container_of(x, struct mdp4_kms, base) 44 45static inline void mdp4_write(struct mdp4_kms *mdp4_kms, u32 reg, u32 data) 46{ 47 msm_writel(data, mdp4_kms->mmio + reg); 48} 49 50static inline u32 mdp4_read(struct mdp4_kms *mdp4_kms, u32 reg) 51{ 52 return msm_readl(mdp4_kms->mmio + reg); 53} 54 55static inline uint32_t pipe2flush(enum mdp4_pipe pipe) 56{ 57 switch (pipe) { 58 case VG1: return MDP4_OVERLAY_FLUSH_VG1; 59 case VG2: return MDP4_OVERLAY_FLUSH_VG2; 60 case RGB1: return MDP4_OVERLAY_FLUSH_RGB1; 61 case RGB2: return MDP4_OVERLAY_FLUSH_RGB2; 62 default: return 0; 63 } 64} 65 66static inline uint32_t ovlp2flush(int ovlp) 67{ 68 switch (ovlp) { 69 case 0: return MDP4_OVERLAY_FLUSH_OVLP0; 70 case 1: return MDP4_OVERLAY_FLUSH_OVLP1; 71 default: return 0; 72 } 73} 74 75static inline uint32_t dma2irq(enum mdp4_dma dma) 76{ 77 switch (dma) { 78 case DMA_P: return MDP4_IRQ_DMA_P_DONE; 79 case DMA_S: return MDP4_IRQ_DMA_S_DONE; 80 case DMA_E: return MDP4_IRQ_DMA_E_DONE; 81 default: return 0; 82 } 83} 84 85static inline uint32_t dma2err(enum mdp4_dma dma) 86{ 87 switch (dma) { 88 case DMA_P: return MDP4_IRQ_PRIMARY_INTF_UDERRUN; 89 case DMA_S: return 0; // ??? 90 case DMA_E: return MDP4_IRQ_EXTERNAL_INTF_UDERRUN; 91 default: return 0; 92 } 93} 94 95static inline uint32_t mixercfg(uint32_t mixer_cfg, int mixer, 96 enum mdp4_pipe pipe, enum mdp_mixer_stage_id stage) 97{ 98 switch (pipe) { 99 case VG1: 100 mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE0__MASK | 101 MDP4_LAYERMIXER_IN_CFG_PIPE0_MIXER1); 102 mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE0(stage) | 103 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE0_MIXER1); 104 break; 105 case VG2: 106 mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE1__MASK | 107 MDP4_LAYERMIXER_IN_CFG_PIPE1_MIXER1); 108 mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE1(stage) | 109 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE1_MIXER1); 110 break; 111 case RGB1: 112 mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE2__MASK | 113 MDP4_LAYERMIXER_IN_CFG_PIPE2_MIXER1); 114 mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE2(stage) | 115 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE2_MIXER1); 116 break; 117 case RGB2: 118 mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE3__MASK | 119 MDP4_LAYERMIXER_IN_CFG_PIPE3_MIXER1); 120 mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE3(stage) | 121 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE3_MIXER1); 122 break; 123 case RGB3: 124 mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE4__MASK | 125 MDP4_LAYERMIXER_IN_CFG_PIPE4_MIXER1); 126 mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE4(stage) | 127 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE4_MIXER1); 128 break; 129 case VG3: 130 mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE5__MASK | 131 MDP4_LAYERMIXER_IN_CFG_PIPE5_MIXER1); 132 mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE5(stage) | 133 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE5_MIXER1); 134 break; 135 case VG4: 136 mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE6__MASK | 137 MDP4_LAYERMIXER_IN_CFG_PIPE6_MIXER1); 138 mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE6(stage) | 139 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE6_MIXER1); 140 break; 141 default: 142 WARN(1, "invalid pipe"); 143 break; 144 } 145 146 return mixer_cfg; 147} 148 149int mdp4_disable(struct mdp4_kms *mdp4_kms); 150int mdp4_enable(struct mdp4_kms *mdp4_kms); 151 152void mdp4_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask, 153 uint32_t old_irqmask); 154void mdp4_irq_preinstall(struct msm_kms *kms); 155int mdp4_irq_postinstall(struct msm_kms *kms); 156void mdp4_irq_uninstall(struct msm_kms *kms); 157irqreturn_t mdp4_irq(struct msm_kms *kms); 158int mdp4_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc); 159void mdp4_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc); 160 161static inline uint32_t mdp4_pipe_caps(enum mdp4_pipe pipe) 162{ 163 switch (pipe) { 164 case VG1: 165 case VG2: 166 case VG3: 167 case VG4: 168 return MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP | 169 MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC; 170 case RGB1: 171 case RGB2: 172 case RGB3: 173 return MDP_PIPE_CAP_SCALE; 174 default: 175 return 0; 176 } 177} 178 179enum mdp4_pipe mdp4_plane_pipe(struct drm_plane *plane); 180struct drm_plane *mdp4_plane_init(struct drm_device *dev, 181 enum mdp4_pipe pipe_id, bool private_plane); 182 183uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc); 184void mdp4_crtc_set_config(struct drm_crtc *crtc, uint32_t config); 185void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf, int mixer); 186void mdp4_crtc_wait_for_commit_done(struct drm_crtc *crtc); 187struct drm_crtc *mdp4_crtc_init(struct drm_device *dev, 188 struct drm_plane *plane, int id, int ovlp_id, 189 enum mdp4_dma dma_id); 190 191long mdp4_dtv_round_pixclk(struct drm_encoder *encoder, unsigned long rate); 192struct drm_encoder *mdp4_dtv_encoder_init(struct drm_device *dev); 193 194long mdp4_lcdc_round_pixclk(struct drm_encoder *encoder, unsigned long rate); 195struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev, 196 struct device_node *panel_node); 197 198struct drm_connector *mdp4_lvds_connector_init(struct drm_device *dev, 199 struct device_node *panel_node, struct drm_encoder *encoder); 200 201#ifdef CONFIG_DRM_MSM_DSI 202struct drm_encoder *mdp4_dsi_encoder_init(struct drm_device *dev); 203#else 204static inline struct drm_encoder *mdp4_dsi_encoder_init(struct drm_device *dev) 205{ 206 return ERR_PTR(-ENODEV); 207} 208#endif 209 210#ifdef CONFIG_COMMON_CLK 211struct clk *mpd4_lvds_pll_init(struct drm_device *dev); 212#else 213static inline struct clk *mpd4_lvds_pll_init(struct drm_device *dev) 214{ 215 return ERR_PTR(-ENODEV); 216} 217#endif 218 219#endif /* __MDP4_KMS_H__ */ 220