drm/msm/sde: explicitly enumerate supported plane formats
Explicitly list supported formats rather than attempting to
infer what is supported based on h/w features. This makes
the determination of supported formats more reliable, and
also opens the way to account for different h/w blocks
supporting different sets of formats.
Change-Id: I39b223638c2c126d57eee5551a57c7b8fd7cb1f5
Signed-off-by: Clarence Ip <cip@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 74050e2..8dca108 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -74,6 +74,7 @@
/* blob properties, always put these first */
PLANE_PROP_SCALER,
PLANE_PROP_CSC,
+ PLANE_PROP_SDE_INFO,
/* # of blob properties */
PLANE_PROP_BLOBCOUNT,
diff --git a/drivers/gpu/drm/msm/sde/sde_formats.c b/drivers/gpu/drm/msm/sde/sde_formats.c
index 25dac8c..ac14bad 100644
--- a/drivers/gpu/drm/msm/sde/sde_formats.c
+++ b/drivers/gpu/drm/msm/sde/sde_formats.c
@@ -814,21 +814,34 @@
return NULL;
}
-uint32_t sde_populate_formats(uint32_t *pixel_formats,
- uint32_t pixel_formats_max, bool rgb_only)
+uint32_t sde_populate_formats(
+ const struct sde_format_extended *format_list,
+ uint32_t *pixel_formats,
+ uint64_t *pixel_modifiers,
+ uint32_t pixel_formats_max)
{
- uint32_t i;
+ uint32_t i, fourcc_format;
- for (i = 0; i < ARRAY_SIZE(sde_format_map); i++) {
- const struct sde_format *fmt = &sde_format_map[i];
+ if (!format_list || !pixel_formats)
+ return 0;
- if (i == pixel_formats_max)
- break;
+ for (i = 0, fourcc_format = 0;
+ format_list->fourcc_format && i < pixel_formats_max;
+ ++format_list) {
+ /* verify if listed format is in sde_format_map? */
- if (rgb_only && SDE_FORMAT_IS_YUV(fmt))
- continue;
-
- pixel_formats[i] = fmt->base.pixel_format;
+ /* optionally return modified formats */
+ if (pixel_modifiers) {
+ /* assume same modifier for all fb planes */
+ pixel_formats[i] = format_list->fourcc_format;
+ pixel_modifiers[i++] = format_list->modifier;
+ } else {
+ /* assume base formats grouped together */
+ if (fourcc_format != format_list->fourcc_format) {
+ fourcc_format = format_list->fourcc_format;
+ pixel_formats[i++] = fourcc_format;
+ }
+ }
}
return i;
diff --git a/drivers/gpu/drm/msm/sde/sde_formats.h b/drivers/gpu/drm/msm/sde/sde_formats.h
index 3400b14..c890484 100644
--- a/drivers/gpu/drm/msm/sde/sde_formats.h
+++ b/drivers/gpu/drm/msm/sde/sde_formats.h
@@ -45,16 +45,17 @@
/**
* sde_populate_formats - populate the given array with fourcc codes supported
- * @pixel_formats: array to populate with fourcc codes
- * @max_formats: length of pixel formats array
- * @rgb_only: exclude any non-rgb formats from the list
- *
+ * @format_list: pointer to list of possible formats
+ * @pixel_formats: array to populate with fourcc codes
+ * @pixel_modifiers: array to populate with drm modifiers, can be NULL
+ * @pixel_formats_max: length of pixel formats array
* Return: number of elements populated
*/
uint32_t sde_populate_formats(
+ const struct sde_format_extended *format_list,
uint32_t *pixel_formats,
- uint32_t max_formats,
- bool rgb_only);
+ uint64_t *pixel_modifiers,
+ uint32_t pixel_formats_max);
/**
* sde_format_check_modified_format - validate format and buffers for
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
index 0b0effa..c2d8eac 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
@@ -223,6 +223,17 @@
};
/**
+ * struct sde_format_extended - define sde specific pixel format+modifier
+ * @fourcc_format: Base FOURCC pixel format code
+ * @modifier: 64-bit drm format modifier, same modifier must be applied to all
+ * framebuffer planes
+ */
+struct sde_format_extended {
+ uint32_t fourcc_format;
+ uint64_t modifier;
+};
+
+/**
* struct sde_sspp_sub_blks : SSPP sub-blocks
* @maxdwnscale: max downscale ratio supported(without DECIMATION)
* @maxupscale: maxupscale ratio supported
@@ -235,6 +246,7 @@
* @pa_blk:
* @hist_lut:
* @pcc_blk:
+ * @format_list: Pointer to list of supported formats
*/
struct sde_sspp_sub_blks {
u32 maxlinewidth;
@@ -250,6 +262,8 @@
struct sde_pp_blk pa_blk;
struct sde_pp_blk hist_lut;
struct sde_pp_blk pcc_blk;
+
+ const struct sde_format_extended *format_list;
};
/**
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 7a4542a..e0094bc 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c
@@ -61,6 +61,84 @@
#define DECIMATION_17X_MAX_H 4
#define DECIMATION_17X_MAX_V 4
+static const struct sde_format_extended plane_formats[] = {
+ {DRM_FORMAT_ARGB8888, 0},
+ {DRM_FORMAT_ABGR8888, 0},
+ {DRM_FORMAT_RGBA8888, 0},
+ {DRM_FORMAT_RGBA8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
+ {DRM_FORMAT_BGRA8888, 0},
+ {DRM_FORMAT_XRGB8888, 0},
+ {DRM_FORMAT_RGBX8888, 0},
+ {DRM_FORMAT_RGBX8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
+ {DRM_FORMAT_RGB888, 0},
+ {DRM_FORMAT_BGR888, 0},
+ {DRM_FORMAT_RGB565, 0},
+ {DRM_FORMAT_RGB565, DRM_FORMAT_MOD_QCOM_COMPRESSED},
+ {DRM_FORMAT_BGR565, 0},
+ {DRM_FORMAT_ARGB1555, 0},
+ {DRM_FORMAT_ABGR1555, 0},
+ {DRM_FORMAT_RGBA5551, 0},
+ {DRM_FORMAT_BGRA5551, 0},
+ {DRM_FORMAT_XRGB1555, 0},
+ {DRM_FORMAT_XBGR1555, 0},
+ {DRM_FORMAT_RGBX5551, 0},
+ {DRM_FORMAT_BGRX5551, 0},
+ {DRM_FORMAT_ARGB4444, 0},
+ {DRM_FORMAT_ABGR4444, 0},
+ {DRM_FORMAT_RGBA4444, 0},
+ {DRM_FORMAT_BGRA4444, 0},
+ {DRM_FORMAT_XRGB4444, 0},
+ {DRM_FORMAT_XBGR4444, 0},
+ {DRM_FORMAT_RGBX4444, 0},
+ {DRM_FORMAT_BGRX4444, 0},
+ {0, 0},
+};
+
+static const struct sde_format_extended plane_formats_yuv[] = {
+ {DRM_FORMAT_ARGB8888, 0},
+ {DRM_FORMAT_ABGR8888, 0},
+ {DRM_FORMAT_RGBA8888, 0},
+ {DRM_FORMAT_RGBA8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
+ {DRM_FORMAT_BGRA8888, 0},
+ {DRM_FORMAT_XRGB8888, 0},
+ {DRM_FORMAT_RGBX8888, 0},
+ {DRM_FORMAT_RGBX8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
+ {DRM_FORMAT_RGB888, 0},
+ {DRM_FORMAT_BGR888, 0},
+ {DRM_FORMAT_RGB565, 0},
+ {DRM_FORMAT_RGB565, DRM_FORMAT_MOD_QCOM_COMPRESSED},
+ {DRM_FORMAT_BGR565, 0},
+ {DRM_FORMAT_ARGB1555, 0},
+ {DRM_FORMAT_ABGR1555, 0},
+ {DRM_FORMAT_RGBA5551, 0},
+ {DRM_FORMAT_BGRA5551, 0},
+ {DRM_FORMAT_XRGB1555, 0},
+ {DRM_FORMAT_XBGR1555, 0},
+ {DRM_FORMAT_RGBX5551, 0},
+ {DRM_FORMAT_BGRX5551, 0},
+ {DRM_FORMAT_ARGB4444, 0},
+ {DRM_FORMAT_ABGR4444, 0},
+ {DRM_FORMAT_RGBA4444, 0},
+ {DRM_FORMAT_BGRA4444, 0},
+ {DRM_FORMAT_XRGB4444, 0},
+ {DRM_FORMAT_XBGR4444, 0},
+ {DRM_FORMAT_RGBX4444, 0},
+ {DRM_FORMAT_BGRX4444, 0},
+
+ {DRM_FORMAT_NV12, 0},
+ {DRM_FORMAT_NV12, DRM_FORMAT_MOD_QCOM_COMPRESSED},
+ {DRM_FORMAT_NV21, 0},
+ {DRM_FORMAT_NV16, 0},
+ {DRM_FORMAT_NV61, 0},
+ {DRM_FORMAT_VYUY, 0},
+ {DRM_FORMAT_UYVY, 0},
+ {DRM_FORMAT_YUYV, 0},
+ {DRM_FORMAT_YVYU, 0},
+ {DRM_FORMAT_YUV420, 0},
+ {DRM_FORMAT_YVU420, 0},
+ {0, 0},
+};
+
/**
* set_cfg_1xx_init(): populate sde sub-blocks reg offsets and instance counts
*/
@@ -68,6 +146,28 @@
{
/* Layer capability */
+ static const struct sde_sspp_sub_blks vig_layer = {
+ .maxlinewidth = 2560,
+ .danger_lut = 0xFFFF,
+ .safe_lut = 0xFF00,
+ .maxdwnscale = 4, .maxupscale = 20,
+ .maxhdeciexp = DECIMATION_17X_MAX_H,
+ .maxvdeciexp = DECIMATION_17X_MAX_V,
+ .src_blk = {.id = SDE_SSPP_SRC,
+ .base = 0x00, .len = 0x150,},
+ .scaler_blk = {.id = SDE_SSPP_SCALER_QSEED2,
+ .base = 0x200, .len = 0x70,},
+ .csc_blk = {.id = SDE_SSPP_CSC,
+ .base = 0x320, .len = 0x44,},
+ .pa_blk = {.id = SDE_SSPP_PA_V1,
+ .base = 0x200, .len = 0x0,},
+ .hist_lut = {.id = SDE_SSPP_HIST_V1,
+ .base = 0xA00, .len = 0x400,},
+ .pcc_blk = {.id = SDE_SSPP_PCC,
+ .base = 0x1780, .len = 0x64,},
+ .format_list = plane_formats_yuv,
+ };
+
static const struct sde_sspp_sub_blks layer = {
.maxlinewidth = 2560,
.danger_lut = 0xFFFF,
@@ -87,6 +187,7 @@
.base = 0xA00, .len = 0x400,},
.pcc_blk = {.id = SDE_SSPP_PCC,
.base = 0x1780, .len = 0x64,},
+ .format_list = plane_formats,
};
static const struct sde_sspp_sub_blks dma = {
@@ -102,6 +203,7 @@
.pa_blk = {.id = 0, .base = 0x200, .len = 0x0,},
.hist_lut = {.id = 0, .base = 0xA00, .len = 0x0,},
.pcc_blk = {.id = SDE_SSPP_PCC, .base = 0x01780, .len = 0x64,},
+ .format_list = plane_formats,
};
static const struct sde_sspp_sub_blks cursor = {
@@ -117,6 +219,7 @@
.pa_blk = {.id = 0, .base = 0x00, .len = 0x0,},
.hist_lut = {.id = 0, .base = 0x00, .len = 0x0,},
.pcc_blk = {.id = 0, .base = 0x00, .len = 0x0,},
+ .format_list = plane_formats,
};
/* MIXER capability */
@@ -176,13 +279,13 @@
.sspp_count = 12,
.sspp = {
{.id = SSPP_VIG0, .base = 0x00005000,
- .features = VIG_17X_MASK, .sblk = &layer},
+ .features = VIG_17X_MASK, .sblk = &vig_layer},
{.id = SSPP_VIG1, .base = 0x00007000,
- .features = VIG_17X_MASK, .sblk = &layer},
+ .features = VIG_17X_MASK, .sblk = &vig_layer},
{.id = SSPP_VIG2, .base = 0x00009000,
- .features = VIG_17X_MASK, .sblk = &layer},
+ .features = VIG_17X_MASK, .sblk = &vig_layer},
{.id = SSPP_VIG3, .base = 0x0000b000,
- .features = VIG_17X_MASK, .sblk = &layer},
+ .features = VIG_17X_MASK, .sblk = &vig_layer},
{.id = SSPP_RGB0, .base = 0x00015000,
.features = RGB_17X_MASK, .sblk = &layer},
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index 0f8a8e1..6841c2b 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -62,6 +62,7 @@
struct msm_property_info property_info;
struct msm_property_data property_data[PLANE_PROP_COUNT];
+ struct drm_property_blob *blob_sde_info;
/* debugfs related stuff */
struct dentry *debugfs_root;
@@ -1105,6 +1106,8 @@
static const struct drm_prop_enum_list e_src_config[] = {
{SDE_DRM_DEINTERLACE, "deinterlace"}
};
+ const struct sde_format_extended *format_list;
+ static struct sde_kms_info sde_info;
struct sde_plane *psde = to_sde_plane(plane);
DBG("");
@@ -1153,6 +1156,29 @@
msm_property_install_blob(&psde->property_info, "csc", 0,
PLANE_PROP_CSC);
}
+ format_list = psde->pipe_sblk->format_list;
+ if (format_list) {
+ /* assume single thread */
+ struct sde_kms_info *info = &sde_info;
+
+ msm_property_install_blob(&psde->property_info, "sde_info",
+ DRM_MODE_PROP_IMMUTABLE,
+ PLANE_PROP_SDE_INFO);
+ sde_kms_info_reset(info);
+ sde_kms_info_start(info, "pixel_formats");
+ while (format_list->fourcc_format) {
+ sde_kms_info_append_format(info,
+ format_list->fourcc_format,
+ format_list->modifier);
+ ++format_list;
+ }
+ sde_kms_info_stop(info);
+ msm_property_set_blob(&psde->property_info,
+ &psde->blob_sde_info,
+ SDE_KMS_INFO_DATA(info),
+ SDE_KMS_INFO_DATALEN(info),
+ PLANE_PROP_SDE_INFO);
+ }
}
static int sde_plane_atomic_set_property(struct drm_plane *plane,
@@ -1231,6 +1257,8 @@
debugfs_remove_recursive(psde->debugfs_root);
+ if (psde->blob_sde_info)
+ drm_property_unreference_blob(psde->blob_sde_info);
msm_property_destroy(&psde->property_info);
mutex_destroy(&psde->lock);
@@ -1478,12 +1506,16 @@
/* cache features mask for later */
psde->features = psde->pipe_hw->cap->features;
psde->pipe_sblk = psde->pipe_hw->cap->sblk;
+ if (!psde->pipe_sblk) {
+ SDE_ERROR("invalid sblk on pipe %d\n", pipe);
+ goto clean_sspp;
+ }
/* add plane to DRM framework */
- psde->nformats = sde_populate_formats(psde->formats,
- ARRAY_SIZE(psde->formats),
- !(psde->features & BIT(SDE_SSPP_CSC)) ||
- !(psde->features & SDE_SSPP_SCALER));
+ psde->nformats = sde_populate_formats(psde->pipe_sblk->format_list,
+ psde->formats,
+ 0,
+ ARRAY_SIZE(psde->formats));
if (!psde->nformats) {
DRM_ERROR("[%u]No valid formats for plane\n", pipe);