1 /* 2 * Copyright (C) 2013 Red Hat 3 * Author: Rob Clark <robdclark@gmail.com> 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 as published by 7 * the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 * 14 * You should have received a copy of the GNU General Public License along with 15 * this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef __MDP4_KMS_H__ 19 #define __MDP4_KMS_H__ 20 21 #include <drm/drm_panel.h> 22 23 #include "msm_drv.h" 24 #include "msm_kms.h" 25 #include "disp/mdp_kms.h" 26 #include "mdp4.xml.h" 27 28 struct device_node; 29 30 struct mdp4_kms { 31 struct mdp_kms base; 32 33 struct drm_device *dev; 34 35 int rev; 36 37 void __iomem *mmio; 38 39 struct regulator *vdd; 40 41 struct clk *clk; 42 struct clk *pclk; 43 struct clk *lut_clk; 44 struct clk *axi_clk; 45 46 struct mdp_irq error_handler; 47 48 bool rpm_enabled; 49 50 /* empty/blank cursor bo to use when cursor is "disabled" */ 51 struct drm_gem_object *blank_cursor_bo; 52 uint64_t blank_cursor_iova; 53 }; 54 #define to_mdp4_kms(x) container_of(x, struct mdp4_kms, base) 55 56 /* platform config data (ie. from DT, or pdata) */ 57 struct mdp4_platform_config { 58 struct iommu_domain *iommu; 59 uint32_t max_clk; 60 }; 61 62 static inline void mdp4_write(struct mdp4_kms *mdp4_kms, u32 reg, u32 data) 63 { 64 msm_writel(data, mdp4_kms->mmio + reg); 65 } 66 67 static inline u32 mdp4_read(struct mdp4_kms *mdp4_kms, u32 reg) 68 { 69 return msm_readl(mdp4_kms->mmio + reg); 70 } 71 72 static inline uint32_t pipe2flush(enum mdp4_pipe pipe) 73 { 74 switch (pipe) { 75 case VG1: return MDP4_OVERLAY_FLUSH_VG1; 76 case VG2: return MDP4_OVERLAY_FLUSH_VG2; 77 case RGB1: return MDP4_OVERLAY_FLUSH_RGB1; 78 case RGB2: return MDP4_OVERLAY_FLUSH_RGB2; 79 default: return 0; 80 } 81 } 82 83 static inline uint32_t ovlp2flush(int ovlp) 84 { 85 switch (ovlp) { 86 case 0: return MDP4_OVERLAY_FLUSH_OVLP0; 87 case 1: return MDP4_OVERLAY_FLUSH_OVLP1; 88 default: return 0; 89 } 90 } 91 92 static inline uint32_t dma2irq(enum mdp4_dma dma) 93 { 94 switch (dma) { 95 case DMA_P: return MDP4_IRQ_DMA_P_DONE; 96 case DMA_S: return MDP4_IRQ_DMA_S_DONE; 97 case DMA_E: return MDP4_IRQ_DMA_E_DONE; 98 default: return 0; 99 } 100 } 101 102 static inline uint32_t dma2err(enum mdp4_dma dma) 103 { 104 switch (dma) { 105 case DMA_P: return MDP4_IRQ_PRIMARY_INTF_UDERRUN; 106 case DMA_S: return 0; // ??? 107 case DMA_E: return MDP4_IRQ_EXTERNAL_INTF_UDERRUN; 108 default: return 0; 109 } 110 } 111 112 static inline uint32_t mixercfg(uint32_t mixer_cfg, int mixer, 113 enum mdp4_pipe pipe, enum mdp_mixer_stage_id stage) 114 { 115 switch (pipe) { 116 case VG1: 117 mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE0__MASK | 118 MDP4_LAYERMIXER_IN_CFG_PIPE0_MIXER1); 119 mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE0(stage) | 120 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE0_MIXER1); 121 break; 122 case VG2: 123 mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE1__MASK | 124 MDP4_LAYERMIXER_IN_CFG_PIPE1_MIXER1); 125 mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE1(stage) | 126 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE1_MIXER1); 127 break; 128 case RGB1: 129 mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE2__MASK | 130 MDP4_LAYERMIXER_IN_CFG_PIPE2_MIXER1); 131 mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE2(stage) | 132 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE2_MIXER1); 133 break; 134 case RGB2: 135 mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE3__MASK | 136 MDP4_LAYERMIXER_IN_CFG_PIPE3_MIXER1); 137 mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE3(stage) | 138 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE3_MIXER1); 139 break; 140 case RGB3: 141 mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE4__MASK | 142 MDP4_LAYERMIXER_IN_CFG_PIPE4_MIXER1); 143 mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE4(stage) | 144 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE4_MIXER1); 145 break; 146 case VG3: 147 mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE5__MASK | 148 MDP4_LAYERMIXER_IN_CFG_PIPE5_MIXER1); 149 mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE5(stage) | 150 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE5_MIXER1); 151 break; 152 case VG4: 153 mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE6__MASK | 154 MDP4_LAYERMIXER_IN_CFG_PIPE6_MIXER1); 155 mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE6(stage) | 156 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE6_MIXER1); 157 break; 158 default: 159 WARN(1, "invalid pipe"); 160 break; 161 } 162 163 return mixer_cfg; 164 } 165 166 int mdp4_disable(struct mdp4_kms *mdp4_kms); 167 int mdp4_enable(struct mdp4_kms *mdp4_kms); 168 169 void mdp4_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask, 170 uint32_t old_irqmask); 171 void mdp4_irq_preinstall(struct msm_kms *kms); 172 int mdp4_irq_postinstall(struct msm_kms *kms); 173 void mdp4_irq_uninstall(struct msm_kms *kms); 174 irqreturn_t mdp4_irq(struct msm_kms *kms); 175 int mdp4_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc); 176 void mdp4_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc); 177 178 static inline uint32_t mdp4_pipe_caps(enum mdp4_pipe pipe) 179 { 180 switch (pipe) { 181 case VG1: 182 case VG2: 183 case VG3: 184 case VG4: 185 return MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP | 186 MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC; 187 case RGB1: 188 case RGB2: 189 case RGB3: 190 return MDP_PIPE_CAP_SCALE; 191 default: 192 return 0; 193 } 194 } 195 196 enum mdp4_pipe mdp4_plane_pipe(struct drm_plane *plane); 197 struct drm_plane *mdp4_plane_init(struct drm_device *dev, 198 enum mdp4_pipe pipe_id, bool private_plane); 199 200 uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc); 201 void mdp4_crtc_set_config(struct drm_crtc *crtc, uint32_t config); 202 void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf, int mixer); 203 void mdp4_crtc_wait_for_commit_done(struct drm_crtc *crtc); 204 struct drm_crtc *mdp4_crtc_init(struct drm_device *dev, 205 struct drm_plane *plane, int id, int ovlp_id, 206 enum mdp4_dma dma_id); 207 208 long mdp4_dtv_round_pixclk(struct drm_encoder *encoder, unsigned long rate); 209 struct drm_encoder *mdp4_dtv_encoder_init(struct drm_device *dev); 210 211 long mdp4_lcdc_round_pixclk(struct drm_encoder *encoder, unsigned long rate); 212 struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev, 213 struct device_node *panel_node); 214 215 struct drm_connector *mdp4_lvds_connector_init(struct drm_device *dev, 216 struct device_node *panel_node, struct drm_encoder *encoder); 217 218 #ifdef CONFIG_DRM_MSM_DSI 219 struct drm_encoder *mdp4_dsi_encoder_init(struct drm_device *dev); 220 #else 221 static inline struct drm_encoder *mdp4_dsi_encoder_init(struct drm_device *dev) 222 { 223 return ERR_PTR(-ENODEV); 224 } 225 #endif 226 227 #ifdef CONFIG_COMMON_CLK 228 struct clk *mpd4_lvds_pll_init(struct drm_device *dev); 229 #else 230 static inline struct clk *mpd4_lvds_pll_init(struct drm_device *dev) 231 { 232 return ERR_PTR(-ENODEV); 233 } 234 #endif 235 236 #ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING 237 /* bus scaling data is associated with extra pointless platform devices, 238 * "dtv", etc.. this is a bit of a hack, but we need a way for encoders 239 * to find their pdata to make the bus-scaling stuff work. 240 */ 241 static inline void *mdp4_find_pdata(const char *devname) 242 { 243 struct device *dev; 244 dev = bus_find_device_by_name(&platform_bus_type, NULL, devname); 245 return dev ? dev->platform_data : NULL; 246 } 247 #endif 248 249 #endif /* __MDP4_KMS_H__ */ 250