summaryrefslogtreecommitdiff
path: root/mediatek.c
diff options
context:
space:
mode:
Diffstat (limited to 'mediatek.c')
-rw-r--r--mediatek.c140
1 files changed, 111 insertions, 29 deletions
diff --git a/mediatek.c b/mediatek.c
index de492e2..562b1d1 100644
--- a/mediatek.c
+++ b/mediatek.c
@@ -19,12 +19,23 @@
#include <mediatek_drm.h>
// clang-format on
+#include "drv_helpers.h"
#include "drv_priv.h"
-#include "helpers.h"
#include "util.h"
#define TILE_TYPE_LINEAR 0
+#if defined(MTK_MT8183) || defined(MTK_MT8186)
+#define SUPPORTS_YUV422_AND_HIGH_BIT_DEPTH_TEXTURING
+#endif
+
+// All platforms except MT8173 should USE_NV12_FOR_HW_VIDEO_DECODING.
+#if defined(MTK_MT8183) || defined(MTK_MT8186) || defined(MTK_MT8192) || defined(MTK_MT8195)
+#define USE_NV12_FOR_HW_VIDEO_DECODING
+#else
+#define DONT_USE_64_ALIGNMENT_FOR_VIDEO_BUFFERS
+#endif
+
struct mediatek_private_map_data {
void *cached_addr;
void *gem_addr;
@@ -35,14 +46,36 @@ static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMA
DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888,
DRM_FORMAT_XRGB8888 };
-#ifdef MTK_MT8183
-static const uint32_t texture_source_formats[] = { DRM_FORMAT_NV21, DRM_FORMAT_NV12,
- DRM_FORMAT_YUYV, DRM_FORMAT_YVU420,
- DRM_FORMAT_YVU420_ANDROID };
-#else
-static const uint32_t texture_source_formats[] = { DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID,
- DRM_FORMAT_NV12 };
+// clang-format off
+static const uint32_t texture_source_formats[] = {
+#ifdef SUPPORTS_YUV422_AND_HIGH_BIT_DEPTH_TEXTURING
+ DRM_FORMAT_NV21,
+ DRM_FORMAT_YUYV,
+ DRM_FORMAT_ABGR2101010,
+ DRM_FORMAT_ABGR16161616F,
#endif
+ DRM_FORMAT_NV12,
+ DRM_FORMAT_YVU420,
+ DRM_FORMAT_YVU420_ANDROID
+};
+
+static const uint32_t video_yuv_formats[] = {
+ DRM_FORMAT_NV21,
+ DRM_FORMAT_NV12,
+ DRM_FORMAT_YVU420,
+ DRM_FORMAT_YVU420_ANDROID
+};
+// clang-format on
+
+static bool is_video_yuv_format(uint32_t format)
+{
+ size_t i;
+ for (i = 0; i < ARRAY_SIZE(video_yuv_formats); ++i) {
+ if (format == video_yuv_formats[i])
+ return true;
+ }
+ return false;
+}
static int mediatek_init(struct driver *drv)
{
@@ -65,7 +98,7 @@ static int mediatek_init(struct driver *drv)
metadata.modifier = DRM_FORMAT_MOD_LINEAR;
drv_modify_combination(drv, DRM_FORMAT_YVU420, &metadata, BO_USE_HW_VIDEO_DECODER);
drv_modify_combination(drv, DRM_FORMAT_YVU420_ANDROID, &metadata, BO_USE_HW_VIDEO_DECODER);
-#if defined(MTK_MT8183) || defined(MTK_MT8192) || defined(MTK_MT8195)
+#ifdef USE_NV12_FOR_HW_VIDEO_DECODING
// TODO(hiroh): Switch to use NV12 for video decoder on MT8173 as well.
drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata, BO_USE_HW_VIDEO_DECODER);
#endif
@@ -107,6 +140,12 @@ static int mediatek_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint
size_t plane;
uint32_t stride;
struct drm_mtk_gem_create gem_create = { 0 };
+ /*
+ * We identify the ChromeOS Camera App buffers via these two USE flags. Those buffers need
+ * the same alignment as the video hardware encoding.
+ */
+ const bool is_camera_preview =
+ (bo->meta.use_flags & BO_USE_SCANOUT) && (bo->meta.use_flags & BO_USE_CAMERA_WRITE);
if (!drv_has_modifier(modifiers, count, DRM_FORMAT_MOD_LINEAR)) {
errno = EINVAL;
@@ -116,12 +155,19 @@ static int mediatek_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint
/*
* Since the ARM L1 cache line size is 64 bytes, align to that as a
- * performance optimization.
+ * performance optimization, except for video buffers on certain platforms,
+ * these should only be accessed from the GPU and VCODEC subsystems (maybe
+ * also MDP), so it's better to align to macroblocks.
*/
stride = drv_stride_from_format(format, width, 0);
+#ifdef DONT_USE_64_ALIGNMENT_FOR_VIDEO_BUFFERS
+ const uint32_t alignment = is_video_yuv_format(format) ? 16 : 64;
+ stride = ALIGN(stride, alignment);
+#else
stride = ALIGN(stride, 64);
+#endif
- if (bo->meta.use_flags & BO_USE_HW_VIDEO_ENCODER) {
+ if ((bo->meta.use_flags & BO_USE_HW_VIDEO_ENCODER) || is_camera_preview) {
uint32_t aligned_height = ALIGN(height, 32);
uint32_t padding[DRV_MAX_PLANES] = { 0 };
@@ -133,7 +179,7 @@ static int mediatek_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint
drv_bo_from_format_and_padding(bo, stride, aligned_height, format, padding);
} else {
-#ifdef MTK_MT8183
+#ifdef SUPPORTS_YUV422_AND_HIGH_BIT_DEPTH_TEXTURING
/*
* JPEG Encoder Accelerator requires 16x16 alignment. We want the buffer
* from camera can be put in JEA directly so align the height to 16
@@ -172,6 +218,7 @@ static void *mediatek_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint3
int ret, prime_fd;
struct drm_mtk_gem_map_off gem_map = { 0 };
struct mediatek_private_map_data *priv;
+ void *addr = NULL;
gem_map.handle = bo->handles[0].u32;
@@ -187,22 +234,38 @@ static void *mediatek_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint3
return MAP_FAILED;
}
- void *addr = mmap(0, bo->meta.total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd,
- gem_map.offset);
+ addr = mmap(0, bo->meta.total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd,
+ gem_map.offset);
+ if (addr == MAP_FAILED)
+ goto out_close_prime_fd;
vma->length = bo->meta.total_size;
priv = calloc(1, sizeof(*priv));
- priv->prime_fd = prime_fd;
- vma->priv = priv;
+ if (!priv)
+ goto out_unmap_addr;
if (bo->meta.use_flags & BO_USE_RENDERSCRIPT) {
priv->cached_addr = calloc(1, bo->meta.total_size);
+ if (!priv->cached_addr)
+ goto out_free_priv;
+
priv->gem_addr = addr;
addr = priv->cached_addr;
}
+ priv->prime_fd = prime_fd;
+ vma->priv = priv;
+
return addr;
+
+out_free_priv:
+ free(priv);
+out_unmap_addr:
+ munmap(addr, bo->meta.total_size);
+out_close_prime_fd:
+ close(prime_fd);
+ return MAP_FAILED;
}
static int mediatek_bo_unmap(struct bo *bo, struct vma *vma)
@@ -258,37 +321,56 @@ static int mediatek_bo_flush(struct bo *bo, struct mapping *mapping)
return 0;
}
-static uint32_t mediatek_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags)
+static void mediatek_resolve_format_and_use_flags(struct driver *drv, uint32_t format,
+ uint64_t use_flags, uint32_t *out_format,
+ uint64_t *out_use_flags)
{
+ *out_format = format;
+ *out_use_flags = use_flags;
switch (format) {
case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
#ifdef MTK_MT8183
/* Only MT8183 Camera subsystem offers private reprocessing
* capability. CAMERA_READ indicates the buffer is intended for
* reprocessing and hence given the private format for MTK. */
- if (use_flags & BO_USE_CAMERA_READ)
- return DRM_FORMAT_MTISP_SXYZW10;
+ if (use_flags & BO_USE_CAMERA_READ) {
+ *out_format = DRM_FORMAT_MTISP_SXYZW10;
+ break;
+ }
#endif
- if (use_flags & BO_USE_CAMERA_WRITE)
- return DRM_FORMAT_NV12;
+ if (use_flags & BO_USE_CAMERA_WRITE) {
+ *out_format = DRM_FORMAT_NV12;
+ break;
+ }
- /*HACK: See b/28671744 */
- return DRM_FORMAT_XBGR8888;
+ /* HACK: See b/28671744 */
+ *out_format = DRM_FORMAT_XBGR8888;
+ *out_use_flags &= ~BO_USE_HW_VIDEO_ENCODER;
+ break;
case DRM_FORMAT_FLEX_YCbCr_420_888:
-#if defined(MTK_MT8183) || defined(MTK_MT8192) || defined(MTK_MT8195)
+#ifdef USE_NV12_FOR_HW_VIDEO_DECODING
// TODO(hiroh): Switch to use NV12 for video decoder on MT8173 as well.
if (use_flags & (BO_USE_HW_VIDEO_DECODER)) {
- return DRM_FORMAT_NV12;
+ *out_format = DRM_FORMAT_NV12;
+ break;
}
#endif
if (use_flags &
(BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_ENCODER)) {
- return DRM_FORMAT_NV12;
+ *out_format = DRM_FORMAT_NV12;
+ break;
}
- return DRM_FORMAT_YVU420;
+
+ /* HACK: See b/139714614 */
+ *out_format = DRM_FORMAT_YVU420;
+ *out_use_flags &= ~BO_USE_SCANOUT;
+ break;
default:
- return format;
+ break;
}
+ /* Mediatek doesn't support YUV overlays */
+ if (is_video_yuv_format(format))
+ *out_use_flags &= ~BO_USE_SCANOUT;
}
const struct backend backend_mediatek = {
@@ -302,7 +384,7 @@ const struct backend backend_mediatek = {
.bo_unmap = mediatek_bo_unmap,
.bo_invalidate = mediatek_bo_invalidate,
.bo_flush = mediatek_bo_flush,
- .resolve_format = mediatek_resolve_format,
+ .resolve_format_and_use_flags = mediatek_resolve_format_and_use_flags,
};
#endif