Commit 389b09a1 authored by Stephane Viau's avatar Stephane Viau Committed by Rob Clark

drm/msm/mdp5: Add START signal to kick off certain pipelines

Some interfaces (WB, DSI Command Mode) need to be kicked off
through a START Signal. This signal needs to be sent at the right
time and requests in some cases to keep track of the pipeline
status (eg: whether pipeline registers are flushed AND output WB
buffers are ready, in case of WB interface).
Signed-off-by: default avatarStephane Viau <sviau@codeaurora.org>
Signed-off-by: default avatarRob Clark <robdclark@gmail.com>
parent d145dd78
...@@ -31,6 +31,7 @@ const struct mdp5_cfg_hw msm8x74_config = { ...@@ -31,6 +31,7 @@ const struct mdp5_cfg_hw msm8x74_config = {
.ctl = { .ctl = {
.count = 5, .count = 5,
.base = { 0x00600, 0x00700, 0x00800, 0x00900, 0x00a00 }, .base = { 0x00600, 0x00700, 0x00800, 0x00900, 0x00a00 },
.flush_hw_mask = 0x0003ffff,
}, },
.pipe_vig = { .pipe_vig = {
.count = 3, .count = 3,
...@@ -78,6 +79,7 @@ const struct mdp5_cfg_hw apq8084_config = { ...@@ -78,6 +79,7 @@ const struct mdp5_cfg_hw apq8084_config = {
.ctl = { .ctl = {
.count = 5, .count = 5,
.base = { 0x00600, 0x00700, 0x00800, 0x00900, 0x00a00 }, .base = { 0x00600, 0x00700, 0x00800, 0x00900, 0x00a00 },
.flush_hw_mask = 0x003fffff,
}, },
.pipe_vig = { .pipe_vig = {
.count = 4, .count = 4,
......
...@@ -44,6 +44,11 @@ struct mdp5_lm_block { ...@@ -44,6 +44,11 @@ struct mdp5_lm_block {
uint32_t nb_stages; /* number of stages per blender */ uint32_t nb_stages; /* number of stages per blender */
}; };
struct mdp5_ctl_block {
MDP5_SUB_BLOCK_DEFINITION;
uint32_t flush_hw_mask; /* FLUSH register's hardware mask */
};
struct mdp5_smp_block { struct mdp5_smp_block {
int mmb_count; /* number of SMP MMBs */ int mmb_count; /* number of SMP MMBs */
int mmb_size; /* MMB: size in bytes */ int mmb_size; /* MMB: size in bytes */
...@@ -55,7 +60,7 @@ struct mdp5_cfg_hw { ...@@ -55,7 +60,7 @@ struct mdp5_cfg_hw {
char *name; char *name;
struct mdp5_smp_block smp; struct mdp5_smp_block smp;
struct mdp5_sub_block ctl; struct mdp5_ctl_block ctl;
struct mdp5_sub_block pipe_vig; struct mdp5_sub_block pipe_vig;
struct mdp5_sub_block pipe_rgb; struct mdp5_sub_block pipe_rgb;
struct mdp5_sub_block pipe_dma; struct mdp5_sub_block pipe_dma;
......
...@@ -82,8 +82,6 @@ static void request_pending(struct drm_crtc *crtc, uint32_t pending) ...@@ -82,8 +82,6 @@ static void request_pending(struct drm_crtc *crtc, uint32_t pending)
mdp_irq_register(&get_kms(crtc)->base, &mdp5_crtc->vblank); mdp_irq_register(&get_kms(crtc)->base, &mdp5_crtc->vblank);
} }
#define mdp5_lm_get_flush(lm) mdp_ctl_flush_mask_lm(lm)
static void crtc_flush(struct drm_crtc *crtc, u32 flush_mask) static void crtc_flush(struct drm_crtc *crtc, u32 flush_mask)
{ {
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
...@@ -110,8 +108,8 @@ static void crtc_flush_all(struct drm_crtc *crtc) ...@@ -110,8 +108,8 @@ static void crtc_flush_all(struct drm_crtc *crtc)
drm_atomic_crtc_for_each_plane(plane, crtc) { drm_atomic_crtc_for_each_plane(plane, crtc) {
flush_mask |= mdp5_plane_get_flush(plane); flush_mask |= mdp5_plane_get_flush(plane);
} }
flush_mask |= mdp5_ctl_get_flush(mdp5_crtc->ctl);
flush_mask |= mdp5_lm_get_flush(mdp5_crtc->lm); flush_mask |= mdp_ctl_flush_mask_lm(mdp5_crtc->lm);
crtc_flush(crtc, flush_mask); crtc_flush(crtc, flush_mask);
} }
...@@ -442,13 +440,14 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -442,13 +440,14 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct mdp5_kms *mdp5_kms = get_kms(crtc); struct mdp5_kms *mdp5_kms = get_kms(crtc);
struct drm_gem_object *cursor_bo, *old_bo; struct drm_gem_object *cursor_bo, *old_bo = NULL;
uint32_t blendcfg, cursor_addr, stride; uint32_t blendcfg, cursor_addr, stride;
int ret, bpp, lm; int ret, bpp, lm;
unsigned int depth; unsigned int depth;
enum mdp5_cursor_alpha cur_alpha = CURSOR_ALPHA_PER_PIXEL; enum mdp5_cursor_alpha cur_alpha = CURSOR_ALPHA_PER_PIXEL;
uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0); uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0);
uint32_t roi_w, roi_h; uint32_t roi_w, roi_h;
bool cursor_enable = true;
unsigned long flags; unsigned long flags;
if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) { if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) {
...@@ -461,7 +460,8 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -461,7 +460,8 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
if (!handle) { if (!handle) {
DBG("Cursor off"); DBG("Cursor off");
return mdp5_ctl_set_cursor(mdp5_crtc->ctl, false); cursor_enable = false;
goto set_cursor;
} }
cursor_bo = drm_gem_object_lookup(dev, file, handle); cursor_bo = drm_gem_object_lookup(dev, file, handle);
...@@ -502,11 +502,14 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -502,11 +502,14 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags); spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags);
ret = mdp5_ctl_set_cursor(mdp5_crtc->ctl, true); set_cursor:
if (ret) ret = mdp5_ctl_set_cursor(mdp5_crtc->ctl, 0, cursor_enable);
if (ret) {
dev_err(dev->dev, "failed to %sable cursor: %d\n",
cursor_enable ? "en" : "dis", ret);
goto end; goto end;
}
flush_mask |= mdp5_ctl_get_flush(mdp5_crtc->ctl);
crtc_flush(crtc, flush_mask); crtc_flush(crtc, flush_mask);
end: end:
...@@ -628,11 +631,13 @@ void mdp5_crtc_set_intf(struct drm_crtc *crtc, struct mdp5_interface *intf) ...@@ -628,11 +631,13 @@ void mdp5_crtc_set_intf(struct drm_crtc *crtc, struct mdp5_interface *intf)
int mdp5_crtc_get_lm(struct drm_crtc *crtc) int mdp5_crtc_get_lm(struct drm_crtc *crtc)
{ {
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
return WARN_ON(!crtc) ? -EINVAL : mdp5_crtc->lm;
}
if (WARN_ON(!crtc)) struct mdp5_ctl *mdp5_crtc_get_ctl(struct drm_crtc *crtc)
return -EINVAL; {
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
return mdp5_crtc->lm; return WARN_ON(!crtc) ? NULL : mdp5_crtc->ctl;
} }
/* initialize crtc */ /* initialize crtc */
......
This diff is collapsed.
...@@ -33,20 +33,13 @@ void mdp5_ctlm_destroy(struct mdp5_ctl_manager *ctlm); ...@@ -33,20 +33,13 @@ void mdp5_ctlm_destroy(struct mdp5_ctl_manager *ctlm);
* which is then used to call the other mdp5_ctl_*(ctl, ...) functions. * which is then used to call the other mdp5_ctl_*(ctl, ...) functions.
*/ */
struct mdp5_ctl *mdp5_ctlm_request(struct mdp5_ctl_manager *ctlm, struct drm_crtc *crtc); struct mdp5_ctl *mdp5_ctlm_request(struct mdp5_ctl_manager *ctlm, struct drm_crtc *crtc);
int mdp5_ctl_get_ctl_id(struct mdp5_ctl *ctl);
struct mdp5_interface; struct mdp5_interface;
int mdp5_ctl_set_intf(struct mdp5_ctl *ctl, struct mdp5_interface *intf); int mdp5_ctl_set_intf(struct mdp5_ctl *ctl, struct mdp5_interface *intf);
int mdp5_ctl_set_encoder_state(struct mdp5_ctl *ctl, bool enabled);
int mdp5_ctl_set_cursor(struct mdp5_ctl *ctl, bool enable); int mdp5_ctl_set_cursor(struct mdp5_ctl *ctl, int cursor_id, bool enable);
/* @blend_cfg: see LM blender config definition below */
int mdp5_ctl_blend(struct mdp5_ctl *ctl, u32 lm, u32 blend_cfg);
/* @flush_mask: see CTL flush masks definitions below */
int mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask);
u32 mdp5_ctl_get_flush(struct mdp5_ctl *ctl);
void mdp5_ctl_release(struct mdp5_ctl *ctl);
/* /*
* blend_cfg (LM blender config): * blend_cfg (LM blender config):
...@@ -73,51 +66,32 @@ static inline u32 mdp_ctl_blend_mask(enum mdp5_pipe pipe, ...@@ -73,51 +66,32 @@ static inline u32 mdp_ctl_blend_mask(enum mdp5_pipe pipe,
} }
/* /*
* flush_mask (CTL flush masks): * mdp5_ctl_blend() - Blend multiple layers on a Layer Mixer (LM)
* *
* The following functions allow each DRM entity to get and store * @blend_cfg: see LM blender config definition below
* their own flush mask. *
* Once stored, these masks will then be accessed through each DRM's * Note:
* interface and used by the caller of mdp5_ctl_commit() to specify * CTL registers need to be flushed after calling this function
* which block(s) need to be flushed through @flush_mask parameter. * (call mdp5_ctl_commit() with mdp_ctl_flush_mask_ctl() mask)
*/ */
int mdp5_ctl_blend(struct mdp5_ctl *ctl, u32 lm, u32 blend_cfg);
#define MDP5_CTL_FLUSH_CURSOR_DUMMY 0x80000000 /**
* mdp_ctl_flush_mask...() - Register FLUSH masks
*
* These masks are used to specify which block(s) need to be flushed
* through @flush_mask parameter in mdp5_ctl_commit(.., flush_mask).
*/
u32 mdp_ctl_flush_mask_lm(int lm);
u32 mdp_ctl_flush_mask_pipe(enum mdp5_pipe pipe);
u32 mdp_ctl_flush_mask_cursor(int cursor_id);
u32 mdp_ctl_flush_mask_encoder(struct mdp5_interface *intf);
static inline u32 mdp_ctl_flush_mask_cursor(int cursor_id) /* @flush_mask: see CTL flush masks definitions below */
{ int mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask);
/* TODO: use id once multiple cursor support is present */
(void)cursor_id;
return MDP5_CTL_FLUSH_CURSOR_DUMMY; void mdp5_ctl_release(struct mdp5_ctl *ctl);
}
static inline u32 mdp_ctl_flush_mask_lm(int lm)
{
switch (lm) {
case 0: return MDP5_CTL_FLUSH_LM0;
case 1: return MDP5_CTL_FLUSH_LM1;
case 2: return MDP5_CTL_FLUSH_LM2;
case 5: return MDP5_CTL_FLUSH_LM5;
default: return 0;
}
}
static inline u32 mdp_ctl_flush_mask_pipe(enum mdp5_pipe pipe)
{
switch (pipe) {
case SSPP_VIG0: return MDP5_CTL_FLUSH_VIG0;
case SSPP_VIG1: return MDP5_CTL_FLUSH_VIG1;
case SSPP_VIG2: return MDP5_CTL_FLUSH_VIG2;
case SSPP_RGB0: return MDP5_CTL_FLUSH_RGB0;
case SSPP_RGB1: return MDP5_CTL_FLUSH_RGB1;
case SSPP_RGB2: return MDP5_CTL_FLUSH_RGB2;
case SSPP_DMA0: return MDP5_CTL_FLUSH_DMA0;
case SSPP_DMA1: return MDP5_CTL_FLUSH_DMA1;
case SSPP_VIG3: return MDP5_CTL_FLUSH_VIG3;
case SSPP_RGB3: return MDP5_CTL_FLUSH_RGB3;
default: return 0;
}
}
#endif /* __MDP5_CTL_H__ */ #endif /* __MDP5_CTL_H__ */
...@@ -217,12 +217,15 @@ static void mdp5_encoder_mode_set(struct drm_encoder *encoder, ...@@ -217,12 +217,15 @@ static void mdp5_encoder_mode_set(struct drm_encoder *encoder,
mdp5_write(mdp5_kms, REG_MDP5_INTF_FRAME_LINE_COUNT_EN(intf), 0x3); /* frame+line? */ mdp5_write(mdp5_kms, REG_MDP5_INTF_FRAME_LINE_COUNT_EN(intf), 0x3); /* frame+line? */
spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags); spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);
mdp5_crtc_set_intf(encoder->crtc, &mdp5_encoder->intf);
} }
static void mdp5_encoder_disable(struct drm_encoder *encoder) static void mdp5_encoder_disable(struct drm_encoder *encoder)
{ {
struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
struct mdp5_kms *mdp5_kms = get_kms(encoder); struct mdp5_kms *mdp5_kms = get_kms(encoder);
struct mdp5_ctl *ctl = mdp5_crtc_get_ctl(encoder->crtc);
int lm = mdp5_crtc_get_lm(encoder->crtc); int lm = mdp5_crtc_get_lm(encoder->crtc);
struct mdp5_interface *intf = &mdp5_encoder->intf; struct mdp5_interface *intf = &mdp5_encoder->intf;
int intfn = mdp5_encoder->intf.num; int intfn = mdp5_encoder->intf.num;
...@@ -231,9 +234,12 @@ static void mdp5_encoder_disable(struct drm_encoder *encoder) ...@@ -231,9 +234,12 @@ static void mdp5_encoder_disable(struct drm_encoder *encoder)
if (WARN_ON(!mdp5_encoder->enabled)) if (WARN_ON(!mdp5_encoder->enabled))
return; return;
mdp5_ctl_set_encoder_state(ctl, false);
spin_lock_irqsave(&mdp5_encoder->intf_lock, flags); spin_lock_irqsave(&mdp5_encoder->intf_lock, flags);
mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intfn), 0); mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intfn), 0);
spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags); spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);
mdp5_ctl_commit(ctl, mdp_ctl_flush_mask_encoder(intf));
/* /*
* Wait for a vsync so we know the ENABLE=0 latched before * Wait for a vsync so we know the ENABLE=0 latched before
...@@ -254,18 +260,21 @@ static void mdp5_encoder_enable(struct drm_encoder *encoder) ...@@ -254,18 +260,21 @@ static void mdp5_encoder_enable(struct drm_encoder *encoder)
{ {
struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
struct mdp5_kms *mdp5_kms = get_kms(encoder); struct mdp5_kms *mdp5_kms = get_kms(encoder);
struct mdp5_ctl *ctl = mdp5_crtc_get_ctl(encoder->crtc);
struct mdp5_interface *intf = &mdp5_encoder->intf;
int intfn = mdp5_encoder->intf.num; int intfn = mdp5_encoder->intf.num;
unsigned long flags; unsigned long flags;
if (WARN_ON(mdp5_encoder->enabled)) if (WARN_ON(mdp5_encoder->enabled))
return; return;
mdp5_crtc_set_intf(encoder->crtc, &mdp5_encoder->intf);
bs_set(mdp5_encoder, 1); bs_set(mdp5_encoder, 1);
spin_lock_irqsave(&mdp5_encoder->intf_lock, flags); spin_lock_irqsave(&mdp5_encoder->intf_lock, flags);
mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intfn), 1); mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intfn), 1);
spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags); spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);
mdp5_ctl_commit(ctl, mdp_ctl_flush_mask_encoder(intf));
mdp5_ctl_set_encoder_state(ctl, true);
mdp5_encoder->enabled = true; mdp5_encoder->enabled = true;
} }
......
...@@ -230,6 +230,7 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev, ...@@ -230,6 +230,7 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev,
uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc); uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc);
int mdp5_crtc_get_lm(struct drm_crtc *crtc); int mdp5_crtc_get_lm(struct drm_crtc *crtc);
struct mdp5_ctl *mdp5_crtc_get_ctl(struct drm_crtc *crtc);
void mdp5_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file); void mdp5_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file);
void mdp5_crtc_set_intf(struct drm_crtc *crtc, struct mdp5_interface *intf); void mdp5_crtc_set_intf(struct drm_crtc *crtc, struct mdp5_interface *intf);
struct drm_crtc *mdp5_crtc_init(struct drm_device *dev, struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment