drm/msm/mdp5: introduce mdp5_hw_pipe
Split out the hardware pipe specifics from mdp5_plane. To start, the hw pipes are statically assigned to planes, but next step is to assign the hw pipes during plane->atomic_check() based on requested caps (scaling, YUV, etc). And then hw pipe re-assignment if required if required SMP blocks changes. Signed-off-by: Rob Clark <robdclark@gmail.com> Reviewed-by: Archit Taneja <architt@codeaurora.org>
This commit is contained in:
Родитель
f5903bad80
Коммит
c056b55dc6
|
@ -37,6 +37,7 @@ msm-y := \
|
||||||
mdp/mdp5/mdp5_irq.o \
|
mdp/mdp5/mdp5_irq.o \
|
||||||
mdp/mdp5/mdp5_mdss.o \
|
mdp/mdp5/mdp5_mdss.o \
|
||||||
mdp/mdp5/mdp5_kms.o \
|
mdp/mdp5/mdp5_kms.o \
|
||||||
|
mdp/mdp5/mdp5_pipe.o \
|
||||||
mdp/mdp5/mdp5_plane.o \
|
mdp/mdp5/mdp5_plane.o \
|
||||||
mdp/mdp5/mdp5_smp.o \
|
mdp/mdp5/mdp5_smp.o \
|
||||||
msm_atomic.o \
|
msm_atomic.o \
|
||||||
|
|
|
@ -27,8 +27,6 @@
|
||||||
#define CURSOR_WIDTH 64
|
#define CURSOR_WIDTH 64
|
||||||
#define CURSOR_HEIGHT 64
|
#define CURSOR_HEIGHT 64
|
||||||
|
|
||||||
#define SSPP_MAX (SSPP_RGB3 + 1) /* TODO: Add SSPP_MAX in mdp5.xml.h */
|
|
||||||
|
|
||||||
struct mdp5_crtc {
|
struct mdp5_crtc {
|
||||||
struct drm_crtc base;
|
struct drm_crtc base;
|
||||||
int id;
|
int id;
|
||||||
|
|
|
@ -119,6 +119,10 @@ static void mdp5_kms_destroy(struct msm_kms *kms)
|
||||||
{
|
{
|
||||||
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
|
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
|
||||||
struct msm_gem_address_space *aspace = mdp5_kms->aspace;
|
struct msm_gem_address_space *aspace = mdp5_kms->aspace;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < mdp5_kms->num_hwpipes; i++)
|
||||||
|
mdp5_pipe_destroy(mdp5_kms->hwpipes[i]);
|
||||||
|
|
||||||
if (aspace) {
|
if (aspace) {
|
||||||
aspace->mmu->funcs->detach(aspace->mmu,
|
aspace->mmu->funcs->detach(aspace->mmu,
|
||||||
|
@ -323,15 +327,6 @@ static int modeset_init_intf(struct mdp5_kms *mdp5_kms, int intf_num)
|
||||||
|
|
||||||
static int modeset_init(struct mdp5_kms *mdp5_kms)
|
static int modeset_init(struct mdp5_kms *mdp5_kms)
|
||||||
{
|
{
|
||||||
static const enum mdp5_pipe rgb_planes[] = {
|
|
||||||
SSPP_RGB0, SSPP_RGB1, SSPP_RGB2, SSPP_RGB3,
|
|
||||||
};
|
|
||||||
static const enum mdp5_pipe vig_planes[] = {
|
|
||||||
SSPP_VIG0, SSPP_VIG1, SSPP_VIG2, SSPP_VIG3,
|
|
||||||
};
|
|
||||||
static const enum mdp5_pipe dma_planes[] = {
|
|
||||||
SSPP_DMA0, SSPP_DMA1,
|
|
||||||
};
|
|
||||||
struct drm_device *dev = mdp5_kms->dev;
|
struct drm_device *dev = mdp5_kms->dev;
|
||||||
struct msm_drm_private *priv = dev->dev_private;
|
struct msm_drm_private *priv = dev->dev_private;
|
||||||
const struct mdp5_cfg_hw *hw_cfg;
|
const struct mdp5_cfg_hw *hw_cfg;
|
||||||
|
@ -339,58 +334,34 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
|
||||||
|
|
||||||
hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);
|
hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);
|
||||||
|
|
||||||
/* construct CRTCs and their private planes: */
|
/* Construct planes equaling the number of hw pipes, and CRTCs
|
||||||
for (i = 0; i < hw_cfg->pipe_rgb.count; i++) {
|
* for the N layer-mixers (LM). The first N planes become primary
|
||||||
|
* planes for the CRTCs, with the remainder as overlay planes:
|
||||||
|
*/
|
||||||
|
for (i = 0; i < mdp5_kms->num_hwpipes; i++) {
|
||||||
|
bool primary = i < mdp5_cfg->lm.count;
|
||||||
struct drm_plane *plane;
|
struct drm_plane *plane;
|
||||||
struct drm_crtc *crtc;
|
struct drm_crtc *crtc;
|
||||||
|
|
||||||
plane = mdp5_plane_init(dev, rgb_planes[i], true,
|
plane = mdp5_plane_init(dev, mdp5_kms->hwpipes[i], primary);
|
||||||
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 %d (%d)\n", i, ret);
|
||||||
pipe2name(rgb_planes[i]), ret);
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!primary)
|
||||||
|
continue;
|
||||||
|
|
||||||
crtc = mdp5_crtc_init(dev, plane, i);
|
crtc = mdp5_crtc_init(dev, plane, i);
|
||||||
if (IS_ERR(crtc)) {
|
if (IS_ERR(crtc)) {
|
||||||
ret = PTR_ERR(crtc);
|
ret = PTR_ERR(crtc);
|
||||||
dev_err(dev->dev, "failed to construct crtc for %s (%d)\n",
|
dev_err(dev->dev, "failed to construct crtc %d (%d)\n", i, ret);
|
||||||
pipe2name(rgb_planes[i]), ret);
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
priv->crtcs[priv->num_crtcs++] = crtc;
|
priv->crtcs[priv->num_crtcs++] = crtc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Construct video planes: */
|
|
||||||
for (i = 0; i < hw_cfg->pipe_vig.count; i++) {
|
|
||||||
struct drm_plane *plane;
|
|
||||||
|
|
||||||
plane = mdp5_plane_init(dev, vig_planes[i], false,
|
|
||||||
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",
|
|
||||||
pipe2name(vig_planes[i]), ret);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* DMA planes */
|
|
||||||
for (i = 0; i < hw_cfg->pipe_dma.count; i++) {
|
|
||||||
struct drm_plane *plane;
|
|
||||||
|
|
||||||
plane = mdp5_plane_init(dev, dma_planes[i], false,
|
|
||||||
hw_cfg->pipe_dma.base[i], hw_cfg->pipe_dma.caps);
|
|
||||||
if (IS_ERR(plane)) {
|
|
||||||
ret = PTR_ERR(plane);
|
|
||||||
dev_err(dev->dev, "failed to construct %s plane: %d\n",
|
|
||||||
pipe2name(dma_planes[i]), ret);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Construct encoders and modeset initialize connector devices
|
/* Construct encoders and modeset initialize connector devices
|
||||||
* for each external display interface.
|
* for each external display interface.
|
||||||
*/
|
*/
|
||||||
|
@ -676,6 +647,67 @@ static void mdp5_destroy(struct platform_device *pdev)
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int construct_pipes(struct mdp5_kms *mdp5_kms, int cnt,
|
||||||
|
const enum mdp5_pipe *pipes, const uint32_t *offsets,
|
||||||
|
uint32_t caps)
|
||||||
|
{
|
||||||
|
struct drm_device *dev = mdp5_kms->dev;
|
||||||
|
int i, ret;
|
||||||
|
|
||||||
|
for (i = 0; i < cnt; i++) {
|
||||||
|
struct mdp5_hw_pipe *hwpipe;
|
||||||
|
|
||||||
|
hwpipe = mdp5_pipe_init(pipes[i], offsets[i], caps);
|
||||||
|
if (IS_ERR(hwpipe)) {
|
||||||
|
ret = PTR_ERR(hwpipe);
|
||||||
|
dev_err(dev->dev, "failed to construct pipe for %s (%d)\n",
|
||||||
|
pipe2name(pipes[i]), ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
hwpipe->idx = mdp5_kms->num_hwpipes;
|
||||||
|
mdp5_kms->hwpipes[mdp5_kms->num_hwpipes++] = hwpipe;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hwpipe_init(struct mdp5_kms *mdp5_kms)
|
||||||
|
{
|
||||||
|
static const enum mdp5_pipe rgb_planes[] = {
|
||||||
|
SSPP_RGB0, SSPP_RGB1, SSPP_RGB2, SSPP_RGB3,
|
||||||
|
};
|
||||||
|
static const enum mdp5_pipe vig_planes[] = {
|
||||||
|
SSPP_VIG0, SSPP_VIG1, SSPP_VIG2, SSPP_VIG3,
|
||||||
|
};
|
||||||
|
static const enum mdp5_pipe dma_planes[] = {
|
||||||
|
SSPP_DMA0, SSPP_DMA1,
|
||||||
|
};
|
||||||
|
const struct mdp5_cfg_hw *hw_cfg;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);
|
||||||
|
|
||||||
|
/* Construct RGB pipes: */
|
||||||
|
ret = construct_pipes(mdp5_kms, hw_cfg->pipe_rgb.count, rgb_planes,
|
||||||
|
hw_cfg->pipe_rgb.base, hw_cfg->pipe_rgb.caps);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Construct video (VIG) pipes: */
|
||||||
|
ret = construct_pipes(mdp5_kms, hw_cfg->pipe_vig.count, vig_planes,
|
||||||
|
hw_cfg->pipe_vig.base, hw_cfg->pipe_vig.caps);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Construct DMA pipes: */
|
||||||
|
ret = construct_pipes(mdp5_kms, hw_cfg->pipe_dma.count, dma_planes,
|
||||||
|
hw_cfg->pipe_dma.base, hw_cfg->pipe_dma.caps);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int mdp5_init(struct platform_device *pdev, struct drm_device *dev)
|
static int mdp5_init(struct platform_device *pdev, struct drm_device *dev)
|
||||||
{
|
{
|
||||||
struct msm_drm_private *priv = dev->dev_private;
|
struct msm_drm_private *priv = dev->dev_private;
|
||||||
|
@ -765,6 +797,10 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = hwpipe_init(mdp5_kms);
|
||||||
|
if (ret)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
/* set uninit-ed kms */
|
/* set uninit-ed kms */
|
||||||
priv->kms = &mdp5_kms->base.base;
|
priv->kms = &mdp5_kms->base.base;
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "mdp5_cfg.h" /* must be included before mdp5.xml.h */
|
#include "mdp5_cfg.h" /* must be included before mdp5.xml.h */
|
||||||
#include "mdp5.xml.h"
|
#include "mdp5.xml.h"
|
||||||
#include "mdp5_ctl.h"
|
#include "mdp5_ctl.h"
|
||||||
|
#include "mdp5_pipe.h"
|
||||||
#include "mdp5_smp.h"
|
#include "mdp5_smp.h"
|
||||||
|
|
||||||
struct mdp5_kms {
|
struct mdp5_kms {
|
||||||
|
@ -33,6 +34,9 @@ struct mdp5_kms {
|
||||||
|
|
||||||
struct platform_device *pdev;
|
struct platform_device *pdev;
|
||||||
|
|
||||||
|
unsigned num_hwpipes;
|
||||||
|
struct mdp5_hw_pipe *hwpipes[SSPP_MAX];
|
||||||
|
|
||||||
struct mdp5_cfg_handler *cfg;
|
struct mdp5_cfg_handler *cfg;
|
||||||
uint32_t caps; /* MDP capabilities (MDP_CAP_XXX bits) */
|
uint32_t caps; /* MDP capabilities (MDP_CAP_XXX bits) */
|
||||||
|
|
||||||
|
@ -207,8 +211,7 @@ 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,
|
struct mdp5_hw_pipe *hwpipe, bool primary);
|
||||||
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);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Red Hat
|
||||||
|
* Author: Rob Clark <robdclark@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 as published by
|
||||||
|
* the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mdp5_kms.h"
|
||||||
|
|
||||||
|
void mdp5_pipe_destroy(struct mdp5_hw_pipe *hwpipe)
|
||||||
|
{
|
||||||
|
kfree(hwpipe);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mdp5_hw_pipe *mdp5_pipe_init(enum mdp5_pipe pipe,
|
||||||
|
uint32_t reg_offset, uint32_t caps)
|
||||||
|
{
|
||||||
|
struct mdp5_hw_pipe *hwpipe;
|
||||||
|
|
||||||
|
hwpipe = kzalloc(sizeof(*hwpipe), GFP_KERNEL);
|
||||||
|
if (!hwpipe)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
hwpipe->name = pipe2name(pipe);
|
||||||
|
hwpipe->pipe = pipe;
|
||||||
|
hwpipe->reg_offset = reg_offset;
|
||||||
|
hwpipe->caps = caps;
|
||||||
|
hwpipe->flush_mask = mdp_ctl_flush_mask_pipe(pipe);
|
||||||
|
|
||||||
|
spin_lock_init(&hwpipe->pipe_lock);
|
||||||
|
|
||||||
|
return hwpipe;
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Red Hat
|
||||||
|
* Author: Rob Clark <robdclark@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 as published by
|
||||||
|
* the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MDP5_PIPE_H__
|
||||||
|
#define __MDP5_PIPE_H__
|
||||||
|
|
||||||
|
#define SSPP_MAX (SSPP_RGB3 + 1) /* TODO: Add SSPP_MAX in mdp5.xml.h */
|
||||||
|
|
||||||
|
/* represents a hw pipe, which is dynamically assigned to a plane */
|
||||||
|
struct mdp5_hw_pipe {
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
const char *name;
|
||||||
|
enum mdp5_pipe pipe;
|
||||||
|
|
||||||
|
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 */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mdp5_hw_pipe *mdp5_pipe_init(enum mdp5_pipe pipe,
|
||||||
|
uint32_t reg_offset, uint32_t caps);
|
||||||
|
void mdp5_pipe_destroy(struct mdp5_hw_pipe *hwpipe);
|
||||||
|
|
||||||
|
#endif /* __MDP5_PIPE_H__ */
|
|
@ -22,13 +22,7 @@
|
||||||
struct mdp5_plane {
|
struct mdp5_plane {
|
||||||
struct drm_plane base;
|
struct drm_plane base;
|
||||||
|
|
||||||
enum mdp5_pipe pipe;
|
struct mdp5_hw_pipe *hwpipe;
|
||||||
|
|
||||||
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 */
|
|
||||||
|
|
||||||
uint32_t nformats;
|
uint32_t nformats;
|
||||||
uint32_t formats[32];
|
uint32_t formats[32];
|
||||||
|
@ -71,8 +65,8 @@ static void mdp5_plane_install_rotation_property(struct drm_device *dev,
|
||||||
{
|
{
|
||||||
struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
|
struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
|
||||||
|
|
||||||
if (!(mdp5_plane->caps & MDP_PIPE_CAP_HFLIP) &&
|
if (!(mdp5_plane->hwpipe->caps & MDP_PIPE_CAP_HFLIP) &&
|
||||||
!(mdp5_plane->caps & MDP_PIPE_CAP_VFLIP))
|
!(mdp5_plane->hwpipe->caps & MDP_PIPE_CAP_VFLIP))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
drm_plane_create_rotation_property(plane,
|
drm_plane_create_rotation_property(plane,
|
||||||
|
@ -301,13 +295,13 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
|
||||||
|
|
||||||
format = to_mdp_format(msm_framebuffer_format(state->fb));
|
format = to_mdp_format(msm_framebuffer_format(state->fb));
|
||||||
if (MDP_FORMAT_IS_YUV(format) &&
|
if (MDP_FORMAT_IS_YUV(format) &&
|
||||||
!pipe_supports_yuv(mdp5_plane->caps)) {
|
!pipe_supports_yuv(mdp5_plane->hwpipe->caps)) {
|
||||||
DBG("Pipe doesn't support YUV\n");
|
DBG("Pipe doesn't support YUV\n");
|
||||||
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(mdp5_plane->caps & MDP_PIPE_CAP_SCALE) &&
|
if (!(mdp5_plane->hwpipe->caps & MDP_PIPE_CAP_SCALE) &&
|
||||||
(((state->src_w >> 16) != state->crtc_w) ||
|
(((state->src_w >> 16) != state->crtc_w) ||
|
||||||
((state->src_h >> 16) != state->crtc_h))) {
|
((state->src_h >> 16) != state->crtc_h))) {
|
||||||
DBG("Pipe doesn't support scaling (%dx%d -> %dx%d)\n",
|
DBG("Pipe doesn't support scaling (%dx%d -> %dx%d)\n",
|
||||||
|
@ -321,11 +315,12 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
|
||||||
DRM_ROTATE_0 |
|
DRM_ROTATE_0 |
|
||||||
DRM_REFLECT_X |
|
DRM_REFLECT_X |
|
||||||
DRM_REFLECT_Y);
|
DRM_REFLECT_Y);
|
||||||
|
|
||||||
hflip = !!(rotation & DRM_REFLECT_X);
|
hflip = !!(rotation & DRM_REFLECT_X);
|
||||||
vflip = !!(rotation & DRM_REFLECT_Y);
|
vflip = !!(rotation & DRM_REFLECT_Y);
|
||||||
|
|
||||||
if ((vflip && !(mdp5_plane->caps & MDP_PIPE_CAP_VFLIP)) ||
|
if ((vflip && !(mdp5_plane->hwpipe->caps & MDP_PIPE_CAP_VFLIP)) ||
|
||||||
(hflip && !(mdp5_plane->caps & MDP_PIPE_CAP_HFLIP))) {
|
(hflip && !(mdp5_plane->hwpipe->caps & MDP_PIPE_CAP_HFLIP))) {
|
||||||
DBG("Pipe doesn't support flip\n");
|
DBG("Pipe doesn't support flip\n");
|
||||||
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -393,7 +388,7 @@ static void set_scanout_locked(struct drm_plane *plane,
|
||||||
{
|
{
|
||||||
struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
|
struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
|
||||||
struct mdp5_kms *mdp5_kms = get_kms(plane);
|
struct mdp5_kms *mdp5_kms = get_kms(plane);
|
||||||
enum mdp5_pipe pipe = mdp5_plane->pipe;
|
enum mdp5_pipe pipe = mdp5_plane->hwpipe->pipe;
|
||||||
|
|
||||||
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_STRIDE_A(pipe),
|
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_STRIDE_A(pipe),
|
||||||
MDP5_PIPE_SRC_STRIDE_A_P0(fb->pitches[0]) |
|
MDP5_PIPE_SRC_STRIDE_A_P0(fb->pitches[0]) |
|
||||||
|
@ -675,12 +670,13 @@ static int mdp5_plane_mode_set(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 *pstate = plane->state;
|
struct drm_plane_state *pstate = plane->state;
|
||||||
|
struct mdp5_hw_pipe *hwpipe = mdp5_plane->hwpipe;
|
||||||
struct mdp5_kms *mdp5_kms = get_kms(plane);
|
struct mdp5_kms *mdp5_kms = get_kms(plane);
|
||||||
enum mdp5_pipe pipe = mdp5_plane->pipe;
|
enum mdp5_pipe pipe = hwpipe->pipe;
|
||||||
const struct mdp_format *format;
|
const struct mdp_format *format;
|
||||||
uint32_t nplanes, config = 0;
|
uint32_t nplanes, config = 0;
|
||||||
uint32_t phasex_step[COMP_MAX] = {0,}, phasey_step[COMP_MAX] = {0,};
|
uint32_t phasex_step[COMP_MAX] = {0,}, phasey_step[COMP_MAX] = {0,};
|
||||||
bool pe = mdp5_plane->caps & MDP_PIPE_CAP_SW_PIX_EXT;
|
bool pe = hwpipe->caps & MDP_PIPE_CAP_SW_PIX_EXT;
|
||||||
int pe_left[COMP_MAX], pe_right[COMP_MAX];
|
int pe_left[COMP_MAX], pe_right[COMP_MAX];
|
||||||
int pe_top[COMP_MAX], pe_bottom[COMP_MAX];
|
int pe_top[COMP_MAX], pe_bottom[COMP_MAX];
|
||||||
uint32_t hdecm = 0, vdecm = 0;
|
uint32_t hdecm = 0, vdecm = 0;
|
||||||
|
@ -711,8 +707,8 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
|
||||||
|
|
||||||
/* Request some memory from the SMP: */
|
/* Request some memory from the SMP: */
|
||||||
if (mdp5_kms->smp) {
|
if (mdp5_kms->smp) {
|
||||||
ret = mdp5_smp_request(mdp5_kms->smp,
|
ret = mdp5_smp_request(mdp5_kms->smp, pipe,
|
||||||
mdp5_plane->pipe, format, src_w, false);
|
format, src_w, false);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -734,7 +730,7 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (mdp5_plane->caps & MDP_PIPE_CAP_SW_PIX_EXT) {
|
if (hwpipe->caps & MDP_PIPE_CAP_SW_PIX_EXT) {
|
||||||
calc_pixel_ext(format, src_w, crtc_w, phasex_step,
|
calc_pixel_ext(format, src_w, crtc_w, phasex_step,
|
||||||
pe_left, pe_right, true);
|
pe_left, pe_right, true);
|
||||||
calc_pixel_ext(format, src_h, crtc_h, phasey_step,
|
calc_pixel_ext(format, src_h, crtc_h, phasey_step,
|
||||||
|
@ -755,7 +751,7 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
|
||||||
hflip = !!(rotation & DRM_REFLECT_X);
|
hflip = !!(rotation & DRM_REFLECT_X);
|
||||||
vflip = !!(rotation & DRM_REFLECT_Y);
|
vflip = !!(rotation & DRM_REFLECT_Y);
|
||||||
|
|
||||||
spin_lock_irqsave(&mdp5_plane->pipe_lock, flags);
|
spin_lock_irqsave(&hwpipe->pipe_lock, flags);
|
||||||
|
|
||||||
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_IMG_SIZE(pipe),
|
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_IMG_SIZE(pipe),
|
||||||
MDP5_PIPE_SRC_IMG_SIZE_WIDTH(min(fb->width, src_w)) |
|
MDP5_PIPE_SRC_IMG_SIZE_WIDTH(min(fb->width, src_w)) |
|
||||||
|
@ -804,12 +800,12 @@ 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);
|
||||||
|
|
||||||
if (mdp5_plane->caps & MDP_PIPE_CAP_SW_PIX_EXT)
|
if (hwpipe->caps & MDP_PIPE_CAP_SW_PIX_EXT)
|
||||||
mdp5_write_pixel_ext(mdp5_kms, pipe, format,
|
mdp5_write_pixel_ext(mdp5_kms, pipe, format,
|
||||||
src_w, pe_left, pe_right,
|
src_w, pe_left, pe_right,
|
||||||
src_h, pe_top, pe_bottom);
|
src_h, pe_top, pe_bottom);
|
||||||
|
|
||||||
if (mdp5_plane->caps & MDP_PIPE_CAP_SCALE) {
|
if (hwpipe->caps & MDP_PIPE_CAP_SCALE) {
|
||||||
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_X(pipe),
|
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_X(pipe),
|
||||||
phasex_step[COMP_0]);
|
phasex_step[COMP_0]);
|
||||||
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(pipe),
|
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(pipe),
|
||||||
|
@ -824,7 +820,7 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
|
||||||
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CONFIG(pipe), config);
|
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CONFIG(pipe), config);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mdp5_plane->caps & MDP_PIPE_CAP_CSC) {
|
if (hwpipe->caps & MDP_PIPE_CAP_CSC) {
|
||||||
if (MDP_FORMAT_IS_YUV(format))
|
if (MDP_FORMAT_IS_YUV(format))
|
||||||
csc_enable(mdp5_kms, pipe,
|
csc_enable(mdp5_kms, pipe,
|
||||||
mdp_get_default_csc_cfg(CSC_YUV2RGB));
|
mdp_get_default_csc_cfg(CSC_YUV2RGB));
|
||||||
|
@ -834,7 +830,7 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
|
||||||
|
|
||||||
set_scanout_locked(plane, fb);
|
set_scanout_locked(plane, fb);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&mdp5_plane->pipe_lock, flags);
|
spin_unlock_irqrestore(&hwpipe->pipe_lock, flags);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -842,14 +838,14 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
|
||||||
enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane)
|
enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane)
|
||||||
{
|
{
|
||||||
struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
|
struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
|
||||||
return mdp5_plane->pipe;
|
return mdp5_plane->hwpipe->pipe;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t mdp5_plane_get_flush(struct drm_plane *plane)
|
uint32_t mdp5_plane_get_flush(struct drm_plane *plane)
|
||||||
{
|
{
|
||||||
struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
|
struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
|
||||||
|
|
||||||
return mdp5_plane->flush_mask;
|
return mdp5_plane->hwpipe->flush_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* called after vsync in thread context */
|
/* called after vsync in thread context */
|
||||||
|
@ -858,7 +854,7 @@ void mdp5_plane_complete_commit(struct drm_plane *plane,
|
||||||
{
|
{
|
||||||
struct mdp5_kms *mdp5_kms = get_kms(plane);
|
struct mdp5_kms *mdp5_kms = get_kms(plane);
|
||||||
struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
|
struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
|
||||||
enum mdp5_pipe pipe = mdp5_plane->pipe;
|
enum mdp5_pipe pipe = mdp5_plane->hwpipe->pipe;
|
||||||
|
|
||||||
if (mdp5_kms->smp) {
|
if (mdp5_kms->smp) {
|
||||||
if (plane_enabled(plane->state)) {
|
if (plane_enabled(plane->state)) {
|
||||||
|
@ -875,8 +871,7 @@ 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,
|
struct mdp5_hw_pipe *hwpipe, bool primary)
|
||||||
uint32_t caps)
|
|
||||||
{
|
{
|
||||||
struct drm_plane *plane = NULL;
|
struct drm_plane *plane = NULL;
|
||||||
struct mdp5_plane *mdp5_plane;
|
struct mdp5_plane *mdp5_plane;
|
||||||
|
@ -891,21 +886,16 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev,
|
||||||
|
|
||||||
plane = &mdp5_plane->base;
|
plane = &mdp5_plane->base;
|
||||||
|
|
||||||
mdp5_plane->pipe = pipe;
|
mdp5_plane->hwpipe = hwpipe;
|
||||||
mdp5_plane->caps = caps;
|
|
||||||
|
|
||||||
mdp5_plane->nformats = mdp_get_formats(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));
|
!pipe_supports_yuv(hwpipe->caps));
|
||||||
|
|
||||||
mdp5_plane->flush_mask = mdp_ctl_flush_mask_pipe(pipe);
|
type = primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
|
||||||
mdp5_plane->reg_offset = reg_offset;
|
|
||||||
spin_lock_init(&mdp5_plane->pipe_lock);
|
|
||||||
|
|
||||||
type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
|
|
||||||
ret = drm_universal_plane_init(dev, plane, 0xff, &mdp5_plane_funcs,
|
ret = drm_universal_plane_init(dev, plane, 0xff, &mdp5_plane_funcs,
|
||||||
mdp5_plane->formats, mdp5_plane->nformats,
|
mdp5_plane->formats, mdp5_plane->nformats,
|
||||||
type, "%s", pipe2name(pipe));
|
type, "%s", hwpipe->name);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче