diff options
| author | Dhaval Patel <pdhaval@quicinc.com> | 2016-09-20 11:12:58 -0700 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-09-20 11:12:58 -0700 |
| commit | cbecc661e13a6a91b5bc9012a4545369a3cbacff (patch) | |
| tree | 587c0c20a9554a496c21cc441b9586deee5bb6d1 /drivers/gpu | |
| parent | 31e9c42150079bbea616b744836c65a317d4b635 (diff) | |
| parent | b936dbe66168a0b046ae5283955d0d68d9bc73de (diff) | |
Merge "drm/msm/sde: add danger/safe/QoS support for source pipe" into dev/msm-4.4-drm_kms
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_hw_catalog.h | 26 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c | 44 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_hw_sspp.c | 64 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_hw_sspp.h | 47 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_kms.c | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_plane.c | 341 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_trace.h | 80 |
7 files changed, 570 insertions, 35 deletions
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h index 72a22c1616d7..e84558e35d2e 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h +++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h @@ -77,6 +77,7 @@ enum { * @SDE_SSPP_IGC, Inverse gamma correction * @SDE_SSPP_PCC, Color correction support * @SDE_SSPP_CURSOR, SSPP can be used as a cursor layer + * @SDE_SSPP_QOS, SSPP support QoS control, danger/safe/creq * @SDE_SSPP_MAX maximum value */ enum { @@ -90,6 +91,7 @@ enum { SDE_SSPP_IGC, SDE_SSPP_PCC, SDE_SSPP_CURSOR, + SDE_SSPP_QOS, SDE_SSPP_MAX }; @@ -257,8 +259,16 @@ struct sde_format_extended { * @maxdwnscale: max downscale ratio supported(without DECIMATION) * @maxupscale: maxupscale ratio supported * @maxwidth: max pixelwidth supported by this pipe - * @danger_lut: LUT to generate danger signals - * @safe_lut: LUT to generate safe signals + * @danger_lut_linear: LUT to generate danger signals for linear format + * @safe_lut_linear: LUT to generate safe signals for linear format + * @danger_lut_tile: LUT to generate danger signals for tile format + * @safe_lut_tile: LUT to generate safe signals for tile format + * @danger_lut_nrt: LUT to generate danger signals for non-realtime use case + * @safe_lut_nrt: LUT to generate safe signals for non-realtime use case + * @creq_lut_nrt: LUT to generate creq signals for non-realtime use case + * @creq_vblank: creq priority during vertical blanking + * @danger_vblank: danger priority during vertical blanking + * @pixel_ram_size: size of latency hiding and de-tiling buffer in bytes * @src_blk: * @scaler_blk: * @csc_blk: @@ -269,8 +279,16 @@ struct sde_format_extended { */ struct sde_sspp_sub_blks { u32 maxlinewidth; - u32 danger_lut; - u32 safe_lut; + u32 danger_lut_linear; + u32 safe_lut_linear; + u32 danger_lut_tile; + u32 safe_lut_tile; + u32 danger_lut_nrt; + u32 safe_lut_nrt; + u32 creq_lut_nrt; + u32 creq_vblank; + u32 danger_vblank; + u32 pixel_ram_size; u32 maxdwnscale; u32 maxupscale; u32 maxhdeciexp; /* max decimation is 2^value */ diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c index 93ac6b69f26e..d8c6fa38b60d 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c @@ -19,17 +19,17 @@ (BIT(SDE_SSPP_SRC) | BIT(SDE_SSPP_SCALER_QSEED2) |\ BIT(SDE_SSPP_CSC) | BIT(SDE_SSPP_PA_V1) |\ BIT(SDE_SSPP_HIST_V1) | BIT(SDE_SSPP_PCC) |\ - BIT(SDE_SSPP_IGC)) + BIT(SDE_SSPP_IGC) | BIT(SDE_SSPP_QOS)) /* RGB layer capability */ #define RGB_17X_MASK \ (BIT(SDE_SSPP_SRC) | BIT(SDE_SSPP_SCALER_RGB) |\ - BIT(SDE_SSPP_PCC) | BIT(SDE_SSPP_IGC)) + BIT(SDE_SSPP_PCC) | BIT(SDE_SSPP_IGC) | BIT(SDE_SSPP_QOS)) /* DMA layer capability */ #define DMA_17X_MASK \ (BIT(SDE_SSPP_SRC) | BIT(SDE_SSPP_PA_V1) |\ - BIT(SDE_SSPP_PCC) | BIT(SDE_SSPP_IGC)) + BIT(SDE_SSPP_PCC) | BIT(SDE_SSPP_IGC) | BIT(SDE_SSPP_QOS)) /* Cursor layer capability */ #define CURSOR_17X_MASK (BIT(SDE_SSPP_SRC) | BIT(SDE_SSPP_CURSOR)) @@ -232,8 +232,16 @@ static inline int set_cfg_1xx_init(struct sde_mdss_cfg *cfg) /* Layer capability */ static const struct sde_sspp_sub_blks vig_layer = { .maxlinewidth = 2560, - .danger_lut = 0xFFFF, - .safe_lut = 0xFF00, + .danger_lut_linear = 0x000f, + .safe_lut_linear = 0xfffc, + .danger_lut_tile = 0xffff, + .safe_lut_tile = 0xff00, + .danger_lut_nrt = 0x0, + .safe_lut_nrt = 0xffff, + .creq_lut_nrt = 0x0, + .creq_vblank = 0x2, + .danger_vblank = 0, + .pixel_ram_size = 50 * 1024, .maxdwnscale = 4, .maxupscale = 20, .maxhdeciexp = DECIMATION_17X_MAX_H, .maxvdeciexp = DECIMATION_17X_MAX_V, @@ -254,8 +262,16 @@ static inline int set_cfg_1xx_init(struct sde_mdss_cfg *cfg) static const struct sde_sspp_sub_blks layer = { .maxlinewidth = 2560, - .danger_lut = 0xFFFF, - .safe_lut = 0xFF00, + .danger_lut_linear = 0x000f, + .safe_lut_linear = 0xfffc, + .danger_lut_tile = 0xffff, + .safe_lut_tile = 0xff00, + .danger_lut_nrt = 0x0, + .safe_lut_nrt = 0xffff, + .creq_lut_nrt = 0x0, + .creq_vblank = 0x2, + .danger_vblank = 0, + .pixel_ram_size = 50 * 1024, .maxdwnscale = 4, .maxupscale = 20, .maxhdeciexp = DECIMATION_17X_MAX_H, .maxvdeciexp = DECIMATION_17X_MAX_V, @@ -276,8 +292,16 @@ static inline int set_cfg_1xx_init(struct sde_mdss_cfg *cfg) static const struct sde_sspp_sub_blks dma = { .maxlinewidth = 2560, - .danger_lut = 0xFFFF, - .safe_lut = 0xFF00, + .danger_lut_linear = 0x000f, + .safe_lut_linear = 0xfffc, + .danger_lut_tile = 0xffff, + .safe_lut_tile = 0xff00, + .danger_lut_nrt = 0x0, + .safe_lut_nrt = 0xffff, + .creq_lut_nrt = 0x0, + .creq_vblank = 0x2, + .danger_vblank = 0, + .pixel_ram_size = 50 * 1024, .maxdwnscale = 1, .maxupscale = 1, .maxhdeciexp = DECIMATION_17X_MAX_H, .maxvdeciexp = DECIMATION_17X_MAX_V, @@ -292,8 +316,6 @@ static inline int set_cfg_1xx_init(struct sde_mdss_cfg *cfg) static const struct sde_sspp_sub_blks cursor = { .maxlinewidth = 128, - .danger_lut = 0xFFFF, - .safe_lut = 0xFF00, .maxdwnscale = 1, .maxupscale = 1, .maxhdeciexp = DECIMATION_17X_MAX_H, .maxvdeciexp = DECIMATION_17X_MAX_V, diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c index 400a5539ce8b..65a0f0f86a3a 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c @@ -50,6 +50,7 @@ #define SSPP_DANGER_LUT 0x60 #define SSPP_SAFE_LUT 0x64 #define SSPP_CREQ_LUT 0x68 +#define SSPP_QOS_CTRL 0x6C #define SSPP_DECIMATION_CONFIG 0xB4 #define SSPP_SRC_ADDR_SW_STATUS 0x70 #define SSPP_SW_PIX_EXT_C0_LR 0x100 @@ -64,6 +65,14 @@ #define SSPP_UBWC_ERROR_STATUS 0x138 #define SSPP_VIG_OP_MODE 0x0 +/* SSPP_QOS_CTRL */ +#define SSPP_QOS_CTRL_VBLANK_EN BIT(16) +#define SSPP_QOS_CTRL_DANGER_SAFE_EN BIT(0) +#define SSPP_QOS_CTRL_DANGER_VBLANK_MASK 0x3 +#define SSPP_QOS_CTRL_DANGER_VBLANK_OFF 4 +#define SSPP_QOS_CTRL_CREQ_VBLANK_MASK 0x3 +#define SSPP_QOS_CTRL_CREQ_VBLANK_OFF 20 + /* SDE_SSPP_SCALER_QSEED2 */ #define SCALE_CONFIG 0x04 #define COMP0_3_PHASE_STEP_X 0x10 @@ -470,16 +479,52 @@ void sde_sspp_setup_pa(struct sde_hw_pipe *c) { } -static void sde_hw_sspp_setup_danger_safe(struct sde_hw_pipe *ctx, - u32 danger_lut, u32 safe_lut) +static void sde_hw_sspp_setup_danger_safe_lut(struct sde_hw_pipe *ctx, + struct sde_hw_pipe_qos_cfg *cfg) +{ + u32 idx; + + if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx)) + return; + + SDE_REG_WRITE(&ctx->hw, SSPP_DANGER_LUT + idx, cfg->danger_lut); + SDE_REG_WRITE(&ctx->hw, SSPP_SAFE_LUT + idx, cfg->safe_lut); +} + +static void sde_hw_sspp_setup_creq_lut(struct sde_hw_pipe *ctx, + struct sde_hw_pipe_qos_cfg *cfg) +{ + u32 idx; + + if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx)) + return; + + SDE_REG_WRITE(&ctx->hw, SSPP_CREQ_LUT + idx, cfg->creq_lut); +} + +static void sde_hw_sspp_setup_qos_ctrl(struct sde_hw_pipe *ctx, + struct sde_hw_pipe_qos_cfg *cfg) { u32 idx; + u32 qos_ctrl = 0; if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx)) return; - SDE_REG_WRITE(&ctx->hw, SSPP_DANGER_LUT + idx, danger_lut); - SDE_REG_WRITE(&ctx->hw, SSPP_SAFE_LUT + idx, safe_lut); + if (cfg->vblank_en) { + qos_ctrl |= ((cfg->creq_vblank & + SSPP_QOS_CTRL_CREQ_VBLANK_MASK) << + SSPP_QOS_CTRL_CREQ_VBLANK_OFF); + qos_ctrl |= ((cfg->danger_vblank & + SSPP_QOS_CTRL_DANGER_VBLANK_MASK) << + SSPP_QOS_CTRL_DANGER_VBLANK_OFF); + qos_ctrl |= SSPP_QOS_CTRL_VBLANK_EN; + } + + if (cfg->danger_safe_en) + qos_ctrl |= SSPP_QOS_CTRL_DANGER_SAFE_EN; + + SDE_REG_WRITE(&ctx->hw, SSPP_QOS_CTRL + idx, qos_ctrl); } static void sde_hw_sspp_qseed2_coeff(void *ctx) @@ -494,7 +539,11 @@ static void _setup_layer_ops(struct sde_hw_sspp_ops *ops, ops->setup_rects = sde_hw_sspp_setup_rects; ops->setup_sourceaddress = sde_hw_sspp_setup_sourceaddress; ops->setup_solidfill = sde_hw_sspp_setup_solidfill; - ops->setup_danger_safe = sde_hw_sspp_setup_danger_safe; + } + if (test_bit(SDE_SSPP_QOS, &features)) { + ops->setup_danger_safe_lut = sde_hw_sspp_setup_danger_safe_lut; + ops->setup_creq_lut = sde_hw_sspp_setup_creq_lut; + ops->setup_qos_ctrl = sde_hw_sspp_setup_qos_ctrl; } if (test_bit(SDE_SSPP_CSC, &features)) ops->setup_csc = sde_hw_sspp_setup_csc; @@ -561,11 +610,6 @@ struct sde_hw_pipe *sde_hw_sspp_init(enum sde_sspp idx, if (test_bit(SDE_SSPP_SCALER_QSEED2, &cfg->features)) sde_hw_sspp_qseed2_coeff(ctx); - if (test_bit(SDE_MDP_PANIC_PER_PIPE, &catalog->mdp[0].features)) - sde_hw_sspp_setup_danger_safe(ctx, - cfg->sblk->danger_lut, - cfg->sblk->safe_lut); - return ctx; } diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.h b/drivers/gpu/drm/msm/sde/sde_hw_sspp.h index 7eb4981f79c5..43070faa5f1c 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.h +++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.h @@ -145,13 +145,23 @@ struct sde_hw_pipe_cfg { }; /** - * struct danger_safe_cfg: - * @danger_lut: - * @safe_lut: + * struct sde_hw_pipe_qos_cfg : Source pipe QoS configuration + * @danger_lut: LUT for generate danger level based on fill level + * @safe_lut: LUT for generate safe level based on fill level + * @creq_lut: LUT for generate creq level based on fill level + * @creq_vblank: creq value generated to vbif during vertical blanking + * @danger_vblank: danger value generated during vertical blanking + * @vblank_en: enable creq_vblank and danger_vblank during vblank + * @danger_safe_en: enable danger safe generation */ -struct danger_safe_cfg { +struct sde_hw_pipe_qos_cfg { u32 danger_lut; u32 safe_lut; + u32 creq_lut; + u32 creq_vblank; + u32 danger_vblank; + bool vblank_en; + bool danger_safe_en; }; /** @@ -226,14 +236,31 @@ struct sde_hw_sspp_ops { void (*setup_igc)(struct sde_hw_pipe *ctx); /** - * setup_danger_safe - setup danger safe LUTS + * setup_danger_safe_lut - setup danger safe LUTs * @ctx: Pointer to pipe context - * @danger_lut: Danger LUT setting - * @safe_lut: Safe LUT setting + * @cfg: Pointer to pipe QoS configuration + * */ - void (*setup_danger_safe)(struct sde_hw_pipe *ctx, - u32 danger_lut, - u32 safe_lut); + void (*setup_danger_safe_lut)(struct sde_hw_pipe *ctx, + struct sde_hw_pipe_qos_cfg *cfg); + + /** + * setup_creq_lut - setup CREQ LUT + * @ctx: Pointer to pipe context + * @cfg: Pointer to pipe QoS configuration + * + */ + void (*setup_creq_lut)(struct sde_hw_pipe *ctx, + struct sde_hw_pipe_qos_cfg *cfg); + + /** + * setup_qos_ctrl - setup QoS control + * @ctx: Pointer to pipe context + * @cfg: Pointer to pipe QoS configuration + * + */ + void (*setup_qos_ctrl)(struct sde_hw_pipe *ctx, + struct sde_hw_pipe_qos_cfg *cfg); /** * setup_histogram - setup histograms diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c index 55f19ce7a337..a255303a109b 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -21,6 +21,9 @@ #include "sde_hw_util.h" #include "sde_hw_intf.h" +#define CREATE_TRACE_POINTS +#include "sde_trace.h" + static const char * const iommu_ports[] = { "mdp_0", }; diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c index 53c7699b13d6..12de055d82ed 100644 --- a/drivers/gpu/drm/msm/sde/sde_plane.c +++ b/drivers/gpu/drm/msm/sde/sde_plane.c @@ -9,6 +9,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ + +#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ + #include <linux/debugfs.h> #include <uapi/drm/sde_drm.h> @@ -18,6 +21,7 @@ #include "sde_fence.h" #include "sde_formats.h" #include "sde_hw_sspp.h" +#include "sde_trace.h" #define DECIMATED_DIMENSION(dim, deci) (((dim) + ((1 << (deci)) - 1)) >> (deci)) #define PHASE_STEP_SHIFT 21 @@ -33,6 +37,20 @@ #define SDE_PLANE_COLOR_FILL_FLAG BIT(31) +/** + * enum sde_plane_qos - Different qos configurations for each pipe + * + * @SDE_PLANE_QOS_VBLANK_CTRL: Setup VBLANK qos for the pipe. + * @SDE_PLANE_QOS_VBLANK_AMORTIZE: Enables Amortization within pipe. + * this configuration is mutually exclusive from VBLANK_CTRL. + * @SDE_PLANE_QOS_PANIC_CTRL: Setup panic for the pipe. + */ +enum sde_plane_qos { + SDE_PLANE_QOS_VBLANK_CTRL = BIT(0), + SDE_PLANE_QOS_VBLANK_AMORTIZE = BIT(1), + SDE_PLANE_QOS_PANIC_CTRL = BIT(2), +}; + struct sde_plane { struct drm_plane base; @@ -50,8 +68,10 @@ struct sde_plane { struct sde_hw_pixel_ext pixel_ext; struct sde_hw_sharp_cfg sharp_cfg; struct sde_hw_scaler3_cfg scaler3_cfg; + struct sde_hw_pipe_qos_cfg pipe_qos_cfg; uint32_t color_fill; bool is_error; + bool is_rt_pipe; struct sde_csc_cfg csc_cfg; struct sde_csc_cfg *csc_ptr; @@ -78,6 +98,315 @@ static bool sde_plane_enabled(struct drm_plane_state *state) return state && state->fb && state->crtc; } +/** + * _sde_plane_calc_fill_level - calculate fill level of the given source format + * @plane: Pointer to drm plane + * @fmt: Pointer to source buffer format + * @src_wdith: width of source buffer + * Return: fill level corresponding to the source buffer/format or 0 if error + */ +static inline int _sde_plane_calc_fill_level(struct drm_plane *plane, + const struct sde_format *fmt, u32 src_width) +{ + struct sde_plane *psde; + u32 fixed_buff_size; + u32 total_fl; + + if (!plane || !fmt) { + SDE_ERROR("invalid arguments\n"); + return 0; + } + + psde = to_sde_plane(plane); + fixed_buff_size = psde->pipe_sblk->pixel_ram_size; + + if (fmt->fetch_planes == SDE_PLANE_PSEUDO_PLANAR) { + if (fmt->chroma_sample == SDE_CHROMA_420) { + /* NV12 */ + total_fl = (fixed_buff_size / 2) / + ((src_width + 32) * fmt->bpp); + } else { + /* non NV12 */ + total_fl = (fixed_buff_size) / + ((src_width + 32) * fmt->bpp); + } + } else { + total_fl = (fixed_buff_size * 2) / + ((src_width + 32) * fmt->bpp); + } + + SDE_DEBUG("plane%u: pnum:%d fmt:%x w:%u fl:%u\n", + plane->base.id, psde->pipe - SSPP_VIG0, + fmt->base.pixel_format, src_width, total_fl); + + return total_fl; +} + +/** + * _sde_plane_get_qos_lut_linear - get linear LUT mapping + * @total_fl: fill level + * Return: LUT setting corresponding to the fill level + */ +static inline u32 _sde_plane_get_qos_lut_linear(u32 total_fl) +{ + u32 qos_lut; + + if (total_fl <= 4) + qos_lut = 0x1B; + else if (total_fl <= 5) + qos_lut = 0x5B; + else if (total_fl <= 6) + qos_lut = 0x15B; + else if (total_fl <= 7) + qos_lut = 0x55B; + else if (total_fl <= 8) + qos_lut = 0x155B; + else if (total_fl <= 9) + qos_lut = 0x555B; + else if (total_fl <= 10) + qos_lut = 0x1555B; + else if (total_fl <= 11) + qos_lut = 0x5555B; + else if (total_fl <= 12) + qos_lut = 0x15555B; + else + qos_lut = 0x55555B; + + return qos_lut; +} + +/** + * _sde_plane_get_qos_lut_macrotile - get macrotile LUT mapping + * @total_fl: fill level + * Return: LUT setting corresponding to the fill level + */ +static inline u32 _sde_plane_get_qos_lut_macrotile(u32 total_fl) +{ + u32 qos_lut; + + if (total_fl <= 10) + qos_lut = 0x1AAff; + else if (total_fl <= 11) + qos_lut = 0x5AAFF; + else if (total_fl <= 12) + qos_lut = 0x15AAFF; + else + qos_lut = 0x55AAFF; + + return qos_lut; +} + +/** + * _sde_plane_is_rt_pipe - check if the given plane requires real-time QoS + * @plane: Pointer to drm plane + * @crtc: Pointer to drm crtc associated with the given plane + */ +static bool _sde_plane_is_rt_pipe(struct drm_plane *plane, + struct drm_crtc *crtc) +{ + struct sde_plane *psde = to_sde_plane(plane); + struct drm_connector *connector; + bool is_rt = false; + + /* check if this plane has a physical connector interface */ + drm_for_each_connector(connector, plane->dev) + if (connector->state && + (connector->state->crtc == crtc) && + (connector->connector_type + != DRM_MODE_CONNECTOR_VIRTUAL)) { + is_rt = true; + break; + } + + SDE_DEBUG("plane%u: pnum:%d rt:%d\n", + plane->base.id, psde->pipe - SSPP_VIG0, is_rt); + + return is_rt; +} + +/** + * _sde_plane_set_qos_lut - set QoS LUT of the given plane + * @plane: Pointer to drm plane + * @fb: Pointer to framebuffer associated with the given plane + */ +static void _sde_plane_set_qos_lut(struct drm_plane *plane, + struct drm_framebuffer *fb) +{ + struct sde_plane *psde; + const struct sde_format *fmt = NULL; + u32 qos_lut; + u32 total_fl = 0; + + if (!plane || !fb) { + SDE_ERROR("invalid arguments plane %d fb %d\n", + plane != 0, fb != 0); + return; + } + + psde = to_sde_plane(plane); + + if (!psde->pipe_hw || !psde->pipe_sblk) { + SDE_ERROR("invalid arguments\n"); + return; + } else if (!psde->pipe_hw->ops.setup_creq_lut) { + return; + } + + if (!psde->is_rt_pipe) { + qos_lut = psde->pipe_sblk->creq_lut_nrt; + } else { + fmt = sde_get_sde_format_ext( + fb->pixel_format, + fb->modifier, + drm_format_num_planes(fb->pixel_format)); + total_fl = _sde_plane_calc_fill_level(plane, fmt, + psde->pipe_cfg.src_rect.w); + + if (SDE_FORMAT_IS_LINEAR(fmt)) + qos_lut = _sde_plane_get_qos_lut_linear(total_fl); + else + qos_lut = _sde_plane_get_qos_lut_macrotile(total_fl); + } + + psde->pipe_qos_cfg.creq_lut = qos_lut; + + trace_sde_perf_set_qos_luts(psde->pipe - SSPP_VIG0, + (fmt) ? fmt->base.pixel_format : 0, + psde->is_rt_pipe, total_fl, qos_lut, + (fmt) ? SDE_FORMAT_IS_LINEAR(fmt) : 0); + + SDE_DEBUG("plane%u: pnum:%d fmt:%x rt:%d fl:%u lut:0x%x\n", + plane->base.id, + psde->pipe - SSPP_VIG0, + (fmt) ? fmt->base.pixel_format : 0, + psde->is_rt_pipe, total_fl, qos_lut); + + psde->pipe_hw->ops.setup_creq_lut(psde->pipe_hw, &psde->pipe_qos_cfg); +} + +/** + * _sde_plane_set_panic_lut - set danger/safe LUT of the given plane + * @plane: Pointer to drm plane + * @fb: Pointer to framebuffer associated with the given plane + */ +static void _sde_plane_set_danger_lut(struct drm_plane *plane, + struct drm_framebuffer *fb) +{ + struct sde_plane *psde; + const struct sde_format *fmt = NULL; + u32 danger_lut, safe_lut; + + if (!plane || !fb) { + SDE_ERROR("invalid arguments\n"); + return; + } + + psde = to_sde_plane(plane); + + if (!psde->pipe_hw || !psde->pipe_sblk) { + SDE_ERROR("invalid arguments\n"); + return; + } else if (!psde->pipe_hw->ops.setup_danger_safe_lut) { + return; + } + + if (!psde->is_rt_pipe) { + danger_lut = psde->pipe_sblk->danger_lut_nrt; + safe_lut = psde->pipe_sblk->safe_lut_nrt; + } else { + fmt = sde_get_sde_format_ext( + fb->pixel_format, + fb->modifier, + drm_format_num_planes(fb->pixel_format)); + + if (SDE_FORMAT_IS_LINEAR(fmt)) { + danger_lut = psde->pipe_sblk->danger_lut_linear; + safe_lut = psde->pipe_sblk->safe_lut_linear; + } else { + danger_lut = psde->pipe_sblk->danger_lut_tile; + safe_lut = psde->pipe_sblk->safe_lut_tile; + } + } + + psde->pipe_qos_cfg.danger_lut = danger_lut; + psde->pipe_qos_cfg.safe_lut = safe_lut; + + trace_sde_perf_set_danger_luts(psde->pipe - SSPP_VIG0, + (fmt) ? fmt->base.pixel_format : 0, + (fmt) ? fmt->fetch_mode : 0, + psde->pipe_qos_cfg.danger_lut, + psde->pipe_qos_cfg.safe_lut); + + SDE_DEBUG("plane%u: pnum:%d fmt:%x mode:%d luts[0x%x, 0x%x]\n", + plane->base.id, + psde->pipe - SSPP_VIG0, + fmt ? fmt->base.pixel_format : 0, + fmt ? fmt->fetch_mode : -1, + psde->pipe_qos_cfg.danger_lut, + psde->pipe_qos_cfg.safe_lut); + + psde->pipe_hw->ops.setup_danger_safe_lut(psde->pipe_hw, + &psde->pipe_qos_cfg); +} + +/** + * _sde_plane_set_qos_ctrl - set QoS control of the given plane + * @plane: Pointer to drm plane + * @enable: true to enable QoS control + * @flags: QoS control mode (enum sde_plane_qos) + */ +static void _sde_plane_set_qos_ctrl(struct drm_plane *plane, + bool enable, u32 flags) +{ + struct sde_plane *psde; + + if (!plane) { + SDE_ERROR("invalid arguments\n"); + return; + } + + psde = to_sde_plane(plane); + + if (!psde->pipe_hw || !psde->pipe_sblk) { + SDE_ERROR("invalid arguments\n"); + return; + } else if (!psde->pipe_hw->ops.setup_qos_ctrl) { + return; + } + + if (flags & SDE_PLANE_QOS_VBLANK_CTRL) { + psde->pipe_qos_cfg.creq_vblank = psde->pipe_sblk->creq_vblank; + psde->pipe_qos_cfg.danger_vblank = + psde->pipe_sblk->danger_vblank; + psde->pipe_qos_cfg.vblank_en = enable; + } + + if (flags & SDE_PLANE_QOS_VBLANK_AMORTIZE) { + /* this feature overrules previous VBLANK_CTRL */ + psde->pipe_qos_cfg.vblank_en = false; + psde->pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */ + } + + if (flags & SDE_PLANE_QOS_PANIC_CTRL) + psde->pipe_qos_cfg.danger_safe_en = enable; + + if (!psde->is_rt_pipe) { + psde->pipe_qos_cfg.vblank_en = false; + psde->pipe_qos_cfg.danger_safe_en = false; + } + + SDE_DEBUG("plane%u: pnum:%d ds:%d vb:%d pri[0x%x, 0x%x]\n", + plane->base.id, + psde->pipe - SSPP_VIG0, + psde->pipe_qos_cfg.danger_safe_en, + psde->pipe_qos_cfg.vblank_en, + psde->pipe_qos_cfg.creq_vblank, + psde->pipe_qos_cfg.danger_vblank); + + psde->pipe_hw->ops.setup_qos_ctrl(psde->pipe_hw, + &psde->pipe_qos_cfg); +} + /* helper to update a state's input fence pointer from the property */ static void _sde_plane_set_input_fence(struct drm_plane *plane, struct sde_plane_state *pstate, uint64_t fd) @@ -709,6 +1038,10 @@ static int _sde_plane_mode_set(struct drm_plane *plane, fmt = to_sde_format(msm_framebuffer_format(fb)); nplanes = fmt->num_planes; + psde->is_rt_pipe = _sde_plane_is_rt_pipe(plane, crtc); + + _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL); + POPULATE_RECT(&src, state->src_x, state->src_y, state->src_w, state->src_h, q16_data); POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, @@ -779,6 +1112,12 @@ static int _sde_plane_mode_set(struct drm_plane *plane, else psde->csc_ptr = 0; + _sde_plane_set_qos_lut(plane, fb); + _sde_plane_set_danger_lut(plane, fb); + + if (plane->type != DRM_PLANE_TYPE_CURSOR) + _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL); + return 0; } @@ -1264,6 +1603,8 @@ static void sde_plane_destroy(struct drm_plane *plane) if (plane) { psde = to_sde_plane(plane); + _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL); + debugfs_remove_recursive(psde->debugfs_root); if (psde->blob_info) diff --git a/drivers/gpu/drm/msm/sde/sde_trace.h b/drivers/gpu/drm/msm/sde/sde_trace.h new file mode 100644 index 000000000000..ba1181cc6119 --- /dev/null +++ b/drivers/gpu/drm/msm/sde/sde_trace.h @@ -0,0 +1,80 @@ +/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only 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. + */ + +#if !defined(_SDE_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) +#define _SDE_TRACE_H_ + +#include <linux/stringify.h> +#include <linux/types.h> +#include <linux/tracepoint.h> + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM sde +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE sde_trace + +TRACE_EVENT(sde_perf_set_qos_luts, + TP_PROTO(u32 pnum, u32 fmt, bool rt, u32 fl, + u32 lut, bool linear), + TP_ARGS(pnum, fmt, rt, fl, lut, linear), + TP_STRUCT__entry( + __field(u32, pnum) + __field(u32, fmt) + __field(bool, rt) + __field(u32, fl) + __field(u32, lut) + __field(bool, linear) + ), + TP_fast_assign( + __entry->pnum = pnum; + __entry->fmt = fmt; + __entry->rt = rt; + __entry->fl = fl; + __entry->lut = lut; + __entry->linear = linear; + ), + TP_printk("pnum=%d fmt=%x rt=%d fl=%d lut=0x%x lin=%d", + __entry->pnum, __entry->fmt, + __entry->rt, __entry->fl, + __entry->lut, __entry->linear) +); + +TRACE_EVENT(sde_perf_set_danger_luts, + TP_PROTO(u32 pnum, u32 fmt, u32 mode, u32 danger_lut, + u32 safe_lut), + TP_ARGS(pnum, fmt, mode, danger_lut, safe_lut), + TP_STRUCT__entry( + __field(u32, pnum) + __field(u32, fmt) + __field(u32, mode) + __field(u32, danger_lut) + __field(u32, safe_lut) + ), + TP_fast_assign( + __entry->pnum = pnum; + __entry->fmt = fmt; + __entry->mode = mode; + __entry->danger_lut = danger_lut; + __entry->safe_lut = safe_lut; + ), + TP_printk("pnum=%d fmt=%x mode=%d luts[0x%x, 0x%x]", + __entry->pnum, __entry->fmt, + __entry->mode, __entry->danger_lut, + __entry->safe_lut) +); + +#endif /* _SDE_TRACE_H_ */ + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#include <trace/define_trace.h> |
