summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDhaval Patel <pdhaval@quicinc.com>2016-09-20 11:12:58 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-09-20 11:12:58 -0700
commitcbecc661e13a6a91b5bc9012a4545369a3cbacff (patch)
tree587c0c20a9554a496c21cc441b9586deee5bb6d1 /drivers/gpu
parent31e9c42150079bbea616b744836c65a317d4b635 (diff)
parentb936dbe66168a0b046ae5283955d0d68d9bc73de (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.h26
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c44
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_sspp.c64
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_sspp.h47
-rw-r--r--drivers/gpu/drm/msm/sde/sde_kms.c3
-rw-r--r--drivers/gpu/drm/msm/sde/sde_plane.c341
-rw-r--r--drivers/gpu/drm/msm/sde/sde_trace.h80
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>