brintos

brintos / linux-shallow public Read only

0
0
Text · 12.0 KiB · 3fefb20 Raw
443 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2013 Red Hat4 * Author: Rob Clark <robdclark@gmail.com>5 */6 7#include <drm/drm_atomic.h>8#include <drm/drm_damage_helper.h>9#include <drm/drm_fourcc.h>10#include <drm/drm_framebuffer.h>11#include <drm/drm_gem_atomic_helper.h>12 13#include "mdp4_kms.h"14 15#define DOWN_SCALE_MAX	816#define UP_SCALE_MAX	817 18struct mdp4_plane {19	struct drm_plane base;20	const char *name;21 22	enum mdp4_pipe pipe;23};24#define to_mdp4_plane(x) container_of(x, struct mdp4_plane, base)25 26/* MDP format helper functions */27static inline28enum mdp4_frame_format mdp4_get_frame_format(struct drm_framebuffer *fb)29{30	bool is_tile = false;31 32	if (fb->modifier == DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)33		is_tile = true;34 35	if (fb->format->format == DRM_FORMAT_NV12 && is_tile)36		return FRAME_TILE_YCBCR_420;37 38	return FRAME_LINEAR;39}40 41static void mdp4_plane_set_scanout(struct drm_plane *plane,42		struct drm_framebuffer *fb);43static int mdp4_plane_mode_set(struct drm_plane *plane,44		struct drm_crtc *crtc, struct drm_framebuffer *fb,45		int crtc_x, int crtc_y,46		unsigned int crtc_w, unsigned int crtc_h,47		uint32_t src_x, uint32_t src_y,48		uint32_t src_w, uint32_t src_h);49 50static struct mdp4_kms *get_kms(struct drm_plane *plane)51{52	struct msm_drm_private *priv = plane->dev->dev_private;53	return to_mdp4_kms(to_mdp_kms(priv->kms));54}55 56/* helper to install properties which are common to planes and crtcs */57static void mdp4_plane_install_properties(struct drm_plane *plane,58		struct drm_mode_object *obj)59{60	// XXX61}62 63static int mdp4_plane_set_property(struct drm_plane *plane,64		struct drm_property *property, uint64_t val)65{66	// XXX67	return -EINVAL;68}69 70static const struct drm_plane_funcs mdp4_plane_funcs = {71		.update_plane = drm_atomic_helper_update_plane,72		.disable_plane = drm_atomic_helper_disable_plane,73		.set_property = mdp4_plane_set_property,74		.reset = drm_atomic_helper_plane_reset,75		.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,76		.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,77};78 79static int mdp4_plane_prepare_fb(struct drm_plane *plane,80				 struct drm_plane_state *new_state)81{82	struct msm_drm_private *priv = plane->dev->dev_private;83	struct msm_kms *kms = priv->kms;84 85	if (!new_state->fb)86		return 0;87 88	drm_gem_plane_helper_prepare_fb(plane, new_state);89 90	return msm_framebuffer_prepare(new_state->fb, kms->aspace, false);91}92 93static void mdp4_plane_cleanup_fb(struct drm_plane *plane,94				  struct drm_plane_state *old_state)95{96	struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);97	struct mdp4_kms *mdp4_kms = get_kms(plane);98	struct msm_kms *kms = &mdp4_kms->base.base;99	struct drm_framebuffer *fb = old_state->fb;100 101	if (!fb)102		return;103 104	DBG("%s: cleanup: FB[%u]", mdp4_plane->name, fb->base.id);105	msm_framebuffer_cleanup(fb, kms->aspace, false);106}107 108 109static int mdp4_plane_atomic_check(struct drm_plane *plane,110		struct drm_atomic_state *state)111{112	return 0;113}114 115static void mdp4_plane_atomic_update(struct drm_plane *plane,116				     struct drm_atomic_state *state)117{118	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,119									   plane);120	int ret;121 122	ret = mdp4_plane_mode_set(plane,123			new_state->crtc, new_state->fb,124			new_state->crtc_x, new_state->crtc_y,125			new_state->crtc_w, new_state->crtc_h,126			new_state->src_x,  new_state->src_y,127			new_state->src_w, new_state->src_h);128	/* atomic_check should have ensured that this doesn't fail */129	WARN_ON(ret < 0);130}131 132static const struct drm_plane_helper_funcs mdp4_plane_helper_funcs = {133		.prepare_fb = mdp4_plane_prepare_fb,134		.cleanup_fb = mdp4_plane_cleanup_fb,135		.atomic_check = mdp4_plane_atomic_check,136		.atomic_update = mdp4_plane_atomic_update,137};138 139static void mdp4_plane_set_scanout(struct drm_plane *plane,140		struct drm_framebuffer *fb)141{142	struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);143	struct mdp4_kms *mdp4_kms = get_kms(plane);144	struct msm_kms *kms = &mdp4_kms->base.base;145	enum mdp4_pipe pipe = mdp4_plane->pipe;146 147	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_STRIDE_A(pipe),148			MDP4_PIPE_SRC_STRIDE_A_P0(fb->pitches[0]) |149			MDP4_PIPE_SRC_STRIDE_A_P1(fb->pitches[1]));150 151	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_STRIDE_B(pipe),152			MDP4_PIPE_SRC_STRIDE_B_P2(fb->pitches[2]) |153			MDP4_PIPE_SRC_STRIDE_B_P3(fb->pitches[3]));154 155	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP0_BASE(pipe),156			msm_framebuffer_iova(fb, kms->aspace, 0));157	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP1_BASE(pipe),158			msm_framebuffer_iova(fb, kms->aspace, 1));159	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP2_BASE(pipe),160			msm_framebuffer_iova(fb, kms->aspace, 2));161	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP3_BASE(pipe),162			msm_framebuffer_iova(fb, kms->aspace, 3));163}164 165static void mdp4_write_csc_config(struct mdp4_kms *mdp4_kms,166		enum mdp4_pipe pipe, struct csc_cfg *csc)167{168	int i;169 170	for (i = 0; i < ARRAY_SIZE(csc->matrix); i++) {171		mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_MV(pipe, i),172				csc->matrix[i]);173	}174 175	for (i = 0; i < ARRAY_SIZE(csc->post_bias) ; i++) {176		mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_PRE_BV(pipe, i),177				csc->pre_bias[i]);178 179		mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_POST_BV(pipe, i),180				csc->post_bias[i]);181	}182 183	for (i = 0; i < ARRAY_SIZE(csc->post_clamp) ; i++) {184		mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_PRE_LV(pipe, i),185				csc->pre_clamp[i]);186 187		mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_POST_LV(pipe, i),188				csc->post_clamp[i]);189	}190}191 192#define MDP4_VG_PHASE_STEP_DEFAULT	0x20000000193 194static int mdp4_plane_mode_set(struct drm_plane *plane,195		struct drm_crtc *crtc, struct drm_framebuffer *fb,196		int crtc_x, int crtc_y,197		unsigned int crtc_w, unsigned int crtc_h,198		uint32_t src_x, uint32_t src_y,199		uint32_t src_w, uint32_t src_h)200{201	struct drm_device *dev = plane->dev;202	struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);203	struct mdp4_kms *mdp4_kms = get_kms(plane);204	enum mdp4_pipe pipe = mdp4_plane->pipe;205	const struct msm_format *format;206	uint32_t op_mode = 0;207	uint32_t phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;208	uint32_t phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;209	enum mdp4_frame_format frame_type;210 211	if (!(crtc && fb)) {212		DBG("%s: disabled!", mdp4_plane->name);213		return 0;214	}215 216	frame_type = mdp4_get_frame_format(fb);217 218	/* src values are in Q16 fixed point, convert to integer: */219	src_x = src_x >> 16;220	src_y = src_y >> 16;221	src_w = src_w >> 16;222	src_h = src_h >> 16;223 224	DBG("%s: FB[%u] %u,%u,%u,%u -> CRTC[%u] %d,%d,%u,%u", mdp4_plane->name,225			fb->base.id, src_x, src_y, src_w, src_h,226			crtc->base.id, crtc_x, crtc_y, crtc_w, crtc_h);227 228	format = msm_framebuffer_format(fb);229 230	if (src_w > (crtc_w * DOWN_SCALE_MAX)) {231		DRM_DEV_ERROR(dev->dev, "Width down scaling exceeds limits!\n");232		return -ERANGE;233	}234 235	if (src_h > (crtc_h * DOWN_SCALE_MAX)) {236		DRM_DEV_ERROR(dev->dev, "Height down scaling exceeds limits!\n");237		return -ERANGE;238	}239 240	if (crtc_w > (src_w * UP_SCALE_MAX)) {241		DRM_DEV_ERROR(dev->dev, "Width up scaling exceeds limits!\n");242		return -ERANGE;243	}244 245	if (crtc_h > (src_h * UP_SCALE_MAX)) {246		DRM_DEV_ERROR(dev->dev, "Height up scaling exceeds limits!\n");247		return -ERANGE;248	}249 250	if (src_w != crtc_w) {251		uint32_t sel_unit = SCALE_FIR;252		op_mode |= MDP4_PIPE_OP_MODE_SCALEX_EN;253 254		if (MSM_FORMAT_IS_YUV(format)) {255			if (crtc_w > src_w)256				sel_unit = SCALE_PIXEL_RPT;257			else if (crtc_w <= (src_w / 4))258				sel_unit = SCALE_MN_PHASE;259 260			op_mode |= MDP4_PIPE_OP_MODE_SCALEX_UNIT_SEL(sel_unit);261			phasex_step = mult_frac(MDP4_VG_PHASE_STEP_DEFAULT,262					src_w, crtc_w);263		}264	}265 266	if (src_h != crtc_h) {267		uint32_t sel_unit = SCALE_FIR;268		op_mode |= MDP4_PIPE_OP_MODE_SCALEY_EN;269 270		if (MSM_FORMAT_IS_YUV(format)) {271 272			if (crtc_h > src_h)273				sel_unit = SCALE_PIXEL_RPT;274			else if (crtc_h <= (src_h / 4))275				sel_unit = SCALE_MN_PHASE;276 277			op_mode |= MDP4_PIPE_OP_MODE_SCALEY_UNIT_SEL(sel_unit);278			phasey_step = mult_frac(MDP4_VG_PHASE_STEP_DEFAULT,279					src_h, crtc_h);280		}281	}282 283	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_SIZE(pipe),284			MDP4_PIPE_SRC_SIZE_WIDTH(src_w) |285			MDP4_PIPE_SRC_SIZE_HEIGHT(src_h));286 287	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_XY(pipe),288			MDP4_PIPE_SRC_XY_X(src_x) |289			MDP4_PIPE_SRC_XY_Y(src_y));290 291	mdp4_write(mdp4_kms, REG_MDP4_PIPE_DST_SIZE(pipe),292			MDP4_PIPE_DST_SIZE_WIDTH(crtc_w) |293			MDP4_PIPE_DST_SIZE_HEIGHT(crtc_h));294 295	mdp4_write(mdp4_kms, REG_MDP4_PIPE_DST_XY(pipe),296			MDP4_PIPE_DST_XY_X(crtc_x) |297			MDP4_PIPE_DST_XY_Y(crtc_y));298 299	mdp4_plane_set_scanout(plane, fb);300 301	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_FORMAT(pipe),302			MDP4_PIPE_SRC_FORMAT_A_BPC(format->bpc_a) |303			MDP4_PIPE_SRC_FORMAT_R_BPC(format->bpc_r_cr) |304			MDP4_PIPE_SRC_FORMAT_G_BPC(format->bpc_g_y) |305			MDP4_PIPE_SRC_FORMAT_B_BPC(format->bpc_b_cb) |306			COND(format->alpha_enable, MDP4_PIPE_SRC_FORMAT_ALPHA_ENABLE) |307			MDP4_PIPE_SRC_FORMAT_CPP(format->bpp - 1) |308			MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT(format->unpack_count - 1) |309			MDP4_PIPE_SRC_FORMAT_FETCH_PLANES(format->fetch_type) |310			MDP4_PIPE_SRC_FORMAT_CHROMA_SAMP(format->chroma_sample) |311			MDP4_PIPE_SRC_FORMAT_FRAME_FORMAT(frame_type) |312			COND(format->flags & MSM_FORMAT_FLAG_UNPACK_TIGHT,313			     MDP4_PIPE_SRC_FORMAT_UNPACK_TIGHT));314 315	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_UNPACK(pipe),316			MDP4_PIPE_SRC_UNPACK_ELEM0(format->element[0]) |317			MDP4_PIPE_SRC_UNPACK_ELEM1(format->element[1]) |318			MDP4_PIPE_SRC_UNPACK_ELEM2(format->element[2]) |319			MDP4_PIPE_SRC_UNPACK_ELEM3(format->element[3]));320 321	if (MSM_FORMAT_IS_YUV(format)) {322		struct csc_cfg *csc = mdp_get_default_csc_cfg(CSC_YUV2RGB);323 324		op_mode |= MDP4_PIPE_OP_MODE_SRC_YCBCR;325		op_mode |= MDP4_PIPE_OP_MODE_CSC_EN;326		mdp4_write_csc_config(mdp4_kms, pipe, csc);327	}328 329	mdp4_write(mdp4_kms, REG_MDP4_PIPE_OP_MODE(pipe), op_mode);330	mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEX_STEP(pipe), phasex_step);331	mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEY_STEP(pipe), phasey_step);332 333	if (frame_type != FRAME_LINEAR)334		mdp4_write(mdp4_kms, REG_MDP4_PIPE_SSTILE_FRAME_SIZE(pipe),335				MDP4_PIPE_SSTILE_FRAME_SIZE_WIDTH(src_w) |336				MDP4_PIPE_SSTILE_FRAME_SIZE_HEIGHT(src_h));337 338	return 0;339}340 341static const char *pipe_names[] = {342		"VG1", "VG2",343		"RGB1", "RGB2", "RGB3",344		"VG3", "VG4",345};346 347enum mdp4_pipe mdp4_plane_pipe(struct drm_plane *plane)348{349	struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);350	return mdp4_plane->pipe;351}352 353static const uint64_t supported_format_modifiers[] = {354	DRM_FORMAT_MOD_SAMSUNG_64_32_TILE,355	DRM_FORMAT_MOD_LINEAR,356	DRM_FORMAT_MOD_INVALID357};358 359static const uint32_t mdp4_rgb_formats[] = {360	DRM_FORMAT_ARGB8888,361	DRM_FORMAT_ABGR8888,362	DRM_FORMAT_RGBA8888,363	DRM_FORMAT_BGRA8888,364	DRM_FORMAT_XRGB8888,365	DRM_FORMAT_XBGR8888,366	DRM_FORMAT_RGBX8888,367	DRM_FORMAT_BGRX8888,368	DRM_FORMAT_RGB888,369	DRM_FORMAT_BGR888,370	DRM_FORMAT_RGB565,371	DRM_FORMAT_BGR565,372};373 374static const uint32_t mdp4_rgb_yuv_formats[] = {375	DRM_FORMAT_ARGB8888,376	DRM_FORMAT_ABGR8888,377	DRM_FORMAT_RGBA8888,378	DRM_FORMAT_BGRA8888,379	DRM_FORMAT_XRGB8888,380	DRM_FORMAT_XBGR8888,381	DRM_FORMAT_RGBX8888,382	DRM_FORMAT_BGRX8888,383	DRM_FORMAT_RGB888,384	DRM_FORMAT_BGR888,385	DRM_FORMAT_RGB565,386	DRM_FORMAT_BGR565,387 388	DRM_FORMAT_NV12,389	DRM_FORMAT_NV21,390	DRM_FORMAT_NV16,391	DRM_FORMAT_NV61,392	DRM_FORMAT_VYUY,393	DRM_FORMAT_UYVY,394	DRM_FORMAT_YUYV,395	DRM_FORMAT_YVYU,396	DRM_FORMAT_YUV420,397	DRM_FORMAT_YVU420,398};399 400/* initialize plane */401struct drm_plane *mdp4_plane_init(struct drm_device *dev,402		enum mdp4_pipe pipe_id, bool private_plane)403{404	struct drm_plane *plane = NULL;405	struct mdp4_plane *mdp4_plane;406	enum drm_plane_type type;407	uint32_t pipe_caps;408	const uint32_t *formats;409	size_t nformats;410 411	type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;412 413	pipe_caps = mdp4_pipe_caps(pipe_id);414	if (pipe_supports_yuv(pipe_caps)) {415		formats = mdp4_rgb_yuv_formats;416		nformats = ARRAY_SIZE(mdp4_rgb_yuv_formats);417	} else {418		formats = mdp4_rgb_formats;419		nformats = ARRAY_SIZE(mdp4_rgb_formats);420	}421 422	mdp4_plane = drmm_universal_plane_alloc(dev, struct mdp4_plane, base,423						0xff, &mdp4_plane_funcs,424						formats, nformats,425						supported_format_modifiers,426						type, NULL);427	if (IS_ERR(mdp4_plane))428		return ERR_CAST(mdp4_plane);429 430	plane = &mdp4_plane->base;431 432	mdp4_plane->pipe = pipe_id;433	mdp4_plane->name = pipe_names[pipe_id];434 435	drm_plane_helper_add(plane, &mdp4_plane_helper_funcs);436 437	mdp4_plane_install_properties(plane, &plane->base);438 439	drm_plane_enable_fb_damage_clips(plane);440 441	return plane;442}443