Commit 3498409f authored by jilai wang's avatar jilai wang Committed by Rob Clark

drm/msm/mdp: Add capabilities to MDP planes (v2)

MDP planes can be implemented using different type of HW pipes,
RGB/VIG/DMA pipes for MDP5 and RGB/VG/DMA pipes for MDP4. Each type
of pipe has different HW capabilities such as scaling, color space
conversion, decimation... Add a variable in plane data structure
to specify the difference of each plane which comes from mdp5_cfg data
and use it to differenciate the plane operation.
V1: Initial change
V2: Fix a typo in mdp4_kms.h
Signed-off-by: default avatarJilai Wang <jilaiw@codeaurora.org>
Signed-off-by: default avatarRob Clark <robdclark@gmail.com>
parent bef799fb
...@@ -175,27 +175,24 @@ irqreturn_t mdp4_irq(struct msm_kms *kms); ...@@ -175,27 +175,24 @@ irqreturn_t mdp4_irq(struct msm_kms *kms);
int mdp4_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc); int mdp4_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
void mdp4_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc); void mdp4_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
static inline bool pipe_supports_yuv(enum mdp4_pipe pipe) static inline uint32_t mdp4_pipe_caps(enum mdp4_pipe pipe)
{ {
switch (pipe) { switch (pipe) {
case VG1: case VG1:
case VG2: case VG2:
case VG3: case VG3:
case VG4: case VG4:
return true; return MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC;
case RGB1:
case RGB2:
case RGB3:
return MDP_PIPE_CAP_SCALE;
default: default:
return false; return 0;
} }
} }
static inline
uint32_t mdp4_get_formats(enum mdp4_pipe pipe_id, uint32_t *pixel_formats,
uint32_t max_formats)
{
return mdp_get_formats(pixel_formats, max_formats,
!pipe_supports_yuv(pipe_id));
}
enum mdp4_pipe mdp4_plane_pipe(struct drm_plane *plane); enum mdp4_pipe mdp4_plane_pipe(struct drm_plane *plane);
struct drm_plane *mdp4_plane_init(struct drm_device *dev, struct drm_plane *mdp4_plane_init(struct drm_device *dev,
enum mdp4_pipe pipe_id, bool private_plane); enum mdp4_pipe pipe_id, bool private_plane);
......
...@@ -26,6 +26,7 @@ struct mdp4_plane { ...@@ -26,6 +26,7 @@ struct mdp4_plane {
enum mdp4_pipe pipe; enum mdp4_pipe pipe;
uint32_t caps;
uint32_t nformats; uint32_t nformats;
uint32_t formats[32]; uint32_t formats[32];
...@@ -382,9 +383,11 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev, ...@@ -382,9 +383,11 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev,
mdp4_plane->pipe = pipe_id; mdp4_plane->pipe = pipe_id;
mdp4_plane->name = pipe_names[pipe_id]; mdp4_plane->name = pipe_names[pipe_id];
mdp4_plane->caps = mdp4_pipe_caps(pipe_id);
mdp4_plane->nformats = mdp4_get_formats(pipe_id, mdp4_plane->formats, mdp4_plane->nformats = mdp_get_formats(mdp4_plane->formats,
ARRAY_SIZE(mdp4_plane->formats)); ARRAY_SIZE(mdp4_plane->formats),
!pipe_supports_yuv(mdp4_plane->caps));
type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
ret = drm_universal_plane_init(dev, plane, 0xff, &mdp4_plane_funcs, ret = drm_universal_plane_init(dev, plane, 0xff, &mdp4_plane_funcs,
......
...@@ -45,14 +45,20 @@ const struct mdp5_cfg_hw msm8x74_config = { ...@@ -45,14 +45,20 @@ const struct mdp5_cfg_hw msm8x74_config = {
.pipe_vig = { .pipe_vig = {
.count = 3, .count = 3,
.base = { 0x01200, 0x01600, 0x01a00 }, .base = { 0x01200, 0x01600, 0x01a00 },
.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC |
MDP_PIPE_CAP_DECIMATION,
}, },
.pipe_rgb = { .pipe_rgb = {
.count = 3, .count = 3,
.base = { 0x01e00, 0x02200, 0x02600 }, .base = { 0x01e00, 0x02200, 0x02600 },
.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_DECIMATION,
}, },
.pipe_dma = { .pipe_dma = {
.count = 2, .count = 2,
.base = { 0x02a00, 0x02e00 }, .base = { 0x02a00, 0x02e00 },
.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
}, },
.lm = { .lm = {
.count = 5, .count = 5,
...@@ -115,14 +121,20 @@ const struct mdp5_cfg_hw apq8084_config = { ...@@ -115,14 +121,20 @@ const struct mdp5_cfg_hw apq8084_config = {
.pipe_vig = { .pipe_vig = {
.count = 4, .count = 4,
.base = { 0x01200, 0x01600, 0x01a00, 0x01e00 }, .base = { 0x01200, 0x01600, 0x01a00, 0x01e00 },
.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC |
MDP_PIPE_CAP_DECIMATION,
}, },
.pipe_rgb = { .pipe_rgb = {
.count = 4, .count = 4,
.base = { 0x02200, 0x02600, 0x02a00, 0x02e00 }, .base = { 0x02200, 0x02600, 0x02a00, 0x02e00 },
.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_DECIMATION,
}, },
.pipe_dma = { .pipe_dma = {
.count = 2, .count = 2,
.base = { 0x03200, 0x03600 }, .base = { 0x03200, 0x03600 },
.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
}, },
.lm = { .lm = {
.count = 6, .count = 6,
...@@ -178,14 +190,20 @@ const struct mdp5_cfg_hw msm8x16_config = { ...@@ -178,14 +190,20 @@ const struct mdp5_cfg_hw msm8x16_config = {
.pipe_vig = { .pipe_vig = {
.count = 1, .count = 1,
.base = { 0x05000 }, .base = { 0x05000 },
.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC |
MDP_PIPE_CAP_DECIMATION,
}, },
.pipe_rgb = { .pipe_rgb = {
.count = 2, .count = 2,
.base = { 0x15000, 0x17000 }, .base = { 0x15000, 0x17000 },
.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_DECIMATION,
}, },
.pipe_dma = { .pipe_dma = {
.count = 1, .count = 1,
.base = { 0x25000 }, .base = { 0x25000 },
.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
}, },
.lm = { .lm = {
.count = 2, /* LM0 and LM3 */ .count = 2, /* LM0 and LM3 */
...@@ -239,16 +257,20 @@ const struct mdp5_cfg_hw msm8x94_config = { ...@@ -239,16 +257,20 @@ const struct mdp5_cfg_hw msm8x94_config = {
.pipe_vig = { .pipe_vig = {
.count = 4, .count = 4,
.base = { 0x05000, 0x07000, 0x09000, 0x0b000 }, .base = { 0x05000, 0x07000, 0x09000, 0x0b000 },
/* TODO: add decimation bit */ .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC |
MDP_PIPE_CAP_DECIMATION,
}, },
.pipe_rgb = { .pipe_rgb = {
.count = 4, .count = 4,
.base = { 0x15000, 0x17000, 0x19000, 0x1b000 }, .base = { 0x15000, 0x17000, 0x19000, 0x1b000 },
/* TODO: add decimation bit */ .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_DECIMATION,
}, },
.pipe_dma = { .pipe_dma = {
.count = 2, .count = 2,
.base = { 0x25000, 0x27000 }, .base = { 0x25000, 0x27000 },
.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
}, },
.lm = { .lm = {
.count = 6, .count = 6,
......
...@@ -46,6 +46,11 @@ struct mdp5_lm_block { ...@@ -46,6 +46,11 @@ struct mdp5_lm_block {
uint32_t max_height; uint32_t max_height;
}; };
struct mdp5_pipe_block {
MDP5_SUB_BLOCK_DEFINITION;
uint32_t caps; /* pipe capabilities */
};
struct mdp5_ctl_block { struct mdp5_ctl_block {
MDP5_SUB_BLOCK_DEFINITION; MDP5_SUB_BLOCK_DEFINITION;
uint32_t flush_hw_mask; /* FLUSH register's hardware mask */ uint32_t flush_hw_mask; /* FLUSH register's hardware mask */
...@@ -72,9 +77,9 @@ struct mdp5_cfg_hw { ...@@ -72,9 +77,9 @@ struct mdp5_cfg_hw {
struct mdp5_sub_block mdp; struct mdp5_sub_block mdp;
struct mdp5_smp_block smp; struct mdp5_smp_block smp;
struct mdp5_ctl_block ctl; struct mdp5_ctl_block ctl;
struct mdp5_sub_block pipe_vig; struct mdp5_pipe_block pipe_vig;
struct mdp5_sub_block pipe_rgb; struct mdp5_pipe_block pipe_rgb;
struct mdp5_sub_block pipe_dma; struct mdp5_pipe_block pipe_dma;
struct mdp5_lm_block lm; struct mdp5_lm_block lm;
struct mdp5_sub_block dspp; struct mdp5_sub_block dspp;
struct mdp5_sub_block ad; struct mdp5_sub_block ad;
......
...@@ -372,7 +372,7 @@ static int modeset_init(struct mdp5_kms *mdp5_kms) ...@@ -372,7 +372,7 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
struct drm_crtc *crtc; struct drm_crtc *crtc;
plane = mdp5_plane_init(dev, crtcs[i], true, plane = mdp5_plane_init(dev, crtcs[i], true,
hw_cfg->pipe_rgb.base[i]); hw_cfg->pipe_rgb.base[i], hw_cfg->pipe_rgb.caps);
if (IS_ERR(plane)) { if (IS_ERR(plane)) {
ret = PTR_ERR(plane); ret = PTR_ERR(plane);
dev_err(dev->dev, "failed to construct plane for %s (%d)\n", dev_err(dev->dev, "failed to construct plane for %s (%d)\n",
...@@ -395,7 +395,7 @@ static int modeset_init(struct mdp5_kms *mdp5_kms) ...@@ -395,7 +395,7 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
struct drm_plane *plane; struct drm_plane *plane;
plane = mdp5_plane_init(dev, pub_planes[i], false, plane = mdp5_plane_init(dev, pub_planes[i], false,
hw_cfg->pipe_vig.base[i]); hw_cfg->pipe_vig.base[i], hw_cfg->pipe_vig.caps);
if (IS_ERR(plane)) { if (IS_ERR(plane)) {
ret = PTR_ERR(plane); ret = PTR_ERR(plane);
dev_err(dev->dev, "failed to construct %s plane: %d\n", dev_err(dev->dev, "failed to construct %s plane: %d\n",
......
...@@ -196,34 +196,14 @@ void mdp5_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc); ...@@ -196,34 +196,14 @@ void mdp5_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
int mdp5_irq_domain_init(struct mdp5_kms *mdp5_kms); int mdp5_irq_domain_init(struct mdp5_kms *mdp5_kms);
void mdp5_irq_domain_fini(struct mdp5_kms *mdp5_kms); void mdp5_irq_domain_fini(struct mdp5_kms *mdp5_kms);
static inline bool pipe_supports_yuv(enum mdp5_pipe pipe)
{
switch (pipe) {
case SSPP_VIG0:
case SSPP_VIG1:
case SSPP_VIG2:
case SSPP_VIG3:
return true;
default:
return false;
}
}
static inline
uint32_t mdp5_get_formats(enum mdp5_pipe pipe, uint32_t *pixel_formats,
uint32_t max_formats)
{
return mdp_get_formats(pixel_formats, max_formats,
!pipe_supports_yuv(pipe));
}
uint32_t mdp5_plane_get_flush(struct drm_plane *plane); uint32_t mdp5_plane_get_flush(struct drm_plane *plane);
void mdp5_plane_complete_flip(struct drm_plane *plane); void mdp5_plane_complete_flip(struct drm_plane *plane);
void mdp5_plane_complete_commit(struct drm_plane *plane, void mdp5_plane_complete_commit(struct drm_plane *plane,
struct drm_plane_state *state); struct drm_plane_state *state);
enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane); enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane);
struct drm_plane *mdp5_plane_init(struct drm_device *dev, struct drm_plane *mdp5_plane_init(struct drm_device *dev,
enum mdp5_pipe pipe, bool private_plane, uint32_t reg_offset); enum mdp5_pipe pipe, bool private_plane,
uint32_t reg_offset, uint32_t caps);
uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc); uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc);
......
...@@ -26,6 +26,7 @@ struct mdp5_plane { ...@@ -26,6 +26,7 @@ struct mdp5_plane {
spinlock_t pipe_lock; /* protect REG_MDP5_PIPE_* registers */ spinlock_t pipe_lock; /* protect REG_MDP5_PIPE_* registers */
uint32_t reg_offset; uint32_t reg_offset;
uint32_t caps;
uint32_t flush_mask; /* used to commit pipe registers */ uint32_t flush_mask; /* used to commit pipe registers */
...@@ -260,10 +261,33 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane, ...@@ -260,10 +261,33 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
{ {
struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
struct drm_plane_state *old_state = plane->state; struct drm_plane_state *old_state = plane->state;
const struct mdp_format *format;
DBG("%s: check (%d -> %d)", mdp5_plane->name, DBG("%s: check (%d -> %d)", mdp5_plane->name,
plane_enabled(old_state), plane_enabled(state)); plane_enabled(old_state), plane_enabled(state));
if (plane_enabled(state)) {
format = to_mdp_format(msm_framebuffer_format(state->fb));
if (MDP_FORMAT_IS_YUV(format) &&
!pipe_supports_yuv(mdp5_plane->caps)) {
dev_err(plane->dev->dev,
"Pipe doesn't support YUV\n");
return -EINVAL;
}
if (!(mdp5_plane->caps & MDP_PIPE_CAP_SCALE) &&
(((state->src_w >> 16) != state->crtc_w) ||
((state->src_h >> 16) != state->crtc_h))) {
dev_err(plane->dev->dev,
"Pipe doesn't support scaling (%dx%d -> %dx%d)\n",
state->src_w >> 16, state->src_h >> 16,
state->crtc_w, state->crtc_h);
return -EINVAL;
}
}
if (plane_enabled(state) && plane_enabled(old_state)) { if (plane_enabled(state) && plane_enabled(old_state)) {
/* we cannot change SMP block configuration during scanout: */ /* we cannot change SMP block configuration during scanout: */
bool full_modeset = false; bool full_modeset = false;
...@@ -637,24 +661,28 @@ static int mdp5_plane_mode_set(struct drm_plane *plane, ...@@ -637,24 +661,28 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
/* not using secure mode: */ /* not using secure mode: */
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_ADDR_SW_STATUS(pipe), 0); mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_ADDR_SW_STATUS(pipe), 0);
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_X(pipe), if (mdp5_plane->caps & MDP_PIPE_CAP_SCALE) {
phasex_step[0]); mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_X(pipe),
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(pipe), phasex_step[0]);
phasey_step[0]); mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(pipe),
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_X(pipe), phasey_step[0]);
phasex_step[1]); mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_X(pipe),
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_Y(pipe), phasex_step[1]);
phasey_step[1]); mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_Y(pipe),
mdp5_write(mdp5_kms, REG_MDP5_PIPE_DECIMATION(pipe), phasey_step[1]);
MDP5_PIPE_DECIMATION_VERT(vdecm) | mdp5_write(mdp5_kms, REG_MDP5_PIPE_DECIMATION(pipe),
MDP5_PIPE_DECIMATION_HORZ(hdecm)); MDP5_PIPE_DECIMATION_VERT(vdecm) |
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CONFIG(pipe), config); MDP5_PIPE_DECIMATION_HORZ(hdecm));
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CONFIG(pipe), config);
if (MDP_FORMAT_IS_YUV(format)) }
csc_enable(mdp5_kms, pipe,
mdp_get_default_csc_cfg(CSC_YUV2RGB)); if (mdp5_plane->caps & MDP_PIPE_CAP_CSC) {
else if (MDP_FORMAT_IS_YUV(format))
csc_disable(mdp5_kms, pipe); csc_enable(mdp5_kms, pipe,
mdp_get_default_csc_cfg(CSC_YUV2RGB));
else
csc_disable(mdp5_kms, pipe);
}
set_scanout_locked(plane, fb); set_scanout_locked(plane, fb);
...@@ -705,7 +733,8 @@ void mdp5_plane_complete_commit(struct drm_plane *plane, ...@@ -705,7 +733,8 @@ void mdp5_plane_complete_commit(struct drm_plane *plane,
/* initialize plane */ /* initialize plane */
struct drm_plane *mdp5_plane_init(struct drm_device *dev, struct drm_plane *mdp5_plane_init(struct drm_device *dev,
enum mdp5_pipe pipe, bool private_plane, uint32_t reg_offset) enum mdp5_pipe pipe, bool private_plane, uint32_t reg_offset,
uint32_t caps)
{ {
struct drm_plane *plane = NULL; struct drm_plane *plane = NULL;
struct mdp5_plane *mdp5_plane; struct mdp5_plane *mdp5_plane;
...@@ -722,9 +751,11 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev, ...@@ -722,9 +751,11 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev,
mdp5_plane->pipe = pipe; mdp5_plane->pipe = pipe;
mdp5_plane->name = pipe2name(pipe); mdp5_plane->name = pipe2name(pipe);
mdp5_plane->caps = caps;
mdp5_plane->nformats = mdp5_get_formats(pipe, mdp5_plane->formats, mdp5_plane->nformats = mdp_get_formats(mdp5_plane->formats,
ARRAY_SIZE(mdp5_plane->formats)); ARRAY_SIZE(mdp5_plane->formats),
!pipe_supports_yuv(mdp5_plane->caps));
mdp5_plane->flush_mask = mdp_ctl_flush_mask_pipe(pipe); mdp5_plane->flush_mask = mdp_ctl_flush_mask_pipe(pipe);
mdp5_plane->reg_offset = reg_offset; mdp5_plane->reg_offset = reg_offset;
......
...@@ -98,6 +98,19 @@ struct mdp_format { ...@@ -98,6 +98,19 @@ struct mdp_format {
uint32_t mdp_get_formats(uint32_t *formats, uint32_t max_formats, bool rgb_only); uint32_t mdp_get_formats(uint32_t *formats, uint32_t max_formats, bool rgb_only);
const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format); const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format);
/* MDP pipe capabilities */
#define MDP_PIPE_CAP_HFLIP BIT(0)
#define MDP_PIPE_CAP_VFLIP BIT(1)
#define MDP_PIPE_CAP_SCALE BIT(2)
#define MDP_PIPE_CAP_CSC BIT(3)
#define MDP_PIPE_CAP_DECIMATION BIT(4)
static inline bool pipe_supports_yuv(uint32_t pipe_caps)
{
return (pipe_caps & MDP_PIPE_CAP_SCALE) &&
(pipe_caps & MDP_PIPE_CAP_CSC);
}
enum csc_type { enum csc_type {
CSC_RGB2RGB = 0, CSC_RGB2RGB = 0,
CSC_YUV2RGB, CSC_YUV2RGB,
......
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