2 * Copyright (C) 2013 Red Hat
3 * Author: Rob Clark <robdclark@gmail.com>
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.
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
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/>.
18 #ifndef __MDP5_KMS_H__
19 #define __MDP5_KMS_H__
23 #include "disp/mdp_kms.h"
24 #include "mdp5_cfg.h" /* must be included before mdp5.xml.h */
26 #include "mdp5_pipe.h"
27 #include "mdp5_mixer.h"
34 struct drm_device
*dev
;
36 struct platform_device
*pdev
;
39 struct mdp5_hw_pipe
*hwpipes
[SSPP_MAX
];
41 unsigned num_hwmixers
;
42 struct mdp5_hw_mixer
*hwmixers
[8];
45 struct mdp5_interface
*intfs
[5];
47 struct mdp5_cfg_handler
*cfg
;
48 uint32_t caps
; /* MDP capabilities (MDP_CAP_XXX bits) */
51 * Global private object state, Do not access directly, use
52 * mdp5_global_get_state()
54 struct drm_modeset_lock glob_state_lock
;
55 struct drm_private_obj glob_state
;
58 struct mdp5_ctl_manager
*ctlm
;
60 /* io/register spaces: */
67 struct clk
*vsync_clk
;
70 * lock to protect access to global resources: ie., following register:
71 * - REG_MDP5_DISP_INTF_SEL
73 spinlock_t resource_lock
;
77 struct mdp_irq error_handler
;
81 #define to_mdp5_kms(x) container_of(x, struct mdp5_kms, base)
83 /* Global private object state for tracking resources that are shared across
84 * multiple kms objects (planes/crtcs/etc).
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
;
90 struct drm_atomic_state
*state
;
91 struct mdp5_kms
*mdp5_kms
;
93 struct mdp5_hw_pipe_state hwpipe
;
94 struct mdp5_hw_mixer_state hwmixer
;
95 struct mdp5_smp_state smp
;
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
);
101 /* Atomic plane state. Subclasses the base drm_plane_state in order to
102 * track assigned hwpipe and hw specific state.
104 struct mdp5_plane_state
{
105 struct drm_plane_state base
;
107 struct mdp5_hw_pipe
*hwpipe
;
108 struct mdp5_hw_pipe
*r_hwpipe
; /* right hwpipe */
110 /* aligned with property */
111 uint8_t premultiplied
;
115 /* assigned by crtc blender */
116 enum mdp_mixer_stage_id stage
;
118 #define to_mdp5_plane_state(x) \
119 container_of(x, struct mdp5_plane_state, base)
121 struct mdp5_pipeline
{
122 struct mdp5_interface
*intf
;
123 struct mdp5_hw_mixer
*mixer
;
124 struct mdp5_hw_mixer
*r_mixer
; /* right mixer */
127 struct mdp5_crtc_state
{
128 struct drm_crtc_state base
;
130 struct mdp5_ctl
*ctl
;
131 struct mdp5_pipeline pipeline
;
133 /* these are derivatives of intf/mixer state in mdp5_pipeline */
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()
148 #define to_mdp5_crtc_state(x) \
149 container_of(x, struct mdp5_crtc_state, base)
151 enum mdp5_intf_mode
{
152 MDP5_INTF_MODE_NONE
= 0,
154 /* Modes used for DSI interface (INTF_DSI type): */
155 MDP5_INTF_DSI_MODE_VIDEO
,
156 MDP5_INTF_DSI_MODE_COMMAND
,
158 /* Modes used for WB interface (INTF_WB type): */
159 MDP5_INTF_WB_MODE_BLOCK
,
160 MDP5_INTF_WB_MODE_LINE
,
163 struct mdp5_interface
{
165 int num
; /* display interface number */
166 enum mdp5_intf_type type
;
167 enum mdp5_intf_mode mode
;
170 struct mdp5_encoder
{
171 struct drm_encoder base
;
172 spinlock_t intf_lock
; /* protect REG_MDP5_INTF_* registers */
176 struct mdp5_interface
*intf
;
177 struct mdp5_ctl
*ctl
;
179 #define to_mdp5_encoder(x) container_of(x, struct mdp5_encoder, base)
181 static inline void mdp5_write(struct mdp5_kms
*mdp5_kms
, u32 reg
, u32 data
)
183 WARN_ON(mdp5_kms
->enable_count
<= 0);
184 msm_writel(data
, mdp5_kms
->mmio
+ reg
);
187 static inline u32
mdp5_read(struct mdp5_kms
*mdp5_kms
, u32 reg
)
189 WARN_ON(mdp5_kms
->enable_count
<= 0);
190 return msm_readl(mdp5_kms
->mmio
+ reg
);
193 static inline const char *stage2name(enum mdp_mixer_stage_id stage
)
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
),
205 static inline const char *pipe2name(enum mdp5_pipe pipe
)
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
),
219 static inline int pipe2nclients(enum mdp5_pipe pipe
)
232 static inline uint32_t intf2err(int 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
;
243 static inline uint32_t intf2vblank(struct mdp5_hw_mixer
*mixer
,
244 struct mdp5_interface
*intf
)
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
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
;
256 if (intf
->type
== INTF_WB
)
257 return MDP5_IRQ_WB_2_DONE
;
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
;
268 static inline uint32_t lm2ppdone(struct mdp5_hw_mixer
*mixer
)
270 return MDP5_IRQ_PING_PONG_0_DONE
<< mixer
->pp
;
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
);
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
);
290 struct mdp5_ctl
*mdp5_crtc_get_ctl(struct drm_crtc
*crtc
);
291 uint32_t mdp5_crtc_vblank(struct drm_crtc
*crtc
);
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
);
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
);
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
);
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
)
323 static inline void mdp5_cmd_encoder_disable(struct drm_encoder
*encoder
)
326 static inline void mdp5_cmd_encoder_enable(struct drm_encoder
*encoder
)
329 static inline int mdp5_cmd_encoder_set_split_display(
330 struct drm_encoder
*encoder
, struct drm_encoder
*slave_encoder
)
336 #endif /* __MDP5_KMS_H__ */