This patchset aims to add support for AFBC in mali display driver with
the help of format modifiers. AFBC modifiers adds some constraints to
framebuffer size, alignment, pitch, formats, etc
In the previous patchset ie
https://lists.freedesktop.org/archives/dri-devel/2018-June/180124.html
I had illustrated how to add support for one format (ie BGR888) with
one valid combination of AFBC modifiers ie
AFBC_SIZE_16X16 | AFBC_YTR | AFBC_SPARSE
Changes from v1:-
In this current patchset, I have enabled the support for all AFBC modifiers
(which are supported on DP500, DP550 and DP650) with all the pixel formats.
Also, we have introduced some new pixel formats which are supported with
AFBC modifiers only as well some other pixel formats which are supported with
LINEAR only.
Please feel free to let me know your thoughts.
Depends on :-
https://patchwork.kernel.org/patch/10460063/
Ayan Kumar Halder (10):
drm: Added a new format DRM_FORMAT_XVYU2101010
drm/arm/malidp: Set the AFBC register bits if the framebuffer has AFBC
modifier
drm/arm/malidp:- Define a common list of AFBC format modifiers
supported for DP500, DP550 and DP650
drm/arm/malidp:- Added support for new YUV formats for DP500, DP550
and DP650
drm/arm/malidp: Define the constraints on each supported drm_fourcc
format for the AFBC modifiers.
drm/arm/malidp: Specified the rotation memory requirements for AFBC
YUV formats
drm/arm/malidp:- Writeback framebuffer does not support any modifiers
drm/arm/malidp:- Use the newly introduced malidp_format_get_bpp()
instead of relying on cpp for calculating framebuffer size
drm/arm/malidp:- Disregard the pitch alignment constraint for AFBC
framebuffer.
drm/arm/malidp: Added support for AFBC modifiers for all layers except
DE_SMART
Brian Starkey (2):
drm/fourcc: Add AFBC yuv fourccs for Mali
drm/afbc: Add AFBC modifier usage documentation
Documentation/gpu/afbc.rst | 233 +++++++++++++++++++++++++++++++
Documentation/gpu/drivers.rst | 1 +
MAINTAINERS | 1 +
drivers/gpu/drm/arm/malidp_drv.c | 45 ++----
drivers/gpu/drm/arm/malidp_drv.h | 6 +
drivers/gpu/drm/arm/malidp_hw.c | 245 ++++++++++++++++++++++++++++----
drivers/gpu/drm/arm/malidp_hw.h | 30 +++-
drivers/gpu/drm/arm/malidp_mw.c | 7 +-
drivers/gpu/drm/arm/malidp_planes.c | 268 +++++++++++++++++++++++++++++++++---
drivers/gpu/drm/arm/malidp_regs.h | 20 +++
drivers/gpu/drm/drm_fourcc.c | 11 ++
include/uapi/drm/drm_fourcc.h | 20 ++-
12 files changed, 799 insertions(+), 88 deletions(-)
create mode 100644 Documentation/gpu/afbc.rst
--
2.7.4
From: Brian Starkey <[email protected]>
As we look to enable AFBC using DRM format modifiers, we run into
problems which we've historically handled via vendor-private details
(i.e. gralloc, on Android).
AFBC (as an encoding) is fully flexible, and for example YUV data can
be encoded into 1, 2 or 3 encoded "planes", much like the linear
equivalents. Component order is also meaningful, as AFBC doesn't
necessarily care about what each "channel" of the data it encodes
contains. Therefore ABGR8888 and RGBA8888 can be encoded in AFBC with
different representations. Similarly, 'X' components may be encoded
into AFBC streams in cases where a decoder expects to decode a 4th
component.
In addition, AFBC is a licensable IP, meaning that to support the
ecosystem we need to ensure that _all_ AFBC users are able to describe
the encodings that they need. This is much better achieved by
preserving meaning in the fourcc codes when they are combined with an
AFBC modifier.
In essence, we want to use the modifier to describe the parameters of
the AFBC encode/decode, and use the fourcc code to describe the data
being encoded/decoded.
To do anything different would be to introduce redundancy - we would
need to duplicate in the modifier information which is _already_
conveyed clearly and non-ambigiously by a fourcc code.
I hope that for RGB this is non-controversial.
(BGRA8888 + MODIFIER_AFBC) is a different format from
(RGBA8888 + MODIFIER_AFBC).
Possibly more controversial is that (XBGR8888 + MODIFIER_AFBC)
is different from (BGR888 + MODIFIER_AFBC). I understand that in some
schemes it is not the case - but in AFBC it is so.
Where we run into problems is where there are not already fourcc codes
which represent the data which the AFBC encoder/decoder is processing.
To that end, we want to introduce new fourcc codes to describe the
data being encoded/decoded, in the places where none of the existing
fourcc codes are applicable.
Where we don't support an equivalent non-compressed layout, or where
no "obvious" linear layout exists, we are proposing adding fourcc
codes which have no associated linear layout - because any layout we
proposed would be completely arbitrary.
Some formats are following the naming conventions from [2].
The summary of the new formats is:
DRM_FORMAT_VUY888 - Packed 8-bit YUV 444. Y followed by U then V.
DRM_FORMAT_VUY101010 - Packed 10-bit YUV 444. Y followed by U then
V. No defined linear encoding.
DRM_FORMAT_Y210 - Packed 10-bit YUV 422. Y followed by U (then Y)
then V. 10-bit samples in 16-bit words.
DRM_FORMAT_Y410 - Packed 10-bit YUV 444, with 2-bit alpha.
DRM_FORMAT_P210 - Semi-planar 10-bit YUV 422. Y plane, followed by
interleaved U-then-V plane. 10-bit samples in
16-bit words.
DRM_FORMAT_YUV420_8BIT - Packed 8-bit YUV 420. Y followed by U then
V. No defined linear encoding
DRM_FORMAT_YUV420_10BIT - Packed 10-bit YUV 420. Y followed by U
then V. No defined linear encoding
Please also note that in the absence of AFBC, we would still need to
add Y410, Y210 and P210.
Full rationale follows:
YUV 444 8-bit, 1-plane
----------------------
The currently defined AYUV format encodes a 4th alpha component,
which makes it unsuitable for representing a 3-component YUV 444
AFBC stream.
The proposed[1] XYUV format which is supported by Mali-DP in linear
layout is also unsuitable, because the component order is the
opposite of the AFBC version, and it encodes a 4th 'X' component.
DRM_FORMAT_VUY888 is the "obvious" format for a 3-component, packed,
YUV 444 8-bit format, with the component order which our HW expects to
encode/decode. It conforms to the same naming convention as the
existing packed YUV 444 format.
The naming here is meant to be consistent with DRM_FORMAT_AYUV and
DRM_FORMAT_XYUV[1]
YUV 444 10-bit, 1-plane
-----------------------
There is no currently-defined YUV 444 10-bit format in
drm_fourcc.h, irrespective of number of planes.
The proposed[1] XVYU2101010 format which is supported by Mali-DP in
linear layout uses the wrong component order, and also encodes a 4th
'X' component, which doesn't match the AFBC version of YUV 444
10-bit which we support.
DRM_FORMAT_Y410 is the same layout as XVYU2101010, but with 2 bits of
alpha. This format is supported with linear layout by Mali GPUs. The
naming follows[2].
There is no "obvious" linear encoding for a 3-component 10:10:10
packed format, and so DRM_FORMAT_VUY101010 defines a component
order, but not a bit encoding. Again, the naming is meant to be
consistent with DRM_FORMAT_AYUV.
YUV 422 8-bit, 1-plane
----------------------
The existing DRM_FORMAT_YUYV (and the other component orders) are
single-planar YUV 422 8-bit formats. Following the convention of
the component orders of the RGB formats, YUYV has the correct
component order for our AFBC encoding (Y followed by U followed by
V). We can use YUYV for AFBC YUV 422 8-bit.
YUV 422 10-bit, 1-plane
-----------------------
There is no currently-defined YUV 422 10-bit format in drm_fourcc.h
DRM_FORMAT_Y210 is analogous to YUYV, but with 10-bits per sample
packed into the upper 10-bits of 16-bit samples. This format is
supported in both linear and AFBC by Mali GPUs.
YUV 422 10-bit, 2-plane
-----------------------
The recently defined DRM_FORMAT_P010 format is a 10-bit semi-planar
YUV 420 format, which has the correct component ordering for an AFBC
2-plane YUV 420 buffer. The linear layout contains meaningless padding
bits, which will not be encoded in an AFBC stream.
YUV 420 8-bit, 1-plane
----------------------
There is no currently defined single-planar YUV 420, 8-bit format
in drm_fourcc.h. There's differing opinions on whether using the
existing fourcc-implied n_planes where possible is a good idea or
not when using modifiers.
For me, it's much more "obvious" to use NV12 for 2-plane AFBC and
YUV420 for 3-plane AFBC. This keeps the aforementioned separation
between the AFBC codec settings (in the modifier) and the pixel data
format (in the fourcc). With different vendors using AFBC, this helps
to ensure that there is no confusion in interoperation. It also
ensures that the AFBC modifiers describe AFBC itself (which is a
licensable component), and not implementation details which are not
defined by AFBC.
The proposed[1] X0L0 format which Mali-DP supports with Linear layout
is unsuitable, as it contains a 4th 'X' component, and our AFBC
decoder expects only 3 components.
To that end, we propose a new YUV 420 8-bit format. There is no
"obvious" linear encoding for a 3-component 8:8:8, 420, packed format,
and so DRM_FORMAT_YUV420_8BIT defines a component order, but not a
bit encoding. I'm happy to hear different naming suggestions.
YUV 420 8-bit, 2-, 3-plane
--------------------------
These already exist, we can use NV12 and YUV420.
YUV 420 10-bit, 1-plane
-----------------------
As above, no current definition exists, and X0L2 encodes a 4th 'X'
channel.
Analogous to DRM_FORMAT_YUV420_8BIT, we define DRM_FORMAT_YUV420_10BIT.
[1] https://lists.freedesktop.org/archives/dri-devel/2018-July/184598.html
[2] https://docs.microsoft.com/en-us/windows/desktop/medfound/10-bit-and-16-bit-yuv-video-formats
Changes since RFC v1:
- Fix confusing subsampling vs bit-depth X:X:X notation in
descriptions (danvet)
- Rename DRM_FORMAT_AVYU1101010 to DRM_FORMAT_Y410 (Lisa Wu)
- Add drm_format_info structures for the new formats, using the
new 'bpp' field for those with non-integer bytes-per-pixel
- Rebase, including Juha-Pekka Heikkila's format definitions
Signed-off-by: Brian Starkey <[email protected]>
Reviewed-by: Liviu Dudau <[email protected]>
---
drivers/gpu/drm/drm_fourcc.c | 10 ++++++++++
include/uapi/drm/drm_fourcc.h | 16 +++++++++++++++-
2 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
index d45a3a4..6b7a62e 100644
--- a/drivers/gpu/drm/drm_fourcc.c
+++ b/drivers/gpu/drm/drm_fourcc.c
@@ -225,10 +225,14 @@ const struct drm_format_info *__drm_format_info(u32 format)
{ .format = DRM_FORMAT_UYVY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_VYUY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_XYUV8888, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
+ { .format = DRM_FORMAT_Y210, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
+ { .format = DRM_FORMAT_VUY888, .depth = 0, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
+ { .format = DRM_FORMAT_Y410, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true },
{ .format = DRM_FORMAT_AYUV, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true },
{ .format = DRM_FORMAT_P010, .depth = 0, .num_planes = 2, .cpp = { 2, 4, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true },
{ .format = DRM_FORMAT_P012, .depth = 0, .num_planes = 2, .cpp = { 2, 4, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true },
{ .format = DRM_FORMAT_P016, .depth = 0, .num_planes = 2, .cpp = { 2, 4, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true },
+ { .format = DRM_FORMAT_P210, .depth = 0, .num_planes = 2, .cpp = { 2, 4, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_Y0L0, .depth = 0, .num_planes = 1,
.char_per_block = { 8, 0, 0 }, .block_w = { 2, 0, 0 }, .block_h = { 2, 0, 0 },
.hsub = 2, .vsub = 2, .has_alpha = true, .is_yuv = true },
@@ -241,6 +245,12 @@ const struct drm_format_info *__drm_format_info(u32 format)
{ .format = DRM_FORMAT_X0L2, .depth = 0, .num_planes = 1,
.char_per_block = { 8, 0, 0 }, .block_w = { 2, 0, 0 }, .block_h = { 2, 0, 0 },
.hsub = 2, .vsub = 2, .is_yuv = true },
+ { .format = DRM_FORMAT_VUY101010, .depth = 0, .num_planes = 1,
+ .cpp = { 0, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
+ { .format = DRM_FORMAT_YUV420_8BIT, .depth = 0, .num_planes = 1,
+ .cpp = { 0, 0, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true },
+ { .format = DRM_FORMAT_YUV420_10BIT, .depth = 0, .num_planes = 1,
+ .cpp = { 0, 0, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true },
};
unsigned int i;
diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
index c6e4598..71b2bc7 100644
--- a/include/uapi/drm/drm_fourcc.h
+++ b/include/uapi/drm/drm_fourcc.h
@@ -149,9 +149,13 @@ extern "C" {
#define DRM_FORMAT_YVYU fourcc_code('Y', 'V', 'Y', 'U') /* [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian */
#define DRM_FORMAT_UYVY fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian */
#define DRM_FORMAT_VYUY fourcc_code('V', 'Y', 'U', 'Y') /* [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian */
+#define DRM_FORMAT_Y210 fourcc_code('Y', '2', '1', '0') /* [63:0] Cr0:0:Y1:0:Cb0:0:Y0:0 10:6:10:6:10:6:10:6 little endian */
#define DRM_FORMAT_AYUV fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */
-#define DRM_FORMAT_XYUV8888 fourcc_code('X', 'Y', 'U', 'V') /* [31:0] X:Y:Cb:Cr 8:8:8:8 little endian */
+#define DRM_FORMAT_XYUV8888 fourcc_code('X', 'Y', 'U', 'V') /* [31:0] X:Y:Cb:Cr 8:8:8:8 little endian */
+#define DRM_FORMAT_VUY888 fourcc_code('V', 'U', '2', '4') /* [23:0] Cr:Cb:Y 8:8:8 little endian */
+#define DRM_FORMAT_Y410 fourcc_code('Y', '4', '1', '0') /* [31:0] A:Cr:Y:Cb 2:10:10:10 little endian */
+#define DRM_FORMAT_VUY101010 fourcc_code('V', 'U', '3', '0') /* Y followed by U then V, 10:10:10. Non-linear modifier only */
/*
* packed YCbCr420 2x2 tiled formats
@@ -168,6 +172,15 @@ extern "C" {
#define DRM_FORMAT_X0L2 fourcc_code('X', '0', 'L', '2')
/*
+ * 1-plane YUV 4:2:0
+ * In these formats, the component ordering is specified (Y, followed by U
+ * then V), but the exact Linear layout is undefined.
+ * These formats can only be used with a non-Linear modifier.
+ */
+#define DRM_FORMAT_YUV420_8BIT fourcc_code('Y', 'U', '0', '8')
+#define DRM_FORMAT_YUV420_10BIT fourcc_code('Y', 'U', '1', '0')
+
+/*
* 2 plane RGB + A
* index 0 = RGB plane, same format as the corresponding non _A8 format has
* index 1 = A plane, [7:0] A
@@ -201,6 +214,7 @@ extern "C" {
* component xxx msb Y [xxx:16-xxx]
* index 1 = Cr:Cb plane, [31:0] Cr:Cb little endian [xxx:16-xxx:xxx:16-xxx]
*/
+#define DRM_FORMAT_P210 fourcc_code('P', '2', '1', '0') /* 2x1 subsampled Cr:Cb plane, 10 bit per channel */
#define DRM_FORMAT_P010 fourcc_code('P', '0', '1', '0') /* 2x2 subsampled Cr:Cb plane, 10 bit per channel */
#define DRM_FORMAT_P012 fourcc_code('P', '0', '1', '2') /* 2x2 subsampled Cr:Cb plane, 12 bit per channel */
#define DRM_FORMAT_P016 fourcc_code('P', '0', '1', '6') /* 2x2 subsampled Cr:Cb plane, 16 bit per channel */
--
2.7.4
In malidp, the writeback pipeline does not support writing crtc output
to a framebuffer with modifiers ie the memory writeback content is
devoid of any compression or tiling, etc.
So we have added a commit check in memory writeback encoder helper function
to validate if the framebuffer has any modifier and if so, return EINVAL.
Signed-off-by: Ayan Kumar halder <[email protected]>
---
drivers/gpu/drm/arm/malidp_mw.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c
index 0484744..90c964a 100644
--- a/drivers/gpu/drm/arm/malidp_mw.c
+++ b/drivers/gpu/drm/arm/malidp_mw.c
@@ -141,6 +141,11 @@ malidp_mw_encoder_atomic_check(struct drm_encoder *encoder,
return -EINVAL;
}
+ if (fb->modifier) {
+ DRM_DEBUG_KMS("Writeback framebuffer does not support modifiers\n");
+ return -EINVAL;
+ }
+
mw_state->format =
malidp_hw_get_format_id(&malidp->dev->hw->map, SE_MEMWRITE,
fb->format->format, !!fb->modifier);
--
2.7.4
The list of modifiers to be supported for each plane has been dynamically generated
from 'malidp_format_modifiers[]' and 'malidp_hw_regmap->features'.
Changes from v1:-
1. Replaced DRM_ERROR() with DRM_DEBUG_KMS() in malidp_format_mod_supported()
to report unsupported modifiers.
Changes from v2:-
1. Removed malidp_format_mod_supported() from the current patch. This has been added
in "PATCH 7/12"
2. Dynamically generate the list of modifiers (to be supported for each plane) from
'malidp_format_modifiers' and features.
Signed-off-by: Ayan Kumar halder <[email protected]>
---
drivers/gpu/drm/arm/malidp_drv.c | 1 +
drivers/gpu/drm/arm/malidp_planes.c | 28 ++++++++++++++++++++++++++--
2 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index b2b97db..be45703 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -388,6 +388,7 @@ static int malidp_init(struct drm_device *drm)
drm->mode_config.max_height = hwdev->max_line_size;
drm->mode_config.funcs = &malidp_mode_config_funcs;
drm->mode_config.helper_private = &malidp_mode_config_helpers;
+ drm->mode_config.allow_fb_modifiers = true;
ret = malidp_crtc_init(drm);
if (ret)
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
index eec0442..01037d0 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -934,6 +934,25 @@ int malidp_de_planes_init(struct drm_device *drm)
BIT(DRM_MODE_BLEND_COVERAGE);
u32 *formats;
int ret, i, j, n;
+ u64 supported_modifiers[MODIFIERS_COUNT_MAX];
+ const u64 *modifiers;
+
+ modifiers = malidp_format_modifiers;
+
+ if (!(map->features & MALIDP_DEVICE_AFBC_SUPPORT_SPLIT)) {
+ /*
+ * Since our hardware does not support SPLIT, so build the list of
+ * supported modifiers excluding SPLIT ones.
+ */
+ while (*modifiers != DRM_FORMAT_MOD_INVALID) {
+ if (!(*modifiers & AFBC_SPLIT))
+ supported_modifiers[j++] = *modifiers;
+
+ modifiers++;
+ }
+ supported_modifiers[j++] = DRM_FORMAT_MOD_INVALID;
+ modifiers = supported_modifiers;
+ }
formats = kcalloc(map->n_pixel_formats, sizeof(*formats), GFP_KERNEL);
if (!formats) {
@@ -958,9 +977,14 @@ int malidp_de_planes_init(struct drm_device *drm)
plane_type = (i == 0) ? DRM_PLANE_TYPE_PRIMARY :
DRM_PLANE_TYPE_OVERLAY;
+
+ /*
+ * All the layers except smart layer supports AFBC modifiers.
+ */
ret = drm_universal_plane_init(drm, &plane->base, crtcs,
- &malidp_de_plane_funcs, formats,
- n, NULL, plane_type, NULL);
+ &malidp_de_plane_funcs, formats, n,
+ (id == DE_SMART) ? NULL : modifiers, plane_type, NULL);
+
if (ret < 0)
goto cleanup;
--
2.7.4
Considering the fact that some of the AFBC specific pixel formats are expressed
in bits per pixel (ie bpp which is not byte aligned), the pitch (ie width * bpp)
is not guaranteed to be aligned to burst size (ie 8 or 16 bytes).
For example, DRM_FORMAT_VUY101010 is 30 bits per pixel. For a framebuffer of
width 32 pixels, the pitch will be 120 bytes which is not aligned to burst size
(ie 16 bytes) for DP650.
Signed-off-by: Ayan Kumar halder <[email protected]>
---
drivers/gpu/drm/arm/malidp_planes.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
index d0a00ee..eec0442 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -529,8 +529,8 @@ static int malidp_de_plane_check(struct drm_plane *plane,
for (i = 0; i < ms->n_planes; i++) {
u8 alignment = malidp_hw_get_pitch_align(mp->hwdev, rotated);
- if ((fb->pitches[i] * drm_format_info_block_height(fb->format, i))
- & (alignment - 1)) {
+ if (((fb->pitches[i] * drm_format_info_block_height(fb->format, i))
+ & (alignment - 1)) && !(fb->modifier)) {
DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n",
fb->pitches[i], i);
return -EINVAL;
--
2.7.4
Formats like DRM_FORMAT_VUY101010, DRM_FORMAT_YUV420_8BIT and
DRM_FORMAT_YUV420_10BIT are expressed in bits per pixel as they have a non
integer value of cpp (thus denoted as '0' in drm_format_info[]). Therefore,
the calculation of AFBC framebuffer size needs to use malidp_format_get_bpp().
Signed-off-by: Ayan Kumar halder <[email protected]>
---
drivers/gpu/drm/arm/malidp_drv.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index 2f0b553..b2b97db 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -297,6 +297,7 @@ malidp_verify_afbc_framebuffer_size(struct drm_device *dev,
struct drm_gem_object *objs = NULL;
u32 afbc_superblock_size = 0, afbc_superblock_height = 0;
u32 afbc_superblock_width = 0, afbc_size = 0;
+ int bpp = 0;
switch (mode_cmd->modifier[0] & AFBC_SIZE_MASK) {
case AFBC_SIZE_16X16:
@@ -313,15 +314,17 @@ malidp_verify_afbc_framebuffer_size(struct drm_device *dev,
n_superblocks = (mode_cmd->width / afbc_superblock_width) *
(mode_cmd->height / afbc_superblock_height);
- afbc_superblock_size = info->cpp[0] * afbc_superblock_width *
- afbc_superblock_height;
+ bpp = malidp_format_get_bpp(info->format);
+
+ afbc_superblock_size = (bpp * afbc_superblock_width * afbc_superblock_height) / BITS_PER_BYTE;
afbc_size = ALIGN(n_superblocks * AFBC_HEADER_SIZE, AFBC_SUPERBLK_ALIGNMENT);
afbc_size += n_superblocks * ALIGN(afbc_superblock_size, AFBC_SUPERBLK_ALIGNMENT);
- if (mode_cmd->width * info->cpp[0] != mode_cmd->pitches[0]) {
- DRM_DEBUG_KMS("Invalid value of pitch (=%u) should be same as width (=%u) * cpp (=%u)\n",
- mode_cmd->pitches[0], mode_cmd->width, info->cpp[0]);
+ if ((mode_cmd->width * bpp) != (mode_cmd->pitches[0] * BITS_PER_BYTE)) {
+ DRM_DEBUG_KMS("Invalid value of (pitch * BITS_PER_BYTE) (=%u) "
+ "should be same as width (=%u) * bpp (=%u)\n",
+ (mode_cmd->pitches[0] * BITS_PER_BYTE), mode_cmd->width, bpp);
return false;
}
--
2.7.4
We have added some new formats to be supported on DP500/DP550/DP650.
Signed-off-by: Ayan Kumar Halder <[email protected]>
Depends on :- https://patchwork.kernel.org/patch/10460063/
---
drivers/gpu/drm/arm/malidp_hw.c | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
index 55d379b..25ac5890 100644
--- a/drivers/gpu/drm/arm/malidp_hw.c
+++ b/drivers/gpu/drm/arm/malidp_hw.c
@@ -49,6 +49,12 @@ static const struct malidp_format_id malidp500_de_formats[] = {
{ DRM_FORMAT_YUYV, DE_VIDEO1, 13 },
{ DRM_FORMAT_NV12, DE_VIDEO1 | SE_MEMWRITE, 14 },
{ DRM_FORMAT_YUV420, DE_VIDEO1, 15 },
+ { DRM_FORMAT_XYUV8888, DE_VIDEO1, 16 },
+ /* These are supported with AFBC only */
+ { DRM_FORMAT_YUV420_8BIT, DE_VIDEO1, 14 },
+ { DRM_FORMAT_VUY888, DE_VIDEO1, 16 },
+ { DRM_FORMAT_VUY101010, DE_VIDEO1, 17 },
+ { DRM_FORMAT_YUV420_10BIT, DE_VIDEO1, 18 }
};
#define MALIDP_ID(__group, __format) \
@@ -74,11 +80,25 @@ static const struct malidp_format_id malidp500_de_formats[] = {
{ DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 1) }, \
{ DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 2) }, \
{ DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 3) }, \
+ /* This is only supported with linear modifier */ \
+ { DRM_FORMAT_XYUV8888, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 0) },\
+ /* This is only supported with AFBC modifier */ \
+ { DRM_FORMAT_VUY888, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 0) }, \
{ DRM_FORMAT_YUYV, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 2) }, \
+ /* This is only supported with linear modifier */ \
{ DRM_FORMAT_UYVY, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 3) }, \
{ DRM_FORMAT_NV12, DE_VIDEO1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(5, 6) }, \
+ /* This is only supported with AFBC modifier */ \
+ { DRM_FORMAT_YUV420_8BIT, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 6) }, \
{ DRM_FORMAT_YUV420, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 7) }, \
- { DRM_FORMAT_X0L2, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 6)}
+ /* This is only supported with linear modifier */ \
+ { DRM_FORMAT_XVYU2101010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 0)}, \
+ /* This is only supported with AFBC modifier */ \
+ { DRM_FORMAT_VUY101010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 0)}, \
+ { DRM_FORMAT_X0L2, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 6)}, \
+ /* This is only supported with AFBC modifier */ \
+ { DRM_FORMAT_YUV420_10BIT, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 7)}, \
+ { DRM_FORMAT_P010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 7)}
static const struct malidp_format_id malidp550_de_formats[] = {
MALIDP_COMMON_FORMATS,
--
2.7.4
The newly supported AFBC YUV formats have the following rotation memory
constraints (in DP550/DP650).
1. DRM_FORMAT_VUY888/DRM_FORMAT_VUY101010 :- It can rotate upto 8
horizontal lines in the AFBC output buffer.
2. DRM_FORMAT_YUV420_8BIT :- It can rotate upto 16 horizontal lines
in the AFBC output buffer.
Also some of the pixel formats are specified in bits per pixel (rather
than bytes per pixel), so the calculation needs to take note of this.
Besides there are some difference between DP550 and DP650 and these are
as follows:-
1. DRM_FORMAT_X0L2 (in uncompressed format) does not support rotation in DP550.
For DP650, it can rotate upto 16 horizontal lines in the AFBC output buffer,
whereas in DP550 (with AFBC), it can rotate upto 8 horizontal lines.
2. DRM_FORMAT_YUV420_10BIT :- It can rotate upto 8 horizontal lines in
dp550 and 16 horizontal lines in DP650.
Signed-off-by: Ayan Kumar halder <[email protected]>
---
drivers/gpu/drm/arm/malidp_hw.c | 101 ++++++++++++++++++++++++++++++++----
drivers/gpu/drm/arm/malidp_hw.h | 5 +-
drivers/gpu/drm/arm/malidp_planes.c | 3 +-
3 files changed, 98 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
index 4a774be..d9866a8 100644
--- a/drivers/gpu/drm/arm/malidp_hw.c
+++ b/drivers/gpu/drm/arm/malidp_hw.c
@@ -375,14 +375,39 @@ static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode *
malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
}
-static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt)
+int malidp_format_get_bpp(u32 fmt)
+{
+ int bpp = drm_format_plane_cpp(fmt, 0) * 8;
+
+ if (bpp == 0) {
+ switch (fmt) {
+ case DRM_FORMAT_VUY101010:
+ bpp = 30;
+ case DRM_FORMAT_YUV420_10BIT:
+ bpp = 15;
+ break;
+ case DRM_FORMAT_YUV420_8BIT:
+ bpp = 12;
+ break;
+ default:
+ bpp = 0;
+ }
+ }
+
+ return bpp;
+}
+
+static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
+ u16 h, u32 fmt, bool has_modifier)
{
/*
* Each layer needs enough rotation memory to fit 8 lines
* worth of pixel data. Required size is then:
* size = rotated_width * (bpp / 8) * 8;
*/
- return w * drm_format_plane_cpp(fmt, 0) * 8;
+ int bpp = malidp_format_get_bpp(fmt);
+
+ return w * bpp;
}
static void malidp500_se_write_pp_coefftab(struct malidp_hw_device *hwdev,
@@ -660,9 +685,9 @@ static void malidp550_modeset(struct malidp_hw_device *hwdev, struct videomode *
malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
}
-static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt)
+static int malidpx50_get_bytes_per_column(u32 fmt)
{
- u32 bytes_per_col;
+ u32 bytes_per_column;
switch (fmt) {
/* 8 lines at 4 bytes per pixel */
@@ -688,19 +713,77 @@ static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16
case DRM_FORMAT_UYVY:
case DRM_FORMAT_YUYV:
case DRM_FORMAT_X0L0:
- case DRM_FORMAT_X0L2:
- bytes_per_col = 32;
+ bytes_per_column = 32;
break;
/* 16 lines at 1.5 bytes per pixel */
case DRM_FORMAT_NV12:
case DRM_FORMAT_YUV420:
- bytes_per_col = 24;
+ /* 8 lines at 3 bytes per pixel */
+ case DRM_FORMAT_VUY888:
+ /* 16 lines at 12 bits per pixel */
+ case DRM_FORMAT_YUV420_8BIT:
+ /* 8 lines at 3 bytes per pixel */
+ case DRM_FORMAT_P010:
+ bytes_per_column = 24;
+ break;
+ /* 8 lines at 30 bits per pixel */
+ case DRM_FORMAT_VUY101010:
+ /* 16 lines at 15 bits per pixel */
+ case DRM_FORMAT_YUV420_10BIT:
+ bytes_per_column = 30;
break;
default:
return -EINVAL;
}
- return w * bytes_per_col;
+ return bytes_per_column;
+}
+
+static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
+ u16 h, u32 fmt, bool has_modifier)
+{
+ int bytes_per_column = 0;
+
+ switch (fmt) {
+ /* 8 lines at 15 bits per pixel */
+ case DRM_FORMAT_YUV420_10BIT:
+ bytes_per_column = 15;
+ break;
+ /* Uncompressed YUV 420 10 bit single plane cannot be rotated */
+ case DRM_FORMAT_X0L2:
+ if (has_modifier)
+ bytes_per_column = 8;
+ else
+ return -EINVAL;
+ break;
+ default:
+ bytes_per_column = malidpx50_get_bytes_per_column(fmt);
+ }
+
+ if (bytes_per_column == -EINVAL)
+ return bytes_per_column;
+
+ return w * bytes_per_column;
+}
+
+static int malidp650_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
+ u16 h, u32 fmt, bool has_modifier)
+{
+ int bytes_per_column = 0;
+
+ switch (fmt) {
+ /* 16 lines at 2 bytes per pixel */
+ case DRM_FORMAT_X0L2:
+ bytes_per_column = 32;
+ break;
+ default:
+ bytes_per_column = malidpx50_get_bytes_per_column(fmt);
+ }
+
+ if (bytes_per_column == -EINVAL)
+ return bytes_per_column;
+
+ return w * bytes_per_column;
}
static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
@@ -979,7 +1062,7 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
.in_config_mode = malidp550_in_config_mode,
.set_config_valid = malidp550_set_config_valid,
.modeset = malidp550_modeset,
- .rotmem_required = malidp550_rotmem_required,
+ .rotmem_required = malidp650_rotmem_required,
.se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
.se_calc_mclk = malidp550_se_calc_mclk,
.enable_memwrite = malidp550_enable_memwrite,
diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h
index 52188f0..e89a06a 100644
--- a/drivers/gpu/drm/arm/malidp_hw.h
+++ b/drivers/gpu/drm/arm/malidp_hw.h
@@ -184,7 +184,8 @@ struct malidp_hw {
* Calculate the required rotation memory given the active area
* and the buffer format.
*/
- int (*rotmem_required)(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt);
+ int (*rotmem_required)(struct malidp_hw_device *hwdev, u16 w, u16 h,
+ u32 fmt, bool has_modifier);
int (*se_set_scaling_coeffs)(struct malidp_hw_device *hwdev,
struct malidp_se_config *se_config,
@@ -326,6 +327,8 @@ void malidp_se_irq_fini(struct malidp_hw_device *hwdev);
u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
u8 layer_id, u32 format, bool has_modifier);
+int malidp_format_get_bpp(u32 fmt);
+
static inline u8 malidp_hw_get_pitch_align(struct malidp_hw_device *hwdev, bool rotated)
{
/*
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
index 0765cee..d0a00ee 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -595,7 +595,8 @@ static int malidp_de_plane_check(struct drm_plane *plane,
val = mp->hwdev->hw->rotmem_required(mp->hwdev, state->crtc_w,
state->crtc_h,
- fb->format->format);
+ fb->format->format,
+ !!(fb->modifier));
if (val < 0)
return val;
--
2.7.4
We need to define a common list of format modifiers supported by each of the Mali
display processors. The difference between DP500 from DP550/650 is that DP500
does not support block split mode (ie AFBC_FORMAT_MOD_SPLIT) and DP550 supports
YUV420 with split mode. We noted these special cases by defining MALIDP_DEVICE_AFBC_SUPPORT_SPLIT
and AFBC_SUPPORT_SPLIT_WITH_YUV_420_10 for malidp_hw_regmap.features
Also we have defined a set of meaningful macros to shorten the modifier names
Signed-off-by: Ayan Kumar halder <[email protected]>
Change-Id: I09fba2032a7474e6ce45af230e0ed18fc1f4c1df
---
drivers/gpu/drm/arm/malidp_drv.c | 8 ++++----
drivers/gpu/drm/arm/malidp_hw.c | 30 ++++++++++++++++++++++++++++--
drivers/gpu/drm/arm/malidp_hw.h | 20 +++++++++++++++-----
3 files changed, 47 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index 505f316..b8db92f 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -293,8 +293,8 @@ malidp_verify_afbc_framebuffer_caps(struct drm_device *dev,
return false;
}
- switch (mode_cmd->modifier[0] & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) {
- case AFBC_FORMAT_MOD_BLOCK_SIZE_16x16:
+ switch (mode_cmd->modifier[0] & AFBC_SIZE_MASK) {
+ case AFBC_SIZE_16X16:
if ((mode_cmd->width % 16) || (mode_cmd->height % 16)) {
DRM_DEBUG_KMS("AFBC buffers must be aligned to 16 pixels\n");
return false;
@@ -319,8 +319,8 @@ malidp_verify_afbc_framebuffer_size(struct drm_device *dev,
u32 afbc_superblock_size = 0, afbc_superblock_height = 0;
u32 afbc_superblock_width = 0, afbc_size = 0;
- switch (mode_cmd->modifier[0] & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) {
- case AFBC_FORMAT_MOD_BLOCK_SIZE_16x16:
+ switch (mode_cmd->modifier[0] & AFBC_SIZE_MASK) {
+ case AFBC_SIZE_16X16:
afbc_superblock_height = 16;
afbc_superblock_width = 16;
break;
diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
index 87b7b12..55d379b 100644
--- a/drivers/gpu/drm/arm/malidp_hw.c
+++ b/drivers/gpu/drm/arm/malidp_hw.c
@@ -137,6 +137,32 @@ static const struct malidp_layer malidp650_layers[] = {
ROTATE_NONE, 0 },
};
+const u64 malidp_format_modifiers[] = {
+ /* All RGB formats (except XRGB, RGBX, XBGR, BGRX) */
+ DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR | AFBC_SPARSE),
+ DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR),
+
+ /* All RGB formats > 16bpp (except XRGB, RGBX, XBGR, BGRX) */
+ DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR | AFBC_SPARSE | AFBC_SPLIT),
+
+ /* All 8 or 10 bit YUV 444 formats. */
+ /* In DP550, 10 bit YUV 420 format also supported */
+ DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_SPARSE | AFBC_SPLIT),
+
+ /* YUV 420, 422 P1 8 bit and YUV 444 8 bit/10 bit formats */
+ DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_SPARSE),
+ DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16),
+
+ /* YUV 420, 422 P1 8, 10 bit formats */
+ DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_CBR | AFBC_SPARSE),
+ DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_CBR),
+
+ /* All formats */
+ DRM_FORMAT_MOD_LINEAR,
+
+ DRM_FORMAT_MOD_INVALID
+};
+
#define SE_N_SCALING_COEFFS 96
static const u16 dp500_se_scaling_coeffs[][SE_N_SCALING_COEFFS] = {
[MALIDP_UPSCALING_COEFFS - 1] = {
@@ -841,7 +867,7 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
.se_base = MALIDP550_SE_BASE,
.dc_base = MALIDP550_DC_BASE,
.out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
- .features = MALIDP_REGMAP_HAS_CLEARIRQ,
+ .features = MALIDP_REGMAP_HAS_CLEARIRQ | MALIDP_DEVICE_AFBC_SUPPORT_SPLIT | AFBC_SUPPORT_SPLIT_WITH_YUV_420_10,
.n_layers = ARRAY_SIZE(malidp550_layers),
.layers = malidp550_layers,
.de_irq_map = {
@@ -887,7 +913,7 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
.se_base = MALIDP550_SE_BASE,
.dc_base = MALIDP550_DC_BASE,
.out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
- .features = MALIDP_REGMAP_HAS_CLEARIRQ,
+ .features = MALIDP_REGMAP_HAS_CLEARIRQ | MALIDP_DEVICE_AFBC_SUPPORT_SPLIT,
.n_layers = ARRAY_SIZE(malidp650_layers),
.layers = malidp650_layers,
.de_irq_map = {
diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h
index 651558f..27b907f 100644
--- a/drivers/gpu/drm/arm/malidp_hw.h
+++ b/drivers/gpu/drm/arm/malidp_hw.h
@@ -95,7 +95,9 @@ struct malidp_se_config {
};
/* regmap features */
-#define MALIDP_REGMAP_HAS_CLEARIRQ (1 << 0)
+#define MALIDP_REGMAP_HAS_CLEARIRQ BIT(0)
+#define MALIDP_DEVICE_AFBC_SUPPORT_SPLIT BIT(1)
+#define AFBC_SUPPORT_SPLIT_WITH_YUV_420_10 BIT(2)
struct malidp_hw_regmap {
/* address offset of the DE register bank */
@@ -390,9 +392,17 @@ static inline void malidp_se_set_enh_coeffs(struct malidp_hw_device *hwdev)
#define MALIDP_GAMMA_LUT_SIZE 4096
-#define AFBC_MOD_VALID_BITS (AFBC_FORMAT_MOD_BLOCK_SIZE_MASK | \
- AFBC_FORMAT_MOD_YTR | AFBC_FORMAT_MOD_SPLIT | \
- AFBC_FORMAT_MOD_SPARSE | AFBC_FORMAT_MOD_CBR | \
- AFBC_FORMAT_MOD_TILED | AFBC_FORMAT_MOD_SC)
+#define AFBC_SIZE_MASK AFBC_FORMAT_MOD_BLOCK_SIZE_MASK
+#define AFBC_SIZE_16X16 AFBC_FORMAT_MOD_BLOCK_SIZE_16x16
+#define AFBC_YTR AFBC_FORMAT_MOD_YTR
+#define AFBC_SPARSE AFBC_FORMAT_MOD_SPARSE
+#define AFBC_CBR AFBC_FORMAT_MOD_CBR
+#define AFBC_SPLIT AFBC_FORMAT_MOD_SPLIT
+#define AFBC_TILED AFBC_FORMAT_MOD_TILED
+#define AFBC_SC AFBC_FORMAT_MOD_SC
+
+#define AFBC_MOD_VALID_BITS (AFBC_SIZE_MASK | AFBC_YTR | AFBC_SPLIT | AFBC_SPARSE | AFBC_CBR | AFBC_TILED | AFBC_SC)
+
+extern const u64 malidp_format_modifiers[];
#endif /* __MALIDP_HW_H__ */
--
2.7.4
From: Brian Starkey <[email protected]>
AFBC is a flexible, proprietary, lossless compression protocol and
format, with a number of defined DRM format modifiers. To facilitate
consistency and compatibility between different AFBC producers and
consumers, document the expectations for usage of the AFBC DRM format
modifiers in a new .rst chapter.
Signed-off-by: Brian Starkey <[email protected]>
Reviewed-by: Liviu Dudau <[email protected]>
---
Documentation/gpu/afbc.rst | 233 ++++++++++++++++++++++++++++++++++++++++++
Documentation/gpu/drivers.rst | 1 +
MAINTAINERS | 1 +
include/uapi/drm/drm_fourcc.h | 3 +
4 files changed, 238 insertions(+)
create mode 100644 Documentation/gpu/afbc.rst
diff --git a/Documentation/gpu/afbc.rst b/Documentation/gpu/afbc.rst
new file mode 100644
index 0000000..922d955
--- /dev/null
+++ b/Documentation/gpu/afbc.rst
@@ -0,0 +1,233 @@
+===================================
+ Arm Framebuffer Compression (AFBC)
+===================================
+
+AFBC is a proprietary lossless image compression protocol and format.
+It provides fine-grained random access and minimizes the amount of
+data transferred between IP blocks.
+
+AFBC can be enabled on drivers which support it via use of the AFBC
+format modifiers defined in drm_fourcc.h. See DRM_FORMAT_MOD_ARM_AFBC(*).
+
+All users of the AFBC modifiers must follow the usage guidelines laid
+out in this document, to ensure compatibility across different AFBC
+producers and consumers.
+
+Components and Ordering
+=======================
+
+AFBC streams can contain several components - where a component
+corresponds to a color channel (i.e. R, G, B, X, A, Y, Cb, Cr).
+The assignment of input/output color channels must be consistent
+between the encoder and the decoder for correct operation, otherwise
+the consumer will interpret the decoded data incorrectly.
+
+Furthermore, when the lossless colorspace transform is used
+(AFBC_FORMAT_MOD_YTR, which should be enabled for RGB buffers for
+maximum compression efficiency), the component order must be:
+
+ * Component 0: R
+ * Component 1: G
+ * Component 2: B
+
+The component ordering is communicated via the fourcc code in the
+fourcc:modifier pair. In general, component '0' is considered to
+reside in the least-significant bits of the corresponding linear
+format. For example, COMP(bits):
+
+ * DRM_FORMAT_ABGR8888
+
+ * Component 0: R(8)
+ * Component 1: G(8)
+ * Component 2: B(8)
+ * Component 3: A(8)
+
+ * DRM_FORMAT_BGR888
+
+ * Component 0: R(8)
+ * Component 1: G(8)
+ * Component 2: B(8)
+
+ * DRM_FORMAT_YUYV
+
+ * Component 0: Y(8)
+ * Component 1: Cb(8, 2x1 subsampled)
+ * Component 2: Cr(8, 2x1 subsampled)
+
+In AFBC, 'X' components are not treated any differently from any other
+component. Therefore, an AFBC buffer with fourcc DRM_FORMAT_XBGR8888
+encodes with 4 components, like so:
+
+ * DRM_FORMAT_XBGR8888
+
+ * Component 0: R(8)
+ * Component 1: G(8)
+ * Component 2: B(8)
+ * Component 3: X(8)
+
+Please note, however, that the inclusion of a "wasted" 'X' channel is
+bad for compression efficiency, and so it's recommended to avoid
+formats containing 'X' bits. If a fourth component is
+required/expected by the encoder/decoder, then it is recommended to
+instead use an equivalent format with alpha, setting all alpha bits to
+'1'. If there is no requirement for a fourth component, then a format
+which doesn't include alpha can be used, e.g. DRM_FORMAT_BGR888.
+
+Number of Planes
+================
+
+Formats which are typically multi-planar in linear layouts (e.g. YUV
+420), can be encoded into one, or multiple, AFBC planes. As with
+component order, the encoder and decoder must agree about the number
+of planes in order to correctly decode the buffer. The fourcc code is
+used to determine the number of encoded planes in an AFBC buffer,
+matching the number of planes for the linear (unmodified) format.
+Within each plane, the component ordering also follows the fourcc
+code:
+
+For example:
+
+ * DRM_FORMAT_YUYV: nplanes = 1
+
+ * Plane 0:
+
+ * Component 0: Y(8)
+ * Component 1: Cb(8, 2x1 subsampled)
+ * Component 2: Cr(8, 2x1 subsampled)
+
+ * DRM_FORMAT_NV12: nplanes = 2
+
+ * Plane 0:
+
+ * Component 0: Y(8)
+
+ * Plane 1:
+
+ * Component 0: Cb(8, 2x1 subsampled)
+ * Component 1: Cr(8, 2x1 subsampled)
+
+Cross-device interoperability
+=============================
+
+For maximum compatibility across devices, the table below defines
+canonical formats for use between AFBC-enabled devices. Formats which
+are listed here must be used exactly as specified when using the AFBC
+modifiers. Formats which are not listed should be avoided.
+
+.. flat-table:: AFBC formats
+
+ * - Fourcc code
+ - Description
+ - Planes/Components
+
+ * - DRM_FORMAT_ABGR2101010
+ - 10-bit per component RGB, with 2-bit alpha
+ - Plane 0: 4 components
+ * Component 0: R(10)
+ * Component 1: G(10)
+ * Component 2: B(10)
+ * Component 3: A(2)
+
+ * - DRM_FORMAT_ABGR8888
+ - 8-bit per component RGB, with 8-bit alpha
+ - Plane 0: 4 components
+ * Component 0: R(8)
+ * Component 1: G(8)
+ * Component 2: B(8)
+ * Component 3: A(8)
+
+ * - DRM_FORMAT_BGR888
+ - 8-bit per component RGB
+ - Plane 0: 3 components
+ * Component 0: R(8)
+ * Component 1: G(8)
+ * Component 2: B(8)
+
+ * - DRM_FORMAT_BGR565
+ - 5/6-bit per component RGB
+ - Plane 0: 3 components
+ * Component 0: R(5)
+ * Component 1: G(6)
+ * Component 2: B(5)
+
+ * - DRM_FORMAT_ABGR1555
+ - 5-bit per component RGB, with 1-bit alpha
+ - Plane 0: 4 components
+ * Component 0: R(5)
+ * Component 1: G(5)
+ * Component 2: B(5)
+ * Component 3: A(1)
+
+ * - DRM_FORMAT_VUY888
+ - 8-bit per component YCbCr 444, single plane
+ - Plane 0: 3 components
+ * Component 0: Y(8)
+ * Component 1: Cb(8)
+ * Component 2: Cr(8)
+
+ * - DRM_FORMAT_VUY101010
+ - 10-bit per component YCbCr 444, single plane
+ - Plane 0: 3 components
+ * Component 0: Y(10)
+ * Component 1: Cb(10)
+ * Component 2: Cr(10)
+
+ * - DRM_FORMAT_YUYV
+ - 8-bit per component YCbCr 422, single plane
+ - Plane 0: 3 components
+ * Component 0: Y(8)
+ * Component 1: Cb(8, 2x1 subsampled)
+ * Component 2: Cr(8, 2x1 subsampled)
+
+ * - DRM_FORMAT_NV16
+ - 8-bit per component YCbCr 422, two plane
+ - Plane 0: 1 component
+ * Component 0: Y(8)
+ Plane 1: 2 components
+ * Component 0: Cb(8, 2x1 subsampled)
+ * Component 1: Cr(8, 2x1 subsampled)
+
+ * - DRM_FORMAT_Y210
+ - 10-bit per component YCbCr 422, single plane
+ - Plane 0: 3 components
+ * Component 0: Y(10)
+ * Component 1: Cb(10, 2x1 subsampled)
+ * Component 2: Cr(10, 2x1 subsampled)
+
+ * - DRM_FORMAT_P210
+ - 10-bit per component YCbCr 422, two plane
+ - Plane 0: 1 component
+ * Component 0: Y(10)
+ Plane 1: 2 components
+ * Component 0: Cb(10, 2x1 subsampled)
+ * Component 1: Cr(10, 2x1 subsampled)
+
+ * - DRM_FORMAT_YUV420_8BIT
+ - 8-bit per component YCbCr 420, single plane
+ - Plane 0: 3 components
+ * Component 0: Y(8)
+ * Component 1: Cb(8, 2x2 subsampled)
+ * Component 2: Cr(8, 2x2 subsampled)
+
+ * - DRM_FORMAT_YUV420_10BIT
+ - 10-bit per component YCbCr 420, single plane
+ - Plane 0: 3 components
+ * Component 0: Y(10)
+ * Component 1: Cb(10, 2x2 subsampled)
+ * Component 2: Cr(10, 2x2 subsampled)
+
+ * - DRM_FORMAT_NV12
+ - 8-bit per component YCbCr 420, two plane
+ - Plane 0: 1 component
+ * Component 0: Y(8)
+ Plane 1: 2 components
+ * Component 0: Cb(8, 2x2 subsampled)
+ * Component 1: Cr(8, 2x2 subsampled)
+
+ * - DRM_FORMAT_P010
+ - 10-bit per component YCbCr 420, two plane
+ - Plane 0: 1 component
+ * Component 0: Y(10)
+ Plane 1: 2 components
+ * Component 0: Cb(10, 2x2 subsampled)
+ * Component 1: Cr(10, 2x2 subsampled)
diff --git a/Documentation/gpu/drivers.rst b/Documentation/gpu/drivers.rst
index 7c16721..c176b34 100644
--- a/Documentation/gpu/drivers.rst
+++ b/Documentation/gpu/drivers.rst
@@ -17,6 +17,7 @@ GPU Driver Documentation
vkms
bridge/dw-hdmi
xen-front
+ afbc
.. only:: subproject and html
diff --git a/MAINTAINERS b/MAINTAINERS
index 254b7b2..aef18e3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1131,6 +1131,7 @@ M: Mali DP Maintainers <[email protected]>
S: Supported
F: drivers/gpu/drm/arm/
F: Documentation/devicetree/bindings/display/arm,malidp.txt
+F: Documentation/gpu/afbc.rst
ARM MFM AND FLOPPY DRIVERS
M: Ian Molton <[email protected]>
diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
index 75c4b5a..0adde4d 100644
--- a/include/uapi/drm/drm_fourcc.h
+++ b/include/uapi/drm/drm_fourcc.h
@@ -597,6 +597,9 @@ extern "C" {
* AFBC has several features which may be supported and/or used, which are
* represented using bits in the modifier. Not all combinations are valid,
* and different devices or use-cases may support different combinations.
+ *
+ * Further information on the use of AFBC modifiers can be found in
+ * Documentation/gpu/afbc.rst
*/
#define DRM_FORMAT_MOD_ARM_AFBC(__afbc_mode) fourcc_mod_code(ARM, __afbc_mode)
--
2.7.4
Added the AFBC decoder registers for DP500 , DP550 and DP650.
These registers control the processing of AFBC buffers. It controls various
features like AFBC decoder enable, lossless transformation and block split
as well as setting of the left, right, top and bottom cropping of AFBC buffers
(in number of pixels).
All the layers (except DE_SMART) support framebuffers with AFBC modifiers.
One needs to set the pixel values of the top, left, bottom and right cropping
for the AFBC framebuffer.
Cropping an AFBC framebuffer is controlled by the AFBC crop registers.
In that case, the layer input size registers should be configured with
framebuffer's dimensions and not with drm_plane_state source width/height
values (which is used for non AFBC framebuffer to denote cropping).
Changes from v1:
- Removed the "if (fb->modifier)" check from malidp_de_plane_update()
and added it in malidp_de_set_plane_afbc(). This will consolidate all the
AFBC specific register configurations in a single function ie
malidp_de_set_plane_afbc().
Changes from v2:
- For AFBC framebuffer, layer input size register should be set to framebuffer's
width and height
Signed-off-by: Ayan Kumar Halder <[email protected]>
---
drivers/gpu/drm/arm/malidp_hw.c | 25 +++++----
drivers/gpu/drm/arm/malidp_hw.h | 2 +
drivers/gpu/drm/arm/malidp_planes.c | 109 +++++++++++++++++++++++++++++++-----
drivers/gpu/drm/arm/malidp_regs.h | 20 +++++++
4 files changed, 130 insertions(+), 26 deletions(-)
diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
index b9bed11..87b7b12 100644
--- a/drivers/gpu/drm/arm/malidp_hw.c
+++ b/drivers/gpu/drm/arm/malidp_hw.c
@@ -94,11 +94,12 @@ static const struct malidp_layer malidp500_layers[] = {
* yuv2rgb matrix offset, mmu control register offset, rotation_features
*/
{ DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE,
- MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB, 0, ROTATE_ANY },
+ MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB, 0, ROTATE_ANY,
+ MALIDP500_DE_LV_AD_CTRL },
{ DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE,
- MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
+ MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY, MALIDP500_DE_LG1_AD_CTRL },
{ DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE,
- MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
+ MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY, MALIDP500_DE_LG2_AD_CTRL },
};
static const struct malidp_layer malidp550_layers[] = {
@@ -106,13 +107,15 @@ static const struct malidp_layer malidp550_layers[] = {
* yuv2rgb matrix offset, mmu control register offset, rotation_features
*/
{ DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
- MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY },
+ MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY,
+ MALIDP550_DE_LV1_AD_CTRL },
{ DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
- MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
+ MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY, MALIDP550_DE_LG_AD_CTRL },
{ DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
- MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY },
+ MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY,
+ MALIDP550_DE_LV2_AD_CTRL },
{ DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
- MALIDP550_DE_LS_R1_STRIDE, 0, 0, ROTATE_NONE },
+ MALIDP550_DE_LS_R1_STRIDE, 0, 0, ROTATE_NONE, 0 },
};
static const struct malidp_layer malidp650_layers[] = {
@@ -122,16 +125,16 @@ static const struct malidp_layer malidp650_layers[] = {
*/
{ DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
- MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY },
+ MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY, MALIDP550_DE_LV1_AD_CTRL },
{ DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
MALIDP_DE_LG_STRIDE, 0, MALIDP650_DE_LG_MMU_CTRL,
- ROTATE_COMPRESSED },
+ ROTATE_COMPRESSED, MALIDP550_DE_LG_AD_CTRL },
{ DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
- MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY },
+ MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY, MALIDP550_DE_LV2_AD_CTRL },
{ DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
MALIDP550_DE_LS_R1_STRIDE, 0, MALIDP650_DE_LS_MMU_CTRL,
- ROTATE_NONE },
+ ROTATE_NONE, 0 },
};
#define SE_N_SCALING_COEFFS 96
diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h
index 40155e2..651558f 100644
--- a/drivers/gpu/drm/arm/malidp_hw.h
+++ b/drivers/gpu/drm/arm/malidp_hw.h
@@ -70,6 +70,8 @@ struct malidp_layer {
s16 yuv2rgb_offset; /* offset to the YUV->RGB matrix entries */
u16 mmu_ctrl_offset; /* offset to the MMU control register */
enum rotation_features rot; /* type of rotation supported */
+ /* address offset for the AFBC decoder registers */
+ u16 afbc_decoder_offset;
};
enum malidp_scaling_coeff_set {
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
index c9a6d3e..cd60f73 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -592,6 +592,80 @@ static void malidp_de_set_mmu_control(struct malidp_plane *mp,
mp->layer->base + mp->layer->mmu_ctrl_offset);
}
+static void malidp_set_plane_base_addr(struct drm_framebuffer *fb,
+ struct malidp_plane *mp,
+ int plane_index)
+{
+ dma_addr_t paddr;
+ u16 ptr;
+ struct drm_plane *plane = &mp->base;
+ bool afbc = fb->modifier ? true : false;
+
+ ptr = mp->layer->ptr + (plane_index << 4);
+
+ /*
+ * For AFBC buffers, cropping is handled by AFBC decoder rather than
+ * pointer manipulation.
+ */
+ if (!afbc) {
+ paddr = drm_fb_cma_get_gem_addr(fb, plane->state,
+ plane_index);
+ } else {
+ struct drm_gem_cma_object *obj;
+
+ obj = drm_fb_cma_get_gem_obj(fb, plane_index);
+
+ if (WARN_ON(!obj))
+ return;
+ paddr = obj->paddr;
+ }
+
+ malidp_hw_write(mp->hwdev, lower_32_bits(paddr), ptr);
+ malidp_hw_write(mp->hwdev, upper_32_bits(paddr), ptr + 4);
+}
+
+static void malidp_de_set_plane_afbc(struct drm_plane *plane)
+{
+ struct malidp_plane *mp;
+ u32 src_w, src_h, val = 0, src_x, src_y;
+ struct drm_framebuffer *fb = plane->state->fb;
+
+ mp = to_malidp_plane(plane);
+
+ /* no afbc_decoder_offset means AFBC is not supported on this plane */
+ if (!mp->layer->afbc_decoder_offset)
+ return;
+
+ if (!fb->modifier) {
+ malidp_hw_write(mp->hwdev, 0, mp->layer->afbc_decoder_offset);
+ return;
+ }
+
+ /* convert src values from Q16 fixed point to integer */
+ src_w = plane->state->src_w >> 16;
+ src_h = plane->state->src_h >> 16;
+ src_x = plane->state->src_x >> 16;
+ src_y = plane->state->src_y >> 16;
+
+ val = ((fb->width - (src_x + src_w)) << MALIDP_AD_CROP_RIGHT_OFFSET) |
+ src_x;
+ malidp_hw_write(mp->hwdev, val,
+ mp->layer->afbc_decoder_offset + MALIDP_AD_CROP_H);
+
+ val = ((fb->height - (src_y + src_h)) << MALIDP_AD_CROP_BOTTOM_OFFSET) |
+ src_y;
+ malidp_hw_write(mp->hwdev, val,
+ mp->layer->afbc_decoder_offset + MALIDP_AD_CROP_V);
+
+ val = MALIDP_AD_EN;
+ if (fb->modifier & AFBC_FORMAT_MOD_SPLIT)
+ val |= MALIDP_AD_BS;
+ if (fb->modifier & AFBC_FORMAT_MOD_YTR)
+ val |= MALIDP_AD_YTR;
+
+ malidp_hw_write(mp->hwdev, val, mp->layer->afbc_decoder_offset);
+}
+
static void malidp_de_plane_update(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
@@ -600,30 +674,33 @@ static void malidp_de_plane_update(struct drm_plane *plane,
struct drm_plane_state *state = plane->state;
u16 pixel_alpha = state->pixel_blend_mode;
u8 plane_alpha = state->alpha >> 8;
+ bool format_has_alpha = state->fb->format->has_alpha;
u32 src_w, src_h, dest_w, dest_h, val;
int i;
+ struct drm_framebuffer *fb = plane->state->fb;
mp = to_malidp_plane(plane);
- /* convert src values from Q16 fixed point to integer */
- src_w = state->src_w >> 16;
- src_h = state->src_h >> 16;
- dest_w = state->crtc_w;
- dest_h = state->crtc_h;
+ /* For AFBC framebuffer, use the framebuffer width and height for configuring
+ * layer input size register.
+ */
+ if (fb->modifier) {
+ src_w = fb->width;
+ src_h = fb->height;
+ } else {
+ /* convert src values from Q16 fixed point to integer */
+ src_w = ms->base.src_w >> 16;
+ src_h = ms->base.src_h >> 16;
+ }
+ dest_w = ms->base.crtc_w;
+ dest_h = ms->base.crtc_h;
val = malidp_hw_read(mp->hwdev, mp->layer->base);
val = (val & ~LAYER_FORMAT_MASK) | ms->format;
malidp_hw_write(mp->hwdev, val, mp->layer->base);
- for (i = 0; i < ms->n_planes; i++) {
- /* calculate the offset for the layer's plane registers */
- u16 ptr = mp->layer->ptr + (i << 4);
- dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(state->fb,
- state, i);
-
- malidp_hw_write(mp->hwdev, lower_32_bits(fb_addr), ptr);
- malidp_hw_write(mp->hwdev, upper_32_bits(fb_addr), ptr + 4);
- }
+ for (i = 0; i < ms->n_planes; i++)
+ malidp_set_plane_base_addr(fb, mp, i);
malidp_de_set_mmu_control(mp, ms);
@@ -657,6 +734,8 @@ static void malidp_de_plane_update(struct drm_plane *plane,
mp->layer->base + MALIDP550_LS_R1_IN_SIZE);
}
+ malidp_de_set_plane_afbc(plane);
+
/* first clear the rotation bits */
val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL);
val &= ~LAYER_ROT_MASK;
@@ -674,7 +753,7 @@ static void malidp_de_plane_update(struct drm_plane *plane,
if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) {
val |= LAYER_COMP_PLANE;
- } else if (state->fb->format->has_alpha) {
+ } else if (format_has_alpha) {
/* We only care about blend mode if the format has alpha */
switch (pixel_alpha) {
case DRM_MODE_BLEND_PREMULTI:
diff --git a/drivers/gpu/drm/arm/malidp_regs.h b/drivers/gpu/drm/arm/malidp_regs.h
index 7ce3e14..a0dd6e1 100644
--- a/drivers/gpu/drm/arm/malidp_regs.h
+++ b/drivers/gpu/drm/arm/malidp_regs.h
@@ -198,10 +198,13 @@
#define MALIDP500_LV_YUV2RGB ((s16)(-0xB8))
#define MALIDP500_DE_LV_BASE 0x00100
#define MALIDP500_DE_LV_PTR_BASE 0x00124
+#define MALIDP500_DE_LV_AD_CTRL 0x00400
#define MALIDP500_DE_LG1_BASE 0x00200
#define MALIDP500_DE_LG1_PTR_BASE 0x0021c
+#define MALIDP500_DE_LG1_AD_CTRL 0x0040c
#define MALIDP500_DE_LG2_BASE 0x00300
#define MALIDP500_DE_LG2_PTR_BASE 0x0031c
+#define MALIDP500_DE_LG2_AD_CTRL 0x00418
#define MALIDP500_SE_BASE 0x00c00
#define MALIDP500_SE_CONTROL 0x00c0c
#define MALIDP500_SE_MEMWRITE_OUT_SIZE 0x00c2c
@@ -228,10 +231,13 @@
#define MALIDP550_LV_YUV2RGB 0x00084
#define MALIDP550_DE_LV1_BASE 0x00100
#define MALIDP550_DE_LV1_PTR_BASE 0x00124
+#define MALIDP550_DE_LV1_AD_CTRL 0x001B8
#define MALIDP550_DE_LV2_BASE 0x00200
#define MALIDP550_DE_LV2_PTR_BASE 0x00224
+#define MALIDP550_DE_LV2_AD_CTRL 0x002B8
#define MALIDP550_DE_LG_BASE 0x00300
#define MALIDP550_DE_LG_PTR_BASE 0x0031c
+#define MALIDP550_DE_LG_AD_CTRL 0x00330
#define MALIDP550_DE_LS_BASE 0x00400
#define MALIDP550_DE_LS_PTR_BASE 0x0042c
#define MALIDP550_DE_PERF_BASE 0x00500
@@ -258,6 +264,20 @@
#define MALIDP_MMU_CTRL_PX_PS(x) (1 << (8 + (x)))
#define MALIDP_MMU_CTRL_PP_NUM_REQ(x) (((x) & 0x7f) << 12)
+/* AFBC register offsets relative to MALIDPXXX_DE_LX_AD_CTRL */
+/* The following register offsets are common for DP500, DP550 and DP650 */
+#define MALIDP_AD_CROP_H 0x4
+#define MALIDP_AD_CROP_V 0x8
+#define MALIDP_AD_END_PTR_LOW 0xc
+#define MALIDP_AD_END_PTR_HIGH 0x10
+
+/* AFBC decoder Registers */
+#define MALIDP_AD_EN BIT(0)
+#define MALIDP_AD_YTR BIT(4)
+#define MALIDP_AD_BS BIT(8)
+#define MALIDP_AD_CROP_RIGHT_OFFSET 16
+#define MALIDP_AD_CROP_BOTTOM_OFFSET 16
+
/*
* Starting with DP550 the register map blocks has been standardised to the
* following layout:
--
2.7.4
We have added a new format ie DRM_FORMAT_XVYU2101010 which is supported
by mali display driver.
Signed-off-by: Ayan Kumar halder <[email protected]>
---
drivers/gpu/drm/drm_fourcc.c | 1 +
include/uapi/drm/drm_fourcc.h | 1 +
2 files changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
index 6b7a62e..d31e1ae 100644
--- a/drivers/gpu/drm/drm_fourcc.c
+++ b/drivers/gpu/drm/drm_fourcc.c
@@ -229,6 +229,7 @@ const struct drm_format_info *__drm_format_info(u32 format)
{ .format = DRM_FORMAT_VUY888, .depth = 0, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_Y410, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true },
{ .format = DRM_FORMAT_AYUV, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true },
+ { .format = DRM_FORMAT_XVYU2101010, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_P010, .depth = 0, .num_planes = 2, .cpp = { 2, 4, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true },
{ .format = DRM_FORMAT_P012, .depth = 0, .num_planes = 2, .cpp = { 2, 4, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true },
{ .format = DRM_FORMAT_P016, .depth = 0, .num_planes = 2, .cpp = { 2, 4, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true },
diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
index 71b2bc7..75c4b5a 100644
--- a/include/uapi/drm/drm_fourcc.h
+++ b/include/uapi/drm/drm_fourcc.h
@@ -153,6 +153,7 @@ extern "C" {
#define DRM_FORMAT_AYUV fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */
#define DRM_FORMAT_XYUV8888 fourcc_code('X', 'Y', 'U', 'V') /* [31:0] X:Y:Cb:Cr 8:8:8:8 little endian */
+#define DRM_FORMAT_XVYU2101010 fourcc_code('X', 'V', '3', '0') /* [31:0] X:Cr:Y:Cb 2:10:10:10 little endian */
#define DRM_FORMAT_VUY888 fourcc_code('V', 'U', '2', '4') /* [23:0] Cr:Cb:Y 8:8:8 little endian */
#define DRM_FORMAT_Y410 fourcc_code('Y', '4', '1', '0') /* [31:0] A:Cr:Y:Cb 2:10:10:10 little endian */
#define DRM_FORMAT_VUY101010 fourcc_code('V', 'U', '3', '0') /* Y followed by U then V, 10:10:10. Non-linear modifier only */
--
2.7.4
The constraints are as follows (for Mali-DP 500, 550, 650) :-
1. AFBC is not supported for the formats defined in malidp_hw_format_is_linear_only()
2. Some of the formats are supported only with AFBC modifiers. Thus we have
introduced a new function 'malidp_hw_format_is_afbc_only()' which verifies the same.
3. AFBC_FORMAT_MOD_YTR needs to be provided for any RGB format.
4. Formats <= 16bpp cannot support AFBC_FORMAT_MOD_SPLIT.
5. CBR should not be set for non-subsampled formats.
6. SMART layer does not support framebuffer with AFBC modifiers.
Return -EINVAL for such a scenario.
7. AFBC_FORMAT_MOD_YTR is not supported for any YUV formats.
8. Formats which are subsampled cannot support AFBC_FORMAT_MOD_SPLIT. However in
DP550, YUV_420_10BIT is supported with AFBC_FORMAT_MOD_SPLIT. This feature has
been identified with MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT.
9. In DP550 and DP650, for YUYV, the hardware supports different format-ids to
be used with and without AFBC modifier. We have used the feature
'MALIDP_DEVICE_AFBC_YUYV_USE_422_P2' to identify this characteristic.
Signed-off-by: Ayan Kumar halder <[email protected]>
---
drivers/gpu/drm/arm/malidp_drv.c | 23 +------
drivers/gpu/drm/arm/malidp_drv.h | 6 ++
drivers/gpu/drm/arm/malidp_hw.c | 71 +++++++++++++++++++--
drivers/gpu/drm/arm/malidp_hw.h | 5 +-
drivers/gpu/drm/arm/malidp_mw.c | 2 +-
drivers/gpu/drm/arm/malidp_planes.c | 124 +++++++++++++++++++++++++++++++++++-
6 files changed, 199 insertions(+), 32 deletions(-)
diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index b8db92f..2f0b553 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -264,29 +264,8 @@ static bool
malidp_verify_afbc_framebuffer_caps(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *mode_cmd)
{
- const struct drm_format_info *info;
-
- if ((mode_cmd->modifier[0] >> 56) != DRM_FORMAT_MOD_VENDOR_ARM) {
- DRM_DEBUG_KMS("Unknown modifier (not Arm)\n");
+ if (malidp_format_mod_supported(dev, mode_cmd->pixel_format, mode_cmd->modifier[0]) == false)
return false;
- }
-
- if (mode_cmd->modifier[0] &
- ~DRM_FORMAT_MOD_ARM_AFBC(AFBC_MOD_VALID_BITS)) {
- DRM_DEBUG_KMS("Unsupported modifiers\n");
- return false;
- }
-
- info = drm_get_format_info(dev, mode_cmd);
- if (!info) {
- DRM_DEBUG_KMS("Unable to get the format information\n");
- return false;
- }
-
- if (info->num_planes != 1) {
- DRM_DEBUG_KMS("AFBC buffers expect one plane\n");
- return false;
- }
if (mode_cmd->offsets[0] != 0) {
DRM_DEBUG_KMS("AFBC buffers' plane offset should be 0\n");
diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h
index b76c86f..019a682 100644
--- a/drivers/gpu/drm/arm/malidp_drv.h
+++ b/drivers/gpu/drm/arm/malidp_drv.h
@@ -90,6 +90,12 @@ struct malidp_crtc_state {
int malidp_de_planes_init(struct drm_device *drm);
int malidp_crtc_init(struct drm_device *drm);
+bool malidp_hw_format_is_linear_only(u32 format);
+bool malidp_hw_format_is_afbc_only(u32 format);
+
+bool malidp_format_mod_supported(struct drm_device *drm,
+ u32 format, u64 modifier);
+
#ifdef CONFIG_DEBUG_FS
void malidp_error(struct malidp_drm *malidp,
struct malidp_error_stats *error_stats, u32 status,
diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
index 25ac5890..4a774be 100644
--- a/drivers/gpu/drm/arm/malidp_hw.c
+++ b/drivers/gpu/drm/arm/malidp_hw.c
@@ -60,6 +60,8 @@ static const struct malidp_format_id malidp500_de_formats[] = {
#define MALIDP_ID(__group, __format) \
((((__group) & 0x7) << 3) | ((__format) & 0x7))
+#define AFBC_YUV_422_FORMAT_ID MALIDP_ID(5, 1)
+
#define MALIDP_COMMON_FORMATS \
/* fourcc, layers supporting the format, internal id */ \
{ DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 0) }, \
@@ -887,7 +889,10 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
.se_base = MALIDP550_SE_BASE,
.dc_base = MALIDP550_DC_BASE,
.out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
- .features = MALIDP_REGMAP_HAS_CLEARIRQ | MALIDP_DEVICE_AFBC_SUPPORT_SPLIT | AFBC_SUPPORT_SPLIT_WITH_YUV_420_10,
+ .features = MALIDP_REGMAP_HAS_CLEARIRQ |
+ MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
+ MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT |
+ MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
.n_layers = ARRAY_SIZE(malidp550_layers),
.layers = malidp550_layers,
.de_irq_map = {
@@ -933,7 +938,9 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
.se_base = MALIDP550_SE_BASE,
.dc_base = MALIDP550_DC_BASE,
.out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
- .features = MALIDP_REGMAP_HAS_CLEARIRQ | MALIDP_DEVICE_AFBC_SUPPORT_SPLIT,
+ .features = MALIDP_REGMAP_HAS_CLEARIRQ |
+ MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
+ MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
.n_layers = ARRAY_SIZE(malidp650_layers),
.layers = malidp650_layers,
.de_irq_map = {
@@ -982,19 +989,73 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
};
u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
- u8 layer_id, u32 format)
+ u8 layer_id, u32 format, bool has_modifier)
{
unsigned int i;
for (i = 0; i < map->n_pixel_formats; i++) {
if (((map->pixel_formats[i].layer & layer_id) == layer_id) &&
- (map->pixel_formats[i].format == format))
- return map->pixel_formats[i].id;
+ (map->pixel_formats[i].format == format)) {
+
+ /*
+ * In some DP550 and DP650, DRM_FORMAT_YUYV + AFBC modifier
+ * is supported by a different h/w format id than
+ * DRM_FORMAT_YUYV (only).
+ */
+ if (format == DRM_FORMAT_YUYV &&
+ (has_modifier) &&
+ (map->features & MALIDP_DEVICE_AFBC_YUYV_USE_422_P2))
+ return AFBC_YUV_422_FORMAT_ID;
+ else
+ return map->pixel_formats[i].id;
+ }
}
return MALIDP_INVALID_FORMAT_ID;
}
+bool malidp_hw_format_is_linear_only(u32 format)
+{
+ switch (format) {
+ case DRM_FORMAT_ARGB2101010:
+ case DRM_FORMAT_RGBA1010102:
+ case DRM_FORMAT_BGRA1010102:
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_RGBA8888:
+ case DRM_FORMAT_BGRA8888:
+ case DRM_FORMAT_XBGR8888:
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_RGBX8888:
+ case DRM_FORMAT_BGRX8888:
+ case DRM_FORMAT_RGB888:
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_ARGB1555:
+ case DRM_FORMAT_RGBA5551:
+ case DRM_FORMAT_BGRA5551:
+ case DRM_FORMAT_UYVY:
+ case DRM_FORMAT_XYUV8888:
+ case DRM_FORMAT_XVYU2101010:
+ case DRM_FORMAT_X0L2:
+ case DRM_FORMAT_X0L0:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool malidp_hw_format_is_afbc_only(u32 format)
+{
+ switch (format) {
+ case DRM_FORMAT_VUY888:
+ case DRM_FORMAT_VUY101010:
+ case DRM_FORMAT_YUV420_8BIT:
+ case DRM_FORMAT_YUV420_10BIT:
+ return true;
+ default:
+ return false;
+ }
+}
+
static void malidp_hw_clear_irq(struct malidp_hw_device *hwdev, u8 block, u32 irq)
{
u32 base = malidp_get_block_base(hwdev, block);
diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h
index 27b907f..52188f0 100644
--- a/drivers/gpu/drm/arm/malidp_hw.h
+++ b/drivers/gpu/drm/arm/malidp_hw.h
@@ -97,7 +97,8 @@ struct malidp_se_config {
/* regmap features */
#define MALIDP_REGMAP_HAS_CLEARIRQ BIT(0)
#define MALIDP_DEVICE_AFBC_SUPPORT_SPLIT BIT(1)
-#define AFBC_SUPPORT_SPLIT_WITH_YUV_420_10 BIT(2)
+#define MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT BIT(2)
+#define MALIDP_DEVICE_AFBC_YUYV_USE_422_P2 BIT(3)
struct malidp_hw_regmap {
/* address offset of the DE register bank */
@@ -323,7 +324,7 @@ int malidp_se_irq_init(struct drm_device *drm, int irq);
void malidp_se_irq_fini(struct malidp_hw_device *hwdev);
u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
- u8 layer_id, u32 format);
+ u8 layer_id, u32 format, bool has_modifier);
static inline u8 malidp_hw_get_pitch_align(struct malidp_hw_device *hwdev, bool rotated)
{
diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c
index 91472e5..0484744 100644
--- a/drivers/gpu/drm/arm/malidp_mw.c
+++ b/drivers/gpu/drm/arm/malidp_mw.c
@@ -143,7 +143,7 @@ malidp_mw_encoder_atomic_check(struct drm_encoder *encoder,
mw_state->format =
malidp_hw_get_format_id(&malidp->dev->hw->map, SE_MEMWRITE,
- fb->format->format);
+ fb->format->format, !!fb->modifier);
if (mw_state->format == MALIDP_INVALID_FORMAT_ID) {
struct drm_format_name_buf format_name;
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
index cd60f73..0765cee 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -52,6 +52,8 @@
#define MALIDP550_LS_ENABLE 0x01c
#define MALIDP550_LS_R1_IN_SIZE 0x020
+#define MODIFIERS_COUNT_MAX 15
+
/*
* This 4-entry look-up-table is used to determine the full 8-bit alpha value
* for formats with 1- or 2-bit alpha channels.
@@ -145,6 +147,117 @@ static void malidp_plane_atomic_print_state(struct drm_printer *p,
drm_printf(p, "\tmmu_prefetch_pgsize=%d\n", ms->mmu_prefetch_pgsize);
}
+bool malidp_format_mod_supported(struct drm_device *drm,
+ u32 format, u64 modifier)
+{
+ const struct drm_format_info *info;
+ const u64 *modifiers;
+ struct malidp_drm *malidp = drm->dev_private;
+ const struct malidp_hw_regmap *map = &malidp->dev->hw->map;
+
+ if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
+ return false;
+
+ /* Some pixel formats are supported without any modifier */
+ if (modifier == DRM_FORMAT_MOD_LINEAR) {
+ /* However these pixel formats need to be supported with
+ * modifiers only
+ */
+ return !malidp_hw_format_is_afbc_only(format);
+ }
+
+ if ((modifier >> 56) != DRM_FORMAT_MOD_VENDOR_ARM) {
+ DRM_ERROR("Unknown modifier (not Arm)\n");
+ return false;
+ }
+
+ if (modifier &
+ ~DRM_FORMAT_MOD_ARM_AFBC(AFBC_MOD_VALID_BITS)) {
+ DRM_DEBUG_KMS("Unsupported modifiers\n");
+ return false;
+ }
+
+ modifiers = malidp_format_modifiers;
+ while (*modifiers != DRM_FORMAT_MOD_INVALID) {
+ if (*modifiers == modifier) {
+ /* SPLIT buffers must use SPARSE layout */
+ if (WARN_ON_ONCE((modifier & AFBC_SPLIT) && !(modifier & AFBC_SPARSE)))
+ return false;
+
+ /* CBR only applies to YUV formats, where YTR should be always 0 */
+ if (WARN_ON_ONCE((modifier & AFBC_CBR) && (modifier & AFBC_YTR)))
+ return false;
+
+ break;
+ }
+
+ modifiers++;
+ }
+
+ /* return false, if the modifier was not found */
+ if (*modifiers == DRM_FORMAT_MOD_INVALID) {
+ DRM_DEBUG_KMS("Unsupported modifier\n");
+ return false;
+ }
+
+ info = drm_format_info(format);
+
+ if (info->num_planes != 1) {
+ DRM_DEBUG_KMS("AFBC buffers expect one plane\n");
+ return false;
+ }
+
+ if (malidp_hw_format_is_linear_only(format) == true) {
+ DRM_DEBUG_KMS("Given format (0x%x) is supported is linear mode only\n", format);
+ return false;
+ }
+
+ /*
+ * RGB formats need to provide YTR modifier and YUV formats should not
+ * provide YTR modifier.
+ */
+ if (!(info->is_yuv) != !!(modifier & AFBC_FORMAT_MOD_YTR)) {
+ DRM_DEBUG_KMS("AFBC_FORMAT_MOD_YTR is %s for %s formats\n",
+ info->is_yuv ? "disallowed" : "mandatory",
+ info->is_yuv ? "YUV" : "RGB");
+ return false;
+ }
+
+ if (modifier & AFBC_SPLIT) {
+ if (!info->is_yuv) {
+ if (drm_format_plane_cpp(format, 0) <= 2) {
+ DRM_DEBUG_KMS("RGB formats <= 16bpp are not supported with SPLIT\n");
+ return false;
+ }
+ }
+
+ if ((drm_format_horz_chroma_subsampling(format) != 1) ||
+ (drm_format_vert_chroma_subsampling(format) != 1)) {
+ if (!(format == DRM_FORMAT_YUV420_10BIT &&
+ (map->features & MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT))) {
+ DRM_DEBUG_KMS("Formats which are sub-sampled should never be split\n");
+ return false;
+ }
+ }
+ }
+
+ if (modifier & AFBC_CBR) {
+ if ((drm_format_horz_chroma_subsampling(format) == 1) ||
+ (drm_format_vert_chroma_subsampling(format) == 1)) {
+ DRM_DEBUG_KMS("Formats which are not sub-sampled should not have CBR set\n");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool malidp_format_mod_supported_per_plane(struct drm_plane *plane,
+ u32 format, u64 modifier)
+{
+ return malidp_format_mod_supported(plane->dev, format, modifier);
+}
+
static const struct drm_plane_funcs malidp_de_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
@@ -153,6 +266,7 @@ static const struct drm_plane_funcs malidp_de_plane_funcs = {
.atomic_duplicate_state = malidp_duplicate_plane_state,
.atomic_destroy_state = malidp_destroy_plane_state,
.atomic_print_state = malidp_plane_atomic_print_state,
+ .format_mod_supported = malidp_format_mod_supported_per_plane,
};
static int malidp_se_check_scaling(struct malidp_plane *mp,
@@ -406,8 +520,8 @@ static int malidp_de_plane_check(struct drm_plane *plane,
fb = state->fb;
ms->format = malidp_hw_get_format_id(&mp->hwdev->hw->map,
- mp->layer->id,
- fb->format->format);
+ mp->layer->id, fb->format->format,
+ !!fb->modifier);
if (ms->format == MALIDP_INVALID_FORMAT_ID)
return -EINVAL;
@@ -469,6 +583,12 @@ static int malidp_de_plane_check(struct drm_plane *plane,
return -EINVAL;
}
+ /* SMART layer does not support AFBC */
+ if (mp->layer->id == DE_SMART && fb->modifier) {
+ DRM_ERROR("AFBC framebuffer not supported in SMART layer");
+ return -EINVAL;
+ }
+
ms->rotmem_size = 0;
if (state->rotation & MALIDP_ROTATED_MASK) {
int val;
--
2.7.4
On Mon, Dec 03, 2018 at 11:31:56AM +0000, Ayan Halder wrote:
> We have added a new format ie DRM_FORMAT_XVYU2101010 which is supported
> by mali display driver.
>
> Signed-off-by: Ayan Kumar halder <[email protected]>
Reviewed-by: Liviu Dudau <[email protected]>
Best regards,
Liviu
> ---
> drivers/gpu/drm/drm_fourcc.c | 1 +
> include/uapi/drm/drm_fourcc.h | 1 +
> 2 files changed, 2 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
> index 6b7a62e..d31e1ae 100644
> --- a/drivers/gpu/drm/drm_fourcc.c
> +++ b/drivers/gpu/drm/drm_fourcc.c
> @@ -229,6 +229,7 @@ const struct drm_format_info *__drm_format_info(u32 format)
> { .format = DRM_FORMAT_VUY888, .depth = 0, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
> { .format = DRM_FORMAT_Y410, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true },
> { .format = DRM_FORMAT_AYUV, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true },
> + { .format = DRM_FORMAT_XVYU2101010, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
> { .format = DRM_FORMAT_P010, .depth = 0, .num_planes = 2, .cpp = { 2, 4, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true },
> { .format = DRM_FORMAT_P012, .depth = 0, .num_planes = 2, .cpp = { 2, 4, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true },
> { .format = DRM_FORMAT_P016, .depth = 0, .num_planes = 2, .cpp = { 2, 4, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true },
> diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
> index 71b2bc7..75c4b5a 100644
> --- a/include/uapi/drm/drm_fourcc.h
> +++ b/include/uapi/drm/drm_fourcc.h
> @@ -153,6 +153,7 @@ extern "C" {
>
> #define DRM_FORMAT_AYUV fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */
> #define DRM_FORMAT_XYUV8888 fourcc_code('X', 'Y', 'U', 'V') /* [31:0] X:Y:Cb:Cr 8:8:8:8 little endian */
> +#define DRM_FORMAT_XVYU2101010 fourcc_code('X', 'V', '3', '0') /* [31:0] X:Cr:Y:Cb 2:10:10:10 little endian */
> #define DRM_FORMAT_VUY888 fourcc_code('V', 'U', '2', '4') /* [23:0] Cr:Cb:Y 8:8:8 little endian */
> #define DRM_FORMAT_Y410 fourcc_code('Y', '4', '1', '0') /* [31:0] A:Cr:Y:Cb 2:10:10:10 little endian */
> #define DRM_FORMAT_VUY101010 fourcc_code('V', 'U', '3', '0') /* Y followed by U then V, 10:10:10. Non-linear modifier only */
> --
> 2.7.4
>
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
On Mon, Dec 03, 2018 at 11:31:58AM +0000, Ayan Halder wrote:
> Added the AFBC decoder registers for DP500 , DP550 and DP650.
> These registers control the processing of AFBC buffers. It controls various
> features like AFBC decoder enable, lossless transformation and block split
> as well as setting of the left, right, top and bottom cropping of AFBC buffers
> (in number of pixels).
> All the layers (except DE_SMART) support framebuffers with AFBC modifiers.
> One needs to set the pixel values of the top, left, bottom and right cropping
> for the AFBC framebuffer.
> Cropping an AFBC framebuffer is controlled by the AFBC crop registers.
> In that case, the layer input size registers should be configured with
> framebuffer's dimensions and not with drm_plane_state source width/height
> values (which is used for non AFBC framebuffer to denote cropping).
>
> Changes from v1:
> - Removed the "if (fb->modifier)" check from malidp_de_plane_update()
> and added it in malidp_de_set_plane_afbc(). This will consolidate all the
> AFBC specific register configurations in a single function ie
> malidp_de_set_plane_afbc().
>
> Changes from v2:
> - For AFBC framebuffer, layer input size register should be set to framebuffer's
> width and height
>
> Signed-off-by: Ayan Kumar Halder <[email protected]>
> ---
> drivers/gpu/drm/arm/malidp_hw.c | 25 +++++----
> drivers/gpu/drm/arm/malidp_hw.h | 2 +
> drivers/gpu/drm/arm/malidp_planes.c | 109 +++++++++++++++++++++++++++++++-----
> drivers/gpu/drm/arm/malidp_regs.h | 20 +++++++
> 4 files changed, 130 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
> index b9bed11..87b7b12 100644
> --- a/drivers/gpu/drm/arm/malidp_hw.c
> +++ b/drivers/gpu/drm/arm/malidp_hw.c
> @@ -94,11 +94,12 @@ static const struct malidp_layer malidp500_layers[] = {
> * yuv2rgb matrix offset, mmu control register offset, rotation_features
> */
> { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE,
> - MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB, 0, ROTATE_ANY },
> + MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB, 0, ROTATE_ANY,
> + MALIDP500_DE_LV_AD_CTRL },
> { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE,
> - MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
> + MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY, MALIDP500_DE_LG1_AD_CTRL },
> { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE,
> - MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
> + MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY, MALIDP500_DE_LG2_AD_CTRL },
> };
>
> static const struct malidp_layer malidp550_layers[] = {
> @@ -106,13 +107,15 @@ static const struct malidp_layer malidp550_layers[] = {
> * yuv2rgb matrix offset, mmu control register offset, rotation_features
> */
> { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
> - MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY },
> + MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY,
> + MALIDP550_DE_LV1_AD_CTRL },
> { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
> - MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
> + MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY, MALIDP550_DE_LG_AD_CTRL },
> { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
> - MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY },
> + MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY,
> + MALIDP550_DE_LV2_AD_CTRL },
> { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
> - MALIDP550_DE_LS_R1_STRIDE, 0, 0, ROTATE_NONE },
> + MALIDP550_DE_LS_R1_STRIDE, 0, 0, ROTATE_NONE, 0 },
> };
>
> static const struct malidp_layer malidp650_layers[] = {
> @@ -122,16 +125,16 @@ static const struct malidp_layer malidp650_layers[] = {
> */
> { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
> MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
> - MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY },
> + MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY, MALIDP550_DE_LV1_AD_CTRL },
> { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
> MALIDP_DE_LG_STRIDE, 0, MALIDP650_DE_LG_MMU_CTRL,
> - ROTATE_COMPRESSED },
> + ROTATE_COMPRESSED, MALIDP550_DE_LG_AD_CTRL },
> { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
> MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
> - MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY },
> + MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY, MALIDP550_DE_LV2_AD_CTRL },
> { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
> MALIDP550_DE_LS_R1_STRIDE, 0, MALIDP650_DE_LS_MMU_CTRL,
> - ROTATE_NONE },
> + ROTATE_NONE, 0 },
> };
>
> #define SE_N_SCALING_COEFFS 96
> diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h
> index 40155e2..651558f 100644
> --- a/drivers/gpu/drm/arm/malidp_hw.h
> +++ b/drivers/gpu/drm/arm/malidp_hw.h
> @@ -70,6 +70,8 @@ struct malidp_layer {
> s16 yuv2rgb_offset; /* offset to the YUV->RGB matrix entries */
> u16 mmu_ctrl_offset; /* offset to the MMU control register */
> enum rotation_features rot; /* type of rotation supported */
> + /* address offset for the AFBC decoder registers */
> + u16 afbc_decoder_offset;
> };
>
> enum malidp_scaling_coeff_set {
> diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
> index c9a6d3e..cd60f73 100644
> --- a/drivers/gpu/drm/arm/malidp_planes.c
> +++ b/drivers/gpu/drm/arm/malidp_planes.c
> @@ -592,6 +592,80 @@ static void malidp_de_set_mmu_control(struct malidp_plane *mp,
> mp->layer->base + mp->layer->mmu_ctrl_offset);
> }
>
> +static void malidp_set_plane_base_addr(struct drm_framebuffer *fb,
> + struct malidp_plane *mp,
> + int plane_index)
> +{
> + dma_addr_t paddr;
> + u16 ptr;
> + struct drm_plane *plane = &mp->base;
> + bool afbc = fb->modifier ? true : false;
> +
> + ptr = mp->layer->ptr + (plane_index << 4);
> +
> + /*
> + * For AFBC buffers, cropping is handled by AFBC decoder rather than
> + * pointer manipulation.
> + */
I think this comment needs to go in malidp_de_plane_update, not in this function.
This function only updates the plane's base address.
> + if (!afbc) {
> + paddr = drm_fb_cma_get_gem_addr(fb, plane->state,
> + plane_index);
> + } else {
> + struct drm_gem_cma_object *obj;
> +
> + obj = drm_fb_cma_get_gem_obj(fb, plane_index);
> +
> + if (WARN_ON(!obj))
> + return;
> + paddr = obj->paddr;
> + }
> +
> + malidp_hw_write(mp->hwdev, lower_32_bits(paddr), ptr);
> + malidp_hw_write(mp->hwdev, upper_32_bits(paddr), ptr + 4);
> +}
> +
> +static void malidp_de_set_plane_afbc(struct drm_plane *plane)
> +{
> + struct malidp_plane *mp;
> + u32 src_w, src_h, val = 0, src_x, src_y;
> + struct drm_framebuffer *fb = plane->state->fb;
> +
> + mp = to_malidp_plane(plane);
> +
> + /* no afbc_decoder_offset means AFBC is not supported on this plane */
> + if (!mp->layer->afbc_decoder_offset)
> + return;
> +
> + if (!fb->modifier) {
> + malidp_hw_write(mp->hwdev, 0, mp->layer->afbc_decoder_offset);
> + return;
> + }
> +
> + /* convert src values from Q16 fixed point to integer */
> + src_w = plane->state->src_w >> 16;
> + src_h = plane->state->src_h >> 16;
> + src_x = plane->state->src_x >> 16;
> + src_y = plane->state->src_y >> 16;
> +
> + val = ((fb->width - (src_x + src_w)) << MALIDP_AD_CROP_RIGHT_OFFSET) |
> + src_x;
> + malidp_hw_write(mp->hwdev, val,
> + mp->layer->afbc_decoder_offset + MALIDP_AD_CROP_H);
> +
> + val = ((fb->height - (src_y + src_h)) << MALIDP_AD_CROP_BOTTOM_OFFSET) |
> + src_y;
> + malidp_hw_write(mp->hwdev, val,
> + mp->layer->afbc_decoder_offset + MALIDP_AD_CROP_V);
> +
> + val = MALIDP_AD_EN;
> + if (fb->modifier & AFBC_FORMAT_MOD_SPLIT)
> + val |= MALIDP_AD_BS;
> + if (fb->modifier & AFBC_FORMAT_MOD_YTR)
> + val |= MALIDP_AD_YTR;
> +
> + malidp_hw_write(mp->hwdev, val, mp->layer->afbc_decoder_offset);
> +}
> +
> static void malidp_de_plane_update(struct drm_plane *plane,
> struct drm_plane_state *old_state)
> {
> @@ -600,30 +674,33 @@ static void malidp_de_plane_update(struct drm_plane *plane,
> struct drm_plane_state *state = plane->state;
> u16 pixel_alpha = state->pixel_blend_mode;
> u8 plane_alpha = state->alpha >> 8;
> + bool format_has_alpha = state->fb->format->has_alpha;
> u32 src_w, src_h, dest_w, dest_h, val;
> int i;
> + struct drm_framebuffer *fb = plane->state->fb;
>
> mp = to_malidp_plane(plane);
>
> - /* convert src values from Q16 fixed point to integer */
> - src_w = state->src_w >> 16;
> - src_h = state->src_h >> 16;
> - dest_w = state->crtc_w;
> - dest_h = state->crtc_h;
> + /* For AFBC framebuffer, use the framebuffer width and height for configuring
> + * layer input size register.
> + */
> + if (fb->modifier) {
> + src_w = fb->width;
> + src_h = fb->height;
> + } else {
> + /* convert src values from Q16 fixed point to integer */
> + src_w = ms->base.src_w >> 16;
> + src_h = ms->base.src_h >> 16;
> + }
> + dest_w = ms->base.crtc_w;
> + dest_h = ms->base.crtc_h;
These two lines above are equivalent to the last two lines you deleted. Why you need this change?
>
> val = malidp_hw_read(mp->hwdev, mp->layer->base);
> val = (val & ~LAYER_FORMAT_MASK) | ms->format;
> malidp_hw_write(mp->hwdev, val, mp->layer->base);
>
> - for (i = 0; i < ms->n_planes; i++) {
> - /* calculate the offset for the layer's plane registers */
> - u16 ptr = mp->layer->ptr + (i << 4);
> - dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(state->fb,
> - state, i);
> -
> - malidp_hw_write(mp->hwdev, lower_32_bits(fb_addr), ptr);
> - malidp_hw_write(mp->hwdev, upper_32_bits(fb_addr), ptr + 4);
> - }
> + for (i = 0; i < ms->n_planes; i++)
> + malidp_set_plane_base_addr(fb, mp, i);
>
> malidp_de_set_mmu_control(mp, ms);
>
> @@ -657,6 +734,8 @@ static void malidp_de_plane_update(struct drm_plane *plane,
> mp->layer->base + MALIDP550_LS_R1_IN_SIZE);
> }
>
> + malidp_de_set_plane_afbc(plane);
I feel like this function call should be done only if (fb->modifier) is
true.
> +
> /* first clear the rotation bits */
> val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL);
> val &= ~LAYER_ROT_MASK;
> @@ -674,7 +753,7 @@ static void malidp_de_plane_update(struct drm_plane *plane,
>
> if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) {
> val |= LAYER_COMP_PLANE;
> - } else if (state->fb->format->has_alpha) {
> + } else if (format_has_alpha) {
This change has nothing to do with AFBC, it should not be in this patch.
> /* We only care about blend mode if the format has alpha */
> switch (pixel_alpha) {
> case DRM_MODE_BLEND_PREMULTI:
> diff --git a/drivers/gpu/drm/arm/malidp_regs.h b/drivers/gpu/drm/arm/malidp_regs.h
> index 7ce3e14..a0dd6e1 100644
> --- a/drivers/gpu/drm/arm/malidp_regs.h
> +++ b/drivers/gpu/drm/arm/malidp_regs.h
> @@ -198,10 +198,13 @@
> #define MALIDP500_LV_YUV2RGB ((s16)(-0xB8))
> #define MALIDP500_DE_LV_BASE 0x00100
> #define MALIDP500_DE_LV_PTR_BASE 0x00124
> +#define MALIDP500_DE_LV_AD_CTRL 0x00400
> #define MALIDP500_DE_LG1_BASE 0x00200
> #define MALIDP500_DE_LG1_PTR_BASE 0x0021c
> +#define MALIDP500_DE_LG1_AD_CTRL 0x0040c
> #define MALIDP500_DE_LG2_BASE 0x00300
> #define MALIDP500_DE_LG2_PTR_BASE 0x0031c
> +#define MALIDP500_DE_LG2_AD_CTRL 0x00418
> #define MALIDP500_SE_BASE 0x00c00
> #define MALIDP500_SE_CONTROL 0x00c0c
> #define MALIDP500_SE_MEMWRITE_OUT_SIZE 0x00c2c
> @@ -228,10 +231,13 @@
> #define MALIDP550_LV_YUV2RGB 0x00084
> #define MALIDP550_DE_LV1_BASE 0x00100
> #define MALIDP550_DE_LV1_PTR_BASE 0x00124
> +#define MALIDP550_DE_LV1_AD_CTRL 0x001B8
> #define MALIDP550_DE_LV2_BASE 0x00200
> #define MALIDP550_DE_LV2_PTR_BASE 0x00224
> +#define MALIDP550_DE_LV2_AD_CTRL 0x002B8
> #define MALIDP550_DE_LG_BASE 0x00300
> #define MALIDP550_DE_LG_PTR_BASE 0x0031c
> +#define MALIDP550_DE_LG_AD_CTRL 0x00330
> #define MALIDP550_DE_LS_BASE 0x00400
> #define MALIDP550_DE_LS_PTR_BASE 0x0042c
> #define MALIDP550_DE_PERF_BASE 0x00500
> @@ -258,6 +264,20 @@
> #define MALIDP_MMU_CTRL_PX_PS(x) (1 << (8 + (x)))
> #define MALIDP_MMU_CTRL_PP_NUM_REQ(x) (((x) & 0x7f) << 12)
>
> +/* AFBC register offsets relative to MALIDPXXX_DE_LX_AD_CTRL */
> +/* The following register offsets are common for DP500, DP550 and DP650 */
> +#define MALIDP_AD_CROP_H 0x4
> +#define MALIDP_AD_CROP_V 0x8
> +#define MALIDP_AD_END_PTR_LOW 0xc
> +#define MALIDP_AD_END_PTR_HIGH 0x10
> +
> +/* AFBC decoder Registers */
> +#define MALIDP_AD_EN BIT(0)
> +#define MALIDP_AD_YTR BIT(4)
> +#define MALIDP_AD_BS BIT(8)
> +#define MALIDP_AD_CROP_RIGHT_OFFSET 16
> +#define MALIDP_AD_CROP_BOTTOM_OFFSET 16
> +
> /*
> * Starting with DP550 the register map blocks has been standardised to the
> * following layout:
> --
> 2.7.4
>
Best regards,
Liviu
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
On Mon, Dec 03, 2018 at 11:31:59AM +0000, Ayan Halder wrote:
> We need to define a common list of format modifiers supported by each of the Mali
> display processors. The difference between DP500 from DP550/650 is that DP500
> does not support block split mode (ie AFBC_FORMAT_MOD_SPLIT) and DP550 supports
> YUV420 with split mode. We noted these special cases by defining MALIDP_DEVICE_AFBC_SUPPORT_SPLIT
> and AFBC_SUPPORT_SPLIT_WITH_YUV_420_10 for malidp_hw_regmap.features
>
> Also we have defined a set of meaningful macros to shorten the modifier names
>
> Signed-off-by: Ayan Kumar halder <[email protected]>
>
> Change-Id: I09fba2032a7474e6ce45af230e0ed18fc1f4c1df
> ---
> drivers/gpu/drm/arm/malidp_drv.c | 8 ++++----
> drivers/gpu/drm/arm/malidp_hw.c | 30 ++++++++++++++++++++++++++++--
> drivers/gpu/drm/arm/malidp_hw.h | 20 +++++++++++++++-----
> 3 files changed, 47 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
> index 505f316..b8db92f 100644
> --- a/drivers/gpu/drm/arm/malidp_drv.c
> +++ b/drivers/gpu/drm/arm/malidp_drv.c
> @@ -293,8 +293,8 @@ malidp_verify_afbc_framebuffer_caps(struct drm_device *dev,
> return false;
> }
>
> - switch (mode_cmd->modifier[0] & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) {
> - case AFBC_FORMAT_MOD_BLOCK_SIZE_16x16:
> + switch (mode_cmd->modifier[0] & AFBC_SIZE_MASK) {
> + case AFBC_SIZE_16X16:
> if ((mode_cmd->width % 16) || (mode_cmd->height % 16)) {
> DRM_DEBUG_KMS("AFBC buffers must be aligned to 16 pixels\n");
> return false;
> @@ -319,8 +319,8 @@ malidp_verify_afbc_framebuffer_size(struct drm_device *dev,
> u32 afbc_superblock_size = 0, afbc_superblock_height = 0;
> u32 afbc_superblock_width = 0, afbc_size = 0;
>
> - switch (mode_cmd->modifier[0] & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) {
> - case AFBC_FORMAT_MOD_BLOCK_SIZE_16x16:
> + switch (mode_cmd->modifier[0] & AFBC_SIZE_MASK) {
> + case AFBC_SIZE_16X16:
> afbc_superblock_height = 16;
> afbc_superblock_width = 16;
> break;
> diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
> index 87b7b12..55d379b 100644
> --- a/drivers/gpu/drm/arm/malidp_hw.c
> +++ b/drivers/gpu/drm/arm/malidp_hw.c
> @@ -137,6 +137,32 @@ static const struct malidp_layer malidp650_layers[] = {
> ROTATE_NONE, 0 },
> };
>
> +const u64 malidp_format_modifiers[] = {
> + /* All RGB formats (except XRGB, RGBX, XBGR, BGRX) */
> + DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR | AFBC_SPARSE),
> + DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR),
> +
> + /* All RGB formats > 16bpp (except XRGB, RGBX, XBGR, BGRX) */
> + DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR | AFBC_SPARSE | AFBC_SPLIT),
> +
> + /* All 8 or 10 bit YUV 444 formats. */
> + /* In DP550, 10 bit YUV 420 format also supported */
> + DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_SPARSE | AFBC_SPLIT),
> +
> + /* YUV 420, 422 P1 8 bit and YUV 444 8 bit/10 bit formats */
> + DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_SPARSE),
> + DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16),
> +
> + /* YUV 420, 422 P1 8, 10 bit formats */
> + DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_CBR | AFBC_SPARSE),
> + DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_CBR),
> +
> + /* All formats */
> + DRM_FORMAT_MOD_LINEAR,
> +
> + DRM_FORMAT_MOD_INVALID
> +};
> +
> #define SE_N_SCALING_COEFFS 96
> static const u16 dp500_se_scaling_coeffs[][SE_N_SCALING_COEFFS] = {
> [MALIDP_UPSCALING_COEFFS - 1] = {
> @@ -841,7 +867,7 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
> .se_base = MALIDP550_SE_BASE,
> .dc_base = MALIDP550_DC_BASE,
> .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
> - .features = MALIDP_REGMAP_HAS_CLEARIRQ,
> + .features = MALIDP_REGMAP_HAS_CLEARIRQ | MALIDP_DEVICE_AFBC_SUPPORT_SPLIT | AFBC_SUPPORT_SPLIT_WITH_YUV_420_10,
> .n_layers = ARRAY_SIZE(malidp550_layers),
> .layers = malidp550_layers,
> .de_irq_map = {
> @@ -887,7 +913,7 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
> .se_base = MALIDP550_SE_BASE,
> .dc_base = MALIDP550_DC_BASE,
> .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
> - .features = MALIDP_REGMAP_HAS_CLEARIRQ,
> + .features = MALIDP_REGMAP_HAS_CLEARIRQ | MALIDP_DEVICE_AFBC_SUPPORT_SPLIT,
> .n_layers = ARRAY_SIZE(malidp650_layers),
> .layers = malidp650_layers,
> .de_irq_map = {
> diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h
> index 651558f..27b907f 100644
> --- a/drivers/gpu/drm/arm/malidp_hw.h
> +++ b/drivers/gpu/drm/arm/malidp_hw.h
> @@ -95,7 +95,9 @@ struct malidp_se_config {
> };
>
> /* regmap features */
> -#define MALIDP_REGMAP_HAS_CLEARIRQ (1 << 0)
> +#define MALIDP_REGMAP_HAS_CLEARIRQ BIT(0)
> +#define MALIDP_DEVICE_AFBC_SUPPORT_SPLIT BIT(1)
> +#define AFBC_SUPPORT_SPLIT_WITH_YUV_420_10 BIT(2)
>
> struct malidp_hw_regmap {
> /* address offset of the DE register bank */
> @@ -390,9 +392,17 @@ static inline void malidp_se_set_enh_coeffs(struct malidp_hw_device *hwdev)
>
> #define MALIDP_GAMMA_LUT_SIZE 4096
>
> -#define AFBC_MOD_VALID_BITS (AFBC_FORMAT_MOD_BLOCK_SIZE_MASK | \
> - AFBC_FORMAT_MOD_YTR | AFBC_FORMAT_MOD_SPLIT | \
> - AFBC_FORMAT_MOD_SPARSE | AFBC_FORMAT_MOD_CBR | \
> - AFBC_FORMAT_MOD_TILED | AFBC_FORMAT_MOD_SC)
> +#define AFBC_SIZE_MASK AFBC_FORMAT_MOD_BLOCK_SIZE_MASK
> +#define AFBC_SIZE_16X16 AFBC_FORMAT_MOD_BLOCK_SIZE_16x16
> +#define AFBC_YTR AFBC_FORMAT_MOD_YTR
> +#define AFBC_SPARSE AFBC_FORMAT_MOD_SPARSE
> +#define AFBC_CBR AFBC_FORMAT_MOD_CBR
> +#define AFBC_SPLIT AFBC_FORMAT_MOD_SPLIT
> +#define AFBC_TILED AFBC_FORMAT_MOD_TILED
> +#define AFBC_SC AFBC_FORMAT_MOD_SC
Why do you need the aliasing of the names? Just to help the typing?
> +
> +#define AFBC_MOD_VALID_BITS (AFBC_SIZE_MASK | AFBC_YTR | AFBC_SPLIT | AFBC_SPARSE | AFBC_CBR | AFBC_TILED | AFBC_SC)
The length of the lines are getting a bit too big, maybe follow the
style of the code you are removing and split the macro into multiple
lines?
Best regards,
Liviu
> +
> +extern const u64 malidp_format_modifiers[];
>
> #endif /* __MALIDP_HW_H__ */
> --
> 2.7.4
>
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
On Mon, Dec 03, 2018 at 11:32:00AM +0000, Ayan Halder wrote:
> We have added some new formats to be supported on DP500/DP550/DP650.
Make a bit more descriptive commit message here, please!
>
> Signed-off-by: Ayan Kumar Halder <[email protected]>
>
> Depends on :- https://patchwork.kernel.org/patch/10460063/
Reviewed-by: Liviu Dudau <[email protected]>
Best regards,
Liviu
> ---
> drivers/gpu/drm/arm/malidp_hw.c | 22 +++++++++++++++++++++-
> 1 file changed, 21 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
> index 55d379b..25ac5890 100644
> --- a/drivers/gpu/drm/arm/malidp_hw.c
> +++ b/drivers/gpu/drm/arm/malidp_hw.c
> @@ -49,6 +49,12 @@ static const struct malidp_format_id malidp500_de_formats[] = {
> { DRM_FORMAT_YUYV, DE_VIDEO1, 13 },
> { DRM_FORMAT_NV12, DE_VIDEO1 | SE_MEMWRITE, 14 },
> { DRM_FORMAT_YUV420, DE_VIDEO1, 15 },
> + { DRM_FORMAT_XYUV8888, DE_VIDEO1, 16 },
> + /* These are supported with AFBC only */
> + { DRM_FORMAT_YUV420_8BIT, DE_VIDEO1, 14 },
> + { DRM_FORMAT_VUY888, DE_VIDEO1, 16 },
> + { DRM_FORMAT_VUY101010, DE_VIDEO1, 17 },
> + { DRM_FORMAT_YUV420_10BIT, DE_VIDEO1, 18 }
> };
>
> #define MALIDP_ID(__group, __format) \
> @@ -74,11 +80,25 @@ static const struct malidp_format_id malidp500_de_formats[] = {
> { DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 1) }, \
> { DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 2) }, \
> { DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 3) }, \
> + /* This is only supported with linear modifier */ \
> + { DRM_FORMAT_XYUV8888, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 0) },\
> + /* This is only supported with AFBC modifier */ \
> + { DRM_FORMAT_VUY888, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 0) }, \
> { DRM_FORMAT_YUYV, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 2) }, \
> + /* This is only supported with linear modifier */ \
> { DRM_FORMAT_UYVY, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 3) }, \
> { DRM_FORMAT_NV12, DE_VIDEO1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(5, 6) }, \
> + /* This is only supported with AFBC modifier */ \
> + { DRM_FORMAT_YUV420_8BIT, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 6) }, \
> { DRM_FORMAT_YUV420, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 7) }, \
> - { DRM_FORMAT_X0L2, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 6)}
> + /* This is only supported with linear modifier */ \
> + { DRM_FORMAT_XVYU2101010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 0)}, \
> + /* This is only supported with AFBC modifier */ \
> + { DRM_FORMAT_VUY101010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 0)}, \
> + { DRM_FORMAT_X0L2, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 6)}, \
> + /* This is only supported with AFBC modifier */ \
> + { DRM_FORMAT_YUV420_10BIT, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 7)}, \
> + { DRM_FORMAT_P010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 7)}
>
> static const struct malidp_format_id malidp550_de_formats[] = {
> MALIDP_COMMON_FORMATS,
> --
> 2.7.4
>
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
On Mon, Dec 03, 2018 at 11:32:01AM +0000, Ayan Halder wrote:
> The constraints are as follows (for Mali-DP 500, 550, 650) :-
>
> 1. AFBC is not supported for the formats defined in malidp_hw_format_is_linear_only()
>
> 2. Some of the formats are supported only with AFBC modifiers. Thus we have
> introduced a new function 'malidp_hw_format_is_afbc_only()' which verifies the same.
>
> 3. AFBC_FORMAT_MOD_YTR needs to be provided for any RGB format.
>
> 4. Formats <= 16bpp cannot support AFBC_FORMAT_MOD_SPLIT.
>
> 5. CBR should not be set for non-subsampled formats.
>
> 6. SMART layer does not support framebuffer with AFBC modifiers.
> Return -EINVAL for such a scenario.
>
> 7. AFBC_FORMAT_MOD_YTR is not supported for any YUV formats.
>
> 8. Formats which are subsampled cannot support AFBC_FORMAT_MOD_SPLIT. However in
> DP550, YUV_420_10BIT is supported with AFBC_FORMAT_MOD_SPLIT. This feature has
> been identified with MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT.
>
> 9. In DP550 and DP650, for YUYV, the hardware supports different format-ids to
> be used with and without AFBC modifier. We have used the feature
> 'MALIDP_DEVICE_AFBC_YUYV_USE_422_P2' to identify this characteristic.
>
> Signed-off-by: Ayan Kumar halder <[email protected]>
> ---
> drivers/gpu/drm/arm/malidp_drv.c | 23 +------
> drivers/gpu/drm/arm/malidp_drv.h | 6 ++
> drivers/gpu/drm/arm/malidp_hw.c | 71 +++++++++++++++++++--
> drivers/gpu/drm/arm/malidp_hw.h | 5 +-
> drivers/gpu/drm/arm/malidp_mw.c | 2 +-
> drivers/gpu/drm/arm/malidp_planes.c | 124 +++++++++++++++++++++++++++++++++++-
> 6 files changed, 199 insertions(+), 32 deletions(-)
>
> diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
> index b8db92f..2f0b553 100644
> --- a/drivers/gpu/drm/arm/malidp_drv.c
> +++ b/drivers/gpu/drm/arm/malidp_drv.c
> @@ -264,29 +264,8 @@ static bool
> malidp_verify_afbc_framebuffer_caps(struct drm_device *dev,
> const struct drm_mode_fb_cmd2 *mode_cmd)
> {
> - const struct drm_format_info *info;
> -
> - if ((mode_cmd->modifier[0] >> 56) != DRM_FORMAT_MOD_VENDOR_ARM) {
> - DRM_DEBUG_KMS("Unknown modifier (not Arm)\n");
> + if (malidp_format_mod_supported(dev, mode_cmd->pixel_format, mode_cmd->modifier[0]) == false)
> return false;
> - }
> -
> - if (mode_cmd->modifier[0] &
> - ~DRM_FORMAT_MOD_ARM_AFBC(AFBC_MOD_VALID_BITS)) {
> - DRM_DEBUG_KMS("Unsupported modifiers\n");
> - return false;
> - }
> -
> - info = drm_get_format_info(dev, mode_cmd);
> - if (!info) {
> - DRM_DEBUG_KMS("Unable to get the format information\n");
> - return false;
> - }
> -
> - if (info->num_planes != 1) {
> - DRM_DEBUG_KMS("AFBC buffers expect one plane\n");
> - return false;
> - }
>
> if (mode_cmd->offsets[0] != 0) {
> DRM_DEBUG_KMS("AFBC buffers' plane offset should be 0\n");
> diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h
> index b76c86f..019a682 100644
> --- a/drivers/gpu/drm/arm/malidp_drv.h
> +++ b/drivers/gpu/drm/arm/malidp_drv.h
> @@ -90,6 +90,12 @@ struct malidp_crtc_state {
> int malidp_de_planes_init(struct drm_device *drm);
> int malidp_crtc_init(struct drm_device *drm);
>
> +bool malidp_hw_format_is_linear_only(u32 format);
> +bool malidp_hw_format_is_afbc_only(u32 format);
> +
> +bool malidp_format_mod_supported(struct drm_device *drm,
> + u32 format, u64 modifier);
> +
> #ifdef CONFIG_DEBUG_FS
> void malidp_error(struct malidp_drm *malidp,
> struct malidp_error_stats *error_stats, u32 status,
> diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
> index 25ac5890..4a774be 100644
> --- a/drivers/gpu/drm/arm/malidp_hw.c
> +++ b/drivers/gpu/drm/arm/malidp_hw.c
> @@ -60,6 +60,8 @@ static const struct malidp_format_id malidp500_de_formats[] = {
> #define MALIDP_ID(__group, __format) \
> ((((__group) & 0x7) << 3) | ((__format) & 0x7))
>
> +#define AFBC_YUV_422_FORMAT_ID MALIDP_ID(5, 1)
> +
> #define MALIDP_COMMON_FORMATS \
> /* fourcc, layers supporting the format, internal id */ \
> { DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 0) }, \
> @@ -887,7 +889,10 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
> .se_base = MALIDP550_SE_BASE,
> .dc_base = MALIDP550_DC_BASE,
> .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
> - .features = MALIDP_REGMAP_HAS_CLEARIRQ | MALIDP_DEVICE_AFBC_SUPPORT_SPLIT | AFBC_SUPPORT_SPLIT_WITH_YUV_420_10,
> + .features = MALIDP_REGMAP_HAS_CLEARIRQ |
> + MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
> + MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT |
Please roll some of these changes into patch 5/12.
> + MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
> .n_layers = ARRAY_SIZE(malidp550_layers),
> .layers = malidp550_layers,
> .de_irq_map = {
> @@ -933,7 +938,9 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
> .se_base = MALIDP550_SE_BASE,
> .dc_base = MALIDP550_DC_BASE,
> .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
> - .features = MALIDP_REGMAP_HAS_CLEARIRQ | MALIDP_DEVICE_AFBC_SUPPORT_SPLIT,
> + .features = MALIDP_REGMAP_HAS_CLEARIRQ |
> + MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
> + MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
> .n_layers = ARRAY_SIZE(malidp650_layers),
> .layers = malidp650_layers,
> .de_irq_map = {
> @@ -982,19 +989,73 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
> };
>
> u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
> - u8 layer_id, u32 format)
> + u8 layer_id, u32 format, bool has_modifier)
> {
> unsigned int i;
>
> for (i = 0; i < map->n_pixel_formats; i++) {
> if (((map->pixel_formats[i].layer & layer_id) == layer_id) &&
> - (map->pixel_formats[i].format == format))
> - return map->pixel_formats[i].id;
> + (map->pixel_formats[i].format == format)) {
> +
> + /*
> + * In some DP550 and DP650, DRM_FORMAT_YUYV + AFBC modifier
> + * is supported by a different h/w format id than
> + * DRM_FORMAT_YUYV (only).
> + */
> + if (format == DRM_FORMAT_YUYV &&
> + (has_modifier) &&
> + (map->features & MALIDP_DEVICE_AFBC_YUYV_USE_422_P2))
> + return AFBC_YUV_422_FORMAT_ID;
> + else
> + return map->pixel_formats[i].id;
> + }
> }
>
> return MALIDP_INVALID_FORMAT_ID;
> }
>
> +bool malidp_hw_format_is_linear_only(u32 format)
> +{
> + switch (format) {
> + case DRM_FORMAT_ARGB2101010:
> + case DRM_FORMAT_RGBA1010102:
> + case DRM_FORMAT_BGRA1010102:
> + case DRM_FORMAT_ARGB8888:
> + case DRM_FORMAT_RGBA8888:
> + case DRM_FORMAT_BGRA8888:
> + case DRM_FORMAT_XBGR8888:
> + case DRM_FORMAT_XRGB8888:
> + case DRM_FORMAT_RGBX8888:
> + case DRM_FORMAT_BGRX8888:
> + case DRM_FORMAT_RGB888:
> + case DRM_FORMAT_RGB565:
> + case DRM_FORMAT_ARGB1555:
> + case DRM_FORMAT_RGBA5551:
> + case DRM_FORMAT_BGRA5551:
> + case DRM_FORMAT_UYVY:
> + case DRM_FORMAT_XYUV8888:
> + case DRM_FORMAT_XVYU2101010:
> + case DRM_FORMAT_X0L2:
> + case DRM_FORMAT_X0L0:
> + return true;
> + default:
> + return false;
> + }
> +}
> +
> +bool malidp_hw_format_is_afbc_only(u32 format)
> +{
> + switch (format) {
> + case DRM_FORMAT_VUY888:
> + case DRM_FORMAT_VUY101010:
> + case DRM_FORMAT_YUV420_8BIT:
> + case DRM_FORMAT_YUV420_10BIT:
> + return true;
> + default:
> + return false;
> + }
> +}
> +
> static void malidp_hw_clear_irq(struct malidp_hw_device *hwdev, u8 block, u32 irq)
> {
> u32 base = malidp_get_block_base(hwdev, block);
> diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h
> index 27b907f..52188f0 100644
> --- a/drivers/gpu/drm/arm/malidp_hw.h
> +++ b/drivers/gpu/drm/arm/malidp_hw.h
> @@ -97,7 +97,8 @@ struct malidp_se_config {
> /* regmap features */
> #define MALIDP_REGMAP_HAS_CLEARIRQ BIT(0)
> #define MALIDP_DEVICE_AFBC_SUPPORT_SPLIT BIT(1)
> -#define AFBC_SUPPORT_SPLIT_WITH_YUV_420_10 BIT(2)
> +#define MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT BIT(2)
> +#define MALIDP_DEVICE_AFBC_YUYV_USE_422_P2 BIT(3)
>
> struct malidp_hw_regmap {
> /* address offset of the DE register bank */
> @@ -323,7 +324,7 @@ int malidp_se_irq_init(struct drm_device *drm, int irq);
> void malidp_se_irq_fini(struct malidp_hw_device *hwdev);
>
> u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
> - u8 layer_id, u32 format);
> + u8 layer_id, u32 format, bool has_modifier);
>
> static inline u8 malidp_hw_get_pitch_align(struct malidp_hw_device *hwdev, bool rotated)
> {
> diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c
> index 91472e5..0484744 100644
> --- a/drivers/gpu/drm/arm/malidp_mw.c
> +++ b/drivers/gpu/drm/arm/malidp_mw.c
> @@ -143,7 +143,7 @@ malidp_mw_encoder_atomic_check(struct drm_encoder *encoder,
>
> mw_state->format =
> malidp_hw_get_format_id(&malidp->dev->hw->map, SE_MEMWRITE,
> - fb->format->format);
> + fb->format->format, !!fb->modifier);
> if (mw_state->format == MALIDP_INVALID_FORMAT_ID) {
> struct drm_format_name_buf format_name;
>
> diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
> index cd60f73..0765cee 100644
> --- a/drivers/gpu/drm/arm/malidp_planes.c
> +++ b/drivers/gpu/drm/arm/malidp_planes.c
> @@ -52,6 +52,8 @@
> #define MALIDP550_LS_ENABLE 0x01c
> #define MALIDP550_LS_R1_IN_SIZE 0x020
>
> +#define MODIFIERS_COUNT_MAX 15
> +
> /*
> * This 4-entry look-up-table is used to determine the full 8-bit alpha value
> * for formats with 1- or 2-bit alpha channels.
> @@ -145,6 +147,117 @@ static void malidp_plane_atomic_print_state(struct drm_printer *p,
> drm_printf(p, "\tmmu_prefetch_pgsize=%d\n", ms->mmu_prefetch_pgsize);
> }
>
> +bool malidp_format_mod_supported(struct drm_device *drm,
> + u32 format, u64 modifier)
> +{
> + const struct drm_format_info *info;
> + const u64 *modifiers;
> + struct malidp_drm *malidp = drm->dev_private;
> + const struct malidp_hw_regmap *map = &malidp->dev->hw->map;
> +
> + if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
> + return false;
> +
> + /* Some pixel formats are supported without any modifier */
> + if (modifier == DRM_FORMAT_MOD_LINEAR) {
> + /* However these pixel formats need to be supported with
Nitpick: multi-line comment style is to start with a line that contains
only the marker for the start of the comment.
> + * modifiers only
> + */
> + return !malidp_hw_format_is_afbc_only(format);
> + }
> +
> + if ((modifier >> 56) != DRM_FORMAT_MOD_VENDOR_ARM) {
> + DRM_ERROR("Unknown modifier (not Arm)\n");
> + return false;
> + }
> +
> + if (modifier &
> + ~DRM_FORMAT_MOD_ARM_AFBC(AFBC_MOD_VALID_BITS)) {
> + DRM_DEBUG_KMS("Unsupported modifiers\n");
> + return false;
> + }
> +
> + modifiers = malidp_format_modifiers;
Actually, looking again at patch 5/12 it looks to me like you could roll
it into this patch completely.
> + while (*modifiers != DRM_FORMAT_MOD_INVALID) {
> + if (*modifiers == modifier) {
> + /* SPLIT buffers must use SPARSE layout */
> + if (WARN_ON_ONCE((modifier & AFBC_SPLIT) && !(modifier & AFBC_SPARSE)))
> + return false;
> +
> + /* CBR only applies to YUV formats, where YTR should be always 0 */
> + if (WARN_ON_ONCE((modifier & AFBC_CBR) && (modifier & AFBC_YTR)))
> + return false;
You can take these checks outside the while() loop as they test if the
modifier passed as a parameter is valid, which you should check before
running through the array. If you do that, then the loop through the
malidp_format_modifiers is a simple "if found, break out of loop" and
then the next check will return false if you iterated over the entire
list.
> +
> + break;
> + }
> +
> + modifiers++;
> + }
> +
> + /* return false, if the modifier was not found */
> + if (*modifiers == DRM_FORMAT_MOD_INVALID) {
> + DRM_DEBUG_KMS("Unsupported modifier\n");
> + return false;
> + }
> +
> + info = drm_format_info(format);
> +
> + if (info->num_planes != 1) {
> + DRM_DEBUG_KMS("AFBC buffers expect one plane\n");
> + return false;
> + }
> +
> + if (malidp_hw_format_is_linear_only(format) == true) {
> + DRM_DEBUG_KMS("Given format (0x%x) is supported is linear mode only\n", format);
> + return false;
> + }
> +
> + /*
> + * RGB formats need to provide YTR modifier and YUV formats should not
> + * provide YTR modifier.
> + */
> + if (!(info->is_yuv) != !!(modifier & AFBC_FORMAT_MOD_YTR)) {
> + DRM_DEBUG_KMS("AFBC_FORMAT_MOD_YTR is %s for %s formats\n",
> + info->is_yuv ? "disallowed" : "mandatory",
> + info->is_yuv ? "YUV" : "RGB");
> + return false;
> + }
> +
> + if (modifier & AFBC_SPLIT) {
> + if (!info->is_yuv) {
> + if (drm_format_plane_cpp(format, 0) <= 2) {
> + DRM_DEBUG_KMS("RGB formats <= 16bpp are not supported with SPLIT\n");
> + return false;
> + }
> + }
> +
> + if ((drm_format_horz_chroma_subsampling(format) != 1) ||
> + (drm_format_vert_chroma_subsampling(format) != 1)) {
> + if (!(format == DRM_FORMAT_YUV420_10BIT &&
> + (map->features & MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT))) {
> + DRM_DEBUG_KMS("Formats which are sub-sampled should never be split\n");
> + return false;
> + }
> + }
> + }
> +
> + if (modifier & AFBC_CBR) {
> + if ((drm_format_horz_chroma_subsampling(format) == 1) ||
> + (drm_format_vert_chroma_subsampling(format) == 1)) {
> + DRM_DEBUG_KMS("Formats which are not sub-sampled should not have CBR set\n");
> + return false;
> + }
> + }
> +
> + return true;
> +}
> +
> +static bool malidp_format_mod_supported_per_plane(struct drm_plane *plane,
> + u32 format, u64 modifier)
> +{
> + return malidp_format_mod_supported(plane->dev, format, modifier);
> +}
> +
> static const struct drm_plane_funcs malidp_de_plane_funcs = {
> .update_plane = drm_atomic_helper_update_plane,
> .disable_plane = drm_atomic_helper_disable_plane,
> @@ -153,6 +266,7 @@ static const struct drm_plane_funcs malidp_de_plane_funcs = {
> .atomic_duplicate_state = malidp_duplicate_plane_state,
> .atomic_destroy_state = malidp_destroy_plane_state,
> .atomic_print_state = malidp_plane_atomic_print_state,
> + .format_mod_supported = malidp_format_mod_supported_per_plane,
> };
>
> static int malidp_se_check_scaling(struct malidp_plane *mp,
> @@ -406,8 +520,8 @@ static int malidp_de_plane_check(struct drm_plane *plane,
> fb = state->fb;
>
> ms->format = malidp_hw_get_format_id(&mp->hwdev->hw->map,
> - mp->layer->id,
> - fb->format->format);
> + mp->layer->id, fb->format->format,
> + !!fb->modifier);
> if (ms->format == MALIDP_INVALID_FORMAT_ID)
> return -EINVAL;
>
> @@ -469,6 +583,12 @@ static int malidp_de_plane_check(struct drm_plane *plane,
> return -EINVAL;
> }
>
> + /* SMART layer does not support AFBC */
> + if (mp->layer->id == DE_SMART && fb->modifier) {
> + DRM_ERROR("AFBC framebuffer not supported in SMART layer");
> + return -EINVAL;
> + }
> +
> ms->rotmem_size = 0;
> if (state->rotation & MALIDP_ROTATED_MASK) {
> int val;
> --
> 2.7.4
>
Best regards,
Liviu
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
On Mon, Dec 03, 2018 at 11:32:02AM +0000, Ayan Halder wrote:
> The newly supported AFBC YUV formats have the following rotation memory
> constraints (in DP550/DP650).
> 1. DRM_FORMAT_VUY888/DRM_FORMAT_VUY101010 :- It can rotate upto 8
> horizontal lines in the AFBC output buffer.
> 2. DRM_FORMAT_YUV420_8BIT :- It can rotate upto 16 horizontal lines
> in the AFBC output buffer.
>
> Also some of the pixel formats are specified in bits per pixel (rather
> than bytes per pixel), so the calculation needs to take note of this.
>
> Besides there are some difference between DP550 and DP650 and these are
> as follows:-
> 1. DRM_FORMAT_X0L2 (in uncompressed format) does not support rotation in DP550.
> For DP650, it can rotate upto 16 horizontal lines in the AFBC output buffer,
> whereas in DP550 (with AFBC), it can rotate upto 8 horizontal lines.
> 2. DRM_FORMAT_YUV420_10BIT :- It can rotate upto 8 horizontal lines in
> dp550 and 16 horizontal lines in DP650.
>
> Signed-off-by: Ayan Kumar halder <[email protected]>
Reviewed-by: Liviu Dudau <[email protected]>
Best regards,
Liviu
> ---
> drivers/gpu/drm/arm/malidp_hw.c | 101 ++++++++++++++++++++++++++++++++----
> drivers/gpu/drm/arm/malidp_hw.h | 5 +-
> drivers/gpu/drm/arm/malidp_planes.c | 3 +-
> 3 files changed, 98 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
> index 4a774be..d9866a8 100644
> --- a/drivers/gpu/drm/arm/malidp_hw.c
> +++ b/drivers/gpu/drm/arm/malidp_hw.c
> @@ -375,14 +375,39 @@ static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode *
> malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
> }
>
> -static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt)
> +int malidp_format_get_bpp(u32 fmt)
> +{
> + int bpp = drm_format_plane_cpp(fmt, 0) * 8;
> +
> + if (bpp == 0) {
> + switch (fmt) {
> + case DRM_FORMAT_VUY101010:
> + bpp = 30;
> + case DRM_FORMAT_YUV420_10BIT:
> + bpp = 15;
> + break;
> + case DRM_FORMAT_YUV420_8BIT:
> + bpp = 12;
> + break;
> + default:
> + bpp = 0;
> + }
> + }
> +
> + return bpp;
> +}
> +
> +static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
> + u16 h, u32 fmt, bool has_modifier)
> {
> /*
> * Each layer needs enough rotation memory to fit 8 lines
> * worth of pixel data. Required size is then:
> * size = rotated_width * (bpp / 8) * 8;
> */
> - return w * drm_format_plane_cpp(fmt, 0) * 8;
> + int bpp = malidp_format_get_bpp(fmt);
> +
> + return w * bpp;
> }
>
> static void malidp500_se_write_pp_coefftab(struct malidp_hw_device *hwdev,
> @@ -660,9 +685,9 @@ static void malidp550_modeset(struct malidp_hw_device *hwdev, struct videomode *
> malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
> }
>
> -static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt)
> +static int malidpx50_get_bytes_per_column(u32 fmt)
> {
> - u32 bytes_per_col;
> + u32 bytes_per_column;
>
> switch (fmt) {
> /* 8 lines at 4 bytes per pixel */
> @@ -688,19 +713,77 @@ static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16
> case DRM_FORMAT_UYVY:
> case DRM_FORMAT_YUYV:
> case DRM_FORMAT_X0L0:
> - case DRM_FORMAT_X0L2:
> - bytes_per_col = 32;
> + bytes_per_column = 32;
> break;
> /* 16 lines at 1.5 bytes per pixel */
> case DRM_FORMAT_NV12:
> case DRM_FORMAT_YUV420:
> - bytes_per_col = 24;
> + /* 8 lines at 3 bytes per pixel */
> + case DRM_FORMAT_VUY888:
> + /* 16 lines at 12 bits per pixel */
> + case DRM_FORMAT_YUV420_8BIT:
> + /* 8 lines at 3 bytes per pixel */
> + case DRM_FORMAT_P010:
> + bytes_per_column = 24;
> + break;
> + /* 8 lines at 30 bits per pixel */
> + case DRM_FORMAT_VUY101010:
> + /* 16 lines at 15 bits per pixel */
> + case DRM_FORMAT_YUV420_10BIT:
> + bytes_per_column = 30;
> break;
> default:
> return -EINVAL;
> }
>
> - return w * bytes_per_col;
> + return bytes_per_column;
> +}
> +
> +static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
> + u16 h, u32 fmt, bool has_modifier)
> +{
> + int bytes_per_column = 0;
> +
> + switch (fmt) {
> + /* 8 lines at 15 bits per pixel */
> + case DRM_FORMAT_YUV420_10BIT:
> + bytes_per_column = 15;
> + break;
> + /* Uncompressed YUV 420 10 bit single plane cannot be rotated */
> + case DRM_FORMAT_X0L2:
> + if (has_modifier)
> + bytes_per_column = 8;
> + else
> + return -EINVAL;
> + break;
> + default:
> + bytes_per_column = malidpx50_get_bytes_per_column(fmt);
> + }
> +
> + if (bytes_per_column == -EINVAL)
> + return bytes_per_column;
> +
> + return w * bytes_per_column;
> +}
> +
> +static int malidp650_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
> + u16 h, u32 fmt, bool has_modifier)
> +{
> + int bytes_per_column = 0;
> +
> + switch (fmt) {
> + /* 16 lines at 2 bytes per pixel */
> + case DRM_FORMAT_X0L2:
> + bytes_per_column = 32;
> + break;
> + default:
> + bytes_per_column = malidpx50_get_bytes_per_column(fmt);
> + }
> +
> + if (bytes_per_column == -EINVAL)
> + return bytes_per_column;
> +
> + return w * bytes_per_column;
> }
>
> static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
> @@ -979,7 +1062,7 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
> .in_config_mode = malidp550_in_config_mode,
> .set_config_valid = malidp550_set_config_valid,
> .modeset = malidp550_modeset,
> - .rotmem_required = malidp550_rotmem_required,
> + .rotmem_required = malidp650_rotmem_required,
> .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
> .se_calc_mclk = malidp550_se_calc_mclk,
> .enable_memwrite = malidp550_enable_memwrite,
> diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h
> index 52188f0..e89a06a 100644
> --- a/drivers/gpu/drm/arm/malidp_hw.h
> +++ b/drivers/gpu/drm/arm/malidp_hw.h
> @@ -184,7 +184,8 @@ struct malidp_hw {
> * Calculate the required rotation memory given the active area
> * and the buffer format.
> */
> - int (*rotmem_required)(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt);
> + int (*rotmem_required)(struct malidp_hw_device *hwdev, u16 w, u16 h,
> + u32 fmt, bool has_modifier);
>
> int (*se_set_scaling_coeffs)(struct malidp_hw_device *hwdev,
> struct malidp_se_config *se_config,
> @@ -326,6 +327,8 @@ void malidp_se_irq_fini(struct malidp_hw_device *hwdev);
> u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
> u8 layer_id, u32 format, bool has_modifier);
>
> +int malidp_format_get_bpp(u32 fmt);
> +
> static inline u8 malidp_hw_get_pitch_align(struct malidp_hw_device *hwdev, bool rotated)
> {
> /*
> diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
> index 0765cee..d0a00ee 100644
> --- a/drivers/gpu/drm/arm/malidp_planes.c
> +++ b/drivers/gpu/drm/arm/malidp_planes.c
> @@ -595,7 +595,8 @@ static int malidp_de_plane_check(struct drm_plane *plane,
>
> val = mp->hwdev->hw->rotmem_required(mp->hwdev, state->crtc_w,
> state->crtc_h,
> - fb->format->format);
> + fb->format->format,
> + !!(fb->modifier));
> if (val < 0)
> return val;
>
> --
> 2.7.4
>
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
On Mon, Dec 03, 2018 at 11:32:03AM +0000, Ayan Halder wrote:
> In malidp, the writeback pipeline does not support writing crtc output
> to a framebuffer with modifiers ie the memory writeback content is
> devoid of any compression or tiling, etc.
> So we have added a commit check in memory writeback encoder helper function
> to validate if the framebuffer has any modifier and if so, return EINVAL.
>
> Signed-off-by: Ayan Kumar halder <[email protected]>
Acked-by: Liviu Dudau <[email protected]>
> ---
> drivers/gpu/drm/arm/malidp_mw.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c
> index 0484744..90c964a 100644
> --- a/drivers/gpu/drm/arm/malidp_mw.c
> +++ b/drivers/gpu/drm/arm/malidp_mw.c
> @@ -141,6 +141,11 @@ malidp_mw_encoder_atomic_check(struct drm_encoder *encoder,
> return -EINVAL;
> }
>
> + if (fb->modifier) {
> + DRM_DEBUG_KMS("Writeback framebuffer does not support modifiers\n");
> + return -EINVAL;
> + }
> +
> mw_state->format =
> malidp_hw_get_format_id(&malidp->dev->hw->map, SE_MEMWRITE,
> fb->format->format, !!fb->modifier);
> --
> 2.7.4
>
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
On Mon, Dec 03, 2018 at 11:32:04AM +0000, Ayan Halder wrote:
> Formats like DRM_FORMAT_VUY101010, DRM_FORMAT_YUV420_8BIT and
> DRM_FORMAT_YUV420_10BIT are expressed in bits per pixel as they have a non
> integer value of cpp (thus denoted as '0' in drm_format_info[]). Therefore,
> the calculation of AFBC framebuffer size needs to use malidp_format_get_bpp().
>
> Signed-off-by: Ayan Kumar halder <[email protected]>
Reviewed-by: Liviu Dudau <[email protected]>
Best regards,
Liviu
> ---
> drivers/gpu/drm/arm/malidp_drv.c | 13 ++++++++-----
> 1 file changed, 8 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
> index 2f0b553..b2b97db 100644
> --- a/drivers/gpu/drm/arm/malidp_drv.c
> +++ b/drivers/gpu/drm/arm/malidp_drv.c
> @@ -297,6 +297,7 @@ malidp_verify_afbc_framebuffer_size(struct drm_device *dev,
> struct drm_gem_object *objs = NULL;
> u32 afbc_superblock_size = 0, afbc_superblock_height = 0;
> u32 afbc_superblock_width = 0, afbc_size = 0;
> + int bpp = 0;
>
> switch (mode_cmd->modifier[0] & AFBC_SIZE_MASK) {
> case AFBC_SIZE_16X16:
> @@ -313,15 +314,17 @@ malidp_verify_afbc_framebuffer_size(struct drm_device *dev,
> n_superblocks = (mode_cmd->width / afbc_superblock_width) *
> (mode_cmd->height / afbc_superblock_height);
>
> - afbc_superblock_size = info->cpp[0] * afbc_superblock_width *
> - afbc_superblock_height;
> + bpp = malidp_format_get_bpp(info->format);
> +
> + afbc_superblock_size = (bpp * afbc_superblock_width * afbc_superblock_height) / BITS_PER_BYTE;
>
> afbc_size = ALIGN(n_superblocks * AFBC_HEADER_SIZE, AFBC_SUPERBLK_ALIGNMENT);
> afbc_size += n_superblocks * ALIGN(afbc_superblock_size, AFBC_SUPERBLK_ALIGNMENT);
>
> - if (mode_cmd->width * info->cpp[0] != mode_cmd->pitches[0]) {
> - DRM_DEBUG_KMS("Invalid value of pitch (=%u) should be same as width (=%u) * cpp (=%u)\n",
> - mode_cmd->pitches[0], mode_cmd->width, info->cpp[0]);
> + if ((mode_cmd->width * bpp) != (mode_cmd->pitches[0] * BITS_PER_BYTE)) {
> + DRM_DEBUG_KMS("Invalid value of (pitch * BITS_PER_BYTE) (=%u) "
> + "should be same as width (=%u) * bpp (=%u)\n",
> + (mode_cmd->pitches[0] * BITS_PER_BYTE), mode_cmd->width, bpp);
> return false;
> }
>
> --
> 2.7.4
>
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
On Mon, Dec 03, 2018 at 11:32:05AM +0000, Ayan Halder wrote:
> Considering the fact that some of the AFBC specific pixel formats are expressed
> in bits per pixel (ie bpp which is not byte aligned), the pitch (ie width * bpp)
> is not guaranteed to be aligned to burst size (ie 8 or 16 bytes).
> For example, DRM_FORMAT_VUY101010 is 30 bits per pixel. For a framebuffer of
> width 32 pixels, the pitch will be 120 bytes which is not aligned to burst size
> (ie 16 bytes) for DP650.
>
> Signed-off-by: Ayan Kumar halder <[email protected]>
Acked-by: Liviu Dudau <[email protected]>
> ---
> drivers/gpu/drm/arm/malidp_planes.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
> index d0a00ee..eec0442 100644
> --- a/drivers/gpu/drm/arm/malidp_planes.c
> +++ b/drivers/gpu/drm/arm/malidp_planes.c
> @@ -529,8 +529,8 @@ static int malidp_de_plane_check(struct drm_plane *plane,
> for (i = 0; i < ms->n_planes; i++) {
> u8 alignment = malidp_hw_get_pitch_align(mp->hwdev, rotated);
>
> - if ((fb->pitches[i] * drm_format_info_block_height(fb->format, i))
> - & (alignment - 1)) {
> + if (((fb->pitches[i] * drm_format_info_block_height(fb->format, i))
> + & (alignment - 1)) && !(fb->modifier)) {
> DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n",
> fb->pitches[i], i);
> return -EINVAL;
> --
> 2.7.4
>
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
On Mon, Dec 03, 2018 at 11:32:06AM +0000, Ayan Halder wrote:
> The list of modifiers to be supported for each plane has been dynamically generated
> from 'malidp_format_modifiers[]' and 'malidp_hw_regmap->features'.
>
> Changes from v1:-
> 1. Replaced DRM_ERROR() with DRM_DEBUG_KMS() in malidp_format_mod_supported()
> to report unsupported modifiers.
>
> Changes from v2:-
> 1. Removed malidp_format_mod_supported() from the current patch. This has been added
> in "PATCH 7/12"
> 2. Dynamically generate the list of modifiers (to be supported for each plane) from
> 'malidp_format_modifiers' and features.
>
> Signed-off-by: Ayan Kumar halder <[email protected]>
Reviewed-by: Liviu Dudau <[email protected]>
Best regards,
Liviu
> ---
> drivers/gpu/drm/arm/malidp_drv.c | 1 +
> drivers/gpu/drm/arm/malidp_planes.c | 28 ++++++++++++++++++++++++++--
> 2 files changed, 27 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
> index b2b97db..be45703 100644
> --- a/drivers/gpu/drm/arm/malidp_drv.c
> +++ b/drivers/gpu/drm/arm/malidp_drv.c
> @@ -388,6 +388,7 @@ static int malidp_init(struct drm_device *drm)
> drm->mode_config.max_height = hwdev->max_line_size;
> drm->mode_config.funcs = &malidp_mode_config_funcs;
> drm->mode_config.helper_private = &malidp_mode_config_helpers;
> + drm->mode_config.allow_fb_modifiers = true;
>
> ret = malidp_crtc_init(drm);
> if (ret)
> diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
> index eec0442..01037d0 100644
> --- a/drivers/gpu/drm/arm/malidp_planes.c
> +++ b/drivers/gpu/drm/arm/malidp_planes.c
> @@ -934,6 +934,25 @@ int malidp_de_planes_init(struct drm_device *drm)
> BIT(DRM_MODE_BLEND_COVERAGE);
> u32 *formats;
> int ret, i, j, n;
> + u64 supported_modifiers[MODIFIERS_COUNT_MAX];
> + const u64 *modifiers;
> +
> + modifiers = malidp_format_modifiers;
> +
> + if (!(map->features & MALIDP_DEVICE_AFBC_SUPPORT_SPLIT)) {
> + /*
> + * Since our hardware does not support SPLIT, so build the list of
> + * supported modifiers excluding SPLIT ones.
> + */
> + while (*modifiers != DRM_FORMAT_MOD_INVALID) {
> + if (!(*modifiers & AFBC_SPLIT))
> + supported_modifiers[j++] = *modifiers;
> +
> + modifiers++;
> + }
> + supported_modifiers[j++] = DRM_FORMAT_MOD_INVALID;
> + modifiers = supported_modifiers;
> + }
>
> formats = kcalloc(map->n_pixel_formats, sizeof(*formats), GFP_KERNEL);
> if (!formats) {
> @@ -958,9 +977,14 @@ int malidp_de_planes_init(struct drm_device *drm)
>
> plane_type = (i == 0) ? DRM_PLANE_TYPE_PRIMARY :
> DRM_PLANE_TYPE_OVERLAY;
> +
> + /*
> + * All the layers except smart layer supports AFBC modifiers.
> + */
> ret = drm_universal_plane_init(drm, &plane->base, crtcs,
> - &malidp_de_plane_funcs, formats,
> - n, NULL, plane_type, NULL);
> + &malidp_de_plane_funcs, formats, n,
> + (id == DE_SMART) ? NULL : modifiers, plane_type, NULL);
> +
> if (ret < 0)
> goto cleanup;
>
> --
> 2.7.4
>
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
On Tue, Dec 04, 2018 at 04:50:51PM +0000, Liviu Dudau wrote:
Hi Liviu,
Please let me know if you agree with my comments. Then I will send a
v4 patch for this.
> On Mon, Dec 03, 2018 at 11:31:58AM +0000, Ayan Halder wrote:
> > Added the AFBC decoder registers for DP500 , DP550 and DP650.
> > These registers control the processing of AFBC buffers. It controls various
> > features like AFBC decoder enable, lossless transformation and block split
> > as well as setting of the left, right, top and bottom cropping of AFBC buffers
> > (in number of pixels).
> > All the layers (except DE_SMART) support framebuffers with AFBC modifiers.
> > One needs to set the pixel values of the top, left, bottom and right cropping
> > for the AFBC framebuffer.
> > Cropping an AFBC framebuffer is controlled by the AFBC crop registers.
> > In that case, the layer input size registers should be configured with
> > framebuffer's dimensions and not with drm_plane_state source width/height
> > values (which is used for non AFBC framebuffer to denote cropping).
> >
> > Changes from v1:
> > - Removed the "if (fb->modifier)" check from malidp_de_plane_update()
> > and added it in malidp_de_set_plane_afbc(). This will consolidate all the
> > AFBC specific register configurations in a single function ie
> > malidp_de_set_plane_afbc().
> >
> > Changes from v2:
> > - For AFBC framebuffer, layer input size register should be set to framebuffer's
> > width and height
> >
> > Signed-off-by: Ayan Kumar Halder <[email protected]>
> > ---
> > drivers/gpu/drm/arm/malidp_hw.c | 25 +++++----
> > drivers/gpu/drm/arm/malidp_hw.h | 2 +
> > drivers/gpu/drm/arm/malidp_planes.c | 109 +++++++++++++++++++++++++++++++-----
> > drivers/gpu/drm/arm/malidp_regs.h | 20 +++++++
> > 4 files changed, 130 insertions(+), 26 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
> > index b9bed11..87b7b12 100644
> > --- a/drivers/gpu/drm/arm/malidp_hw.c
> > +++ b/drivers/gpu/drm/arm/malidp_hw.c
> > @@ -94,11 +94,12 @@ static const struct malidp_layer malidp500_layers[] = {
> > * yuv2rgb matrix offset, mmu control register offset, rotation_features
> > */
> > { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE,
> > - MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB, 0, ROTATE_ANY },
> > + MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB, 0, ROTATE_ANY,
> > + MALIDP500_DE_LV_AD_CTRL },
> > { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE,
> > - MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
> > + MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY, MALIDP500_DE_LG1_AD_CTRL },
> > { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE,
> > - MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
> > + MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY, MALIDP500_DE_LG2_AD_CTRL },
> > };
> >
> > static const struct malidp_layer malidp550_layers[] = {
> > @@ -106,13 +107,15 @@ static const struct malidp_layer malidp550_layers[] = {
> > * yuv2rgb matrix offset, mmu control register offset, rotation_features
> > */
> > { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
> > - MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY },
> > + MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY,
> > + MALIDP550_DE_LV1_AD_CTRL },
> > { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
> > - MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
> > + MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY, MALIDP550_DE_LG_AD_CTRL },
> > { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
> > - MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY },
> > + MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY,
> > + MALIDP550_DE_LV2_AD_CTRL },
> > { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
> > - MALIDP550_DE_LS_R1_STRIDE, 0, 0, ROTATE_NONE },
> > + MALIDP550_DE_LS_R1_STRIDE, 0, 0, ROTATE_NONE, 0 },
> > };
> >
> > static const struct malidp_layer malidp650_layers[] = {
> > @@ -122,16 +125,16 @@ static const struct malidp_layer malidp650_layers[] = {
> > */
> > { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
> > MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
> > - MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY },
> > + MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY, MALIDP550_DE_LV1_AD_CTRL },
> > { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
> > MALIDP_DE_LG_STRIDE, 0, MALIDP650_DE_LG_MMU_CTRL,
> > - ROTATE_COMPRESSED },
> > + ROTATE_COMPRESSED, MALIDP550_DE_LG_AD_CTRL },
> > { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
> > MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
> > - MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY },
> > + MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY, MALIDP550_DE_LV2_AD_CTRL },
> > { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
> > MALIDP550_DE_LS_R1_STRIDE, 0, MALIDP650_DE_LS_MMU_CTRL,
> > - ROTATE_NONE },
> > + ROTATE_NONE, 0 },
> > };
> >
> > #define SE_N_SCALING_COEFFS 96
> > diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h
> > index 40155e2..651558f 100644
> > --- a/drivers/gpu/drm/arm/malidp_hw.h
> > +++ b/drivers/gpu/drm/arm/malidp_hw.h
> > @@ -70,6 +70,8 @@ struct malidp_layer {
> > s16 yuv2rgb_offset; /* offset to the YUV->RGB matrix entries */
> > u16 mmu_ctrl_offset; /* offset to the MMU control register */
> > enum rotation_features rot; /* type of rotation supported */
> > + /* address offset for the AFBC decoder registers */
> > + u16 afbc_decoder_offset;
> > };
> >
> > enum malidp_scaling_coeff_set {
> > diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
> > index c9a6d3e..cd60f73 100644
> > --- a/drivers/gpu/drm/arm/malidp_planes.c
> > +++ b/drivers/gpu/drm/arm/malidp_planes.c
> > @@ -592,6 +592,80 @@ static void malidp_de_set_mmu_control(struct malidp_plane *mp,
> > mp->layer->base + mp->layer->mmu_ctrl_offset);
> > }
> >
> > +static void malidp_set_plane_base_addr(struct drm_framebuffer *fb,
> > + struct malidp_plane *mp,
> > + int plane_index)
> > +{
> > + dma_addr_t paddr;
> > + u16 ptr;
> > + struct drm_plane *plane = &mp->base;
> > + bool afbc = fb->modifier ? true : false;
> > +
> > + ptr = mp->layer->ptr + (plane_index << 4);
> > +
> > + /*
> > + * For AFBC buffers, cropping is handled by AFBC decoder rather than
> > + * pointer manipulation.
> > + */
>
> I think this comment needs to go in malidp_de_plane_update, not in this function.
> This function only updates the plane's base address.
>
I will reword the comment like this if it sounds sane :-
drm_fb_cma_get_gem_addr() alters the physical base address of the framebuffer
as per the plane's src_x, src_y co-ordinates (ie to take care of source cropping).
For AFBC, this is not needed as the cropping is handled by _AD_CROP_H
and _AD_CROP_V registers.
> > + if (!afbc) {
> > + paddr = drm_fb_cma_get_gem_addr(fb, plane->state,
> > + plane_index);
> > + } else {
> > + struct drm_gem_cma_object *obj;
> > +
> > + obj = drm_fb_cma_get_gem_obj(fb, plane_index);
> > +
> > + if (WARN_ON(!obj))
> > + return;
> > + paddr = obj->paddr;
> > + }
> > +
> > + malidp_hw_write(mp->hwdev, lower_32_bits(paddr), ptr);
> > + malidp_hw_write(mp->hwdev, upper_32_bits(paddr), ptr + 4);
> > +}
> > +
> > +static void malidp_de_set_plane_afbc(struct drm_plane *plane)
> > +{
> > + struct malidp_plane *mp;
> > + u32 src_w, src_h, val = 0, src_x, src_y;
> > + struct drm_framebuffer *fb = plane->state->fb;
> > +
> > + mp = to_malidp_plane(plane);
> > +
> > + /* no afbc_decoder_offset means AFBC is not supported on this plane */
> > + if (!mp->layer->afbc_decoder_offset)
> > + return;
> > +
> > + if (!fb->modifier) {
> > + malidp_hw_write(mp->hwdev, 0, mp->layer->afbc_decoder_offset);
> > + return;
> > + }
> > +
> > + /* convert src values from Q16 fixed point to integer */
> > + src_w = plane->state->src_w >> 16;
> > + src_h = plane->state->src_h >> 16;
> > + src_x = plane->state->src_x >> 16;
> > + src_y = plane->state->src_y >> 16;
> > +
> > + val = ((fb->width - (src_x + src_w)) << MALIDP_AD_CROP_RIGHT_OFFSET) |
> > + src_x;
> > + malidp_hw_write(mp->hwdev, val,
> > + mp->layer->afbc_decoder_offset + MALIDP_AD_CROP_H);
> > +
> > + val = ((fb->height - (src_y + src_h)) << MALIDP_AD_CROP_BOTTOM_OFFSET) |
> > + src_y;
> > + malidp_hw_write(mp->hwdev, val,
> > + mp->layer->afbc_decoder_offset + MALIDP_AD_CROP_V);
> > +
> > + val = MALIDP_AD_EN;
> > + if (fb->modifier & AFBC_FORMAT_MOD_SPLIT)
> > + val |= MALIDP_AD_BS;
> > + if (fb->modifier & AFBC_FORMAT_MOD_YTR)
> > + val |= MALIDP_AD_YTR;
> > +
> > + malidp_hw_write(mp->hwdev, val, mp->layer->afbc_decoder_offset);
> > +}
> > +
> > static void malidp_de_plane_update(struct drm_plane *plane,
> > struct drm_plane_state *old_state)
> > {
> > @@ -600,30 +674,33 @@ static void malidp_de_plane_update(struct drm_plane *plane,
> > struct drm_plane_state *state = plane->state;
> > u16 pixel_alpha = state->pixel_blend_mode;
> > u8 plane_alpha = state->alpha >> 8;
> > + bool format_has_alpha = state->fb->format->has_alpha;
> > u32 src_w, src_h, dest_w, dest_h, val;
> > int i;
> > + struct drm_framebuffer *fb = plane->state->fb;
> >
> > mp = to_malidp_plane(plane);
> >
> > - /* convert src values from Q16 fixed point to integer */
> > - src_w = state->src_w >> 16;
> > - src_h = state->src_h >> 16;
> > - dest_w = state->crtc_w;
> > - dest_h = state->crtc_h;
> > + /* For AFBC framebuffer, use the framebuffer width and height for configuring
> > + * layer input size register.
> > + */
> > + if (fb->modifier) {
> > + src_w = fb->width;
> > + src_h = fb->height;
> > + } else {
> > + /* convert src values from Q16 fixed point to integer */
> > + src_w = ms->base.src_w >> 16;
> > + src_h = ms->base.src_h >> 16;
> > + }
> > + dest_w = ms->base.crtc_w;
> > + dest_h = ms->base.crtc_h;
>
> These two lines above are equivalent to the last two lines you deleted. Why you need this change?
>
Agreed, I will remove this change.
> >
> > val = malidp_hw_read(mp->hwdev, mp->layer->base);
> > val = (val & ~LAYER_FORMAT_MASK) | ms->format;
> > malidp_hw_write(mp->hwdev, val, mp->layer->base);
> >
> > - for (i = 0; i < ms->n_planes; i++) {
> > - /* calculate the offset for the layer's plane registers */
> > - u16 ptr = mp->layer->ptr + (i << 4);
> > - dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(state->fb,
> > - state, i);
> > -
> > - malidp_hw_write(mp->hwdev, lower_32_bits(fb_addr), ptr);
> > - malidp_hw_write(mp->hwdev, upper_32_bits(fb_addr), ptr + 4);
> > - }
> > + for (i = 0; i < ms->n_planes; i++)
> > + malidp_set_plane_base_addr(fb, mp, i);
> >
> > malidp_de_set_mmu_control(mp, ms);
> >
> > @@ -657,6 +734,8 @@ static void malidp_de_plane_update(struct drm_plane *plane,
> > mp->layer->base + MALIDP550_LS_R1_IN_SIZE);
> > }
> >
> > + malidp_de_set_plane_afbc(plane);
>
> I feel like this function call should be done only if (fb->modifier) is
> true.
We need to call this function even is fb->modifier = 0. Please refer
to the following snippet in malidp_de_set_plane_afbc()
if (!fb->modifier) {
malidp_hw_write(mp->hwdev, 0, mp->layer->afbc_decoder_offset);
return;
}
I will prefer to keep all the AFBC register configuration in a single
function.
Thanks,
Ayan Kumar Halder
>
> > +
> > /* first clear the rotation bits */
> > val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL);
> > val &= ~LAYER_ROT_MASK;
> > @@ -674,7 +753,7 @@ static void malidp_de_plane_update(struct drm_plane *plane,
> >
> > if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) {
> > val |= LAYER_COMP_PLANE;
> > - } else if (state->fb->format->has_alpha) {
> > + } else if (format_has_alpha) {
>
> This change has nothing to do with AFBC, it should not be in this patch.
>
> > /* We only care about blend mode if the format has alpha */
> > switch (pixel_alpha) {
> > case DRM_MODE_BLEND_PREMULTI:
> > diff --git a/drivers/gpu/drm/arm/malidp_regs.h b/drivers/gpu/drm/arm/malidp_regs.h
> > index 7ce3e14..a0dd6e1 100644
> > --- a/drivers/gpu/drm/arm/malidp_regs.h
> > +++ b/drivers/gpu/drm/arm/malidp_regs.h
> > @@ -198,10 +198,13 @@
> > #define MALIDP500_LV_YUV2RGB ((s16)(-0xB8))
> > #define MALIDP500_DE_LV_BASE 0x00100
> > #define MALIDP500_DE_LV_PTR_BASE 0x00124
> > +#define MALIDP500_DE_LV_AD_CTRL 0x00400
> > #define MALIDP500_DE_LG1_BASE 0x00200
> > #define MALIDP500_DE_LG1_PTR_BASE 0x0021c
> > +#define MALIDP500_DE_LG1_AD_CTRL 0x0040c
> > #define MALIDP500_DE_LG2_BASE 0x00300
> > #define MALIDP500_DE_LG2_PTR_BASE 0x0031c
> > +#define MALIDP500_DE_LG2_AD_CTRL 0x00418
> > #define MALIDP500_SE_BASE 0x00c00
> > #define MALIDP500_SE_CONTROL 0x00c0c
> > #define MALIDP500_SE_MEMWRITE_OUT_SIZE 0x00c2c
> > @@ -228,10 +231,13 @@
> > #define MALIDP550_LV_YUV2RGB 0x00084
> > #define MALIDP550_DE_LV1_BASE 0x00100
> > #define MALIDP550_DE_LV1_PTR_BASE 0x00124
> > +#define MALIDP550_DE_LV1_AD_CTRL 0x001B8
> > #define MALIDP550_DE_LV2_BASE 0x00200
> > #define MALIDP550_DE_LV2_PTR_BASE 0x00224
> > +#define MALIDP550_DE_LV2_AD_CTRL 0x002B8
> > #define MALIDP550_DE_LG_BASE 0x00300
> > #define MALIDP550_DE_LG_PTR_BASE 0x0031c
> > +#define MALIDP550_DE_LG_AD_CTRL 0x00330
> > #define MALIDP550_DE_LS_BASE 0x00400
> > #define MALIDP550_DE_LS_PTR_BASE 0x0042c
> > #define MALIDP550_DE_PERF_BASE 0x00500
> > @@ -258,6 +264,20 @@
> > #define MALIDP_MMU_CTRL_PX_PS(x) (1 << (8 + (x)))
> > #define MALIDP_MMU_CTRL_PP_NUM_REQ(x) (((x) & 0x7f) << 12)
> >
> > +/* AFBC register offsets relative to MALIDPXXX_DE_LX_AD_CTRL */
> > +/* The following register offsets are common for DP500, DP550 and DP650 */
> > +#define MALIDP_AD_CROP_H 0x4
> > +#define MALIDP_AD_CROP_V 0x8
> > +#define MALIDP_AD_END_PTR_LOW 0xc
> > +#define MALIDP_AD_END_PTR_HIGH 0x10
> > +
> > +/* AFBC decoder Registers */
> > +#define MALIDP_AD_EN BIT(0)
> > +#define MALIDP_AD_YTR BIT(4)
> > +#define MALIDP_AD_BS BIT(8)
> > +#define MALIDP_AD_CROP_RIGHT_OFFSET 16
> > +#define MALIDP_AD_CROP_BOTTOM_OFFSET 16
> > +
> > /*
> > * Starting with DP550 the register map blocks has been standardised to the
> > * following layout:
> > --
> > 2.7.4
> >
>
> Best regards,
> Liviu
>
>
> --
> ====================
> | I would like to |
> | fix the world, |
> | but they're not |
> | giving me the |
> \ source code! /
> ---------------
> ??\_(???)_/??
> _______________________________________________
> dri-devel mailing list
> [email protected]
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
On Tue, Dec 04, 2018 at 04:57:46PM +0000, Liviu Dudau wrote:
Hi Liviu,
> On Mon, Dec 03, 2018 at 11:32:00AM +0000, Ayan Halder wrote:
> > We have added some new formats to be supported on DP500/DP550/DP650.
>
> Make a bit more descriptive commit message here, please!
>
I will keep the following commit message :-
""We have added support for some AFBC only pixel formats like :-
DRM_FORMAT_YUV420_8BIT (single plane YUV 420 8 bit format)
DRM_FORMAT_VUY888 (single plane YUV 444 8 bit format)
DRM_FORMAT_VUY101010 (single plane YUV 444 10 bit format)
DRM_FORMAT_YUV420_10BIT (single plane YUV 420 10 bit format)
Generally, these formats are supported by our hardware using the same hw-ids as
the equivalent multi plane pixel formats.
Also we have added support for XYUV 444 8 and 10 bit formats.""
Let me know if this looks fine.
Thanks,
Ayan Kumar halder
> >
> > Signed-off-by: Ayan Kumar Halder <[email protected]>
> >
> > Depends on :- https://patchwork.kernel.org/patch/10460063/
>
> Reviewed-by: Liviu Dudau <[email protected]>
>
> Best regards,
> Liviu
>
> > ---
> > drivers/gpu/drm/arm/malidp_hw.c | 22 +++++++++++++++++++++-
> > 1 file changed, 21 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
> > index 55d379b..25ac5890 100644
> > --- a/drivers/gpu/drm/arm/malidp_hw.c
> > +++ b/drivers/gpu/drm/arm/malidp_hw.c
> > @@ -49,6 +49,12 @@ static const struct malidp_format_id malidp500_de_formats[] = {
> > { DRM_FORMAT_YUYV, DE_VIDEO1, 13 },
> > { DRM_FORMAT_NV12, DE_VIDEO1 | SE_MEMWRITE, 14 },
> > { DRM_FORMAT_YUV420, DE_VIDEO1, 15 },
> > + { DRM_FORMAT_XYUV8888, DE_VIDEO1, 16 },
> > + /* These are supported with AFBC only */
> > + { DRM_FORMAT_YUV420_8BIT, DE_VIDEO1, 14 },
> > + { DRM_FORMAT_VUY888, DE_VIDEO1, 16 },
> > + { DRM_FORMAT_VUY101010, DE_VIDEO1, 17 },
> > + { DRM_FORMAT_YUV420_10BIT, DE_VIDEO1, 18 }
> > };
> >
> > #define MALIDP_ID(__group, __format) \
> > @@ -74,11 +80,25 @@ static const struct malidp_format_id malidp500_de_formats[] = {
> > { DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 1) }, \
> > { DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 2) }, \
> > { DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 3) }, \
> > + /* This is only supported with linear modifier */ \
> > + { DRM_FORMAT_XYUV8888, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 0) },\
> > + /* This is only supported with AFBC modifier */ \
> > + { DRM_FORMAT_VUY888, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 0) }, \
> > { DRM_FORMAT_YUYV, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 2) }, \
> > + /* This is only supported with linear modifier */ \
> > { DRM_FORMAT_UYVY, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 3) }, \
> > { DRM_FORMAT_NV12, DE_VIDEO1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(5, 6) }, \
> > + /* This is only supported with AFBC modifier */ \
> > + { DRM_FORMAT_YUV420_8BIT, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 6) }, \
> > { DRM_FORMAT_YUV420, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 7) }, \
> > - { DRM_FORMAT_X0L2, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 6)}
> > + /* This is only supported with linear modifier */ \
> > + { DRM_FORMAT_XVYU2101010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 0)}, \
> > + /* This is only supported with AFBC modifier */ \
> > + { DRM_FORMAT_VUY101010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 0)}, \
> > + { DRM_FORMAT_X0L2, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 6)}, \
> > + /* This is only supported with AFBC modifier */ \
> > + { DRM_FORMAT_YUV420_10BIT, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 7)}, \
> > + { DRM_FORMAT_P010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 7)}
> >
> > static const struct malidp_format_id malidp550_de_formats[] = {
> > MALIDP_COMMON_FORMATS,
> > --
> > 2.7.4
> >
>
> --
> ====================
> | I would like to |
> | fix the world, |
> | but they're not |
> | giving me the |
> \ source code! /
> ---------------
> ??\_(???)_/??
> _______________________________________________
> dri-devel mailing list
> [email protected]
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
On Tue, Dec 04, 2018 at 05:49:12PM +0000, Liviu Dudau wrote:
> On Mon, Dec 03, 2018 at 11:32:01AM +0000, Ayan Halder wrote:
> > The constraints are as follows (for Mali-DP 500, 550, 650) :-
> >
> > 1. AFBC is not supported for the formats defined in malidp_hw_format_is_linear_only()
> >
> > 2. Some of the formats are supported only with AFBC modifiers. Thus we have
> > introduced a new function 'malidp_hw_format_is_afbc_only()' which verifies the same.
> >
> > 3. AFBC_FORMAT_MOD_YTR needs to be provided for any RGB format.
> >
> > 4. Formats <= 16bpp cannot support AFBC_FORMAT_MOD_SPLIT.
> >
> > 5. CBR should not be set for non-subsampled formats.
> >
> > 6. SMART layer does not support framebuffer with AFBC modifiers.
> > Return -EINVAL for such a scenario.
> >
> > 7. AFBC_FORMAT_MOD_YTR is not supported for any YUV formats.
> >
> > 8. Formats which are subsampled cannot support AFBC_FORMAT_MOD_SPLIT. However in
> > DP550, YUV_420_10BIT is supported with AFBC_FORMAT_MOD_SPLIT. This feature has
> > been identified with MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT.
> >
> > 9. In DP550 and DP650, for YUYV, the hardware supports different format-ids to
> > be used with and without AFBC modifier. We have used the feature
> > 'MALIDP_DEVICE_AFBC_YUYV_USE_422_P2' to identify this characteristic.
> >
> > Signed-off-by: Ayan Kumar halder <[email protected]>
> > ---
> > drivers/gpu/drm/arm/malidp_drv.c | 23 +------
> > drivers/gpu/drm/arm/malidp_drv.h | 6 ++
> > drivers/gpu/drm/arm/malidp_hw.c | 71 +++++++++++++++++++--
> > drivers/gpu/drm/arm/malidp_hw.h | 5 +-
> > drivers/gpu/drm/arm/malidp_mw.c | 2 +-
> > drivers/gpu/drm/arm/malidp_planes.c | 124 +++++++++++++++++++++++++++++++++++-
> > 6 files changed, 199 insertions(+), 32 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
> > index b8db92f..2f0b553 100644
> > --- a/drivers/gpu/drm/arm/malidp_drv.c
> > +++ b/drivers/gpu/drm/arm/malidp_drv.c
> > @@ -264,29 +264,8 @@ static bool
> > malidp_verify_afbc_framebuffer_caps(struct drm_device *dev,
> > const struct drm_mode_fb_cmd2 *mode_cmd)
> > {
> > - const struct drm_format_info *info;
> > -
> > - if ((mode_cmd->modifier[0] >> 56) != DRM_FORMAT_MOD_VENDOR_ARM) {
> > - DRM_DEBUG_KMS("Unknown modifier (not Arm)\n");
> > + if (malidp_format_mod_supported(dev, mode_cmd->pixel_format, mode_cmd->modifier[0]) == false)
> > return false;
> > - }
> > -
> > - if (mode_cmd->modifier[0] &
> > - ~DRM_FORMAT_MOD_ARM_AFBC(AFBC_MOD_VALID_BITS)) {
> > - DRM_DEBUG_KMS("Unsupported modifiers\n");
> > - return false;
> > - }
> > -
> > - info = drm_get_format_info(dev, mode_cmd);
> > - if (!info) {
> > - DRM_DEBUG_KMS("Unable to get the format information\n");
> > - return false;
> > - }
> > -
> > - if (info->num_planes != 1) {
> > - DRM_DEBUG_KMS("AFBC buffers expect one plane\n");
> > - return false;
> > - }
> >
> > if (mode_cmd->offsets[0] != 0) {
> > DRM_DEBUG_KMS("AFBC buffers' plane offset should be 0\n");
> > diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h
> > index b76c86f..019a682 100644
> > --- a/drivers/gpu/drm/arm/malidp_drv.h
> > +++ b/drivers/gpu/drm/arm/malidp_drv.h
> > @@ -90,6 +90,12 @@ struct malidp_crtc_state {
> > int malidp_de_planes_init(struct drm_device *drm);
> > int malidp_crtc_init(struct drm_device *drm);
> >
> > +bool malidp_hw_format_is_linear_only(u32 format);
> > +bool malidp_hw_format_is_afbc_only(u32 format);
> > +
> > +bool malidp_format_mod_supported(struct drm_device *drm,
> > + u32 format, u64 modifier);
> > +
> > #ifdef CONFIG_DEBUG_FS
> > void malidp_error(struct malidp_drm *malidp,
> > struct malidp_error_stats *error_stats, u32 status,
> > diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
> > index 25ac5890..4a774be 100644
> > --- a/drivers/gpu/drm/arm/malidp_hw.c
> > +++ b/drivers/gpu/drm/arm/malidp_hw.c
> > @@ -60,6 +60,8 @@ static const struct malidp_format_id malidp500_de_formats[] = {
> > #define MALIDP_ID(__group, __format) \
> > ((((__group) & 0x7) << 3) | ((__format) & 0x7))
> >
> > +#define AFBC_YUV_422_FORMAT_ID MALIDP_ID(5, 1)
> > +
> > #define MALIDP_COMMON_FORMATS \
> > /* fourcc, layers supporting the format, internal id */ \
> > { DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 0) }, \
> > @@ -887,7 +889,10 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
> > .se_base = MALIDP550_SE_BASE,
> > .dc_base = MALIDP550_DC_BASE,
> > .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
> > - .features = MALIDP_REGMAP_HAS_CLEARIRQ | MALIDP_DEVICE_AFBC_SUPPORT_SPLIT | AFBC_SUPPORT_SPLIT_WITH_YUV_420_10,
> > + .features = MALIDP_REGMAP_HAS_CLEARIRQ |
> > + MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
> > + MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT |
>
> Please roll some of these changes into patch 5/12.
>
> > + MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
> > .n_layers = ARRAY_SIZE(malidp550_layers),
> > .layers = malidp550_layers,
> > .de_irq_map = {
> > @@ -933,7 +938,9 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
> > .se_base = MALIDP550_SE_BASE,
> > .dc_base = MALIDP550_DC_BASE,
> > .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
> > - .features = MALIDP_REGMAP_HAS_CLEARIRQ | MALIDP_DEVICE_AFBC_SUPPORT_SPLIT,
> > + .features = MALIDP_REGMAP_HAS_CLEARIRQ |
> > + MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
> > + MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
> > .n_layers = ARRAY_SIZE(malidp650_layers),
> > .layers = malidp650_layers,
> > .de_irq_map = {
> > @@ -982,19 +989,73 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
> > };
> >
> > u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
> > - u8 layer_id, u32 format)
> > + u8 layer_id, u32 format, bool has_modifier)
> > {
> > unsigned int i;
> >
> > for (i = 0; i < map->n_pixel_formats; i++) {
> > if (((map->pixel_formats[i].layer & layer_id) == layer_id) &&
> > - (map->pixel_formats[i].format == format))
> > - return map->pixel_formats[i].id;
> > + (map->pixel_formats[i].format == format)) {
> > +
> > + /*
> > + * In some DP550 and DP650, DRM_FORMAT_YUYV + AFBC modifier
> > + * is supported by a different h/w format id than
> > + * DRM_FORMAT_YUYV (only).
> > + */
> > + if (format == DRM_FORMAT_YUYV &&
> > + (has_modifier) &&
> > + (map->features & MALIDP_DEVICE_AFBC_YUYV_USE_422_P2))
> > + return AFBC_YUV_422_FORMAT_ID;
> > + else
> > + return map->pixel_formats[i].id;
> > + }
> > }
> >
> > return MALIDP_INVALID_FORMAT_ID;
> > }
> >
> > +bool malidp_hw_format_is_linear_only(u32 format)
> > +{
> > + switch (format) {
> > + case DRM_FORMAT_ARGB2101010:
> > + case DRM_FORMAT_RGBA1010102:
> > + case DRM_FORMAT_BGRA1010102:
> > + case DRM_FORMAT_ARGB8888:
> > + case DRM_FORMAT_RGBA8888:
> > + case DRM_FORMAT_BGRA8888:
> > + case DRM_FORMAT_XBGR8888:
> > + case DRM_FORMAT_XRGB8888:
> > + case DRM_FORMAT_RGBX8888:
> > + case DRM_FORMAT_BGRX8888:
> > + case DRM_FORMAT_RGB888:
> > + case DRM_FORMAT_RGB565:
> > + case DRM_FORMAT_ARGB1555:
> > + case DRM_FORMAT_RGBA5551:
> > + case DRM_FORMAT_BGRA5551:
> > + case DRM_FORMAT_UYVY:
> > + case DRM_FORMAT_XYUV8888:
> > + case DRM_FORMAT_XVYU2101010:
> > + case DRM_FORMAT_X0L2:
> > + case DRM_FORMAT_X0L0:
> > + return true;
> > + default:
> > + return false;
> > + }
> > +}
> > +
> > +bool malidp_hw_format_is_afbc_only(u32 format)
> > +{
> > + switch (format) {
> > + case DRM_FORMAT_VUY888:
> > + case DRM_FORMAT_VUY101010:
> > + case DRM_FORMAT_YUV420_8BIT:
> > + case DRM_FORMAT_YUV420_10BIT:
> > + return true;
> > + default:
> > + return false;
> > + }
> > +}
> > +
> > static void malidp_hw_clear_irq(struct malidp_hw_device *hwdev, u8 block, u32 irq)
> > {
> > u32 base = malidp_get_block_base(hwdev, block);
> > diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h
> > index 27b907f..52188f0 100644
> > --- a/drivers/gpu/drm/arm/malidp_hw.h
> > +++ b/drivers/gpu/drm/arm/malidp_hw.h
> > @@ -97,7 +97,8 @@ struct malidp_se_config {
> > /* regmap features */
> > #define MALIDP_REGMAP_HAS_CLEARIRQ BIT(0)
> > #define MALIDP_DEVICE_AFBC_SUPPORT_SPLIT BIT(1)
> > -#define AFBC_SUPPORT_SPLIT_WITH_YUV_420_10 BIT(2)
> > +#define MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT BIT(2)
> > +#define MALIDP_DEVICE_AFBC_YUYV_USE_422_P2 BIT(3)
> >
> > struct malidp_hw_regmap {
> > /* address offset of the DE register bank */
> > @@ -323,7 +324,7 @@ int malidp_se_irq_init(struct drm_device *drm, int irq);
> > void malidp_se_irq_fini(struct malidp_hw_device *hwdev);
> >
> > u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
> > - u8 layer_id, u32 format);
> > + u8 layer_id, u32 format, bool has_modifier);
> >
> > static inline u8 malidp_hw_get_pitch_align(struct malidp_hw_device *hwdev, bool rotated)
> > {
> > diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c
> > index 91472e5..0484744 100644
> > --- a/drivers/gpu/drm/arm/malidp_mw.c
> > +++ b/drivers/gpu/drm/arm/malidp_mw.c
> > @@ -143,7 +143,7 @@ malidp_mw_encoder_atomic_check(struct drm_encoder *encoder,
> >
> > mw_state->format =
> > malidp_hw_get_format_id(&malidp->dev->hw->map, SE_MEMWRITE,
> > - fb->format->format);
> > + fb->format->format, !!fb->modifier);
> > if (mw_state->format == MALIDP_INVALID_FORMAT_ID) {
> > struct drm_format_name_buf format_name;
> >
> > diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
> > index cd60f73..0765cee 100644
> > --- a/drivers/gpu/drm/arm/malidp_planes.c
> > +++ b/drivers/gpu/drm/arm/malidp_planes.c
> > @@ -52,6 +52,8 @@
> > #define MALIDP550_LS_ENABLE 0x01c
> > #define MALIDP550_LS_R1_IN_SIZE 0x020
> >
> > +#define MODIFIERS_COUNT_MAX 15
> > +
> > /*
> > * This 4-entry look-up-table is used to determine the full 8-bit alpha value
> > * for formats with 1- or 2-bit alpha channels.
> > @@ -145,6 +147,117 @@ static void malidp_plane_atomic_print_state(struct drm_printer *p,
> > drm_printf(p, "\tmmu_prefetch_pgsize=%d\n", ms->mmu_prefetch_pgsize);
> > }
> >
> > +bool malidp_format_mod_supported(struct drm_device *drm,
> > + u32 format, u64 modifier)
> > +{
> > + const struct drm_format_info *info;
> > + const u64 *modifiers;
> > + struct malidp_drm *malidp = drm->dev_private;
> > + const struct malidp_hw_regmap *map = &malidp->dev->hw->map;
> > +
> > + if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
> > + return false;
> > +
> > + /* Some pixel formats are supported without any modifier */
> > + if (modifier == DRM_FORMAT_MOD_LINEAR) {
> > + /* However these pixel formats need to be supported with
>
> Nitpick: multi-line comment style is to start with a line that contains
> only the marker for the start of the comment.
Agreed
>
> > + * modifiers only
> > + */
> > + return !malidp_hw_format_is_afbc_only(format);
> > + }
> > +
> > + if ((modifier >> 56) != DRM_FORMAT_MOD_VENDOR_ARM) {
> > + DRM_ERROR("Unknown modifier (not Arm)\n");
> > + return false;
> > + }
> > +
> > + if (modifier &
> > + ~DRM_FORMAT_MOD_ARM_AFBC(AFBC_MOD_VALID_BITS)) {
> > + DRM_DEBUG_KMS("Unsupported modifiers\n");
> > + return false;
> > + }
> > +
> > + modifiers = malidp_format_modifiers;
>
> Actually, looking again at patch 5/12 it looks to me like you could roll
> it into this patch completely.
>
Agreed, I will merge patch 5/12 "Defining a common list of AFBC
modifiers" with the current patch ("adding constraints for each format
and modifier").
> > + while (*modifiers != DRM_FORMAT_MOD_INVALID) {
> > + if (*modifiers == modifier) {
> > + /* SPLIT buffers must use SPARSE layout */
> > + if (WARN_ON_ONCE((modifier & AFBC_SPLIT) && !(modifier & AFBC_SPARSE)))
> > + return false;
> > +
> > + /* CBR only applies to YUV formats, where YTR should be always 0 */
> > + if (WARN_ON_ONCE((modifier & AFBC_CBR) && (modifier & AFBC_YTR)))
> > + return false;
>
> You can take these checks outside the while() loop as they test if the
> modifier passed as a parameter is valid, which you should check before
> running through the array. If you do that, then the loop through the
> malidp_format_modifiers is a simple "if found, break out of loop" and
> then the next check will return false if you iterated over the entire
> list.
>
Agreed
> > +
> > + break;
> > + }
> > +
> > + modifiers++;
> > + }
> > +
> > + /* return false, if the modifier was not found */
> > + if (*modifiers == DRM_FORMAT_MOD_INVALID) {
> > + DRM_DEBUG_KMS("Unsupported modifier\n");
> > + return false;
> > + }
> > +
> > + info = drm_format_info(format);
> > +
> > + if (info->num_planes != 1) {
> > + DRM_DEBUG_KMS("AFBC buffers expect one plane\n");
> > + return false;
> > + }
> > +
> > + if (malidp_hw_format_is_linear_only(format) == true) {
> > + DRM_DEBUG_KMS("Given format (0x%x) is supported is linear mode only\n", format);
> > + return false;
> > + }
> > +
> > + /*
> > + * RGB formats need to provide YTR modifier and YUV formats should not
> > + * provide YTR modifier.
> > + */
> > + if (!(info->is_yuv) != !!(modifier & AFBC_FORMAT_MOD_YTR)) {
> > + DRM_DEBUG_KMS("AFBC_FORMAT_MOD_YTR is %s for %s formats\n",
> > + info->is_yuv ? "disallowed" : "mandatory",
> > + info->is_yuv ? "YUV" : "RGB");
> > + return false;
> > + }
> > +
> > + if (modifier & AFBC_SPLIT) {
> > + if (!info->is_yuv) {
> > + if (drm_format_plane_cpp(format, 0) <= 2) {
> > + DRM_DEBUG_KMS("RGB formats <= 16bpp are not supported with SPLIT\n");
> > + return false;
> > + }
> > + }
> > +
> > + if ((drm_format_horz_chroma_subsampling(format) != 1) ||
> > + (drm_format_vert_chroma_subsampling(format) != 1)) {
> > + if (!(format == DRM_FORMAT_YUV420_10BIT &&
> > + (map->features & MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT))) {
> > + DRM_DEBUG_KMS("Formats which are sub-sampled should never be split\n");
> > + return false;
> > + }
> > + }
> > + }
> > +
> > + if (modifier & AFBC_CBR) {
> > + if ((drm_format_horz_chroma_subsampling(format) == 1) ||
> > + (drm_format_vert_chroma_subsampling(format) == 1)) {
> > + DRM_DEBUG_KMS("Formats which are not sub-sampled should not have CBR set\n");
> > + return false;
> > + }
> > + }
> > +
> > + return true;
> > +}
> > +
> > +static bool malidp_format_mod_supported_per_plane(struct drm_plane *plane,
> > + u32 format, u64 modifier)
> > +{
> > + return malidp_format_mod_supported(plane->dev, format, modifier);
> > +}
> > +
> > static const struct drm_plane_funcs malidp_de_plane_funcs = {
> > .update_plane = drm_atomic_helper_update_plane,
> > .disable_plane = drm_atomic_helper_disable_plane,
> > @@ -153,6 +266,7 @@ static const struct drm_plane_funcs malidp_de_plane_funcs = {
> > .atomic_duplicate_state = malidp_duplicate_plane_state,
> > .atomic_destroy_state = malidp_destroy_plane_state,
> > .atomic_print_state = malidp_plane_atomic_print_state,
> > + .format_mod_supported = malidp_format_mod_supported_per_plane,
> > };
> >
> > static int malidp_se_check_scaling(struct malidp_plane *mp,
> > @@ -406,8 +520,8 @@ static int malidp_de_plane_check(struct drm_plane *plane,
> > fb = state->fb;
> >
> > ms->format = malidp_hw_get_format_id(&mp->hwdev->hw->map,
> > - mp->layer->id,
> > - fb->format->format);
> > + mp->layer->id, fb->format->format,
> > + !!fb->modifier);
> > if (ms->format == MALIDP_INVALID_FORMAT_ID)
> > return -EINVAL;
> >
> > @@ -469,6 +583,12 @@ static int malidp_de_plane_check(struct drm_plane *plane,
> > return -EINVAL;
> > }
> >
> > + /* SMART layer does not support AFBC */
> > + if (mp->layer->id == DE_SMART && fb->modifier) {
> > + DRM_ERROR("AFBC framebuffer not supported in SMART layer");
> > + return -EINVAL;
> > + }
> > +
> > ms->rotmem_size = 0;
> > if (state->rotation & MALIDP_ROTATED_MASK) {
> > int val;
> > --
> > 2.7.4
> >
>
> Best regards,
> Liviu
>
>
> --
> ====================
> | I would like to |
> | fix the world, |
> | but they're not |
> | giving me the |
> \ source code! /
> ---------------
> ??\_(???)_/??
> _______________________________________________
> dri-devel mailing list
> [email protected]
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
On Fri, Dec 14, 2018 at 01:45:13PM +0000, Ayan Halder wrote:
> On Tue, Dec 04, 2018 at 04:50:51PM +0000, Liviu Dudau wrote:
>
> Hi Liviu,
>
> Please let me know if you agree with my comments. Then I will send a
> v4 patch for this.
> > On Mon, Dec 03, 2018 at 11:31:58AM +0000, Ayan Halder wrote:
> > > Added the AFBC decoder registers for DP500 , DP550 and DP650.
> > > These registers control the processing of AFBC buffers. It controls various
> > > features like AFBC decoder enable, lossless transformation and block split
> > > as well as setting of the left, right, top and bottom cropping of AFBC buffers
> > > (in number of pixels).
> > > All the layers (except DE_SMART) support framebuffers with AFBC modifiers.
> > > One needs to set the pixel values of the top, left, bottom and right cropping
> > > for the AFBC framebuffer.
> > > Cropping an AFBC framebuffer is controlled by the AFBC crop registers.
> > > In that case, the layer input size registers should be configured with
> > > framebuffer's dimensions and not with drm_plane_state source width/height
> > > values (which is used for non AFBC framebuffer to denote cropping).
> > >
> > > Changes from v1:
> > > - Removed the "if (fb->modifier)" check from malidp_de_plane_update()
> > > and added it in malidp_de_set_plane_afbc(). This will consolidate all the
> > > AFBC specific register configurations in a single function ie
> > > malidp_de_set_plane_afbc().
> > >
> > > Changes from v2:
> > > - For AFBC framebuffer, layer input size register should be set to framebuffer's
> > > width and height
> > >
> > > Signed-off-by: Ayan Kumar Halder <[email protected]>
> > > ---
> > > drivers/gpu/drm/arm/malidp_hw.c | 25 +++++----
> > > drivers/gpu/drm/arm/malidp_hw.h | 2 +
> > > drivers/gpu/drm/arm/malidp_planes.c | 109 +++++++++++++++++++++++++++++++-----
> > > drivers/gpu/drm/arm/malidp_regs.h | 20 +++++++
> > > 4 files changed, 130 insertions(+), 26 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
> > > index b9bed11..87b7b12 100644
> > > --- a/drivers/gpu/drm/arm/malidp_hw.c
> > > +++ b/drivers/gpu/drm/arm/malidp_hw.c
> > > @@ -94,11 +94,12 @@ static const struct malidp_layer malidp500_layers[] = {
> > > * yuv2rgb matrix offset, mmu control register offset, rotation_features
> > > */
> > > { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE,
> > > - MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB, 0, ROTATE_ANY },
> > > + MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB, 0, ROTATE_ANY,
> > > + MALIDP500_DE_LV_AD_CTRL },
> > > { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE,
> > > - MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
> > > + MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY, MALIDP500_DE_LG1_AD_CTRL },
> > > { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE,
> > > - MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
> > > + MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY, MALIDP500_DE_LG2_AD_CTRL },
> > > };
> > >
> > > static const struct malidp_layer malidp550_layers[] = {
> > > @@ -106,13 +107,15 @@ static const struct malidp_layer malidp550_layers[] = {
> > > * yuv2rgb matrix offset, mmu control register offset, rotation_features
> > > */
> > > { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
> > > - MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY },
> > > + MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY,
> > > + MALIDP550_DE_LV1_AD_CTRL },
> > > { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
> > > - MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
> > > + MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY, MALIDP550_DE_LG_AD_CTRL },
> > > { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
> > > - MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY },
> > > + MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY,
> > > + MALIDP550_DE_LV2_AD_CTRL },
> > > { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
> > > - MALIDP550_DE_LS_R1_STRIDE, 0, 0, ROTATE_NONE },
> > > + MALIDP550_DE_LS_R1_STRIDE, 0, 0, ROTATE_NONE, 0 },
> > > };
> > >
> > > static const struct malidp_layer malidp650_layers[] = {
> > > @@ -122,16 +125,16 @@ static const struct malidp_layer malidp650_layers[] = {
> > > */
> > > { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
> > > MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
> > > - MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY },
> > > + MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY, MALIDP550_DE_LV1_AD_CTRL },
> > > { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
> > > MALIDP_DE_LG_STRIDE, 0, MALIDP650_DE_LG_MMU_CTRL,
> > > - ROTATE_COMPRESSED },
> > > + ROTATE_COMPRESSED, MALIDP550_DE_LG_AD_CTRL },
> > > { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
> > > MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
> > > - MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY },
> > > + MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY, MALIDP550_DE_LV2_AD_CTRL },
> > > { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
> > > MALIDP550_DE_LS_R1_STRIDE, 0, MALIDP650_DE_LS_MMU_CTRL,
> > > - ROTATE_NONE },
> > > + ROTATE_NONE, 0 },
> > > };
> > >
> > > #define SE_N_SCALING_COEFFS 96
> > > diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h
> > > index 40155e2..651558f 100644
> > > --- a/drivers/gpu/drm/arm/malidp_hw.h
> > > +++ b/drivers/gpu/drm/arm/malidp_hw.h
> > > @@ -70,6 +70,8 @@ struct malidp_layer {
> > > s16 yuv2rgb_offset; /* offset to the YUV->RGB matrix entries */
> > > u16 mmu_ctrl_offset; /* offset to the MMU control register */
> > > enum rotation_features rot; /* type of rotation supported */
> > > + /* address offset for the AFBC decoder registers */
> > > + u16 afbc_decoder_offset;
> > > };
> > >
> > > enum malidp_scaling_coeff_set {
> > > diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
> > > index c9a6d3e..cd60f73 100644
> > > --- a/drivers/gpu/drm/arm/malidp_planes.c
> > > +++ b/drivers/gpu/drm/arm/malidp_planes.c
> > > @@ -592,6 +592,80 @@ static void malidp_de_set_mmu_control(struct malidp_plane *mp,
> > > mp->layer->base + mp->layer->mmu_ctrl_offset);
> > > }
> > >
> > > +static void malidp_set_plane_base_addr(struct drm_framebuffer *fb,
> > > + struct malidp_plane *mp,
> > > + int plane_index)
> > > +{
> > > + dma_addr_t paddr;
> > > + u16 ptr;
> > > + struct drm_plane *plane = &mp->base;
> > > + bool afbc = fb->modifier ? true : false;
> > > +
> > > + ptr = mp->layer->ptr + (plane_index << 4);
> > > +
> > > + /*
> > > + * For AFBC buffers, cropping is handled by AFBC decoder rather than
> > > + * pointer manipulation.
> > > + */
> >
> > I think this comment needs to go in malidp_de_plane_update, not in this function.
> > This function only updates the plane's base address.
> >
> I will reword the comment like this if it sounds sane :-
>
> drm_fb_cma_get_gem_addr() alters the physical base address of the framebuffer
> as per the plane's src_x, src_y co-ordinates (ie to take care of source cropping).
> For AFBC, this is not needed as the cropping is handled by _AD_CROP_H
> and _AD_CROP_V registers.
Yeah, that sounds more in line with what the code does.
>
> > > + if (!afbc) {
> > > + paddr = drm_fb_cma_get_gem_addr(fb, plane->state,
> > > + plane_index);
> > > + } else {
> > > + struct drm_gem_cma_object *obj;
> > > +
> > > + obj = drm_fb_cma_get_gem_obj(fb, plane_index);
> > > +
> > > + if (WARN_ON(!obj))
> > > + return;
> > > + paddr = obj->paddr;
> > > + }
> > > +
> > > + malidp_hw_write(mp->hwdev, lower_32_bits(paddr), ptr);
> > > + malidp_hw_write(mp->hwdev, upper_32_bits(paddr), ptr + 4);
> > > +}
> > > +
> > > +static void malidp_de_set_plane_afbc(struct drm_plane *plane)
> > > +{
> > > + struct malidp_plane *mp;
> > > + u32 src_w, src_h, val = 0, src_x, src_y;
> > > + struct drm_framebuffer *fb = plane->state->fb;
> > > +
> > > + mp = to_malidp_plane(plane);
> > > +
> > > + /* no afbc_decoder_offset means AFBC is not supported on this plane */
> > > + if (!mp->layer->afbc_decoder_offset)
> > > + return;
> > > +
> > > + if (!fb->modifier) {
> > > + malidp_hw_write(mp->hwdev, 0, mp->layer->afbc_decoder_offset);
> > > + return;
> > > + }
> > > +
> > > + /* convert src values from Q16 fixed point to integer */
> > > + src_w = plane->state->src_w >> 16;
> > > + src_h = plane->state->src_h >> 16;
> > > + src_x = plane->state->src_x >> 16;
> > > + src_y = plane->state->src_y >> 16;
> > > +
> > > + val = ((fb->width - (src_x + src_w)) << MALIDP_AD_CROP_RIGHT_OFFSET) |
> > > + src_x;
> > > + malidp_hw_write(mp->hwdev, val,
> > > + mp->layer->afbc_decoder_offset + MALIDP_AD_CROP_H);
> > > +
> > > + val = ((fb->height - (src_y + src_h)) << MALIDP_AD_CROP_BOTTOM_OFFSET) |
> > > + src_y;
> > > + malidp_hw_write(mp->hwdev, val,
> > > + mp->layer->afbc_decoder_offset + MALIDP_AD_CROP_V);
> > > +
> > > + val = MALIDP_AD_EN;
> > > + if (fb->modifier & AFBC_FORMAT_MOD_SPLIT)
> > > + val |= MALIDP_AD_BS;
> > > + if (fb->modifier & AFBC_FORMAT_MOD_YTR)
> > > + val |= MALIDP_AD_YTR;
> > > +
> > > + malidp_hw_write(mp->hwdev, val, mp->layer->afbc_decoder_offset);
> > > +}
> > > +
> > > static void malidp_de_plane_update(struct drm_plane *plane,
> > > struct drm_plane_state *old_state)
> > > {
> > > @@ -600,30 +674,33 @@ static void malidp_de_plane_update(struct drm_plane *plane,
> > > struct drm_plane_state *state = plane->state;
> > > u16 pixel_alpha = state->pixel_blend_mode;
> > > u8 plane_alpha = state->alpha >> 8;
> > > + bool format_has_alpha = state->fb->format->has_alpha;
> > > u32 src_w, src_h, dest_w, dest_h, val;
> > > int i;
> > > + struct drm_framebuffer *fb = plane->state->fb;
> > >
> > > mp = to_malidp_plane(plane);
> > >
> > > - /* convert src values from Q16 fixed point to integer */
> > > - src_w = state->src_w >> 16;
> > > - src_h = state->src_h >> 16;
> > > - dest_w = state->crtc_w;
> > > - dest_h = state->crtc_h;
> > > + /* For AFBC framebuffer, use the framebuffer width and height for configuring
> > > + * layer input size register.
> > > + */
> > > + if (fb->modifier) {
> > > + src_w = fb->width;
> > > + src_h = fb->height;
> > > + } else {
> > > + /* convert src values from Q16 fixed point to integer */
> > > + src_w = ms->base.src_w >> 16;
> > > + src_h = ms->base.src_h >> 16;
> > > + }
> > > + dest_w = ms->base.crtc_w;
> > > + dest_h = ms->base.crtc_h;
> >
> > These two lines above are equivalent to the last two lines you deleted. Why you need this change?
> >
> Agreed, I will remove this change.
> > >
> > > val = malidp_hw_read(mp->hwdev, mp->layer->base);
> > > val = (val & ~LAYER_FORMAT_MASK) | ms->format;
> > > malidp_hw_write(mp->hwdev, val, mp->layer->base);
> > >
> > > - for (i = 0; i < ms->n_planes; i++) {
> > > - /* calculate the offset for the layer's plane registers */
> > > - u16 ptr = mp->layer->ptr + (i << 4);
> > > - dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(state->fb,
> > > - state, i);
> > > -
> > > - malidp_hw_write(mp->hwdev, lower_32_bits(fb_addr), ptr);
> > > - malidp_hw_write(mp->hwdev, upper_32_bits(fb_addr), ptr + 4);
> > > - }
> > > + for (i = 0; i < ms->n_planes; i++)
> > > + malidp_set_plane_base_addr(fb, mp, i);
> > >
> > > malidp_de_set_mmu_control(mp, ms);
> > >
> > > @@ -657,6 +734,8 @@ static void malidp_de_plane_update(struct drm_plane *plane,
> > > mp->layer->base + MALIDP550_LS_R1_IN_SIZE);
> > > }
> > >
> > > + malidp_de_set_plane_afbc(plane);
> >
> > I feel like this function call should be done only if (fb->modifier) is
> > true.
> We need to call this function even is fb->modifier = 0. Please refer
> to the following snippet in malidp_de_set_plane_afbc()
>
> if (!fb->modifier) {
> malidp_hw_write(mp->hwdev, 0, mp->layer->afbc_decoder_offset);
> return;
> }
Right, that is to reset the afbc_decoder_offset, correct? Still, it
would look a bit more obvious if the code looked like this here:
if (!fb->modifier)
malidp_hw_write(mp->hwdev, 0, mp->layer->afbc_decoder_offset);
else
malidp_de_set_plane_afbc(plane);
> I will prefer to keep all the AFBC register configuration in a single
> function.
But I agree, it is probably easier to keep them all together. Please
discard my previous comment.
Best regards,
Liviu
>
> Thanks,
> Ayan Kumar Halder
> >
> > > +
> > > /* first clear the rotation bits */
> > > val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL);
> > > val &= ~LAYER_ROT_MASK;
> > > @@ -674,7 +753,7 @@ static void malidp_de_plane_update(struct drm_plane *plane,
> > >
> > > if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) {
> > > val |= LAYER_COMP_PLANE;
> > > - } else if (state->fb->format->has_alpha) {
> > > + } else if (format_has_alpha) {
> >
> > This change has nothing to do with AFBC, it should not be in this patch.
> >
> > > /* We only care about blend mode if the format has alpha */
> > > switch (pixel_alpha) {
> > > case DRM_MODE_BLEND_PREMULTI:
> > > diff --git a/drivers/gpu/drm/arm/malidp_regs.h b/drivers/gpu/drm/arm/malidp_regs.h
> > > index 7ce3e14..a0dd6e1 100644
> > > --- a/drivers/gpu/drm/arm/malidp_regs.h
> > > +++ b/drivers/gpu/drm/arm/malidp_regs.h
> > > @@ -198,10 +198,13 @@
> > > #define MALIDP500_LV_YUV2RGB ((s16)(-0xB8))
> > > #define MALIDP500_DE_LV_BASE 0x00100
> > > #define MALIDP500_DE_LV_PTR_BASE 0x00124
> > > +#define MALIDP500_DE_LV_AD_CTRL 0x00400
> > > #define MALIDP500_DE_LG1_BASE 0x00200
> > > #define MALIDP500_DE_LG1_PTR_BASE 0x0021c
> > > +#define MALIDP500_DE_LG1_AD_CTRL 0x0040c
> > > #define MALIDP500_DE_LG2_BASE 0x00300
> > > #define MALIDP500_DE_LG2_PTR_BASE 0x0031c
> > > +#define MALIDP500_DE_LG2_AD_CTRL 0x00418
> > > #define MALIDP500_SE_BASE 0x00c00
> > > #define MALIDP500_SE_CONTROL 0x00c0c
> > > #define MALIDP500_SE_MEMWRITE_OUT_SIZE 0x00c2c
> > > @@ -228,10 +231,13 @@
> > > #define MALIDP550_LV_YUV2RGB 0x00084
> > > #define MALIDP550_DE_LV1_BASE 0x00100
> > > #define MALIDP550_DE_LV1_PTR_BASE 0x00124
> > > +#define MALIDP550_DE_LV1_AD_CTRL 0x001B8
> > > #define MALIDP550_DE_LV2_BASE 0x00200
> > > #define MALIDP550_DE_LV2_PTR_BASE 0x00224
> > > +#define MALIDP550_DE_LV2_AD_CTRL 0x002B8
> > > #define MALIDP550_DE_LG_BASE 0x00300
> > > #define MALIDP550_DE_LG_PTR_BASE 0x0031c
> > > +#define MALIDP550_DE_LG_AD_CTRL 0x00330
> > > #define MALIDP550_DE_LS_BASE 0x00400
> > > #define MALIDP550_DE_LS_PTR_BASE 0x0042c
> > > #define MALIDP550_DE_PERF_BASE 0x00500
> > > @@ -258,6 +264,20 @@
> > > #define MALIDP_MMU_CTRL_PX_PS(x) (1 << (8 + (x)))
> > > #define MALIDP_MMU_CTRL_PP_NUM_REQ(x) (((x) & 0x7f) << 12)
> > >
> > > +/* AFBC register offsets relative to MALIDPXXX_DE_LX_AD_CTRL */
> > > +/* The following register offsets are common for DP500, DP550 and DP650 */
> > > +#define MALIDP_AD_CROP_H 0x4
> > > +#define MALIDP_AD_CROP_V 0x8
> > > +#define MALIDP_AD_END_PTR_LOW 0xc
> > > +#define MALIDP_AD_END_PTR_HIGH 0x10
> > > +
> > > +/* AFBC decoder Registers */
> > > +#define MALIDP_AD_EN BIT(0)
> > > +#define MALIDP_AD_YTR BIT(4)
> > > +#define MALIDP_AD_BS BIT(8)
> > > +#define MALIDP_AD_CROP_RIGHT_OFFSET 16
> > > +#define MALIDP_AD_CROP_BOTTOM_OFFSET 16
> > > +
> > > /*
> > > * Starting with DP550 the register map blocks has been standardised to the
> > > * following layout:
> > > --
> > > 2.7.4
> > >
> >
> > Best regards,
> > Liviu
> >
> >
> > --
> > ====================
> > | I would like to |
> > | fix the world, |
> > | but they're not |
> > | giving me the |
> > \ source code! /
> > ---------------
> > ??\_(???)_/??
> > _______________________________________________
> > dri-devel mailing list
> > [email protected]
> > https://lists.freedesktop.org/mailman/listinfo/dri-devel
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
On Fri, Dec 14, 2018 at 02:12:23PM +0000, Ayan Halder wrote:
> On Tue, Dec 04, 2018 at 04:57:46PM +0000, Liviu Dudau wrote:
>
> Hi Liviu,
> > On Mon, Dec 03, 2018 at 11:32:00AM +0000, Ayan Halder wrote:
> > > We have added some new formats to be supported on DP500/DP550/DP650.
> >
> > Make a bit more descriptive commit message here, please!
> >
> I will keep the following commit message :-
>
> ""We have added support for some AFBC only pixel formats like :-
> DRM_FORMAT_YUV420_8BIT (single plane YUV 420 8 bit format)
> DRM_FORMAT_VUY888 (single plane YUV 444 8 bit format)
> DRM_FORMAT_VUY101010 (single plane YUV 444 10 bit format)
> DRM_FORMAT_YUV420_10BIT (single plane YUV 420 10 bit format)
>
> Generally, these formats are supported by our hardware using the same hw-ids as
> the equivalent multi plane pixel formats.
>
> Also we have added support for XYUV 444 8 and 10 bit formats.""
>
> Let me know if this looks fine.
Yes, LGTM.
Best regards,
Liviu
>
> Thanks,
> Ayan Kumar halder
> > >
> > > Signed-off-by: Ayan Kumar Halder <[email protected]>
> > >
> > > Depends on :- https://patchwork.kernel.org/patch/10460063/
> >
> > Reviewed-by: Liviu Dudau <[email protected]>
> >
> > Best regards,
> > Liviu
> >
> > > ---
> > > drivers/gpu/drm/arm/malidp_hw.c | 22 +++++++++++++++++++++-
> > > 1 file changed, 21 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
> > > index 55d379b..25ac5890 100644
> > > --- a/drivers/gpu/drm/arm/malidp_hw.c
> > > +++ b/drivers/gpu/drm/arm/malidp_hw.c
> > > @@ -49,6 +49,12 @@ static const struct malidp_format_id malidp500_de_formats[] = {
> > > { DRM_FORMAT_YUYV, DE_VIDEO1, 13 },
> > > { DRM_FORMAT_NV12, DE_VIDEO1 | SE_MEMWRITE, 14 },
> > > { DRM_FORMAT_YUV420, DE_VIDEO1, 15 },
> > > + { DRM_FORMAT_XYUV8888, DE_VIDEO1, 16 },
> > > + /* These are supported with AFBC only */
> > > + { DRM_FORMAT_YUV420_8BIT, DE_VIDEO1, 14 },
> > > + { DRM_FORMAT_VUY888, DE_VIDEO1, 16 },
> > > + { DRM_FORMAT_VUY101010, DE_VIDEO1, 17 },
> > > + { DRM_FORMAT_YUV420_10BIT, DE_VIDEO1, 18 }
> > > };
> > >
> > > #define MALIDP_ID(__group, __format) \
> > > @@ -74,11 +80,25 @@ static const struct malidp_format_id malidp500_de_formats[] = {
> > > { DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 1) }, \
> > > { DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 2) }, \
> > > { DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 3) }, \
> > > + /* This is only supported with linear modifier */ \
> > > + { DRM_FORMAT_XYUV8888, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 0) },\
> > > + /* This is only supported with AFBC modifier */ \
> > > + { DRM_FORMAT_VUY888, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 0) }, \
> > > { DRM_FORMAT_YUYV, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 2) }, \
> > > + /* This is only supported with linear modifier */ \
> > > { DRM_FORMAT_UYVY, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 3) }, \
> > > { DRM_FORMAT_NV12, DE_VIDEO1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(5, 6) }, \
> > > + /* This is only supported with AFBC modifier */ \
> > > + { DRM_FORMAT_YUV420_8BIT, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 6) }, \
> > > { DRM_FORMAT_YUV420, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 7) }, \
> > > - { DRM_FORMAT_X0L2, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 6)}
> > > + /* This is only supported with linear modifier */ \
> > > + { DRM_FORMAT_XVYU2101010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 0)}, \
> > > + /* This is only supported with AFBC modifier */ \
> > > + { DRM_FORMAT_VUY101010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 0)}, \
> > > + { DRM_FORMAT_X0L2, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 6)}, \
> > > + /* This is only supported with AFBC modifier */ \
> > > + { DRM_FORMAT_YUV420_10BIT, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 7)}, \
> > > + { DRM_FORMAT_P010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 7)}
> > >
> > > static const struct malidp_format_id malidp550_de_formats[] = {
> > > MALIDP_COMMON_FORMATS,
> > > --
> > > 2.7.4
> > >
> >
> > --
> > ====================
> > | I would like to |
> > | fix the world, |
> > | but they're not |
> > | giving me the |
> > \ source code! /
> > ---------------
> > ??\_(???)_/??
> > _______________________________________________
> > dri-devel mailing list
> > [email protected]
> > https://lists.freedesktop.org/mailman/listinfo/dri-devel
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
Hi Liviu,
On Mon, 2018-12-03 at 11:31 +0000, Ayan Halder wrote:
> From: Brian Starkey <[email protected]>
>
> AFBC is a flexible, proprietary, lossless compression protocol and
> format, with a number of defined DRM format modifiers. To facilitate
> consistency and compatibility between different AFBC producers and
> consumers, document the expectations for usage of the AFBC DRM format
> modifiers in a new .rst chapter.
>
> Signed-off-by: Brian Starkey <[email protected]>
> Reviewed-by: Liviu Dudau <[email protected]>
> ---
I can't find this commit anywhere. Did you decide to reject
this or perhaps it just fell thru the cracks?
Thanks!
Ezequiel
> Documentation/gpu/afbc.rst | 233 ++++++++++++++++++++++++++++++++++++++++++
> Documentation/gpu/drivers.rst | 1 +
> MAINTAINERS | 1 +
> include/uapi/drm/drm_fourcc.h | 3 +
> 4 files changed, 238 insertions(+)
> create mode 100644 Documentation/gpu/afbc.rst
>
> diff --git a/Documentation/gpu/afbc.rst b/Documentation/gpu/afbc.rst
> new file mode 100644
> index 0000000..922d955
> --- /dev/null
> +++ b/Documentation/gpu/afbc.rst
> @@ -0,0 +1,233 @@
> +===================================
> + Arm Framebuffer Compression (AFBC)
> +===================================
> +
> +AFBC is a proprietary lossless image compression protocol and format.
> +It provides fine-grained random access and minimizes the amount of
> +data transferred between IP blocks.
> +
> +AFBC can be enabled on drivers which support it via use of the AFBC
> +format modifiers defined in drm_fourcc.h. See DRM_FORMAT_MOD_ARM_AFBC(*).
> +
> +All users of the AFBC modifiers must follow the usage guidelines laid
> +out in this document, to ensure compatibility across different AFBC
> +producers and consumers.
> +
> +Components and Ordering
> +=======================
> +
> +AFBC streams can contain several components - where a component
> +corresponds to a color channel (i.e. R, G, B, X, A, Y, Cb, Cr).
> +The assignment of input/output color channels must be consistent
> +between the encoder and the decoder for correct operation, otherwise
> +the consumer will interpret the decoded data incorrectly.
> +
> +Furthermore, when the lossless colorspace transform is used
> +(AFBC_FORMAT_MOD_YTR, which should be enabled for RGB buffers for
> +maximum compression efficiency), the component order must be:
> +
> + * Component 0: R
> + * Component 1: G
> + * Component 2: B
> +
> +The component ordering is communicated via the fourcc code in the
> +fourcc:modifier pair. In general, component '0' is considered to
> +reside in the least-significant bits of the corresponding linear
> +format. For example, COMP(bits):
> +
> + * DRM_FORMAT_ABGR8888
> +
> + * Component 0: R(8)
> + * Component 1: G(8)
> + * Component 2: B(8)
> + * Component 3: A(8)
> +
> + * DRM_FORMAT_BGR888
> +
> + * Component 0: R(8)
> + * Component 1: G(8)
> + * Component 2: B(8)
> +
> + * DRM_FORMAT_YUYV
> +
> + * Component 0: Y(8)
> + * Component 1: Cb(8, 2x1 subsampled)
> + * Component 2: Cr(8, 2x1 subsampled)
> +
> +In AFBC, 'X' components are not treated any differently from any other
> +component. Therefore, an AFBC buffer with fourcc DRM_FORMAT_XBGR8888
> +encodes with 4 components, like so:
> +
> + * DRM_FORMAT_XBGR8888
> +
> + * Component 0: R(8)
> + * Component 1: G(8)
> + * Component 2: B(8)
> + * Component 3: X(8)
> +
> +Please note, however, that the inclusion of a "wasted" 'X' channel is
> +bad for compression efficiency, and so it's recommended to avoid
> +formats containing 'X' bits. If a fourth component is
> +required/expected by the encoder/decoder, then it is recommended to
> +instead use an equivalent format with alpha, setting all alpha bits to
> +'1'. If there is no requirement for a fourth component, then a format
> +which doesn't include alpha can be used, e.g. DRM_FORMAT_BGR888.
> +
> +Number of Planes
> +================
> +
> +Formats which are typically multi-planar in linear layouts (e.g. YUV
> +420), can be encoded into one, or multiple, AFBC planes. As with
> +component order, the encoder and decoder must agree about the number
> +of planes in order to correctly decode the buffer. The fourcc code is
> +used to determine the number of encoded planes in an AFBC buffer,
> +matching the number of planes for the linear (unmodified) format.
> +Within each plane, the component ordering also follows the fourcc
> +code:
> +
> +For example:
> +
> + * DRM_FORMAT_YUYV: nplanes = 1
> +
> + * Plane 0:
> +
> + * Component 0: Y(8)
> + * Component 1: Cb(8, 2x1 subsampled)
> + * Component 2: Cr(8, 2x1 subsampled)
> +
> + * DRM_FORMAT_NV12: nplanes = 2
> +
> + * Plane 0:
> +
> + * Component 0: Y(8)
> +
> + * Plane 1:
> +
> + * Component 0: Cb(8, 2x1 subsampled)
> + * Component 1: Cr(8, 2x1 subsampled)
> +
> +Cross-device interoperability
> +=============================
> +
> +For maximum compatibility across devices, the table below defines
> +canonical formats for use between AFBC-enabled devices. Formats which
> +are listed here must be used exactly as specified when using the AFBC
> +modifiers. Formats which are not listed should be avoided.
> +
> +.. flat-table:: AFBC formats
> +
> + * - Fourcc code
> + - Description
> + - Planes/Components
> +
> + * - DRM_FORMAT_ABGR2101010
> + - 10-bit per component RGB, with 2-bit alpha
> + - Plane 0: 4 components
> + * Component 0: R(10)
> + * Component 1: G(10)
> + * Component 2: B(10)
> + * Component 3: A(2)
> +
> + * - DRM_FORMAT_ABGR8888
> + - 8-bit per component RGB, with 8-bit alpha
> + - Plane 0: 4 components
> + * Component 0: R(8)
> + * Component 1: G(8)
> + * Component 2: B(8)
> + * Component 3: A(8)
> +
> + * - DRM_FORMAT_BGR888
> + - 8-bit per component RGB
> + - Plane 0: 3 components
> + * Component 0: R(8)
> + * Component 1: G(8)
> + * Component 2: B(8)
> +
> + * - DRM_FORMAT_BGR565
> + - 5/6-bit per component RGB
> + - Plane 0: 3 components
> + * Component 0: R(5)
> + * Component 1: G(6)
> + * Component 2: B(5)
> +
> + * - DRM_FORMAT_ABGR1555
> + - 5-bit per component RGB, with 1-bit alpha
> + - Plane 0: 4 components
> + * Component 0: R(5)
> + * Component 1: G(5)
> + * Component 2: B(5)
> + * Component 3: A(1)
> +
> + * - DRM_FORMAT_VUY888
> + - 8-bit per component YCbCr 444, single plane
> + - Plane 0: 3 components
> + * Component 0: Y(8)
> + * Component 1: Cb(8)
> + * Component 2: Cr(8)
> +
> + * - DRM_FORMAT_VUY101010
> + - 10-bit per component YCbCr 444, single plane
> + - Plane 0: 3 components
> + * Component 0: Y(10)
> + * Component 1: Cb(10)
> + * Component 2: Cr(10)
> +
> + * - DRM_FORMAT_YUYV
> + - 8-bit per component YCbCr 422, single plane
> + - Plane 0: 3 components
> + * Component 0: Y(8)
> + * Component 1: Cb(8, 2x1 subsampled)
> + * Component 2: Cr(8, 2x1 subsampled)
> +
> + * - DRM_FORMAT_NV16
> + - 8-bit per component YCbCr 422, two plane
> + - Plane 0: 1 component
> + * Component 0: Y(8)
> + Plane 1: 2 components
> + * Component 0: Cb(8, 2x1 subsampled)
> + * Component 1: Cr(8, 2x1 subsampled)
> +
> + * - DRM_FORMAT_Y210
> + - 10-bit per component YCbCr 422, single plane
> + - Plane 0: 3 components
> + * Component 0: Y(10)
> + * Component 1: Cb(10, 2x1 subsampled)
> + * Component 2: Cr(10, 2x1 subsampled)
> +
> + * - DRM_FORMAT_P210
> + - 10-bit per component YCbCr 422, two plane
> + - Plane 0: 1 component
> + * Component 0: Y(10)
> + Plane 1: 2 components
> + * Component 0: Cb(10, 2x1 subsampled)
> + * Component 1: Cr(10, 2x1 subsampled)
> +
> + * - DRM_FORMAT_YUV420_8BIT
> + - 8-bit per component YCbCr 420, single plane
> + - Plane 0: 3 components
> + * Component 0: Y(8)
> + * Component 1: Cb(8, 2x2 subsampled)
> + * Component 2: Cr(8, 2x2 subsampled)
> +
> + * - DRM_FORMAT_YUV420_10BIT
> + - 10-bit per component YCbCr 420, single plane
> + - Plane 0: 3 components
> + * Component 0: Y(10)
> + * Component 1: Cb(10, 2x2 subsampled)
> + * Component 2: Cr(10, 2x2 subsampled)
> +
> + * - DRM_FORMAT_NV12
> + - 8-bit per component YCbCr 420, two plane
> + - Plane 0: 1 component
> + * Component 0: Y(8)
> + Plane 1: 2 components
> + * Component 0: Cb(8, 2x2 subsampled)
> + * Component 1: Cr(8, 2x2 subsampled)
> +
> + * - DRM_FORMAT_P010
> + - 10-bit per component YCbCr 420, two plane
> + - Plane 0: 1 component
> + * Component 0: Y(10)
> + Plane 1: 2 components
> + * Component 0: Cb(10, 2x2 subsampled)
> + * Component 1: Cr(10, 2x2 subsampled)
> diff --git a/Documentation/gpu/drivers.rst b/Documentation/gpu/drivers.rst
> index 7c16721..c176b34 100644
> --- a/Documentation/gpu/drivers.rst
> +++ b/Documentation/gpu/drivers.rst
> @@ -17,6 +17,7 @@ GPU Driver Documentation
> vkms
> bridge/dw-hdmi
> xen-front
> + afbc
>
> .. only:: subproject and html
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 254b7b2..aef18e3 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1131,6 +1131,7 @@ M: Mali DP Maintainers <[email protected]>
> S: Supported
> F: drivers/gpu/drm/arm/
> F: Documentation/devicetree/bindings/display/arm,malidp.txt
> +F: Documentation/gpu/afbc.rst
>
> ARM MFM AND FLOPPY DRIVERS
> M: Ian Molton <[email protected]>
> diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
> index 75c4b5a..0adde4d 100644
> --- a/include/uapi/drm/drm_fourcc.h
> +++ b/include/uapi/drm/drm_fourcc.h
> @@ -597,6 +597,9 @@ extern "C" {
> * AFBC has several features which may be supported and/or used, which are
> * represented using bits in the modifier. Not all combinations are valid,
> * and different devices or use-cases may support different combinations.
> + *
> + * Further information on the use of AFBC modifiers can be found in
> + * Documentation/gpu/afbc.rst
> */
> #define DRM_FORMAT_MOD_ARM_AFBC(__afbc_mode) fourcc_mod_code(ARM, __afbc_mode)
>
On Thu, Jan 03, 2019 at 05:44:26PM -0300, Ezequiel Garcia wrote:
> Hi Liviu,
>
> On Mon, 2018-12-03 at 11:31 +0000, Ayan Halder wrote:
> > From: Brian Starkey <[email protected]>
> >
> > AFBC is a flexible, proprietary, lossless compression protocol and
> > format, with a number of defined DRM format modifiers. To facilitate
> > consistency and compatibility between different AFBC producers and
> > consumers, document the expectations for usage of the AFBC DRM format
> > modifiers in a new .rst chapter.
> >
> > Signed-off-by: Brian Starkey <[email protected]>
> > Reviewed-by: Liviu Dudau <[email protected]>
> > ---
>
> I can't find this commit anywhere. Did you decide to reject
> this or perhaps it just fell thru the cracks?
Cracks have opened wide enough to let this through, sorry about that!
I've now sent a pull request to get it merged.
Best regards,
Liviu
>
> Thanks!
> Ezequiel
>
>
> > Documentation/gpu/afbc.rst | 233 ++++++++++++++++++++++++++++++++++++++++++
> > Documentation/gpu/drivers.rst | 1 +
> > MAINTAINERS | 1 +
> > include/uapi/drm/drm_fourcc.h | 3 +
> > 4 files changed, 238 insertions(+)
> > create mode 100644 Documentation/gpu/afbc.rst
> >
> > diff --git a/Documentation/gpu/afbc.rst b/Documentation/gpu/afbc.rst
> > new file mode 100644
> > index 0000000..922d955
> > --- /dev/null
> > +++ b/Documentation/gpu/afbc.rst
> > @@ -0,0 +1,233 @@
> > +===================================
> > + Arm Framebuffer Compression (AFBC)
> > +===================================
> > +
> > +AFBC is a proprietary lossless image compression protocol and format.
> > +It provides fine-grained random access and minimizes the amount of
> > +data transferred between IP blocks.
> > +
> > +AFBC can be enabled on drivers which support it via use of the AFBC
> > +format modifiers defined in drm_fourcc.h. See DRM_FORMAT_MOD_ARM_AFBC(*).
> > +
> > +All users of the AFBC modifiers must follow the usage guidelines laid
> > +out in this document, to ensure compatibility across different AFBC
> > +producers and consumers.
> > +
> > +Components and Ordering
> > +=======================
> > +
> > +AFBC streams can contain several components - where a component
> > +corresponds to a color channel (i.e. R, G, B, X, A, Y, Cb, Cr).
> > +The assignment of input/output color channels must be consistent
> > +between the encoder and the decoder for correct operation, otherwise
> > +the consumer will interpret the decoded data incorrectly.
> > +
> > +Furthermore, when the lossless colorspace transform is used
> > +(AFBC_FORMAT_MOD_YTR, which should be enabled for RGB buffers for
> > +maximum compression efficiency), the component order must be:
> > +
> > + * Component 0: R
> > + * Component 1: G
> > + * Component 2: B
> > +
> > +The component ordering is communicated via the fourcc code in the
> > +fourcc:modifier pair. In general, component '0' is considered to
> > +reside in the least-significant bits of the corresponding linear
> > +format. For example, COMP(bits):
> > +
> > + * DRM_FORMAT_ABGR8888
> > +
> > + * Component 0: R(8)
> > + * Component 1: G(8)
> > + * Component 2: B(8)
> > + * Component 3: A(8)
> > +
> > + * DRM_FORMAT_BGR888
> > +
> > + * Component 0: R(8)
> > + * Component 1: G(8)
> > + * Component 2: B(8)
> > +
> > + * DRM_FORMAT_YUYV
> > +
> > + * Component 0: Y(8)
> > + * Component 1: Cb(8, 2x1 subsampled)
> > + * Component 2: Cr(8, 2x1 subsampled)
> > +
> > +In AFBC, 'X' components are not treated any differently from any other
> > +component. Therefore, an AFBC buffer with fourcc DRM_FORMAT_XBGR8888
> > +encodes with 4 components, like so:
> > +
> > + * DRM_FORMAT_XBGR8888
> > +
> > + * Component 0: R(8)
> > + * Component 1: G(8)
> > + * Component 2: B(8)
> > + * Component 3: X(8)
> > +
> > +Please note, however, that the inclusion of a "wasted" 'X' channel is
> > +bad for compression efficiency, and so it's recommended to avoid
> > +formats containing 'X' bits. If a fourth component is
> > +required/expected by the encoder/decoder, then it is recommended to
> > +instead use an equivalent format with alpha, setting all alpha bits to
> > +'1'. If there is no requirement for a fourth component, then a format
> > +which doesn't include alpha can be used, e.g. DRM_FORMAT_BGR888.
> > +
> > +Number of Planes
> > +================
> > +
> > +Formats which are typically multi-planar in linear layouts (e.g. YUV
> > +420), can be encoded into one, or multiple, AFBC planes. As with
> > +component order, the encoder and decoder must agree about the number
> > +of planes in order to correctly decode the buffer. The fourcc code is
> > +used to determine the number of encoded planes in an AFBC buffer,
> > +matching the number of planes for the linear (unmodified) format.
> > +Within each plane, the component ordering also follows the fourcc
> > +code:
> > +
> > +For example:
> > +
> > + * DRM_FORMAT_YUYV: nplanes = 1
> > +
> > + * Plane 0:
> > +
> > + * Component 0: Y(8)
> > + * Component 1: Cb(8, 2x1 subsampled)
> > + * Component 2: Cr(8, 2x1 subsampled)
> > +
> > + * DRM_FORMAT_NV12: nplanes = 2
> > +
> > + * Plane 0:
> > +
> > + * Component 0: Y(8)
> > +
> > + * Plane 1:
> > +
> > + * Component 0: Cb(8, 2x1 subsampled)
> > + * Component 1: Cr(8, 2x1 subsampled)
> > +
> > +Cross-device interoperability
> > +=============================
> > +
> > +For maximum compatibility across devices, the table below defines
> > +canonical formats for use between AFBC-enabled devices. Formats which
> > +are listed here must be used exactly as specified when using the AFBC
> > +modifiers. Formats which are not listed should be avoided.
> > +
> > +.. flat-table:: AFBC formats
> > +
> > + * - Fourcc code
> > + - Description
> > + - Planes/Components
> > +
> > + * - DRM_FORMAT_ABGR2101010
> > + - 10-bit per component RGB, with 2-bit alpha
> > + - Plane 0: 4 components
> > + * Component 0: R(10)
> > + * Component 1: G(10)
> > + * Component 2: B(10)
> > + * Component 3: A(2)
> > +
> > + * - DRM_FORMAT_ABGR8888
> > + - 8-bit per component RGB, with 8-bit alpha
> > + - Plane 0: 4 components
> > + * Component 0: R(8)
> > + * Component 1: G(8)
> > + * Component 2: B(8)
> > + * Component 3: A(8)
> > +
> > + * - DRM_FORMAT_BGR888
> > + - 8-bit per component RGB
> > + - Plane 0: 3 components
> > + * Component 0: R(8)
> > + * Component 1: G(8)
> > + * Component 2: B(8)
> > +
> > + * - DRM_FORMAT_BGR565
> > + - 5/6-bit per component RGB
> > + - Plane 0: 3 components
> > + * Component 0: R(5)
> > + * Component 1: G(6)
> > + * Component 2: B(5)
> > +
> > + * - DRM_FORMAT_ABGR1555
> > + - 5-bit per component RGB, with 1-bit alpha
> > + - Plane 0: 4 components
> > + * Component 0: R(5)
> > + * Component 1: G(5)
> > + * Component 2: B(5)
> > + * Component 3: A(1)
> > +
> > + * - DRM_FORMAT_VUY888
> > + - 8-bit per component YCbCr 444, single plane
> > + - Plane 0: 3 components
> > + * Component 0: Y(8)
> > + * Component 1: Cb(8)
> > + * Component 2: Cr(8)
> > +
> > + * - DRM_FORMAT_VUY101010
> > + - 10-bit per component YCbCr 444, single plane
> > + - Plane 0: 3 components
> > + * Component 0: Y(10)
> > + * Component 1: Cb(10)
> > + * Component 2: Cr(10)
> > +
> > + * - DRM_FORMAT_YUYV
> > + - 8-bit per component YCbCr 422, single plane
> > + - Plane 0: 3 components
> > + * Component 0: Y(8)
> > + * Component 1: Cb(8, 2x1 subsampled)
> > + * Component 2: Cr(8, 2x1 subsampled)
> > +
> > + * - DRM_FORMAT_NV16
> > + - 8-bit per component YCbCr 422, two plane
> > + - Plane 0: 1 component
> > + * Component 0: Y(8)
> > + Plane 1: 2 components
> > + * Component 0: Cb(8, 2x1 subsampled)
> > + * Component 1: Cr(8, 2x1 subsampled)
> > +
> > + * - DRM_FORMAT_Y210
> > + - 10-bit per component YCbCr 422, single plane
> > + - Plane 0: 3 components
> > + * Component 0: Y(10)
> > + * Component 1: Cb(10, 2x1 subsampled)
> > + * Component 2: Cr(10, 2x1 subsampled)
> > +
> > + * - DRM_FORMAT_P210
> > + - 10-bit per component YCbCr 422, two plane
> > + - Plane 0: 1 component
> > + * Component 0: Y(10)
> > + Plane 1: 2 components
> > + * Component 0: Cb(10, 2x1 subsampled)
> > + * Component 1: Cr(10, 2x1 subsampled)
> > +
> > + * - DRM_FORMAT_YUV420_8BIT
> > + - 8-bit per component YCbCr 420, single plane
> > + - Plane 0: 3 components
> > + * Component 0: Y(8)
> > + * Component 1: Cb(8, 2x2 subsampled)
> > + * Component 2: Cr(8, 2x2 subsampled)
> > +
> > + * - DRM_FORMAT_YUV420_10BIT
> > + - 10-bit per component YCbCr 420, single plane
> > + - Plane 0: 3 components
> > + * Component 0: Y(10)
> > + * Component 1: Cb(10, 2x2 subsampled)
> > + * Component 2: Cr(10, 2x2 subsampled)
> > +
> > + * - DRM_FORMAT_NV12
> > + - 8-bit per component YCbCr 420, two plane
> > + - Plane 0: 1 component
> > + * Component 0: Y(8)
> > + Plane 1: 2 components
> > + * Component 0: Cb(8, 2x2 subsampled)
> > + * Component 1: Cr(8, 2x2 subsampled)
> > +
> > + * - DRM_FORMAT_P010
> > + - 10-bit per component YCbCr 420, two plane
> > + - Plane 0: 1 component
> > + * Component 0: Y(10)
> > + Plane 1: 2 components
> > + * Component 0: Cb(10, 2x2 subsampled)
> > + * Component 1: Cr(10, 2x2 subsampled)
> > diff --git a/Documentation/gpu/drivers.rst b/Documentation/gpu/drivers.rst
> > index 7c16721..c176b34 100644
> > --- a/Documentation/gpu/drivers.rst
> > +++ b/Documentation/gpu/drivers.rst
> > @@ -17,6 +17,7 @@ GPU Driver Documentation
> > vkms
> > bridge/dw-hdmi
> > xen-front
> > + afbc
> >
> > .. only:: subproject and html
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 254b7b2..aef18e3 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -1131,6 +1131,7 @@ M: Mali DP Maintainers <[email protected]>
> > S: Supported
> > F: drivers/gpu/drm/arm/
> > F: Documentation/devicetree/bindings/display/arm,malidp.txt
> > +F: Documentation/gpu/afbc.rst
> >
> > ARM MFM AND FLOPPY DRIVERS
> > M: Ian Molton <[email protected]>
> > diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
> > index 75c4b5a..0adde4d 100644
> > --- a/include/uapi/drm/drm_fourcc.h
> > +++ b/include/uapi/drm/drm_fourcc.h
> > @@ -597,6 +597,9 @@ extern "C" {
> > * AFBC has several features which may be supported and/or used, which are
> > * represented using bits in the modifier. Not all combinations are valid,
> > * and different devices or use-cases may support different combinations.
> > + *
> > + * Further information on the use of AFBC modifiers can be found in
> > + * Documentation/gpu/afbc.rst
> > */
> > #define DRM_FORMAT_MOD_ARM_AFBC(__afbc_mode) fourcc_mod_code(ARM, __afbc_mode)
> >
>
>
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
On Fri, 11 Jan 2019, Liviu Dudau <[email protected]> wrote:
> On Thu, Jan 03, 2019 at 05:44:26PM -0300, Ezequiel Garcia wrote:
>> Hi Liviu,
>>
>> On Mon, 2018-12-03 at 11:31 +0000, Ayan Halder wrote:
>> > From: Brian Starkey <[email protected]>
>> >
>> > AFBC is a flexible, proprietary, lossless compression protocol and
>> > format, with a number of defined DRM format modifiers. To facilitate
>> > consistency and compatibility between different AFBC producers and
>> > consumers, document the expectations for usage of the AFBC DRM format
>> > modifiers in a new .rst chapter.
>> >
>> > Signed-off-by: Brian Starkey <[email protected]>
>> > Reviewed-by: Liviu Dudau <[email protected]>
>> > ---
>>
>> I can't find this commit anywhere. Did you decide to reject
>> this or perhaps it just fell thru the cracks?
>
> Cracks have opened wide enough to let this through, sorry about that!
>
> I've now sent a pull request to get it merged.
Okay, so this is a very late comment, so feel free to ignore or,
perhaps, add a change on top.
Documentation/gpu mostly contains files that document high level stuff,
mostly one file per driver (with names matching the directories under
drivers/gpu/drm) or one file per drm core functional area.
Perhaps start an arm.rst, or at least name it more descriptively, say
arm-fbc.rst? Contrast msm-crash-dump.rst.
BR,
Jani.
>
> Best regards,
> Liviu
>
>>
>> Thanks!
>> Ezequiel
>>
>>
>> > Documentation/gpu/afbc.rst | 233 ++++++++++++++++++++++++++++++++++++++++++
>> > Documentation/gpu/drivers.rst | 1 +
>> > MAINTAINERS | 1 +
>> > include/uapi/drm/drm_fourcc.h | 3 +
>> > 4 files changed, 238 insertions(+)
>> > create mode 100644 Documentation/gpu/afbc.rst
>> >
>> > diff --git a/Documentation/gpu/afbc.rst b/Documentation/gpu/afbc.rst
>> > new file mode 100644
>> > index 0000000..922d955
>> > --- /dev/null
>> > +++ b/Documentation/gpu/afbc.rst
>> > @@ -0,0 +1,233 @@
>> > +===================================
>> > + Arm Framebuffer Compression (AFBC)
>> > +===================================
>> > +
>> > +AFBC is a proprietary lossless image compression protocol and format.
>> > +It provides fine-grained random access and minimizes the amount of
>> > +data transferred between IP blocks.
>> > +
>> > +AFBC can be enabled on drivers which support it via use of the AFBC
>> > +format modifiers defined in drm_fourcc.h. See DRM_FORMAT_MOD_ARM_AFBC(*).
>> > +
>> > +All users of the AFBC modifiers must follow the usage guidelines laid
>> > +out in this document, to ensure compatibility across different AFBC
>> > +producers and consumers.
>> > +
>> > +Components and Ordering
>> > +=======================
>> > +
>> > +AFBC streams can contain several components - where a component
>> > +corresponds to a color channel (i.e. R, G, B, X, A, Y, Cb, Cr).
>> > +The assignment of input/output color channels must be consistent
>> > +between the encoder and the decoder for correct operation, otherwise
>> > +the consumer will interpret the decoded data incorrectly.
>> > +
>> > +Furthermore, when the lossless colorspace transform is used
>> > +(AFBC_FORMAT_MOD_YTR, which should be enabled for RGB buffers for
>> > +maximum compression efficiency), the component order must be:
>> > +
>> > + * Component 0: R
>> > + * Component 1: G
>> > + * Component 2: B
>> > +
>> > +The component ordering is communicated via the fourcc code in the
>> > +fourcc:modifier pair. In general, component '0' is considered to
>> > +reside in the least-significant bits of the corresponding linear
>> > +format. For example, COMP(bits):
>> > +
>> > + * DRM_FORMAT_ABGR8888
>> > +
>> > + * Component 0: R(8)
>> > + * Component 1: G(8)
>> > + * Component 2: B(8)
>> > + * Component 3: A(8)
>> > +
>> > + * DRM_FORMAT_BGR888
>> > +
>> > + * Component 0: R(8)
>> > + * Component 1: G(8)
>> > + * Component 2: B(8)
>> > +
>> > + * DRM_FORMAT_YUYV
>> > +
>> > + * Component 0: Y(8)
>> > + * Component 1: Cb(8, 2x1 subsampled)
>> > + * Component 2: Cr(8, 2x1 subsampled)
>> > +
>> > +In AFBC, 'X' components are not treated any differently from any other
>> > +component. Therefore, an AFBC buffer with fourcc DRM_FORMAT_XBGR8888
>> > +encodes with 4 components, like so:
>> > +
>> > + * DRM_FORMAT_XBGR8888
>> > +
>> > + * Component 0: R(8)
>> > + * Component 1: G(8)
>> > + * Component 2: B(8)
>> > + * Component 3: X(8)
>> > +
>> > +Please note, however, that the inclusion of a "wasted" 'X' channel is
>> > +bad for compression efficiency, and so it's recommended to avoid
>> > +formats containing 'X' bits. If a fourth component is
>> > +required/expected by the encoder/decoder, then it is recommended to
>> > +instead use an equivalent format with alpha, setting all alpha bits to
>> > +'1'. If there is no requirement for a fourth component, then a format
>> > +which doesn't include alpha can be used, e.g. DRM_FORMAT_BGR888.
>> > +
>> > +Number of Planes
>> > +================
>> > +
>> > +Formats which are typically multi-planar in linear layouts (e.g. YUV
>> > +420), can be encoded into one, or multiple, AFBC planes. As with
>> > +component order, the encoder and decoder must agree about the number
>> > +of planes in order to correctly decode the buffer. The fourcc code is
>> > +used to determine the number of encoded planes in an AFBC buffer,
>> > +matching the number of planes for the linear (unmodified) format.
>> > +Within each plane, the component ordering also follows the fourcc
>> > +code:
>> > +
>> > +For example:
>> > +
>> > + * DRM_FORMAT_YUYV: nplanes = 1
>> > +
>> > + * Plane 0:
>> > +
>> > + * Component 0: Y(8)
>> > + * Component 1: Cb(8, 2x1 subsampled)
>> > + * Component 2: Cr(8, 2x1 subsampled)
>> > +
>> > + * DRM_FORMAT_NV12: nplanes = 2
>> > +
>> > + * Plane 0:
>> > +
>> > + * Component 0: Y(8)
>> > +
>> > + * Plane 1:
>> > +
>> > + * Component 0: Cb(8, 2x1 subsampled)
>> > + * Component 1: Cr(8, 2x1 subsampled)
>> > +
>> > +Cross-device interoperability
>> > +=============================
>> > +
>> > +For maximum compatibility across devices, the table below defines
>> > +canonical formats for use between AFBC-enabled devices. Formats which
>> > +are listed here must be used exactly as specified when using the AFBC
>> > +modifiers. Formats which are not listed should be avoided.
>> > +
>> > +.. flat-table:: AFBC formats
>> > +
>> > + * - Fourcc code
>> > + - Description
>> > + - Planes/Components
>> > +
>> > + * - DRM_FORMAT_ABGR2101010
>> > + - 10-bit per component RGB, with 2-bit alpha
>> > + - Plane 0: 4 components
>> > + * Component 0: R(10)
>> > + * Component 1: G(10)
>> > + * Component 2: B(10)
>> > + * Component 3: A(2)
>> > +
>> > + * - DRM_FORMAT_ABGR8888
>> > + - 8-bit per component RGB, with 8-bit alpha
>> > + - Plane 0: 4 components
>> > + * Component 0: R(8)
>> > + * Component 1: G(8)
>> > + * Component 2: B(8)
>> > + * Component 3: A(8)
>> > +
>> > + * - DRM_FORMAT_BGR888
>> > + - 8-bit per component RGB
>> > + - Plane 0: 3 components
>> > + * Component 0: R(8)
>> > + * Component 1: G(8)
>> > + * Component 2: B(8)
>> > +
>> > + * - DRM_FORMAT_BGR565
>> > + - 5/6-bit per component RGB
>> > + - Plane 0: 3 components
>> > + * Component 0: R(5)
>> > + * Component 1: G(6)
>> > + * Component 2: B(5)
>> > +
>> > + * - DRM_FORMAT_ABGR1555
>> > + - 5-bit per component RGB, with 1-bit alpha
>> > + - Plane 0: 4 components
>> > + * Component 0: R(5)
>> > + * Component 1: G(5)
>> > + * Component 2: B(5)
>> > + * Component 3: A(1)
>> > +
>> > + * - DRM_FORMAT_VUY888
>> > + - 8-bit per component YCbCr 444, single plane
>> > + - Plane 0: 3 components
>> > + * Component 0: Y(8)
>> > + * Component 1: Cb(8)
>> > + * Component 2: Cr(8)
>> > +
>> > + * - DRM_FORMAT_VUY101010
>> > + - 10-bit per component YCbCr 444, single plane
>> > + - Plane 0: 3 components
>> > + * Component 0: Y(10)
>> > + * Component 1: Cb(10)
>> > + * Component 2: Cr(10)
>> > +
>> > + * - DRM_FORMAT_YUYV
>> > + - 8-bit per component YCbCr 422, single plane
>> > + - Plane 0: 3 components
>> > + * Component 0: Y(8)
>> > + * Component 1: Cb(8, 2x1 subsampled)
>> > + * Component 2: Cr(8, 2x1 subsampled)
>> > +
>> > + * - DRM_FORMAT_NV16
>> > + - 8-bit per component YCbCr 422, two plane
>> > + - Plane 0: 1 component
>> > + * Component 0: Y(8)
>> > + Plane 1: 2 components
>> > + * Component 0: Cb(8, 2x1 subsampled)
>> > + * Component 1: Cr(8, 2x1 subsampled)
>> > +
>> > + * - DRM_FORMAT_Y210
>> > + - 10-bit per component YCbCr 422, single plane
>> > + - Plane 0: 3 components
>> > + * Component 0: Y(10)
>> > + * Component 1: Cb(10, 2x1 subsampled)
>> > + * Component 2: Cr(10, 2x1 subsampled)
>> > +
>> > + * - DRM_FORMAT_P210
>> > + - 10-bit per component YCbCr 422, two plane
>> > + - Plane 0: 1 component
>> > + * Component 0: Y(10)
>> > + Plane 1: 2 components
>> > + * Component 0: Cb(10, 2x1 subsampled)
>> > + * Component 1: Cr(10, 2x1 subsampled)
>> > +
>> > + * - DRM_FORMAT_YUV420_8BIT
>> > + - 8-bit per component YCbCr 420, single plane
>> > + - Plane 0: 3 components
>> > + * Component 0: Y(8)
>> > + * Component 1: Cb(8, 2x2 subsampled)
>> > + * Component 2: Cr(8, 2x2 subsampled)
>> > +
>> > + * - DRM_FORMAT_YUV420_10BIT
>> > + - 10-bit per component YCbCr 420, single plane
>> > + - Plane 0: 3 components
>> > + * Component 0: Y(10)
>> > + * Component 1: Cb(10, 2x2 subsampled)
>> > + * Component 2: Cr(10, 2x2 subsampled)
>> > +
>> > + * - DRM_FORMAT_NV12
>> > + - 8-bit per component YCbCr 420, two plane
>> > + - Plane 0: 1 component
>> > + * Component 0: Y(8)
>> > + Plane 1: 2 components
>> > + * Component 0: Cb(8, 2x2 subsampled)
>> > + * Component 1: Cr(8, 2x2 subsampled)
>> > +
>> > + * - DRM_FORMAT_P010
>> > + - 10-bit per component YCbCr 420, two plane
>> > + - Plane 0: 1 component
>> > + * Component 0: Y(10)
>> > + Plane 1: 2 components
>> > + * Component 0: Cb(10, 2x2 subsampled)
>> > + * Component 1: Cr(10, 2x2 subsampled)
>> > diff --git a/Documentation/gpu/drivers.rst b/Documentation/gpu/drivers.rst
>> > index 7c16721..c176b34 100644
>> > --- a/Documentation/gpu/drivers.rst
>> > +++ b/Documentation/gpu/drivers.rst
>> > @@ -17,6 +17,7 @@ GPU Driver Documentation
>> > vkms
>> > bridge/dw-hdmi
>> > xen-front
>> > + afbc
>> >
>> > .. only:: subproject and html
>> >
>> > diff --git a/MAINTAINERS b/MAINTAINERS
>> > index 254b7b2..aef18e3 100644
>> > --- a/MAINTAINERS
>> > +++ b/MAINTAINERS
>> > @@ -1131,6 +1131,7 @@ M: Mali DP Maintainers <[email protected]>
>> > S: Supported
>> > F: drivers/gpu/drm/arm/
>> > F: Documentation/devicetree/bindings/display/arm,malidp.txt
>> > +F: Documentation/gpu/afbc.rst
>> >
>> > ARM MFM AND FLOPPY DRIVERS
>> > M: Ian Molton <[email protected]>
>> > diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
>> > index 75c4b5a..0adde4d 100644
>> > --- a/include/uapi/drm/drm_fourcc.h
>> > +++ b/include/uapi/drm/drm_fourcc.h
>> > @@ -597,6 +597,9 @@ extern "C" {
>> > * AFBC has several features which may be supported and/or used, which are
>> > * represented using bits in the modifier. Not all combinations are valid,
>> > * and different devices or use-cases may support different combinations.
>> > + *
>> > + * Further information on the use of AFBC modifiers can be found in
>> > + * Documentation/gpu/afbc.rst
>> > */
>> > #define DRM_FORMAT_MOD_ARM_AFBC(__afbc_mode) fourcc_mod_code(ARM, __afbc_mode)
>> >
>>
>>
--
Jani Nikula, Intel Open Source Graphics Center
Hi Jani,
On Mon, Jan 14, 2019 at 02:23:46PM +0200, Jani Nikula wrote:
> On Fri, 11 Jan 2019, Liviu Dudau <[email protected]> wrote:
> > On Thu, Jan 03, 2019 at 05:44:26PM -0300, Ezequiel Garcia wrote:
> >> Hi Liviu,
> >>
> >> On Mon, 2018-12-03 at 11:31 +0000, Ayan Halder wrote:
> >> > From: Brian Starkey <[email protected]>
> >> >
> >> > AFBC is a flexible, proprietary, lossless compression protocol and
> >> > format, with a number of defined DRM format modifiers. To facilitate
> >> > consistency and compatibility between different AFBC producers and
> >> > consumers, document the expectations for usage of the AFBC DRM format
> >> > modifiers in a new .rst chapter.
> >> >
> >> > Signed-off-by: Brian Starkey <[email protected]>
> >> > Reviewed-by: Liviu Dudau <[email protected]>
> >> > ---
> >>
> >> I can't find this commit anywhere. Did you decide to reject
> >> this or perhaps it just fell thru the cracks?
> >
> > Cracks have opened wide enough to let this through, sorry about that!
> >
> > I've now sent a pull request to get it merged.
>
> Okay, so this is a very late comment, so feel free to ignore or,
> perhaps, add a change on top.
>
> Documentation/gpu mostly contains files that document high level stuff,
> mostly one file per driver (with names matching the directories under
> drivers/gpu/drm) or one file per drm core functional area.
>
> Perhaps start an arm.rst, or at least name it more descriptively, say
> arm-fbc.rst? Contrast msm-crash-dump.rst.
I did deliberately put it at the top-level, as AFBC is implemented by
IPs from many different vendors. The intention of this file is to try
and ensure interop between those different vendors' drivers. I fear
that if we namespace it 'arm' then it will be regarded as
Arm-specific, whereas it's meant to set the standard for the AFBC
implementations in all vendors' DRM drivers. That only applies if they
use the AFBC modifiers Arm has defined, but IMO that's what we should
be pushing for instead of having each vendor define their own local
AFBC modifiers, because that will make interop a nightmare. The Arm
definitions should cover all conformant implementations.
AFBC is a relatively well-established name, whereas arm-fbc is not a
term anyone will be familiar with. We could name the file
"arm-afbc.rst", though I am slightly against namespacing it that way
for the reason mentioned above - it does/will/should apply to more
than just the gpu/drm/arm tree.
Best regards,
-Brian
>
> BR,
> Jani.
>
>
> >
> > Best regards,
> > Liviu
> >
> >>
> >> Thanks!
> >> Ezequiel
> >>
> >>
> >> > Documentation/gpu/afbc.rst | 233 ++++++++++++++++++++++++++++++++++++++++++
> >> > Documentation/gpu/drivers.rst | 1 +
> >> > MAINTAINERS | 1 +
> >> > include/uapi/drm/drm_fourcc.h | 3 +
> >> > 4 files changed, 238 insertions(+)
> >> > create mode 100644 Documentation/gpu/afbc.rst
> >> >
> >> > diff --git a/Documentation/gpu/afbc.rst b/Documentation/gpu/afbc.rst
> >> > new file mode 100644
> >> > index 0000000..922d955
> >> > --- /dev/null
> >> > +++ b/Documentation/gpu/afbc.rst
> >> > @@ -0,0 +1,233 @@
> >> > +===================================
> >> > + Arm Framebuffer Compression (AFBC)
> >> > +===================================
> >> > +
> >> > +AFBC is a proprietary lossless image compression protocol and format.
> >> > +It provides fine-grained random access and minimizes the amount of
> >> > +data transferred between IP blocks.
> >> > +
> >> > +AFBC can be enabled on drivers which support it via use of the AFBC
> >> > +format modifiers defined in drm_fourcc.h. See DRM_FORMAT_MOD_ARM_AFBC(*).
> >> > +
> >> > +All users of the AFBC modifiers must follow the usage guidelines laid
> >> > +out in this document, to ensure compatibility across different AFBC
> >> > +producers and consumers.
> >> > +
> >> > +Components and Ordering
> >> > +=======================
> >> > +
> >> > +AFBC streams can contain several components - where a component
> >> > +corresponds to a color channel (i.e. R, G, B, X, A, Y, Cb, Cr).
> >> > +The assignment of input/output color channels must be consistent
> >> > +between the encoder and the decoder for correct operation, otherwise
> >> > +the consumer will interpret the decoded data incorrectly.
> >> > +
> >> > +Furthermore, when the lossless colorspace transform is used
> >> > +(AFBC_FORMAT_MOD_YTR, which should be enabled for RGB buffers for
> >> > +maximum compression efficiency), the component order must be:
> >> > +
> >> > + * Component 0: R
> >> > + * Component 1: G
> >> > + * Component 2: B
> >> > +
> >> > +The component ordering is communicated via the fourcc code in the
> >> > +fourcc:modifier pair. In general, component '0' is considered to
> >> > +reside in the least-significant bits of the corresponding linear
> >> > +format. For example, COMP(bits):
> >> > +
> >> > + * DRM_FORMAT_ABGR8888
> >> > +
> >> > + * Component 0: R(8)
> >> > + * Component 1: G(8)
> >> > + * Component 2: B(8)
> >> > + * Component 3: A(8)
> >> > +
> >> > + * DRM_FORMAT_BGR888
> >> > +
> >> > + * Component 0: R(8)
> >> > + * Component 1: G(8)
> >> > + * Component 2: B(8)
> >> > +
> >> > + * DRM_FORMAT_YUYV
> >> > +
> >> > + * Component 0: Y(8)
> >> > + * Component 1: Cb(8, 2x1 subsampled)
> >> > + * Component 2: Cr(8, 2x1 subsampled)
> >> > +
> >> > +In AFBC, 'X' components are not treated any differently from any other
> >> > +component. Therefore, an AFBC buffer with fourcc DRM_FORMAT_XBGR8888
> >> > +encodes with 4 components, like so:
> >> > +
> >> > + * DRM_FORMAT_XBGR8888
> >> > +
> >> > + * Component 0: R(8)
> >> > + * Component 1: G(8)
> >> > + * Component 2: B(8)
> >> > + * Component 3: X(8)
> >> > +
> >> > +Please note, however, that the inclusion of a "wasted" 'X' channel is
> >> > +bad for compression efficiency, and so it's recommended to avoid
> >> > +formats containing 'X' bits. If a fourth component is
> >> > +required/expected by the encoder/decoder, then it is recommended to
> >> > +instead use an equivalent format with alpha, setting all alpha bits to
> >> > +'1'. If there is no requirement for a fourth component, then a format
> >> > +which doesn't include alpha can be used, e.g. DRM_FORMAT_BGR888.
> >> > +
> >> > +Number of Planes
> >> > +================
> >> > +
> >> > +Formats which are typically multi-planar in linear layouts (e.g. YUV
> >> > +420), can be encoded into one, or multiple, AFBC planes. As with
> >> > +component order, the encoder and decoder must agree about the number
> >> > +of planes in order to correctly decode the buffer. The fourcc code is
> >> > +used to determine the number of encoded planes in an AFBC buffer,
> >> > +matching the number of planes for the linear (unmodified) format.
> >> > +Within each plane, the component ordering also follows the fourcc
> >> > +code:
> >> > +
> >> > +For example:
> >> > +
> >> > + * DRM_FORMAT_YUYV: nplanes = 1
> >> > +
> >> > + * Plane 0:
> >> > +
> >> > + * Component 0: Y(8)
> >> > + * Component 1: Cb(8, 2x1 subsampled)
> >> > + * Component 2: Cr(8, 2x1 subsampled)
> >> > +
> >> > + * DRM_FORMAT_NV12: nplanes = 2
> >> > +
> >> > + * Plane 0:
> >> > +
> >> > + * Component 0: Y(8)
> >> > +
> >> > + * Plane 1:
> >> > +
> >> > + * Component 0: Cb(8, 2x1 subsampled)
> >> > + * Component 1: Cr(8, 2x1 subsampled)
> >> > +
> >> > +Cross-device interoperability
> >> > +=============================
> >> > +
> >> > +For maximum compatibility across devices, the table below defines
> >> > +canonical formats for use between AFBC-enabled devices. Formats which
> >> > +are listed here must be used exactly as specified when using the AFBC
> >> > +modifiers. Formats which are not listed should be avoided.
> >> > +
> >> > +.. flat-table:: AFBC formats
> >> > +
> >> > + * - Fourcc code
> >> > + - Description
> >> > + - Planes/Components
> >> > +
> >> > + * - DRM_FORMAT_ABGR2101010
> >> > + - 10-bit per component RGB, with 2-bit alpha
> >> > + - Plane 0: 4 components
> >> > + * Component 0: R(10)
> >> > + * Component 1: G(10)
> >> > + * Component 2: B(10)
> >> > + * Component 3: A(2)
> >> > +
> >> > + * - DRM_FORMAT_ABGR8888
> >> > + - 8-bit per component RGB, with 8-bit alpha
> >> > + - Plane 0: 4 components
> >> > + * Component 0: R(8)
> >> > + * Component 1: G(8)
> >> > + * Component 2: B(8)
> >> > + * Component 3: A(8)
> >> > +
> >> > + * - DRM_FORMAT_BGR888
> >> > + - 8-bit per component RGB
> >> > + - Plane 0: 3 components
> >> > + * Component 0: R(8)
> >> > + * Component 1: G(8)
> >> > + * Component 2: B(8)
> >> > +
> >> > + * - DRM_FORMAT_BGR565
> >> > + - 5/6-bit per component RGB
> >> > + - Plane 0: 3 components
> >> > + * Component 0: R(5)
> >> > + * Component 1: G(6)
> >> > + * Component 2: B(5)
> >> > +
> >> > + * - DRM_FORMAT_ABGR1555
> >> > + - 5-bit per component RGB, with 1-bit alpha
> >> > + - Plane 0: 4 components
> >> > + * Component 0: R(5)
> >> > + * Component 1: G(5)
> >> > + * Component 2: B(5)
> >> > + * Component 3: A(1)
> >> > +
> >> > + * - DRM_FORMAT_VUY888
> >> > + - 8-bit per component YCbCr 444, single plane
> >> > + - Plane 0: 3 components
> >> > + * Component 0: Y(8)
> >> > + * Component 1: Cb(8)
> >> > + * Component 2: Cr(8)
> >> > +
> >> > + * - DRM_FORMAT_VUY101010
> >> > + - 10-bit per component YCbCr 444, single plane
> >> > + - Plane 0: 3 components
> >> > + * Component 0: Y(10)
> >> > + * Component 1: Cb(10)
> >> > + * Component 2: Cr(10)
> >> > +
> >> > + * - DRM_FORMAT_YUYV
> >> > + - 8-bit per component YCbCr 422, single plane
> >> > + - Plane 0: 3 components
> >> > + * Component 0: Y(8)
> >> > + * Component 1: Cb(8, 2x1 subsampled)
> >> > + * Component 2: Cr(8, 2x1 subsampled)
> >> > +
> >> > + * - DRM_FORMAT_NV16
> >> > + - 8-bit per component YCbCr 422, two plane
> >> > + - Plane 0: 1 component
> >> > + * Component 0: Y(8)
> >> > + Plane 1: 2 components
> >> > + * Component 0: Cb(8, 2x1 subsampled)
> >> > + * Component 1: Cr(8, 2x1 subsampled)
> >> > +
> >> > + * - DRM_FORMAT_Y210
> >> > + - 10-bit per component YCbCr 422, single plane
> >> > + - Plane 0: 3 components
> >> > + * Component 0: Y(10)
> >> > + * Component 1: Cb(10, 2x1 subsampled)
> >> > + * Component 2: Cr(10, 2x1 subsampled)
> >> > +
> >> > + * - DRM_FORMAT_P210
> >> > + - 10-bit per component YCbCr 422, two plane
> >> > + - Plane 0: 1 component
> >> > + * Component 0: Y(10)
> >> > + Plane 1: 2 components
> >> > + * Component 0: Cb(10, 2x1 subsampled)
> >> > + * Component 1: Cr(10, 2x1 subsampled)
> >> > +
> >> > + * - DRM_FORMAT_YUV420_8BIT
> >> > + - 8-bit per component YCbCr 420, single plane
> >> > + - Plane 0: 3 components
> >> > + * Component 0: Y(8)
> >> > + * Component 1: Cb(8, 2x2 subsampled)
> >> > + * Component 2: Cr(8, 2x2 subsampled)
> >> > +
> >> > + * - DRM_FORMAT_YUV420_10BIT
> >> > + - 10-bit per component YCbCr 420, single plane
> >> > + - Plane 0: 3 components
> >> > + * Component 0: Y(10)
> >> > + * Component 1: Cb(10, 2x2 subsampled)
> >> > + * Component 2: Cr(10, 2x2 subsampled)
> >> > +
> >> > + * - DRM_FORMAT_NV12
> >> > + - 8-bit per component YCbCr 420, two plane
> >> > + - Plane 0: 1 component
> >> > + * Component 0: Y(8)
> >> > + Plane 1: 2 components
> >> > + * Component 0: Cb(8, 2x2 subsampled)
> >> > + * Component 1: Cr(8, 2x2 subsampled)
> >> > +
> >> > + * - DRM_FORMAT_P010
> >> > + - 10-bit per component YCbCr 420, two plane
> >> > + - Plane 0: 1 component
> >> > + * Component 0: Y(10)
> >> > + Plane 1: 2 components
> >> > + * Component 0: Cb(10, 2x2 subsampled)
> >> > + * Component 1: Cr(10, 2x2 subsampled)
> >> > diff --git a/Documentation/gpu/drivers.rst b/Documentation/gpu/drivers.rst
> >> > index 7c16721..c176b34 100644
> >> > --- a/Documentation/gpu/drivers.rst
> >> > +++ b/Documentation/gpu/drivers.rst
> >> > @@ -17,6 +17,7 @@ GPU Driver Documentation
> >> > vkms
> >> > bridge/dw-hdmi
> >> > xen-front
> >> > + afbc
> >> >
> >> > .. only:: subproject and html
> >> >
> >> > diff --git a/MAINTAINERS b/MAINTAINERS
> >> > index 254b7b2..aef18e3 100644
> >> > --- a/MAINTAINERS
> >> > +++ b/MAINTAINERS
> >> > @@ -1131,6 +1131,7 @@ M: Mali DP Maintainers <[email protected]>
> >> > S: Supported
> >> > F: drivers/gpu/drm/arm/
> >> > F: Documentation/devicetree/bindings/display/arm,malidp.txt
> >> > +F: Documentation/gpu/afbc.rst
> >> >
> >> > ARM MFM AND FLOPPY DRIVERS
> >> > M: Ian Molton <[email protected]>
> >> > diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
> >> > index 75c4b5a..0adde4d 100644
> >> > --- a/include/uapi/drm/drm_fourcc.h
> >> > +++ b/include/uapi/drm/drm_fourcc.h
> >> > @@ -597,6 +597,9 @@ extern "C" {
> >> > * AFBC has several features which may be supported and/or used, which are
> >> > * represented using bits in the modifier. Not all combinations are valid,
> >> > * and different devices or use-cases may support different combinations.
> >> > + *
> >> > + * Further information on the use of AFBC modifiers can be found in
> >> > + * Documentation/gpu/afbc.rst
> >> > */
> >> > #define DRM_FORMAT_MOD_ARM_AFBC(__afbc_mode) fourcc_mod_code(ARM, __afbc_mode)
> >> >
> >>
> >>
>
> --
> Jani Nikula, Intel Open Source Graphics Center
On Mon, 14 Jan 2019, Brian Starkey <[email protected]> wrote:
> AFBC is a relatively well-established name, whereas arm-fbc is not a
> term anyone will be familiar with.
First time I ever heard of AFBC. ;)
> We could name the file "arm-afbc.rst", though I am slightly against
> namespacing it that way for the reason mentioned above - it
> does/will/should apply to more than just the gpu/drm/arm tree.
Fair enough. It's not like the name is part of the ABI, so I guess let's
go with this, and we can rename later if we come up with a better name.
BR,
Jani.
--
Jani Nikula, Intel Open Source Graphics Center