mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-20 11:28:15 +07:00
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: Jilai Wang <jilaiw@codeaurora.org> Signed-off-by: Rob Clark <robdclark@gmail.com>
This commit is contained in:
parent
bef799fb77
commit
3498409f03
@ -175,27 +175,24 @@ irqreturn_t mdp4_irq(struct msm_kms *kms);
|
||||
int mdp4_enable_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) {
|
||||
case VG1:
|
||||
case VG2:
|
||||
case VG3:
|
||||
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:
|
||||
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);
|
||||
struct drm_plane *mdp4_plane_init(struct drm_device *dev,
|
||||
enum mdp4_pipe pipe_id, bool private_plane);
|
||||
|
@ -26,6 +26,7 @@ struct mdp4_plane {
|
||||
|
||||
enum mdp4_pipe pipe;
|
||||
|
||||
uint32_t caps;
|
||||
uint32_t nformats;
|
||||
uint32_t formats[32];
|
||||
|
||||
@ -382,9 +383,11 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev,
|
||||
|
||||
mdp4_plane->pipe = 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,
|
||||
ARRAY_SIZE(mdp4_plane->formats));
|
||||
mdp4_plane->nformats = mdp_get_formats(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;
|
||||
ret = drm_universal_plane_init(dev, plane, 0xff, &mdp4_plane_funcs,
|
||||
|
@ -45,14 +45,20 @@ const struct mdp5_cfg_hw msm8x74_config = {
|
||||
.pipe_vig = {
|
||||
.count = 3,
|
||||
.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 = {
|
||||
.count = 3,
|
||||
.base = { 0x01e00, 0x02200, 0x02600 },
|
||||
.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
|
||||
MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_DECIMATION,
|
||||
},
|
||||
.pipe_dma = {
|
||||
.count = 2,
|
||||
.base = { 0x02a00, 0x02e00 },
|
||||
.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
|
||||
},
|
||||
.lm = {
|
||||
.count = 5,
|
||||
@ -115,14 +121,20 @@ const struct mdp5_cfg_hw apq8084_config = {
|
||||
.pipe_vig = {
|
||||
.count = 4,
|
||||
.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 = {
|
||||
.count = 4,
|
||||
.base = { 0x02200, 0x02600, 0x02a00, 0x02e00 },
|
||||
.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
|
||||
MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_DECIMATION,
|
||||
},
|
||||
.pipe_dma = {
|
||||
.count = 2,
|
||||
.base = { 0x03200, 0x03600 },
|
||||
.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
|
||||
},
|
||||
.lm = {
|
||||
.count = 6,
|
||||
@ -178,14 +190,20 @@ const struct mdp5_cfg_hw msm8x16_config = {
|
||||
.pipe_vig = {
|
||||
.count = 1,
|
||||
.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 = {
|
||||
.count = 2,
|
||||
.base = { 0x15000, 0x17000 },
|
||||
.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
|
||||
MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_DECIMATION,
|
||||
},
|
||||
.pipe_dma = {
|
||||
.count = 1,
|
||||
.base = { 0x25000 },
|
||||
.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
|
||||
},
|
||||
.lm = {
|
||||
.count = 2, /* LM0 and LM3 */
|
||||
@ -239,16 +257,20 @@ const struct mdp5_cfg_hw msm8x94_config = {
|
||||
.pipe_vig = {
|
||||
.count = 4,
|
||||
.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 = {
|
||||
.count = 4,
|
||||
.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 = {
|
||||
.count = 2,
|
||||
.base = { 0x25000, 0x27000 },
|
||||
.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
|
||||
},
|
||||
.lm = {
|
||||
.count = 6,
|
||||
|
@ -46,6 +46,11 @@ struct mdp5_lm_block {
|
||||
uint32_t max_height;
|
||||
};
|
||||
|
||||
struct mdp5_pipe_block {
|
||||
MDP5_SUB_BLOCK_DEFINITION;
|
||||
uint32_t caps; /* pipe capabilities */
|
||||
};
|
||||
|
||||
struct mdp5_ctl_block {
|
||||
MDP5_SUB_BLOCK_DEFINITION;
|
||||
uint32_t flush_hw_mask; /* FLUSH register's hardware mask */
|
||||
@ -72,9 +77,9 @@ struct mdp5_cfg_hw {
|
||||
struct mdp5_sub_block mdp;
|
||||
struct mdp5_smp_block smp;
|
||||
struct mdp5_ctl_block ctl;
|
||||
struct mdp5_sub_block pipe_vig;
|
||||
struct mdp5_sub_block pipe_rgb;
|
||||
struct mdp5_sub_block pipe_dma;
|
||||
struct mdp5_pipe_block pipe_vig;
|
||||
struct mdp5_pipe_block pipe_rgb;
|
||||
struct mdp5_pipe_block pipe_dma;
|
||||
struct mdp5_lm_block lm;
|
||||
struct mdp5_sub_block dspp;
|
||||
struct mdp5_sub_block ad;
|
||||
|
@ -372,7 +372,7 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
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)) {
|
||||
ret = PTR_ERR(plane);
|
||||
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)
|
||||
struct drm_plane *plane;
|
||||
|
||||
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)) {
|
||||
ret = PTR_ERR(plane);
|
||||
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);
|
||||
int mdp5_irq_domain_init(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);
|
||||
void mdp5_plane_complete_flip(struct drm_plane *plane);
|
||||
void mdp5_plane_complete_commit(struct drm_plane *plane,
|
||||
struct drm_plane_state *state);
|
||||
enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane);
|
||||
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);
|
||||
|
||||
|
@ -26,6 +26,7 @@ struct mdp5_plane {
|
||||
|
||||
spinlock_t pipe_lock; /* protect REG_MDP5_PIPE_* registers */
|
||||
uint32_t reg_offset;
|
||||
uint32_t caps;
|
||||
|
||||
uint32_t flush_mask; /* used to commit pipe registers */
|
||||
|
||||
@ -260,10 +261,33 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
|
||||
{
|
||||
struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
|
||||
struct drm_plane_state *old_state = plane->state;
|
||||
const struct mdp_format *format;
|
||||
|
||||
DBG("%s: check (%d -> %d)", mdp5_plane->name,
|
||||
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)) {
|
||||
/* we cannot change SMP block configuration during scanout: */
|
||||
bool full_modeset = false;
|
||||
@ -637,24 +661,28 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
|
||||
/* not using secure mode: */
|
||||
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),
|
||||
phasex_step[0]);
|
||||
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(pipe),
|
||||
phasey_step[0]);
|
||||
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_X(pipe),
|
||||
phasex_step[1]);
|
||||
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_Y(pipe),
|
||||
phasey_step[1]);
|
||||
mdp5_write(mdp5_kms, REG_MDP5_PIPE_DECIMATION(pipe),
|
||||
MDP5_PIPE_DECIMATION_VERT(vdecm) |
|
||||
MDP5_PIPE_DECIMATION_HORZ(hdecm));
|
||||
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CONFIG(pipe), config);
|
||||
if (mdp5_plane->caps & MDP_PIPE_CAP_SCALE) {
|
||||
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_X(pipe),
|
||||
phasex_step[0]);
|
||||
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(pipe),
|
||||
phasey_step[0]);
|
||||
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_X(pipe),
|
||||
phasex_step[1]);
|
||||
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_Y(pipe),
|
||||
phasey_step[1]);
|
||||
mdp5_write(mdp5_kms, REG_MDP5_PIPE_DECIMATION(pipe),
|
||||
MDP5_PIPE_DECIMATION_VERT(vdecm) |
|
||||
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));
|
||||
else
|
||||
csc_disable(mdp5_kms, pipe);
|
||||
if (mdp5_plane->caps & MDP_PIPE_CAP_CSC) {
|
||||
if (MDP_FORMAT_IS_YUV(format))
|
||||
csc_enable(mdp5_kms, pipe,
|
||||
mdp_get_default_csc_cfg(CSC_YUV2RGB));
|
||||
else
|
||||
csc_disable(mdp5_kms, pipe);
|
||||
}
|
||||
|
||||
set_scanout_locked(plane, fb);
|
||||
|
||||
@ -705,7 +733,8 @@ void mdp5_plane_complete_commit(struct drm_plane *plane,
|
||||
|
||||
/* initialize plane */
|
||||
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 mdp5_plane *mdp5_plane;
|
||||
@ -722,9 +751,11 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev,
|
||||
|
||||
mdp5_plane->pipe = pipe;
|
||||
mdp5_plane->name = pipe2name(pipe);
|
||||
mdp5_plane->caps = caps;
|
||||
|
||||
mdp5_plane->nformats = mdp5_get_formats(pipe, mdp5_plane->formats,
|
||||
ARRAY_SIZE(mdp5_plane->formats));
|
||||
mdp5_plane->nformats = mdp_get_formats(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->reg_offset = reg_offset;
|
||||
|
@ -98,6 +98,19 @@ struct mdp_format {
|
||||
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);
|
||||
|
||||
/* 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 {
|
||||
CSC_RGB2RGB = 0,
|
||||
CSC_YUV2RGB,
|
||||
|
Loading…
Reference in New Issue
Block a user