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 __MDP5_KMS_H__ 19 #define __MDP5_KMS_H__ 20 21 #include "msm_drv.h" 22 #include "msm_kms.h" 23 #include "disp/mdp_kms.h" 24 #include "mdp5_cfg.h" /* must be included before mdp5.xml.h */ 25 #include "mdp5.xml.h" 26 #include "mdp5_pipe.h" 27 #include "mdp5_mixer.h" 28 #include "mdp5_ctl.h" 29 #include "mdp5_smp.h" 30 31 struct mdp5_kms { 32 struct mdp_kms base; 33 34 struct drm_device *dev; 35 36 struct platform_device *pdev; 37 38 unsigned num_hwpipes; 39 struct mdp5_hw_pipe *hwpipes[SSPP_MAX]; 40 41 unsigned num_hwmixers; 42 struct mdp5_hw_mixer *hwmixers[8]; 43 44 unsigned num_intfs; 45 struct mdp5_interface *intfs[5]; 46 47 struct mdp5_cfg_handler *cfg; 48 uint32_t caps; /* MDP capabilities (MDP_CAP_XXX bits) */ 49 50 /* 51 * Global private object state, Do not access directly, use 52 * mdp5_global_get_state() 53 */ 54 struct drm_modeset_lock glob_state_lock; 55 struct drm_private_obj glob_state; 56 57 struct mdp5_smp *smp; 58 struct mdp5_ctl_manager *ctlm; 59 60 /* io/register spaces: */ 61 void __iomem *mmio; 62 63 struct clk *axi_clk; 64 struct clk *ahb_clk; 65 struct clk *core_clk; 66 struct clk *lut_clk; 67 struct clk *vsync_clk; 68 69 /* 70 * lock to protect access to global resources: ie., following register: 71 * - REG_MDP5_DISP_INTF_SEL 72 */ 73 spinlock_t resource_lock; 74 75 bool rpm_enabled; 76 77 struct mdp_irq error_handler; 78 79 int enable_count; 80 }; 81 #define to_mdp5_kms(x) container_of(x, struct mdp5_kms, base) 82 83 /* Global private object state for tracking resources that are shared across 84 * multiple kms objects (planes/crtcs/etc). 85 */ 86 #define to_mdp5_global_state(x) container_of(x, struct mdp5_global_state, base) 87 struct mdp5_global_state { 88 struct drm_private_state base; 89 90 struct drm_atomic_state *state; 91 struct mdp5_kms *mdp5_kms; 92 93 struct mdp5_hw_pipe_state hwpipe; 94 struct mdp5_hw_mixer_state hwmixer; 95 struct mdp5_smp_state smp; 96 }; 97 98 struct mdp5_global_state * mdp5_get_existing_global_state(struct mdp5_kms *mdp5_kms); 99 struct mdp5_global_state *__must_check mdp5_get_global_state(struct drm_atomic_state *s); 100 101 /* Atomic plane state. Subclasses the base drm_plane_state in order to 102 * track assigned hwpipe and hw specific state. 103 */ 104 struct mdp5_plane_state { 105 struct drm_plane_state base; 106 107 struct mdp5_hw_pipe *hwpipe; 108 struct mdp5_hw_pipe *r_hwpipe; /* right hwpipe */ 109 110 /* aligned with property */ 111 uint8_t premultiplied; 112 uint8_t zpos; 113 uint8_t alpha; 114 115 /* assigned by crtc blender */ 116 enum mdp_mixer_stage_id stage; 117 }; 118 #define to_mdp5_plane_state(x) \ 119 container_of(x, struct mdp5_plane_state, base) 120 121 struct mdp5_pipeline { 122 struct mdp5_interface *intf; 123 struct mdp5_hw_mixer *mixer; 124 struct mdp5_hw_mixer *r_mixer; /* right mixer */ 125 }; 126 127 struct mdp5_crtc_state { 128 struct drm_crtc_state base; 129 130 struct mdp5_ctl *ctl; 131 struct mdp5_pipeline pipeline; 132 133 /* these are derivatives of intf/mixer state in mdp5_pipeline */ 134 u32 vblank_irqmask; 135 u32 err_irqmask; 136 u32 pp_done_irqmask; 137 138 bool cmd_mode; 139 140 /* should we not write CTL[n].START register on flush? If the 141 * encoder has changed this is set to true, since encoder->enable() 142 * is called after crtc state is committed, but we only want to 143 * write the CTL[n].START register once. This lets us defer 144 * writing CTL[n].START until encoder->enable() 145 */ 146 bool defer_start; 147 }; 148 #define to_mdp5_crtc_state(x) \ 149 container_of(x, struct mdp5_crtc_state, base) 150 151 enum mdp5_intf_mode { 152 MDP5_INTF_MODE_NONE = 0, 153 154 /* Modes used for DSI interface (INTF_DSI type): */ 155 MDP5_INTF_DSI_MODE_VIDEO, 156 MDP5_INTF_DSI_MODE_COMMAND, 157 158 /* Modes used for WB interface (INTF_WB type): */ 159 MDP5_INTF_WB_MODE_BLOCK, 160 MDP5_INTF_WB_MODE_LINE, 161 }; 162 163 struct mdp5_interface { 164 int idx; 165 int num; /* display interface number */ 166 enum mdp5_intf_type type; 167 enum mdp5_intf_mode mode; 168 }; 169 170 struct mdp5_encoder { 171 struct drm_encoder base; 172 spinlock_t intf_lock; /* protect REG_MDP5_INTF_* registers */ 173 bool enabled; 174 uint32_t bsc; 175 176 struct mdp5_interface *intf; 177 struct mdp5_ctl *ctl; 178 }; 179 #define to_mdp5_encoder(x) container_of(x, struct mdp5_encoder, base) 180 181 static inline void mdp5_write(struct mdp5_kms *mdp5_kms, u32 reg, u32 data) 182 { 183 WARN_ON(mdp5_kms->enable_count <= 0); 184 msm_writel(data, mdp5_kms->mmio + reg); 185 } 186 187 static inline u32 mdp5_read(struct mdp5_kms *mdp5_kms, u32 reg) 188 { 189 WARN_ON(mdp5_kms->enable_count <= 0); 190 return msm_readl(mdp5_kms->mmio + reg); 191 } 192 193 static inline const char *stage2name(enum mdp_mixer_stage_id stage) 194 { 195 static const char *names[] = { 196 #define NAME(n) [n] = #n 197 NAME(STAGE_UNUSED), NAME(STAGE_BASE), 198 NAME(STAGE0), NAME(STAGE1), NAME(STAGE2), 199 NAME(STAGE3), NAME(STAGE4), NAME(STAGE6), 200 #undef NAME 201 }; 202 return names[stage]; 203 } 204 205 static inline const char *pipe2name(enum mdp5_pipe pipe) 206 { 207 static const char *names[] = { 208 #define NAME(n) [SSPP_ ## n] = #n 209 NAME(VIG0), NAME(VIG1), NAME(VIG2), 210 NAME(RGB0), NAME(RGB1), NAME(RGB2), 211 NAME(DMA0), NAME(DMA1), 212 NAME(VIG3), NAME(RGB3), 213 NAME(CURSOR0), NAME(CURSOR1), 214 #undef NAME 215 }; 216 return names[pipe]; 217 } 218 219 static inline int pipe2nclients(enum mdp5_pipe pipe) 220 { 221 switch (pipe) { 222 case SSPP_RGB0: 223 case SSPP_RGB1: 224 case SSPP_RGB2: 225 case SSPP_RGB3: 226 return 1; 227 default: 228 return 3; 229 } 230 } 231 232 static inline uint32_t intf2err(int intf_num) 233 { 234 switch (intf_num) { 235 case 0: return MDP5_IRQ_INTF0_UNDER_RUN; 236 case 1: return MDP5_IRQ_INTF1_UNDER_RUN; 237 case 2: return MDP5_IRQ_INTF2_UNDER_RUN; 238 case 3: return MDP5_IRQ_INTF3_UNDER_RUN; 239 default: return 0; 240 } 241 } 242 243 static inline uint32_t intf2vblank(struct mdp5_hw_mixer *mixer, 244 struct mdp5_interface *intf) 245 { 246 /* 247 * In case of DSI Command Mode, the Ping Pong's read pointer IRQ 248 * acts as a Vblank signal. The Ping Pong buffer used is bound to 249 * layer mixer. 250 */ 251 252 if ((intf->type == INTF_DSI) && 253 (intf->mode == MDP5_INTF_DSI_MODE_COMMAND)) 254 return MDP5_IRQ_PING_PONG_0_RD_PTR << mixer->pp; 255 256 if (intf->type == INTF_WB) 257 return MDP5_IRQ_WB_2_DONE; 258 259 switch (intf->num) { 260 case 0: return MDP5_IRQ_INTF0_VSYNC; 261 case 1: return MDP5_IRQ_INTF1_VSYNC; 262 case 2: return MDP5_IRQ_INTF2_VSYNC; 263 case 3: return MDP5_IRQ_INTF3_VSYNC; 264 default: return 0; 265 } 266 } 267 268 static inline uint32_t lm2ppdone(struct mdp5_hw_mixer *mixer) 269 { 270 return MDP5_IRQ_PING_PONG_0_DONE << mixer->pp; 271 } 272 273 void mdp5_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask, 274 uint32_t old_irqmask); 275 void mdp5_irq_preinstall(struct msm_kms *kms); 276 int mdp5_irq_postinstall(struct msm_kms *kms); 277 void mdp5_irq_uninstall(struct msm_kms *kms); 278 irqreturn_t mdp5_irq(struct msm_kms *kms); 279 int mdp5_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc); 280 void mdp5_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc); 281 int mdp5_irq_domain_init(struct mdp5_kms *mdp5_kms); 282 void mdp5_irq_domain_fini(struct mdp5_kms *mdp5_kms); 283 284 uint32_t mdp5_plane_get_flush(struct drm_plane *plane); 285 enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane); 286 enum mdp5_pipe mdp5_plane_right_pipe(struct drm_plane *plane); 287 struct drm_plane *mdp5_plane_init(struct drm_device *dev, 288 enum drm_plane_type type); 289 290 struct mdp5_ctl *mdp5_crtc_get_ctl(struct drm_crtc *crtc); 291 uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc); 292 293 struct mdp5_hw_mixer *mdp5_crtc_get_mixer(struct drm_crtc *crtc); 294 struct mdp5_pipeline *mdp5_crtc_get_pipeline(struct drm_crtc *crtc); 295 void mdp5_crtc_set_pipeline(struct drm_crtc *crtc); 296 void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc); 297 struct drm_crtc *mdp5_crtc_init(struct drm_device *dev, 298 struct drm_plane *plane, 299 struct drm_plane *cursor_plane, int id); 300 301 struct drm_encoder *mdp5_encoder_init(struct drm_device *dev, 302 struct mdp5_interface *intf, struct mdp5_ctl *ctl); 303 int mdp5_vid_encoder_set_split_display(struct drm_encoder *encoder, 304 struct drm_encoder *slave_encoder); 305 void mdp5_encoder_set_intf_mode(struct drm_encoder *encoder, bool cmd_mode); 306 int mdp5_encoder_get_linecount(struct drm_encoder *encoder); 307 u32 mdp5_encoder_get_framecount(struct drm_encoder *encoder); 308 309 #ifdef CONFIG_DRM_MSM_DSI 310 void mdp5_cmd_encoder_mode_set(struct drm_encoder *encoder, 311 struct drm_display_mode *mode, 312 struct drm_display_mode *adjusted_mode); 313 void mdp5_cmd_encoder_disable(struct drm_encoder *encoder); 314 void mdp5_cmd_encoder_enable(struct drm_encoder *encoder); 315 int mdp5_cmd_encoder_set_split_display(struct drm_encoder *encoder, 316 struct drm_encoder *slave_encoder); 317 #else 318 static inline void mdp5_cmd_encoder_mode_set(struct drm_encoder *encoder, 319 struct drm_display_mode *mode, 320 struct drm_display_mode *adjusted_mode) 321 { 322 } 323 static inline void mdp5_cmd_encoder_disable(struct drm_encoder *encoder) 324 { 325 } 326 static inline void mdp5_cmd_encoder_enable(struct drm_encoder *encoder) 327 { 328 } 329 static inline int mdp5_cmd_encoder_set_split_display( 330 struct drm_encoder *encoder, struct drm_encoder *slave_encoder) 331 { 332 return -EINVAL; 333 } 334 #endif 335 336 #endif /* __MDP5_KMS_H__ */ 337