Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit be55dab2 authored by abeykun's avatar abeykun Committed by Gerrit - the friendly Code Review server
Browse files

drm/msm/sde: add p010 format support in sde



Add MOD_QCOM_DX modifier on top of DRM_FORMAT_NV12
base format and update plane size calculation to support
linear and compressed p010 buffers.

Change-Id: I93bd9557e5c4a4a038891f24730edbbec1dba262
Signed-off-by: default avatarAlexander Beykun <abeykun@codeaurora.org>
parent 6f56b2a9
Loading
Loading
Loading
Loading
+136 −75
Original line number Diff line number Diff line
@@ -11,12 +11,15 @@
 */

#include <uapi/drm/drm_fourcc.h>
#include <uapi/media/msm_media_info.h>

#include "sde_kms.h"
#include "sde_formats.h"

#define SDE_UBWC_META_MACRO_W_H		16
#define SDE_UBWC_META_BLOCK_SIZE	256
#define SDE_UBWC_PLANE_SIZE_ALIGNMENT	4096

#define SDE_MAX_IMG_WIDTH		0x3FFF
#define SDE_MAX_IMG_HEIGHT		0x3FFF

@@ -81,6 +84,23 @@ alpha, chroma, count, bp, flg, fm, np) \
	.num_planes = np                                                  \
}

#define PSEUDO_YUV_FMT_LOOSE(fmt, a, r, g, b, e0, e1, chroma, flg, fm, np)\
{                                                                         \
	.base.pixel_format = DRM_FORMAT_ ## fmt,                          \
	.fetch_planes = SDE_PLANE_PSEUDO_PLANAR,                          \
	.alpha_enable = false,                                            \
	.element = { (e0), (e1), 0, 0 },                                  \
	.bits = { g, b, r, a },                                           \
	.chroma_sample = chroma,                                          \
	.unpack_align_msb = 1,                                            \
	.unpack_tight = 0,                                                \
	.unpack_count = 2,                                                \
	.bpp = 2,                                                         \
	.fetch_mode = fm,                                                 \
	.flag = flg,                                                      \
	.num_planes = np                                                  \
}

#define PLANAR_YUV_FMT(fmt, a, r, g, b, e0, e1, e2, alpha, chroma, bp,    \
flg, fm, np)                                                      \
{                                                                         \
@@ -99,6 +119,16 @@ flg, fm, np) \
	.num_planes = np                                                  \
}

/*
 * struct sde_media_color_map - maps drm format to media format
 * @format: DRM base pixel format
 * @color: Media API color related to DRM format
 */
struct sde_media_color_map {
	uint32_t format;
	uint32_t color;
};

static const struct sde_format sde_format_map[] = {
	INTERLEAVED_RGB_FMT(ARGB8888,
		COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
@@ -421,6 +451,22 @@ static const struct sde_format sde_format_map_ubwc[] = {
		SDE_FETCH_UBWC, 4),
};

static const struct sde_format sde_format_map_p010[] = {
	PSEUDO_YUV_FMT_LOOSE(NV12,
		0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
		C1_B_Cb, C2_R_Cr,
		SDE_CHROMA_420, (SDE_FORMAT_FLAG_YUV | SDE_FORMAT_FLAG_DX),
		SDE_FETCH_LINEAR, 2),
};

static const struct sde_format sde_format_map_p010_ubwc[] = {
	PSEUDO_YUV_FMT_LOOSE(NV12,
		0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
		C1_B_Cb, C2_R_Cr,
		SDE_CHROMA_420, (SDE_FORMAT_FLAG_YUV | SDE_FORMAT_FLAG_DX),
		SDE_FETCH_UBWC, 4),
};

/* _sde_get_v_h_subsample_rate - Get subsample rates for all formats we support
 *   Note: Not using the drm_format_*_subsampling since we have formats
 */
@@ -452,6 +498,37 @@ static void _sde_get_v_h_subsample_rate(
	}
}

static int _sde_format_get_media_color_ubwc(const struct sde_format *fmt)
{
	static const struct sde_media_color_map sde_media_ubwc_map[] = {
		{DRM_FORMAT_RGBA8888, COLOR_FMT_RGBA8888_UBWC},
		{DRM_FORMAT_RGBX8888, COLOR_FMT_RGBA8888_UBWC},
		{DRM_FORMAT_RGBA1010102, COLOR_FMT_RGBA1010102_UBWC},
		{DRM_FORMAT_RGBX1010102, COLOR_FMT_RGBA1010102_UBWC},
		{DRM_FORMAT_RGB565, COLOR_FMT_RGB565_UBWC},
	};
	int color_fmt = -1;
	int i;

	if (fmt->base.pixel_format == DRM_FORMAT_NV12) {
		if (SDE_FORMAT_IS_DX(fmt)) {
			if (fmt->unpack_tight)
				color_fmt = COLOR_FMT_NV12_BPP10_UBWC;
			else
				color_fmt = COLOR_FMT_P010_UBWC;
		} else
			color_fmt = COLOR_FMT_NV12_UBWC;
		return color_fmt;
	}

	for (i = 0; i < ARRAY_SIZE(sde_media_ubwc_map); ++i)
		if (fmt->base.pixel_format == sde_media_ubwc_map[i].format) {
			color_fmt = sde_media_ubwc_map[i].color;
			break;
		}
	return color_fmt;
}

static int _sde_format_get_plane_sizes_ubwc(
		const struct sde_format *fmt,
		const uint32_t width,
@@ -459,6 +536,7 @@ static int _sde_format_get_plane_sizes_ubwc(
		struct sde_hw_fmt_layout *layout)
{
	int i;
	int color;

	memset(layout, 0, sizeof(struct sde_hw_fmt_layout));
	layout->format = fmt;
@@ -466,84 +544,53 @@ static int _sde_format_get_plane_sizes_ubwc(
	layout->height = height;
	layout->num_planes = fmt->num_planes;

	if (fmt->base.pixel_format == DRM_FORMAT_NV12) {
		uint32_t y_stride_alignment, uv_stride_alignment;
		uint32_t y_height_alignment, uv_height_alignment;
		uint32_t y_tile_width = 32;
		uint32_t y_tile_height = 8;
		uint32_t uv_tile_width = y_tile_width / 2;
		uint32_t uv_tile_height = y_tile_height;
		uint32_t y_bpp_numer = 1, y_bpp_denom = 1;
		uint32_t uv_bpp_numer = 1, uv_bpp_denom = 1;

		y_stride_alignment = 128;
		uv_stride_alignment = 64;
		y_height_alignment = 32;
		uv_height_alignment = 32;
		y_bpp_numer = 1;
		uv_bpp_numer = 2;
		y_bpp_denom = 1;
		uv_bpp_denom = 1;
	color = _sde_format_get_media_color_ubwc(fmt);
	if (color < 0) {
		DRM_ERROR("UBWC format not supported for fmt:0x%X\n",
			fmt->base.pixel_format);
		return -EINVAL;
	}

	if (SDE_FORMAT_IS_YUV(layout->format)) {
		uint32_t y_sclines, uv_sclines;
		uint32_t y_meta_scanlines = 0;
		uint32_t uv_meta_scanlines = 0;

		layout->num_planes = 4;
		/* Y bitstream stride and plane size */
		layout->plane_pitch[0] = ALIGN(width, y_stride_alignment);
		layout->plane_pitch[0] = (layout->plane_pitch[0] * y_bpp_numer)
				/ y_bpp_denom;
		layout->plane_size[0] = ALIGN(layout->plane_pitch[0] *
				ALIGN(height, y_height_alignment), 4096);

		/* CbCr bitstream stride and plane size */
		layout->plane_pitch[1] = ALIGN(width / 2, uv_stride_alignment);
		layout->plane_pitch[1] = (layout->plane_pitch[1] * uv_bpp_numer)
				/ uv_bpp_denom;
		layout->plane_size[1] = ALIGN(layout->plane_pitch[1] *
			ALIGN(height / 2, uv_height_alignment), 4096);

		/* Y meta data stride and plane size */
		layout->plane_pitch[2] = ALIGN(
				DIV_ROUND_UP(width, y_tile_width), 64);
		layout->plane_size[2] = ALIGN(layout->plane_pitch[2] *
			ALIGN(DIV_ROUND_UP(height, y_tile_height), 16), 4096);

		/* CbCr meta data stride and plane size */
		layout->plane_pitch[3] = ALIGN(
				DIV_ROUND_UP(width / 2, uv_tile_width), 64);
		layout->plane_size[3] = ALIGN(layout->plane_pitch[3] *
			ALIGN(DIV_ROUND_UP(height / 2, uv_tile_height), 16),
			4096);

	} else if (fmt->base.pixel_format == DRM_FORMAT_ABGR8888 ||
		fmt->base.pixel_format == DRM_FORMAT_XBGR8888    ||
		fmt->base.pixel_format == DRM_FORMAT_BGRA1010102 ||
		fmt->base.pixel_format == DRM_FORMAT_BGRX1010102 ||
		fmt->base.pixel_format == DRM_FORMAT_BGR565) {

		uint32_t stride_alignment, aligned_bitstream_width;

		if (fmt->base.pixel_format == DRM_FORMAT_BGR565)
			stride_alignment = 128;
		else
			stride_alignment = 64;
		layout->num_planes = 3;
		layout->plane_pitch[0] = VENUS_Y_STRIDE(color, width);
		y_sclines = VENUS_Y_SCANLINES(color, height);
		layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] *
			y_sclines, SDE_UBWC_PLANE_SIZE_ALIGNMENT);

		layout->plane_pitch[1] = VENUS_UV_STRIDE(color, width);
		uv_sclines = VENUS_UV_SCANLINES(color, height);
		layout->plane_size[1] = MSM_MEDIA_ALIGN(layout->plane_pitch[1] *
			uv_sclines, SDE_UBWC_PLANE_SIZE_ALIGNMENT);

		layout->plane_pitch[2] = VENUS_Y_META_STRIDE(color, width);
		y_meta_scanlines = VENUS_Y_META_SCANLINES(color, height);
		layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] *
			y_meta_scanlines, SDE_UBWC_PLANE_SIZE_ALIGNMENT);

		layout->plane_pitch[3] = VENUS_UV_META_STRIDE(color, width);
		uv_meta_scanlines = VENUS_UV_META_SCANLINES(color, height);
		layout->plane_size[3] = MSM_MEDIA_ALIGN(layout->plane_pitch[3] *
			uv_meta_scanlines, SDE_UBWC_PLANE_SIZE_ALIGNMENT);

	} else {
		uint32_t rgb_scanlines, rgb_meta_scanlines;

		/* Nothing in plane[1] */
		layout->num_planes = 3;

		/* RGB bitstream stride and plane size */
		aligned_bitstream_width = ALIGN(width, stride_alignment);
		layout->plane_pitch[0] = aligned_bitstream_width * fmt->bpp;
		layout->plane_size[0] = ALIGN(fmt->bpp * aligned_bitstream_width
				* ALIGN(height, 16), 4096);
		layout->plane_pitch[0] = VENUS_RGB_STRIDE(color, width);
		rgb_scanlines = VENUS_RGB_SCANLINES(color, height);
		layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] *
			rgb_scanlines, SDE_UBWC_PLANE_SIZE_ALIGNMENT);

		/* RGB meta data stride and plane size */
		layout->plane_pitch[2] = ALIGN(DIV_ROUND_UP(
				aligned_bitstream_width, 16), 64);
		layout->plane_size[2] = ALIGN(layout->plane_pitch[2] *
			ALIGN(DIV_ROUND_UP(height, 4), 16), 4096);
	} else {
		DRM_ERROR("UBWC format not supported for fmt:0x%X\n",
			fmt->base.pixel_format);
		return -EINVAL;
		layout->plane_pitch[2] = VENUS_RGB_META_STRIDE(color, width);
		rgb_meta_scanlines = VENUS_RGB_META_SCANLINES(color, height);
		layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] *
			rgb_meta_scanlines, SDE_UBWC_PLANE_SIZE_ALIGNMENT);
	}

	for (i = 0; i < SDE_MAX_PLANES; i++)
@@ -574,6 +621,7 @@ static int _sde_format_get_plane_sizes_linear(
	} else {
		uint32_t v_subsample, h_subsample;
		uint32_t chroma_samp;
		uint32_t bpp = 1;

		chroma_samp = fmt->chroma_sample;
		_sde_get_v_h_subsample_rate(chroma_samp, &v_subsample,
@@ -584,8 +632,11 @@ static int _sde_format_get_plane_sizes_linear(
			return -EINVAL;
		}

		layout->plane_pitch[0] = width;
		layout->plane_pitch[1] = width / h_subsample;
		if ((fmt->base.pixel_format == DRM_FORMAT_NV12) &&
			(SDE_FORMAT_IS_DX(fmt)))
			bpp = 2;
		layout->plane_pitch[0] = width * bpp;
		layout->plane_pitch[1] = layout->plane_pitch[0] / h_subsample;
		layout->plane_size[0] = layout->plane_pitch[0] * height;
		layout->plane_size[1] = layout->plane_pitch[1] *
				(height / v_subsample);
@@ -926,6 +977,16 @@ const struct sde_format *sde_get_sde_format_ext(
		map_size = ARRAY_SIZE(sde_format_map_ubwc);
		DBG("found fmt 0x%X DRM_FORMAT_MOD_QCOM_COMPRESSED", format);
		break;
	case DRM_FORMAT_MOD_QCOM_DX:
		map = sde_format_map_p010;
		map_size = ARRAY_SIZE(sde_format_map_p010);
		DBG("found fmt 0x%X DRM_FORMAT_MOD_QCOM_DX", format);
		break;
	case (DRM_FORMAT_MOD_QCOM_DX | DRM_FORMAT_MOD_QCOM_COMPRESSED):
		map = sde_format_map_p010_ubwc;
		map_size = ARRAY_SIZE(sde_format_map_p010_ubwc);
		DBG("found fmt 0x%X DRM_FORMAT_MOD_QCOM_COMPRESSED/DX", format);
		break;
	default:
		DRM_ERROR("unsupported format modifier %llX\n", mod0);
		return NULL;
+8 −1
Original line number Diff line number Diff line
@@ -241,8 +241,15 @@ extern "C" {
 */
#define DRM_FORMAT_MOD_QCOM_COMPRESSED	fourcc_mod_code(QCOM, 1)

/*
 * QTI DX Format
 *
 * Refers to a DX variant of the base format.
 * Implementation may be platform and base-format specific.
 */
#define DRM_FORMAT_MOD_QCOM_DX	fourcc_mod_code(QCOM, 0x2)

#if defined(__cplusplus)
}
#endif

#endif /* DRM_FOURCC_H */