1 /* SPDX-License-Identifier: GPL-2.0-only */
3 * Copyright (C) 2013 Red Hat
4 * Author: Rob Clark <robdclark@gmail.com>
12 #include "disp/mdp_kms.h"
13 #include "mdp5_cfg.h" /* must be included before mdp5.xml.h */
15 #include "mdp5_pipe.h"
16 #include "mdp5_mixer.h"
23 struct drm_device
*dev
;
25 struct platform_device
*pdev
;
28 struct mdp5_hw_pipe
*hwpipes
[SSPP_MAX
];
30 unsigned num_hwmixers
;
31 struct mdp5_hw_mixer
*hwmixers
[8];
34 struct mdp5_interface
*intfs
[5];
36 struct mdp5_cfg_handler
*cfg
;
37 uint32_t caps
; /* MDP capabilities (MDP_CAP_XXX bits) */
40 * Global private object state, Do not access directly, use
41 * mdp5_global_get_state()
43 struct drm_modeset_lock glob_state_lock
;
44 struct drm_private_obj glob_state
;
47 struct mdp5_ctl_manager
*ctlm
;
49 /* io/register spaces: */
57 struct clk
*tbu_rt_clk
;
58 struct clk
*vsync_clk
;
61 * lock to protect access to global resources: ie., following register:
62 * - REG_MDP5_DISP_INTF_SEL
64 spinlock_t resource_lock
;
68 struct mdp_irq error_handler
;
72 #define to_mdp5_kms(x) container_of(x, struct mdp5_kms, base)
74 /* Global private object state for tracking resources that are shared across
75 * multiple kms objects (planes/crtcs/etc).
77 #define to_mdp5_global_state(x) container_of(x, struct mdp5_global_state, base)
78 struct mdp5_global_state
{
79 struct drm_private_state base
;
81 struct drm_atomic_state
*state
;
82 struct mdp5_kms
*mdp5_kms
;
84 struct mdp5_hw_pipe_state hwpipe
;
85 struct mdp5_hw_mixer_state hwmixer
;
86 struct mdp5_smp_state smp
;
89 struct mdp5_global_state
* mdp5_get_existing_global_state(struct mdp5_kms
*mdp5_kms
);
90 struct mdp5_global_state
*__must_check
mdp5_get_global_state(struct drm_atomic_state
*s
);
92 /* Atomic plane state. Subclasses the base drm_plane_state in order to
93 * track assigned hwpipe and hw specific state.
95 struct mdp5_plane_state
{
96 struct drm_plane_state base
;
98 struct mdp5_hw_pipe
*hwpipe
;
99 struct mdp5_hw_pipe
*r_hwpipe
; /* right hwpipe */
101 /* aligned with property */
102 uint8_t premultiplied
;
106 /* assigned by crtc blender */
107 enum mdp_mixer_stage_id stage
;
109 #define to_mdp5_plane_state(x) \
110 container_of(x, struct mdp5_plane_state, base)
112 struct mdp5_pipeline
{
113 struct mdp5_interface
*intf
;
114 struct mdp5_hw_mixer
*mixer
;
115 struct mdp5_hw_mixer
*r_mixer
; /* right mixer */
118 struct mdp5_crtc_state
{
119 struct drm_crtc_state base
;
121 struct mdp5_ctl
*ctl
;
122 struct mdp5_pipeline pipeline
;
124 /* these are derivatives of intf/mixer state in mdp5_pipeline */
131 /* should we not write CTL[n].START register on flush? If the
132 * encoder has changed this is set to true, since encoder->enable()
133 * is called after crtc state is committed, but we only want to
134 * write the CTL[n].START register once. This lets us defer
135 * writing CTL[n].START until encoder->enable()
139 #define to_mdp5_crtc_state(x) \
140 container_of(x, struct mdp5_crtc_state, base)
142 enum mdp5_intf_mode
{
143 MDP5_INTF_MODE_NONE
= 0,
145 /* Modes used for DSI interface (INTF_DSI type): */
146 MDP5_INTF_DSI_MODE_VIDEO
,
147 MDP5_INTF_DSI_MODE_COMMAND
,
149 /* Modes used for WB interface (INTF_WB type): */
150 MDP5_INTF_WB_MODE_BLOCK
,
151 MDP5_INTF_WB_MODE_LINE
,
154 struct mdp5_interface
{
156 int num
; /* display interface number */
157 enum mdp5_intf_type type
;
158 enum mdp5_intf_mode mode
;
161 struct mdp5_encoder
{
162 struct drm_encoder base
;
163 spinlock_t intf_lock
; /* protect REG_MDP5_INTF_* registers */
167 struct mdp5_interface
*intf
;
168 struct mdp5_ctl
*ctl
;
170 #define to_mdp5_encoder(x) container_of(x, struct mdp5_encoder, base)
172 static inline void mdp5_write(struct mdp5_kms
*mdp5_kms
, u32 reg
, u32 data
)
174 WARN_ON(mdp5_kms
->enable_count
<= 0);
175 msm_writel(data
, mdp5_kms
->mmio
+ reg
);
178 static inline u32
mdp5_read(struct mdp5_kms
*mdp5_kms
, u32 reg
)
180 WARN_ON(mdp5_kms
->enable_count
<= 0);
181 return msm_readl(mdp5_kms
->mmio
+ reg
);
184 static inline const char *stage2name(enum mdp_mixer_stage_id stage
)
186 static const char *names
[] = {
187 #define NAME(n) [n] = #n
188 NAME(STAGE_UNUSED
), NAME(STAGE_BASE
),
189 NAME(STAGE0
), NAME(STAGE1
), NAME(STAGE2
),
190 NAME(STAGE3
), NAME(STAGE4
), NAME(STAGE6
),
196 static inline const char *pipe2name(enum mdp5_pipe pipe
)
198 static const char *names
[] = {
199 #define NAME(n) [SSPP_ ## n] = #n
200 NAME(VIG0
), NAME(VIG1
), NAME(VIG2
),
201 NAME(RGB0
), NAME(RGB1
), NAME(RGB2
),
202 NAME(DMA0
), NAME(DMA1
),
203 NAME(VIG3
), NAME(RGB3
),
204 NAME(CURSOR0
), NAME(CURSOR1
),
210 static inline int pipe2nclients(enum mdp5_pipe pipe
)
223 static inline uint32_t intf2err(int intf_num
)
226 case 0: return MDP5_IRQ_INTF0_UNDER_RUN
;
227 case 1: return MDP5_IRQ_INTF1_UNDER_RUN
;
228 case 2: return MDP5_IRQ_INTF2_UNDER_RUN
;
229 case 3: return MDP5_IRQ_INTF3_UNDER_RUN
;
234 static inline uint32_t intf2vblank(struct mdp5_hw_mixer
*mixer
,
235 struct mdp5_interface
*intf
)
238 * In case of DSI Command Mode, the Ping Pong's read pointer IRQ
239 * acts as a Vblank signal. The Ping Pong buffer used is bound to
243 if ((intf
->type
== INTF_DSI
) &&
244 (intf
->mode
== MDP5_INTF_DSI_MODE_COMMAND
))
245 return MDP5_IRQ_PING_PONG_0_RD_PTR
<< mixer
->pp
;
247 if (intf
->type
== INTF_WB
)
248 return MDP5_IRQ_WB_2_DONE
;
251 case 0: return MDP5_IRQ_INTF0_VSYNC
;
252 case 1: return MDP5_IRQ_INTF1_VSYNC
;
253 case 2: return MDP5_IRQ_INTF2_VSYNC
;
254 case 3: return MDP5_IRQ_INTF3_VSYNC
;
259 static inline uint32_t lm2ppdone(struct mdp5_hw_mixer
*mixer
)
261 return MDP5_IRQ_PING_PONG_0_DONE
<< mixer
->pp
;
264 void mdp5_set_irqmask(struct mdp_kms
*mdp_kms
, uint32_t irqmask
,
265 uint32_t old_irqmask
);
266 void mdp5_irq_preinstall(struct msm_kms
*kms
);
267 int mdp5_irq_postinstall(struct msm_kms
*kms
);
268 void mdp5_irq_uninstall(struct msm_kms
*kms
);
269 irqreturn_t
mdp5_irq(struct msm_kms
*kms
);
270 int mdp5_enable_vblank(struct msm_kms
*kms
, struct drm_crtc
*crtc
);
271 void mdp5_disable_vblank(struct msm_kms
*kms
, struct drm_crtc
*crtc
);
272 int mdp5_irq_domain_init(struct mdp5_kms
*mdp5_kms
);
273 void mdp5_irq_domain_fini(struct mdp5_kms
*mdp5_kms
);
275 uint32_t mdp5_plane_get_flush(struct drm_plane
*plane
);
276 enum mdp5_pipe
mdp5_plane_pipe(struct drm_plane
*plane
);
277 enum mdp5_pipe
mdp5_plane_right_pipe(struct drm_plane
*plane
);
278 struct drm_plane
*mdp5_plane_init(struct drm_device
*dev
,
279 enum drm_plane_type type
);
281 struct mdp5_ctl
*mdp5_crtc_get_ctl(struct drm_crtc
*crtc
);
282 uint32_t mdp5_crtc_vblank(struct drm_crtc
*crtc
);
284 struct mdp5_hw_mixer
*mdp5_crtc_get_mixer(struct drm_crtc
*crtc
);
285 struct mdp5_pipeline
*mdp5_crtc_get_pipeline(struct drm_crtc
*crtc
);
286 void mdp5_crtc_set_pipeline(struct drm_crtc
*crtc
);
287 void mdp5_crtc_wait_for_commit_done(struct drm_crtc
*crtc
);
288 struct drm_crtc
*mdp5_crtc_init(struct drm_device
*dev
,
289 struct drm_plane
*plane
,
290 struct drm_plane
*cursor_plane
, int id
);
292 struct drm_encoder
*mdp5_encoder_init(struct drm_device
*dev
,
293 struct mdp5_interface
*intf
, struct mdp5_ctl
*ctl
);
294 int mdp5_vid_encoder_set_split_display(struct drm_encoder
*encoder
,
295 struct drm_encoder
*slave_encoder
);
296 void mdp5_encoder_set_intf_mode(struct drm_encoder
*encoder
, bool cmd_mode
);
297 int mdp5_encoder_get_linecount(struct drm_encoder
*encoder
);
298 u32
mdp5_encoder_get_framecount(struct drm_encoder
*encoder
);
300 #ifdef CONFIG_DRM_MSM_DSI
301 void mdp5_cmd_encoder_mode_set(struct drm_encoder
*encoder
,
302 struct drm_display_mode
*mode
,
303 struct drm_display_mode
*adjusted_mode
);
304 void mdp5_cmd_encoder_disable(struct drm_encoder
*encoder
);
305 void mdp5_cmd_encoder_enable(struct drm_encoder
*encoder
);
306 int mdp5_cmd_encoder_set_split_display(struct drm_encoder
*encoder
,
307 struct drm_encoder
*slave_encoder
);
309 static inline void mdp5_cmd_encoder_mode_set(struct drm_encoder
*encoder
,
310 struct drm_display_mode
*mode
,
311 struct drm_display_mode
*adjusted_mode
)
314 static inline void mdp5_cmd_encoder_disable(struct drm_encoder
*encoder
)
317 static inline void mdp5_cmd_encoder_enable(struct drm_encoder
*encoder
)
320 static inline int mdp5_cmd_encoder_set_split_display(
321 struct drm_encoder
*encoder
, struct drm_encoder
*slave_encoder
)
327 #endif /* __MDP5_KMS_H__ */