Merge tag 'drm-next-msm-5.8-2020-06-08' of git://anongit.freedesktop.org/drm/drm
Pull drm msm updates from Dave Airlie: "This tree has been in next for a couple of weeks, but Rob missed an arm32 build issue, so I was awaiting the tree with a patch reverted. - new gpu support: a405, a640, a650 - dpu: color processing support - mdp5: support for msm8x36 (the thing with a405) - some prep work for per-context pagetables (ie the part that does not depend on in-flight iommu patches) - last but not least, UABI update for submit ioctl to support syncobj (from Bas)" * tag 'drm-next-msm-5.8-2020-06-08' of git://anongit.freedesktop.org/drm/drm: (30 commits) Revert "drm/msm/dpu: add support for clk and bw scaling for display" drm/msm/a6xx: skip HFI set freq if GMU is powered down drm/msm: Update the MMU helper function APIs drm/msm: Refactor address space initialization drm/msm: Attach the IOMMU device during initialization drm/msm/dpu: dpu_setup_dspp_pcc() can be static drm/msm/a6xx: a6xx_hfi_send_start() can be static drm/msm/a4xx: add a405_registers for a405 device drm/msm/a4xx: add adreno a405 support drm/msm/a6xx: update a6xx_hw_init for A640 and A650 drm/msm/a6xx: enable GMU log drm/msm/a6xx: update pdc/rscc GMU registers for A640/A650 drm/msm/a6xx: A640/A650 GMU firmware path drm/msm/a6xx: HFI v2 for A640 and A650 drm/msm/a6xx: add A640/A650 to gpulist drm/msm/a6xx: use msm_gem for GMU memory objects drm/msm: add internal MSM_BO_MAP_PRIV flag drm/msm: add msm_gem_get_and_pin_iova_range drm/msm: Check for powered down HW in the devfreq callbacks drm/msm/dpu: update bandwidth threshold check ...
这个提交包含在:
@@ -36,22 +36,6 @@ static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc)
|
||||
return to_dpu_kms(priv->kms);
|
||||
}
|
||||
|
||||
static bool _dpu_core_video_mode_intf_connected(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_crtc *tmp_crtc;
|
||||
|
||||
drm_for_each_crtc(tmp_crtc, crtc->dev) {
|
||||
if ((dpu_crtc_get_intf_mode(tmp_crtc) == INTF_MODE_VIDEO) &&
|
||||
tmp_crtc->enabled) {
|
||||
DPU_DEBUG("video interface connected crtc:%d\n",
|
||||
tmp_crtc->base.id);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void _dpu_core_perf_calc_crtc(struct dpu_kms *kms,
|
||||
struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *state,
|
||||
@@ -94,7 +78,6 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc,
|
||||
u32 bw, threshold;
|
||||
u64 bw_sum_of_intfs = 0;
|
||||
enum dpu_crtc_client_type curr_client_type;
|
||||
bool is_video_mode;
|
||||
struct dpu_crtc_state *dpu_cstate;
|
||||
struct drm_crtc *tmp_crtc;
|
||||
struct dpu_kms *kms;
|
||||
@@ -144,11 +127,7 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc,
|
||||
bw = DIV_ROUND_UP_ULL(bw_sum_of_intfs, 1000);
|
||||
DPU_DEBUG("calculated bandwidth=%uk\n", bw);
|
||||
|
||||
is_video_mode = dpu_crtc_get_intf_mode(crtc) == INTF_MODE_VIDEO;
|
||||
threshold = (is_video_mode ||
|
||||
_dpu_core_video_mode_intf_connected(crtc)) ?
|
||||
kms->catalog->perf.max_bw_low :
|
||||
kms->catalog->perf.max_bw_high;
|
||||
threshold = kms->catalog->perf.max_bw_high;
|
||||
|
||||
DPU_DEBUG("final threshold bw limit = %d\n", threshold);
|
||||
|
||||
|
@@ -9,6 +9,7 @@
|
||||
#include <linux/sort.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/bits.h>
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_flip_work.h>
|
||||
@@ -20,6 +21,7 @@
|
||||
#include "dpu_kms.h"
|
||||
#include "dpu_hw_lm.h"
|
||||
#include "dpu_hw_ctl.h"
|
||||
#include "dpu_hw_dspp.h"
|
||||
#include "dpu_crtc.h"
|
||||
#include "dpu_plane.h"
|
||||
#include "dpu_encoder.h"
|
||||
@@ -40,6 +42,9 @@
|
||||
/* timeout in ms waiting for frame done */
|
||||
#define DPU_CRTC_FRAME_DONE_TIMEOUT_MS 60
|
||||
|
||||
#define CONVERT_S3_15(val) \
|
||||
(((((u64)val) & ~BIT_ULL(63)) >> 17) & GENMASK_ULL(17, 0))
|
||||
|
||||
static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc)
|
||||
{
|
||||
struct msm_drm_private *priv = crtc->dev->dev_private;
|
||||
@@ -88,11 +93,9 @@ static void _dpu_crtc_setup_blend_cfg(struct dpu_crtc_mixer *mixer,
|
||||
|
||||
static void _dpu_crtc_program_lm_output_roi(struct drm_crtc *crtc)
|
||||
{
|
||||
struct dpu_crtc *dpu_crtc;
|
||||
struct dpu_crtc_state *crtc_state;
|
||||
int lm_idx, lm_horiz_position;
|
||||
|
||||
dpu_crtc = to_dpu_crtc(crtc);
|
||||
crtc_state = to_dpu_crtc_state(crtc->state);
|
||||
|
||||
lm_horiz_position = 0;
|
||||
@@ -422,6 +425,74 @@ static void _dpu_crtc_setup_lm_bounds(struct drm_crtc *crtc,
|
||||
drm_mode_debug_printmodeline(adj_mode);
|
||||
}
|
||||
|
||||
static void _dpu_crtc_get_pcc_coeff(struct drm_crtc_state *state,
|
||||
struct dpu_hw_pcc_cfg *cfg)
|
||||
{
|
||||
struct drm_color_ctm *ctm;
|
||||
|
||||
memset(cfg, 0, sizeof(struct dpu_hw_pcc_cfg));
|
||||
|
||||
ctm = (struct drm_color_ctm *)state->ctm->data;
|
||||
|
||||
if (!ctm)
|
||||
return;
|
||||
|
||||
cfg->r.r = CONVERT_S3_15(ctm->matrix[0]);
|
||||
cfg->g.r = CONVERT_S3_15(ctm->matrix[1]);
|
||||
cfg->b.r = CONVERT_S3_15(ctm->matrix[2]);
|
||||
|
||||
cfg->r.g = CONVERT_S3_15(ctm->matrix[3]);
|
||||
cfg->g.g = CONVERT_S3_15(ctm->matrix[4]);
|
||||
cfg->b.g = CONVERT_S3_15(ctm->matrix[5]);
|
||||
|
||||
cfg->r.b = CONVERT_S3_15(ctm->matrix[6]);
|
||||
cfg->g.b = CONVERT_S3_15(ctm->matrix[7]);
|
||||
cfg->b.b = CONVERT_S3_15(ctm->matrix[8]);
|
||||
}
|
||||
|
||||
static void _dpu_crtc_setup_cp_blocks(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_crtc_state *state = crtc->state;
|
||||
struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc->state);
|
||||
struct dpu_crtc_mixer *mixer = cstate->mixers;
|
||||
struct dpu_hw_pcc_cfg cfg;
|
||||
struct dpu_hw_ctl *ctl;
|
||||
struct dpu_hw_mixer *lm;
|
||||
struct dpu_hw_dspp *dspp;
|
||||
int i;
|
||||
|
||||
|
||||
if (!state->color_mgmt_changed)
|
||||
return;
|
||||
|
||||
for (i = 0; i < cstate->num_mixers; i++) {
|
||||
ctl = mixer[i].lm_ctl;
|
||||
lm = mixer[i].hw_lm;
|
||||
dspp = mixer[i].hw_dspp;
|
||||
|
||||
if (!dspp || !dspp->ops.setup_pcc)
|
||||
continue;
|
||||
|
||||
if (!state->ctm) {
|
||||
dspp->ops.setup_pcc(dspp, NULL);
|
||||
} else {
|
||||
_dpu_crtc_get_pcc_coeff(state, &cfg);
|
||||
dspp->ops.setup_pcc(dspp, &cfg);
|
||||
}
|
||||
|
||||
mixer[i].flush_mask |= ctl->ops.get_bitmask_dspp(ctl,
|
||||
mixer[i].hw_dspp->idx);
|
||||
|
||||
/* stage config flush mask */
|
||||
ctl->ops.update_pending_flush(ctl, mixer[i].flush_mask);
|
||||
|
||||
DPU_DEBUG("lm %d, ctl %d, flush mask 0x%x\n",
|
||||
mixer[i].hw_lm->idx - DSPP_0,
|
||||
ctl->idx - CTL_0,
|
||||
mixer[i].flush_mask);
|
||||
}
|
||||
}
|
||||
|
||||
static void dpu_crtc_atomic_begin(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *old_state)
|
||||
{
|
||||
@@ -430,7 +501,6 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc,
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_device *dev;
|
||||
unsigned long flags;
|
||||
struct dpu_crtc_smmu_state_data *smmu_state;
|
||||
|
||||
if (!crtc) {
|
||||
DPU_ERROR("invalid crtc\n");
|
||||
@@ -448,7 +518,6 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc,
|
||||
dpu_crtc = to_dpu_crtc(crtc);
|
||||
cstate = to_dpu_crtc_state(crtc->state);
|
||||
dev = crtc->dev;
|
||||
smmu_state = &dpu_crtc->smmu_state;
|
||||
|
||||
_dpu_crtc_setup_lm_bounds(crtc, crtc->state);
|
||||
|
||||
@@ -475,6 +544,8 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc,
|
||||
|
||||
_dpu_crtc_blend_setup(crtc);
|
||||
|
||||
_dpu_crtc_setup_cp_blocks(crtc);
|
||||
|
||||
/*
|
||||
* PP_DONE irq is only used by command mode for now.
|
||||
* It is better to request pending before FLUSH and START trigger
|
||||
@@ -491,7 +562,6 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc,
|
||||
struct drm_device *dev;
|
||||
struct drm_plane *plane;
|
||||
struct msm_drm_private *priv;
|
||||
struct msm_drm_thread *event_thread;
|
||||
unsigned long flags;
|
||||
struct dpu_crtc_state *cstate;
|
||||
|
||||
@@ -513,8 +583,6 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc,
|
||||
return;
|
||||
}
|
||||
|
||||
event_thread = &priv->event_thread[crtc->index];
|
||||
|
||||
if (dpu_crtc->event) {
|
||||
DPU_DEBUG("already received dpu_crtc->event\n");
|
||||
} else {
|
||||
@@ -567,7 +635,6 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc,
|
||||
static void dpu_crtc_destroy_state(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *state)
|
||||
{
|
||||
struct dpu_crtc *dpu_crtc;
|
||||
struct dpu_crtc_state *cstate;
|
||||
|
||||
if (!crtc || !state) {
|
||||
@@ -575,7 +642,6 @@ static void dpu_crtc_destroy_state(struct drm_crtc *crtc,
|
||||
return;
|
||||
}
|
||||
|
||||
dpu_crtc = to_dpu_crtc(crtc);
|
||||
cstate = to_dpu_crtc_state(state);
|
||||
|
||||
DPU_DEBUG("crtc%d\n", crtc->base.id);
|
||||
@@ -662,11 +728,9 @@ static void dpu_crtc_reset(struct drm_crtc *crtc)
|
||||
/**
|
||||
* dpu_crtc_duplicate_state - state duplicate hook
|
||||
* @crtc: Pointer to drm crtc structure
|
||||
* @Returns: Pointer to new drm_crtc_state structure
|
||||
*/
|
||||
static struct drm_crtc_state *dpu_crtc_duplicate_state(struct drm_crtc *crtc)
|
||||
{
|
||||
struct dpu_crtc *dpu_crtc;
|
||||
struct dpu_crtc_state *cstate, *old_cstate;
|
||||
|
||||
if (!crtc || !crtc->state) {
|
||||
@@ -674,7 +738,6 @@ static struct drm_crtc_state *dpu_crtc_duplicate_state(struct drm_crtc *crtc)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dpu_crtc = to_dpu_crtc(crtc);
|
||||
old_cstate = to_dpu_crtc_state(crtc->state);
|
||||
cstate = kmemdup(old_cstate, sizeof(*old_cstate), GFP_KERNEL);
|
||||
if (!cstate) {
|
||||
@@ -693,9 +756,7 @@ static void dpu_crtc_disable(struct drm_crtc *crtc,
|
||||
{
|
||||
struct dpu_crtc *dpu_crtc;
|
||||
struct dpu_crtc_state *cstate;
|
||||
struct drm_display_mode *mode;
|
||||
struct drm_encoder *encoder;
|
||||
struct msm_drm_private *priv;
|
||||
unsigned long flags;
|
||||
bool release_bandwidth = false;
|
||||
|
||||
@@ -705,8 +766,6 @@ static void dpu_crtc_disable(struct drm_crtc *crtc,
|
||||
}
|
||||
dpu_crtc = to_dpu_crtc(crtc);
|
||||
cstate = to_dpu_crtc_state(crtc->state);
|
||||
mode = &cstate->base.adjusted_mode;
|
||||
priv = crtc->dev->dev_private;
|
||||
|
||||
DRM_DEBUG_KMS("crtc%d\n", crtc->base.id);
|
||||
|
||||
@@ -768,14 +827,12 @@ static void dpu_crtc_enable(struct drm_crtc *crtc,
|
||||
{
|
||||
struct dpu_crtc *dpu_crtc;
|
||||
struct drm_encoder *encoder;
|
||||
struct msm_drm_private *priv;
|
||||
bool request_bandwidth;
|
||||
|
||||
if (!crtc) {
|
||||
DPU_ERROR("invalid crtc\n");
|
||||
return;
|
||||
}
|
||||
priv = crtc->dev->dev_private;
|
||||
|
||||
pm_runtime_get_sync(crtc->dev->dev);
|
||||
|
||||
@@ -1319,6 +1376,8 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane,
|
||||
|
||||
drm_crtc_helper_add(crtc, &dpu_crtc_helper_funcs);
|
||||
|
||||
drm_crtc_enable_color_mgmt(crtc, 0, true, 0);
|
||||
|
||||
/* save user friendly CRTC name for later */
|
||||
snprintf(dpu_crtc->name, DPU_CRTC_NAME_SIZE, "crtc%u", crtc->base.id);
|
||||
|
||||
|
@@ -73,12 +73,14 @@ struct dpu_crtc_smmu_state_data {
|
||||
* struct dpu_crtc_mixer: stores the map for each virtual pipeline in the CRTC
|
||||
* @hw_lm: LM HW Driver context
|
||||
* @lm_ctl: CTL Path HW driver context
|
||||
* @lm_dspp: DSPP HW driver context
|
||||
* @mixer_op_mode: mixer blending operation mode
|
||||
* @flush_mask: mixer flush mask for ctl, mixer and pipe
|
||||
*/
|
||||
struct dpu_crtc_mixer {
|
||||
struct dpu_hw_mixer *hw_lm;
|
||||
struct dpu_hw_ctl *lm_ctl;
|
||||
struct dpu_hw_dspp *hw_dspp;
|
||||
u32 mixer_op_mode;
|
||||
u32 flush_mask;
|
||||
};
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include "dpu_hw_catalog.h"
|
||||
#include "dpu_hw_intf.h"
|
||||
#include "dpu_hw_ctl.h"
|
||||
#include "dpu_hw_dspp.h"
|
||||
#include "dpu_formats.h"
|
||||
#include "dpu_encoder_phys.h"
|
||||
#include "dpu_crtc.h"
|
||||
@@ -536,6 +537,7 @@ static struct msm_display_topology dpu_encoder_get_topology(
|
||||
* 1 LM, 1 INTF
|
||||
* 2 LM, 1 INTF (stream merge to support high resolution interfaces)
|
||||
*
|
||||
* Adding color blocks only to primary interface
|
||||
*/
|
||||
if (intf_count == 2)
|
||||
topology.num_lm = 2;
|
||||
@@ -544,6 +546,9 @@ static struct msm_display_topology dpu_encoder_get_topology(
|
||||
else
|
||||
topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1;
|
||||
|
||||
if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_DSI)
|
||||
topology.num_dspp = topology.num_lm;
|
||||
|
||||
topology.num_enc = 0;
|
||||
topology.num_intf = intf_count;
|
||||
|
||||
@@ -959,7 +964,8 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
|
||||
struct dpu_hw_blk *hw_pp[MAX_CHANNELS_PER_ENC];
|
||||
struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
|
||||
struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
|
||||
int num_lm, num_ctl, num_pp;
|
||||
struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC] = { NULL };
|
||||
int num_lm, num_ctl, num_pp, num_dspp;
|
||||
int i, j;
|
||||
|
||||
if (!drm_enc) {
|
||||
@@ -1008,6 +1014,9 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
|
||||
drm_enc->base.id, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
|
||||
num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
|
||||
drm_enc->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
|
||||
num_dspp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
|
||||
drm_enc->base.id, DPU_HW_BLK_DSPP, hw_dspp,
|
||||
ARRAY_SIZE(hw_dspp));
|
||||
|
||||
for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
|
||||
dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
|
||||
@@ -1020,6 +1029,7 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
|
||||
|
||||
cstate->mixers[i].hw_lm = to_dpu_hw_mixer(hw_lm[i]);
|
||||
cstate->mixers[i].lm_ctl = to_dpu_hw_ctl(hw_ctl[ctl_idx]);
|
||||
cstate->mixers[i].hw_dspp = to_dpu_hw_dspp(hw_dspp[i]);
|
||||
}
|
||||
|
||||
cstate->num_mixers = num_lm;
|
||||
|
@@ -41,6 +41,8 @@
|
||||
#define PINGPONG_SDM845_SPLIT_MASK \
|
||||
(PINGPONG_SDM845_MASK | BIT(DPU_PINGPONG_TE2))
|
||||
|
||||
#define DSPP_SC7180_MASK BIT(DPU_DSPP_PCC)
|
||||
|
||||
#define DEFAULT_PIXEL_RAM_SIZE (50 * 1024)
|
||||
#define DEFAULT_DPU_LINE_WIDTH 2048
|
||||
#define DEFAULT_DPU_OUTPUT_LINE_WIDTH 2560
|
||||
@@ -291,29 +293,30 @@ static const struct dpu_lm_sub_blks sdm845_lm_sblk = {
|
||||
},
|
||||
};
|
||||
|
||||
#define LM_BLK(_name, _id, _base, _fmask, _sblk, _pp, _lmpair) \
|
||||
#define LM_BLK(_name, _id, _base, _fmask, _sblk, _pp, _lmpair, _dspp) \
|
||||
{ \
|
||||
.name = _name, .id = _id, \
|
||||
.base = _base, .len = 0x320, \
|
||||
.features = _fmask, \
|
||||
.sblk = _sblk, \
|
||||
.pingpong = _pp, \
|
||||
.lm_pair_mask = (1 << _lmpair) \
|
||||
.lm_pair_mask = (1 << _lmpair), \
|
||||
.dspp = _dspp \
|
||||
}
|
||||
|
||||
static const struct dpu_lm_cfg sdm845_lm[] = {
|
||||
LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK,
|
||||
&sdm845_lm_sblk, PINGPONG_0, LM_1),
|
||||
&sdm845_lm_sblk, PINGPONG_0, LM_1, 0),
|
||||
LM_BLK("lm_1", LM_1, 0x45000, MIXER_SDM845_MASK,
|
||||
&sdm845_lm_sblk, PINGPONG_1, LM_0),
|
||||
&sdm845_lm_sblk, PINGPONG_1, LM_0, 0),
|
||||
LM_BLK("lm_2", LM_2, 0x46000, MIXER_SDM845_MASK,
|
||||
&sdm845_lm_sblk, PINGPONG_2, LM_5),
|
||||
&sdm845_lm_sblk, PINGPONG_2, LM_5, 0),
|
||||
LM_BLK("lm_3", LM_3, 0x0, MIXER_SDM845_MASK,
|
||||
&sdm845_lm_sblk, PINGPONG_MAX, 0),
|
||||
&sdm845_lm_sblk, PINGPONG_MAX, 0, 0),
|
||||
LM_BLK("lm_4", LM_4, 0x0, MIXER_SDM845_MASK,
|
||||
&sdm845_lm_sblk, PINGPONG_MAX, 0),
|
||||
&sdm845_lm_sblk, PINGPONG_MAX, 0, 0),
|
||||
LM_BLK("lm_5", LM_5, 0x49000, MIXER_SDM845_MASK,
|
||||
&sdm845_lm_sblk, PINGPONG_3, LM_2),
|
||||
&sdm845_lm_sblk, PINGPONG_3, LM_2, 0),
|
||||
};
|
||||
|
||||
/* SC7180 */
|
||||
@@ -328,11 +331,30 @@ static const struct dpu_lm_sub_blks sc7180_lm_sblk = {
|
||||
|
||||
static const struct dpu_lm_cfg sc7180_lm[] = {
|
||||
LM_BLK("lm_0", LM_0, 0x44000, MIXER_SC7180_MASK,
|
||||
&sc7180_lm_sblk, PINGPONG_0, LM_1),
|
||||
&sc7180_lm_sblk, PINGPONG_0, LM_1, DSPP_0),
|
||||
LM_BLK("lm_1", LM_1, 0x45000, MIXER_SC7180_MASK,
|
||||
&sc7180_lm_sblk, PINGPONG_1, LM_0),
|
||||
&sc7180_lm_sblk, PINGPONG_1, LM_0, 0),
|
||||
};
|
||||
|
||||
/*************************************************************
|
||||
* DSPP sub blocks config
|
||||
*************************************************************/
|
||||
static const struct dpu_dspp_sub_blks sc7180_dspp_sblk = {
|
||||
.pcc = {.id = DPU_DSPP_PCC, .base = 0x1700,
|
||||
.len = 0x90, .version = 0x10000},
|
||||
};
|
||||
|
||||
#define DSPP_BLK(_name, _id, _base) \
|
||||
{\
|
||||
.name = _name, .id = _id, \
|
||||
.base = _base, .len = 0x1800, \
|
||||
.features = DSPP_SC7180_MASK, \
|
||||
.sblk = &sc7180_dspp_sblk \
|
||||
}
|
||||
|
||||
static const struct dpu_dspp_cfg sc7180_dspp[] = {
|
||||
DSPP_BLK("dspp_0", DSPP_0, 0x54000),
|
||||
};
|
||||
/*************************************************************
|
||||
* PINGPONG sub blocks config
|
||||
*************************************************************/
|
||||
@@ -515,8 +537,8 @@ static const struct dpu_perf_cfg sdm845_perf_data = {
|
||||
};
|
||||
|
||||
static const struct dpu_perf_cfg sc7180_perf_data = {
|
||||
.max_bw_low = 3900000,
|
||||
.max_bw_high = 5500000,
|
||||
.max_bw_low = 6800000,
|
||||
.max_bw_high = 6800000,
|
||||
.min_core_ib = 2400000,
|
||||
.min_llcc_ib = 800000,
|
||||
.min_dram_ib = 800000,
|
||||
@@ -587,6 +609,8 @@ static void sc7180_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
|
||||
.sspp = sc7180_sspp,
|
||||
.mixer_count = ARRAY_SIZE(sc7180_lm),
|
||||
.mixer = sc7180_lm,
|
||||
.dspp_count = ARRAY_SIZE(sc7180_dspp),
|
||||
.dspp = sc7180_dspp,
|
||||
.pingpong_count = ARRAY_SIZE(sc7180_pp),
|
||||
.pingpong = sc7180_pp,
|
||||
.intf_count = ARRAY_SIZE(sc7180_intf),
|
||||
|
@@ -145,6 +145,17 @@ enum {
|
||||
DPU_MIXER_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* DSPP sub-blocks
|
||||
* @DPU_DSPP_PCC Panel color correction block
|
||||
* @DPU_DSPP_GC Gamma correction block
|
||||
*/
|
||||
enum {
|
||||
DPU_DSPP_PCC = 0x1,
|
||||
DPU_DSPP_GC,
|
||||
DPU_DSPP_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* PINGPONG sub-blocks
|
||||
* @DPU_PINGPONG_TE Tear check block
|
||||
@@ -377,6 +388,16 @@ struct dpu_lm_sub_blks {
|
||||
struct dpu_pp_blk gc;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dpu_dspp_sub_blks: Information of DSPP block
|
||||
* @gc : gamma correction block
|
||||
* @pcc: pixel color correction block
|
||||
*/
|
||||
struct dpu_dspp_sub_blks {
|
||||
struct dpu_pp_blk gc;
|
||||
struct dpu_pp_blk pcc;
|
||||
};
|
||||
|
||||
struct dpu_pingpong_sub_blks {
|
||||
struct dpu_pp_blk te;
|
||||
struct dpu_pp_blk te2;
|
||||
@@ -471,9 +492,23 @@ struct dpu_lm_cfg {
|
||||
DPU_HW_BLK_INFO;
|
||||
const struct dpu_lm_sub_blks *sblk;
|
||||
u32 pingpong;
|
||||
u32 dspp;
|
||||
unsigned long lm_pair_mask;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dpu_dspp_cfg - information of DSPP blocks
|
||||
* @id enum identifying this block
|
||||
* @base register offset of this block
|
||||
* @features bit mask identifying sub-blocks/features
|
||||
* supported by this block
|
||||
* @sblk sub-blocks information
|
||||
*/
|
||||
struct dpu_dspp_cfg {
|
||||
DPU_HW_BLK_INFO;
|
||||
const struct dpu_dspp_sub_blks *sblk;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dpu_pingpong_cfg - information of PING-PONG blocks
|
||||
* @id enum identifying this block
|
||||
@@ -688,6 +723,9 @@ struct dpu_mdss_cfg {
|
||||
|
||||
u32 ad_count;
|
||||
|
||||
u32 dspp_count;
|
||||
const struct dpu_dspp_cfg *dspp;
|
||||
|
||||
/* Add additional block data structures here */
|
||||
|
||||
struct dpu_perf_cfg perf;
|
||||
@@ -716,6 +754,7 @@ struct dpu_mdss_hw_cfg_handler {
|
||||
#define BLK_PINGPONG(s) ((s)->pingpong)
|
||||
#define BLK_INTF(s) ((s)->intf)
|
||||
#define BLK_AD(s) ((s)->ad)
|
||||
#define BLK_DSPP(s) ((s)->dspp)
|
||||
|
||||
/**
|
||||
* dpu_hw_catalog_init - dpu hardware catalog init API retrieves
|
||||
|
@@ -272,6 +272,31 @@ static int dpu_hw_ctl_active_get_bitmask_intf(struct dpu_hw_ctl *ctx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t dpu_hw_ctl_get_bitmask_dspp(struct dpu_hw_ctl *ctx,
|
||||
enum dpu_dspp dspp)
|
||||
{
|
||||
uint32_t flushbits = 0;
|
||||
|
||||
switch (dspp) {
|
||||
case DSPP_0:
|
||||
flushbits = BIT(13);
|
||||
break;
|
||||
case DSPP_1:
|
||||
flushbits = BIT(14);
|
||||
break;
|
||||
case DSPP_2:
|
||||
flushbits = BIT(15);
|
||||
break;
|
||||
case DSPP_3:
|
||||
flushbits = BIT(21);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return flushbits;
|
||||
}
|
||||
|
||||
static u32 dpu_hw_ctl_poll_reset_status(struct dpu_hw_ctl *ctx, u32 timeout_us)
|
||||
{
|
||||
struct dpu_hw_blk_reg_map *c = &ctx->hw;
|
||||
@@ -548,6 +573,7 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
|
||||
ops->setup_blendstage = dpu_hw_ctl_setup_blendstage;
|
||||
ops->get_bitmask_sspp = dpu_hw_ctl_get_bitmask_sspp;
|
||||
ops->get_bitmask_mixer = dpu_hw_ctl_get_bitmask_mixer;
|
||||
ops->get_bitmask_dspp = dpu_hw_ctl_get_bitmask_dspp;
|
||||
};
|
||||
|
||||
static struct dpu_hw_blk_ops dpu_hw_ops;
|
||||
|
@@ -139,6 +139,9 @@ struct dpu_hw_ctl_ops {
|
||||
uint32_t (*get_bitmask_mixer)(struct dpu_hw_ctl *ctx,
|
||||
enum dpu_lm blk);
|
||||
|
||||
uint32_t (*get_bitmask_dspp)(struct dpu_hw_ctl *ctx,
|
||||
enum dpu_dspp blk);
|
||||
|
||||
/**
|
||||
* Query the value of the intf flush mask
|
||||
* No effect on hardware
|
||||
|
@@ -0,0 +1,129 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "dpu_hwio.h"
|
||||
#include "dpu_hw_catalog.h"
|
||||
#include "dpu_hw_lm.h"
|
||||
#include "dpu_hw_dspp.h"
|
||||
#include "dpu_kms.h"
|
||||
|
||||
|
||||
/* DSPP_PCC */
|
||||
#define PCC_EN BIT(0)
|
||||
#define PCC_DIS 0
|
||||
#define PCC_RED_R_OFF 0x10
|
||||
#define PCC_RED_G_OFF 0x1C
|
||||
#define PCC_RED_B_OFF 0x28
|
||||
#define PCC_GREEN_R_OFF 0x14
|
||||
#define PCC_GREEN_G_OFF 0x20
|
||||
#define PCC_GREEN_B_OFF 0x2C
|
||||
#define PCC_BLUE_R_OFF 0x18
|
||||
#define PCC_BLUE_G_OFF 0x24
|
||||
#define PCC_BLUE_B_OFF 0x30
|
||||
|
||||
static void dpu_setup_dspp_pcc(struct dpu_hw_dspp *ctx,
|
||||
struct dpu_hw_pcc_cfg *cfg)
|
||||
{
|
||||
|
||||
u32 base = ctx->cap->sblk->pcc.base;
|
||||
|
||||
if (!ctx || !base) {
|
||||
DRM_ERROR("invalid ctx %pK pcc base 0x%x\n", ctx, base);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cfg) {
|
||||
DRM_DEBUG_DRIVER("disable pcc feature\n");
|
||||
DPU_REG_WRITE(&ctx->hw, base, PCC_DIS);
|
||||
return;
|
||||
}
|
||||
|
||||
DPU_REG_WRITE(&ctx->hw, base + PCC_RED_R_OFF, cfg->r.r);
|
||||
DPU_REG_WRITE(&ctx->hw, base + PCC_RED_G_OFF, cfg->r.g);
|
||||
DPU_REG_WRITE(&ctx->hw, base + PCC_RED_B_OFF, cfg->r.b);
|
||||
|
||||
DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_R_OFF, cfg->g.r);
|
||||
DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_G_OFF, cfg->g.g);
|
||||
DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_B_OFF, cfg->g.b);
|
||||
|
||||
DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_R_OFF, cfg->b.r);
|
||||
DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_G_OFF, cfg->b.g);
|
||||
DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_B_OFF, cfg->b.b);
|
||||
|
||||
DPU_REG_WRITE(&ctx->hw, base, PCC_EN);
|
||||
}
|
||||
|
||||
static void _setup_dspp_ops(struct dpu_hw_dspp *c,
|
||||
unsigned long features)
|
||||
{
|
||||
if (test_bit(DPU_DSPP_PCC, &features) &&
|
||||
IS_SC7180_TARGET(c->hw.hwversion))
|
||||
c->ops.setup_pcc = dpu_setup_dspp_pcc;
|
||||
}
|
||||
|
||||
static const struct dpu_dspp_cfg *_dspp_offset(enum dpu_dspp dspp,
|
||||
const struct dpu_mdss_cfg *m,
|
||||
void __iomem *addr,
|
||||
struct dpu_hw_blk_reg_map *b)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!m || !addr || !b)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
for (i = 0; i < m->dspp_count; i++) {
|
||||
if (dspp == m->dspp[i].id) {
|
||||
b->base_off = addr;
|
||||
b->blk_off = m->dspp[i].base;
|
||||
b->length = m->dspp[i].len;
|
||||
b->hwversion = m->hwversion;
|
||||
b->log_mask = DPU_DBG_MASK_DSPP;
|
||||
return &m->dspp[i];
|
||||
}
|
||||
}
|
||||
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static struct dpu_hw_blk_ops dpu_hw_ops;
|
||||
|
||||
struct dpu_hw_dspp *dpu_hw_dspp_init(enum dpu_dspp idx,
|
||||
void __iomem *addr,
|
||||
const struct dpu_mdss_cfg *m)
|
||||
{
|
||||
struct dpu_hw_dspp *c;
|
||||
const struct dpu_dspp_cfg *cfg;
|
||||
|
||||
if (!addr || !m)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
c = kzalloc(sizeof(*c), GFP_KERNEL);
|
||||
if (!c)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
cfg = _dspp_offset(idx, m, addr, &c->hw);
|
||||
if (IS_ERR_OR_NULL(cfg)) {
|
||||
kfree(c);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
/* Assign ops */
|
||||
c->idx = idx;
|
||||
c->cap = cfg;
|
||||
_setup_dspp_ops(c, c->cap->features);
|
||||
|
||||
dpu_hw_blk_init(&c->base, DPU_HW_BLK_DSPP, idx, &dpu_hw_ops);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void dpu_hw_dspp_destroy(struct dpu_hw_dspp *dspp)
|
||||
{
|
||||
if (dspp)
|
||||
dpu_hw_blk_destroy(&dspp->base);
|
||||
|
||||
kfree(dspp);
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,100 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DPU_HW_DSPP_H
|
||||
#define _DPU_HW_DSPP_H
|
||||
|
||||
#include "dpu_hw_blk.h"
|
||||
|
||||
struct dpu_hw_dspp;
|
||||
|
||||
/**
|
||||
* struct dpu_hw_pcc_coeff - PCC coefficient structure for each color
|
||||
* component.
|
||||
* @r: red coefficient.
|
||||
* @g: green coefficient.
|
||||
* @b: blue coefficient.
|
||||
*/
|
||||
|
||||
struct dpu_hw_pcc_coeff {
|
||||
__u32 r;
|
||||
__u32 g;
|
||||
__u32 b;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dpu_hw_pcc - pcc feature structure
|
||||
* @r: red coefficients.
|
||||
* @g: green coefficients.
|
||||
* @b: blue coefficients.
|
||||
*/
|
||||
struct dpu_hw_pcc_cfg {
|
||||
struct dpu_hw_pcc_coeff r;
|
||||
struct dpu_hw_pcc_coeff g;
|
||||
struct dpu_hw_pcc_coeff b;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dpu_hw_dspp_ops - interface to the dspp hardware driver functions
|
||||
* Caller must call the init function to get the dspp context for each dspp
|
||||
* Assumption is these functions will be called after clocks are enabled
|
||||
*/
|
||||
struct dpu_hw_dspp_ops {
|
||||
/**
|
||||
* setup_pcc - setup dspp pcc
|
||||
* @ctx: Pointer to dspp context
|
||||
* @cfg: Pointer to configuration
|
||||
*/
|
||||
void (*setup_pcc)(struct dpu_hw_dspp *ctx, struct dpu_hw_pcc_cfg *cfg);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dpu_hw_dspp - dspp description
|
||||
* @base: Hardware block base structure
|
||||
* @hw: Block hardware details
|
||||
* @idx: DSPP index
|
||||
* @cap: Pointer to layer_cfg
|
||||
* @ops: Pointer to operations possible for this DSPP
|
||||
*/
|
||||
struct dpu_hw_dspp {
|
||||
struct dpu_hw_blk base;
|
||||
struct dpu_hw_blk_reg_map hw;
|
||||
|
||||
/* dspp */
|
||||
int idx;
|
||||
const struct dpu_dspp_cfg *cap;
|
||||
|
||||
/* Ops */
|
||||
struct dpu_hw_dspp_ops ops;
|
||||
};
|
||||
|
||||
/**
|
||||
* dpu_hw_dspp - convert base object dpu_hw_base to container
|
||||
* @hw: Pointer to base hardware block
|
||||
* return: Pointer to hardware block container
|
||||
*/
|
||||
static inline struct dpu_hw_dspp *to_dpu_hw_dspp(struct dpu_hw_blk *hw)
|
||||
{
|
||||
return container_of(hw, struct dpu_hw_dspp, base);
|
||||
}
|
||||
|
||||
/**
|
||||
* dpu_hw_dspp_init - initializes the dspp hw driver object.
|
||||
* should be called once before accessing every dspp.
|
||||
* @idx: DSPP index for which driver object is required
|
||||
* @addr: Mapped register io address of MDP
|
||||
* @Return: pointer to structure or ERR_PTR
|
||||
*/
|
||||
struct dpu_hw_dspp *dpu_hw_dspp_init(enum dpu_dspp idx,
|
||||
void __iomem *addr, const struct dpu_mdss_cfg *m);
|
||||
|
||||
/**
|
||||
* dpu_hw_dspp_destroy(): Destroys DSPP driver context
|
||||
* @dspp: Pointer to DSPP driver context
|
||||
*/
|
||||
void dpu_hw_dspp_destroy(struct dpu_hw_dspp *dspp);
|
||||
|
||||
#endif /*_DPU_HW_DSPP_H */
|
||||
|
@@ -95,6 +95,7 @@ enum dpu_hw_blk_type {
|
||||
DPU_HW_BLK_PINGPONG,
|
||||
DPU_HW_BLK_INTF,
|
||||
DPU_HW_BLK_WB,
|
||||
DPU_HW_BLK_DSPP,
|
||||
DPU_HW_BLK_MAX,
|
||||
};
|
||||
|
||||
@@ -425,5 +426,6 @@ struct dpu_mdss_color {
|
||||
#define DPU_DBG_MASK_TOP (1 << 7)
|
||||
#define DPU_DBG_MASK_VBIF (1 << 8)
|
||||
#define DPU_DBG_MASK_ROT (1 << 9)
|
||||
#define DPU_DBG_MASK_DSPP (1 << 10)
|
||||
|
||||
#endif /* _DPU_HW_MDSS_H */
|
||||
|
@@ -772,29 +772,21 @@ static int _dpu_kms_mmu_init(struct dpu_kms *dpu_kms)
|
||||
{
|
||||
struct iommu_domain *domain;
|
||||
struct msm_gem_address_space *aspace;
|
||||
int ret;
|
||||
struct msm_mmu *mmu;
|
||||
|
||||
domain = iommu_domain_alloc(&platform_bus_type);
|
||||
if (!domain)
|
||||
return 0;
|
||||
|
||||
domain->geometry.aperture_start = 0x1000;
|
||||
domain->geometry.aperture_end = 0xffffffff;
|
||||
mmu = msm_iommu_new(dpu_kms->dev->dev, domain);
|
||||
aspace = msm_gem_address_space_create(mmu, "dpu1",
|
||||
0x1000, 0xfffffff);
|
||||
|
||||
aspace = msm_gem_address_space_create(dpu_kms->dev->dev,
|
||||
domain, "dpu1");
|
||||
if (IS_ERR(aspace)) {
|
||||
iommu_domain_free(domain);
|
||||
mmu->funcs->destroy(mmu);
|
||||
return PTR_ERR(aspace);
|
||||
}
|
||||
|
||||
ret = aspace->mmu->funcs->attach(aspace->mmu);
|
||||
if (ret) {
|
||||
DPU_ERROR("failed to attach iommu %d\n", ret);
|
||||
msm_gem_address_space_put(aspace);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dpu_kms->base.aspace = aspace;
|
||||
return 0;
|
||||
}
|
||||
|
@@ -158,6 +158,7 @@ struct dpu_global_state {
|
||||
uint32_t mixer_to_enc_id[LM_MAX - LM_0];
|
||||
uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
|
||||
uint32_t intf_to_enc_id[INTF_MAX - INTF_0];
|
||||
uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
|
||||
};
|
||||
|
||||
struct dpu_global_state
|
||||
|
@@ -9,6 +9,7 @@
|
||||
#include "dpu_hw_ctl.h"
|
||||
#include "dpu_hw_pingpong.h"
|
||||
#include "dpu_hw_intf.h"
|
||||
#include "dpu_hw_dspp.h"
|
||||
#include "dpu_encoder.h"
|
||||
#include "dpu_trace.h"
|
||||
|
||||
@@ -174,6 +175,23 @@ int dpu_rm_init(struct dpu_rm *rm,
|
||||
rm->ctl_blks[ctl->id - CTL_0] = &hw->base;
|
||||
}
|
||||
|
||||
for (i = 0; i < cat->dspp_count; i++) {
|
||||
struct dpu_hw_dspp *hw;
|
||||
const struct dpu_dspp_cfg *dspp = &cat->dspp[i];
|
||||
|
||||
if (dspp->id < DSPP_0 || dspp->id >= DSPP_MAX) {
|
||||
DPU_ERROR("skip dspp %d with invalid id\n", dspp->id);
|
||||
continue;
|
||||
}
|
||||
hw = dpu_hw_dspp_init(dspp->id, mmio, cat);
|
||||
if (IS_ERR_OR_NULL(hw)) {
|
||||
rc = PTR_ERR(hw);
|
||||
DPU_ERROR("failed dspp object creation: err %d\n", rc);
|
||||
goto fail;
|
||||
}
|
||||
rm->dspp_blks[dspp->id - DSPP_0] = &hw->base;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@@ -222,12 +240,17 @@ static bool _dpu_rm_check_lm_peer(struct dpu_rm *rm, int primary_idx,
|
||||
* if lm, and all other hardwired blocks connected to the lm (pp) is
|
||||
* available and appropriate
|
||||
* @pp_idx: output parameter, index of pingpong block attached to the layer
|
||||
* mixer in rm->pongpong_blks[].
|
||||
* mixer in rm->pingpong_blks[].
|
||||
* @dspp_idx: output parameter, index of dspp block attached to the layer
|
||||
* mixer in rm->dspp_blks[].
|
||||
* @reqs: input parameter, rm requirements for HW blocks needed in the
|
||||
* datapath.
|
||||
* @Return: true if lm matches all requirements, false otherwise
|
||||
*/
|
||||
static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
|
||||
struct dpu_global_state *global_state,
|
||||
uint32_t enc_id, int lm_idx, int *pp_idx)
|
||||
uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx,
|
||||
struct dpu_rm_requirements *reqs)
|
||||
{
|
||||
const struct dpu_lm_cfg *lm_cfg;
|
||||
int idx;
|
||||
@@ -251,6 +274,23 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
|
||||
return false;
|
||||
}
|
||||
*pp_idx = idx;
|
||||
|
||||
if (!reqs->topology.num_dspp)
|
||||
return true;
|
||||
|
||||
idx = lm_cfg->dspp - DSPP_0;
|
||||
if (idx < 0 || idx >= ARRAY_SIZE(rm->dspp_blks)) {
|
||||
DPU_ERROR("failed to get dspp on lm %d\n", lm_cfg->dspp);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (reserved_by_other(global_state->dspp_to_enc_id, idx, enc_id)) {
|
||||
DPU_DEBUG("lm %d dspp %d already reserved\n", lm_cfg->id,
|
||||
lm_cfg->dspp);
|
||||
return false;
|
||||
}
|
||||
*dspp_idx = idx;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -262,6 +302,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
|
||||
{
|
||||
int lm_idx[MAX_BLOCKS];
|
||||
int pp_idx[MAX_BLOCKS];
|
||||
int dspp_idx[MAX_BLOCKS] = {0};
|
||||
int i, j, lm_count = 0;
|
||||
|
||||
if (!reqs->topology.num_lm) {
|
||||
@@ -279,7 +320,8 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
|
||||
lm_idx[lm_count] = i;
|
||||
|
||||
if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state,
|
||||
enc_id, i, &pp_idx[lm_count])) {
|
||||
enc_id, i, &pp_idx[lm_count],
|
||||
&dspp_idx[lm_count], reqs)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -299,7 +341,8 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
|
||||
|
||||
if (!_dpu_rm_check_lm_and_get_connected_blks(rm,
|
||||
global_state, enc_id, j,
|
||||
&pp_idx[lm_count])) {
|
||||
&pp_idx[lm_count], &dspp_idx[lm_count],
|
||||
reqs)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -316,6 +359,8 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
|
||||
for (i = 0; i < lm_count; i++) {
|
||||
global_state->mixer_to_enc_id[lm_idx[i]] = enc_id;
|
||||
global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id;
|
||||
global_state->dspp_to_enc_id[dspp_idx[i]] =
|
||||
reqs->topology.num_dspp ? enc_id : 0;
|
||||
|
||||
trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id,
|
||||
pp_idx[i] + PINGPONG_0);
|
||||
@@ -560,6 +605,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
|
||||
hw_to_enc_id = global_state->intf_to_enc_id;
|
||||
max_blks = ARRAY_SIZE(rm->intf_blks);
|
||||
break;
|
||||
case DPU_HW_BLK_DSPP:
|
||||
hw_blks = rm->dspp_blks;
|
||||
hw_to_enc_id = global_state->dspp_to_enc_id;
|
||||
max_blks = ARRAY_SIZE(rm->dspp_blks);
|
||||
break;
|
||||
default:
|
||||
DPU_ERROR("blk type %d not managed by rm\n", type);
|
||||
return 0;
|
||||
|
@@ -19,6 +19,7 @@ struct dpu_global_state;
|
||||
* @mixer_blks: array of layer mixer hardware resources
|
||||
* @ctl_blks: array of ctl hardware resources
|
||||
* @intf_blks: array of intf hardware resources
|
||||
* @dspp_blks: array of dspp hardware resources
|
||||
* @lm_max_width: cached layer mixer maximum width
|
||||
* @rm_lock: resource manager mutex
|
||||
*/
|
||||
@@ -27,6 +28,7 @@ struct dpu_rm {
|
||||
struct dpu_hw_blk *mixer_blks[LM_MAX - LM_0];
|
||||
struct dpu_hw_blk *ctl_blks[CTL_MAX - CTL_0];
|
||||
struct dpu_hw_blk *intf_blks[INTF_MAX - INTF_0];
|
||||
struct dpu_hw_blk *dspp_blks[DSPP_MAX - DSPP_0];
|
||||
|
||||
uint32_t lm_max_width;
|
||||
};
|
||||
|
@@ -510,18 +510,20 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
|
||||
mdelay(16);
|
||||
|
||||
if (config->iommu) {
|
||||
aspace = msm_gem_address_space_create(&pdev->dev,
|
||||
config->iommu, "mdp4");
|
||||
struct msm_mmu *mmu = msm_iommu_new(&pdev->dev,
|
||||
config->iommu);
|
||||
|
||||
aspace = msm_gem_address_space_create(mmu,
|
||||
"mdp4", 0x1000, 0xffffffff);
|
||||
|
||||
if (IS_ERR(aspace)) {
|
||||
if (!IS_ERR(mmu))
|
||||
mmu->funcs->destroy(mmu);
|
||||
ret = PTR_ERR(aspace);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
kms->aspace = aspace;
|
||||
|
||||
ret = aspace->mmu->funcs->attach(aspace->mmu);
|
||||
if (ret)
|
||||
goto fail;
|
||||
} else {
|
||||
DRM_DEV_INFO(dev->dev, "no iommu, fallback to phys "
|
||||
"contig buffers for scanout\n");
|
||||
@@ -569,10 +571,6 @@ static struct mdp4_platform_config *mdp4_get_config(struct platform_device *dev)
|
||||
/* TODO: Chips that aren't apq8064 have a 200 Mhz max_clk */
|
||||
config.max_clk = 266667000;
|
||||
config.iommu = iommu_domain_alloc(&platform_bus_type);
|
||||
if (config.iommu) {
|
||||
config.iommu->geometry.aperture_start = 0x1000;
|
||||
config.iommu->geometry.aperture_end = 0xffffffff;
|
||||
}
|
||||
|
||||
return &config;
|
||||
}
|
||||
|
@@ -342,6 +342,81 @@ static const struct mdp5_cfg_hw msm8x16_config = {
|
||||
.max_clk = 320000000,
|
||||
};
|
||||
|
||||
static const struct mdp5_cfg_hw msm8x36_config = {
|
||||
.name = "msm8x36",
|
||||
.mdp = {
|
||||
.count = 1,
|
||||
.base = { 0x0 },
|
||||
.caps = MDP_CAP_SMP |
|
||||
0,
|
||||
},
|
||||
.smp = {
|
||||
.mmb_count = 8,
|
||||
.mmb_size = 10240,
|
||||
.clients = {
|
||||
[SSPP_VIG0] = 1, [SSPP_DMA0] = 4,
|
||||
[SSPP_RGB0] = 7, [SSPP_RGB1] = 8,
|
||||
},
|
||||
},
|
||||
.ctl = {
|
||||
.count = 3,
|
||||
.base = { 0x01000, 0x01200, 0x01400 },
|
||||
.flush_hw_mask = 0x4003ffff,
|
||||
},
|
||||
.pipe_vig = {
|
||||
.count = 1,
|
||||
.base = { 0x04000 },
|
||||
.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 = { 0x14000, 0x16000 },
|
||||
.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
|
||||
MDP_PIPE_CAP_DECIMATION,
|
||||
},
|
||||
.pipe_dma = {
|
||||
.count = 1,
|
||||
.base = { 0x24000 },
|
||||
.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
|
||||
},
|
||||
.lm = {
|
||||
.count = 2,
|
||||
.base = { 0x44000, 0x47000 },
|
||||
.instances = {
|
||||
{ .id = 0, .pp = 0, .dspp = 0,
|
||||
.caps = MDP_LM_CAP_DISPLAY, },
|
||||
{ .id = 1, .pp = -1, .dspp = -1,
|
||||
.caps = MDP_LM_CAP_WB, },
|
||||
},
|
||||
.nb_stages = 8,
|
||||
.max_width = 2560,
|
||||
.max_height = 0xFFFF,
|
||||
},
|
||||
.pp = {
|
||||
.count = 1,
|
||||
.base = { 0x70000 },
|
||||
},
|
||||
.ad = {
|
||||
.count = 1,
|
||||
.base = { 0x78000 },
|
||||
},
|
||||
.dspp = {
|
||||
.count = 1,
|
||||
.base = { 0x54000 },
|
||||
},
|
||||
.intf = {
|
||||
.base = { 0x00000, 0x6a800, 0x6b000 },
|
||||
.connect = {
|
||||
[0] = INTF_DISABLED,
|
||||
[1] = INTF_DSI,
|
||||
[2] = INTF_DSI,
|
||||
},
|
||||
},
|
||||
.max_clk = 366670000,
|
||||
};
|
||||
|
||||
static const struct mdp5_cfg_hw msm8x94_config = {
|
||||
.name = "msm8x94",
|
||||
.mdp = {
|
||||
@@ -840,6 +915,7 @@ static const struct mdp5_cfg_handler cfg_handlers_v1[] = {
|
||||
{ .revision = 2, .config = { .hw = &msm8x74v2_config } },
|
||||
{ .revision = 3, .config = { .hw = &apq8084_config } },
|
||||
{ .revision = 6, .config = { .hw = &msm8x16_config } },
|
||||
{ .revision = 8, .config = { .hw = &msm8x36_config } },
|
||||
{ .revision = 9, .config = { .hw = &msm8x94_config } },
|
||||
{ .revision = 7, .config = { .hw = &msm8x96_config } },
|
||||
{ .revision = 11, .config = { .hw = &msm8x76_config } },
|
||||
@@ -941,10 +1017,6 @@ static struct mdp5_cfg_platform *mdp5_get_config(struct platform_device *dev)
|
||||
static struct mdp5_cfg_platform config = {};
|
||||
|
||||
config.iommu = iommu_domain_alloc(&platform_bus_type);
|
||||
if (config.iommu) {
|
||||
config.iommu->geometry.aperture_start = 0x1000;
|
||||
config.iommu->geometry.aperture_end = 0xffffffff;
|
||||
}
|
||||
|
||||
return &config;
|
||||
}
|
||||
|
@@ -959,7 +959,7 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
|
||||
if (!ctl)
|
||||
return -EINVAL;
|
||||
|
||||
/* don't support LM cursors when we we have source split enabled */
|
||||
/* don't support LM cursors when we have source split enabled */
|
||||
if (mdp5_cstate->pipeline.r_mixer)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1030,7 +1030,7 @@ static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* don't support LM cursors when we we have source split enabled */
|
||||
/* don't support LM cursors when we have source split enabled */
|
||||
if (mdp5_cstate->pipeline.r_mixer)
|
||||
return -EINVAL;
|
||||
|
||||
|
@@ -624,25 +624,25 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
|
||||
mdelay(16);
|
||||
|
||||
if (config->platform.iommu) {
|
||||
struct msm_mmu *mmu;
|
||||
|
||||
iommu_dev = &pdev->dev;
|
||||
if (!dev_iommu_fwspec_get(iommu_dev))
|
||||
iommu_dev = iommu_dev->parent;
|
||||
|
||||
aspace = msm_gem_address_space_create(iommu_dev,
|
||||
config->platform.iommu, "mdp5");
|
||||
mmu = msm_iommu_new(iommu_dev, config->platform.iommu);
|
||||
|
||||
aspace = msm_gem_address_space_create(mmu, "mdp5",
|
||||
0x1000, 0xffffffff);
|
||||
|
||||
if (IS_ERR(aspace)) {
|
||||
if (!IS_ERR(mmu))
|
||||
mmu->funcs->destroy(mmu);
|
||||
ret = PTR_ERR(aspace);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
kms->aspace = aspace;
|
||||
|
||||
ret = aspace->mmu->funcs->attach(aspace->mmu);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(&pdev->dev, "failed to attach iommu: %d\n",
|
||||
ret);
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
DRM_DEV_INFO(&pdev->dev,
|
||||
"no iommu, fallback to phys contig buffers for scanout\n");
|
||||
@@ -935,7 +935,8 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev)
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
mdp5_destroy(pdev);
|
||||
if (mdp5_kms)
|
||||
mdp5_destroy(pdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
在新工单中引用
屏蔽一个用户