diff options
Diffstat (limited to 'drivers/gpu/drm/vkms')
| -rw-r--r-- | drivers/gpu/drm/vkms/vkms_composer.c | 38 | ||||
| -rw-r--r-- | drivers/gpu/drm/vkms/vkms_crtc.c | 5 | ||||
| -rw-r--r-- | drivers/gpu/drm/vkms/vkms_drv.c | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/vkms/vkms_drv.h | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/vkms/vkms_formats.c | 145 | ||||
| -rw-r--r-- | drivers/gpu/drm/vkms/vkms_formats.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/vkms/vkms_plane.c | 50 | 
7 files changed, 129 insertions, 123 deletions
| diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index 8e53fa80742b..906d3df40cdb 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -4,6 +4,7 @@  #include <drm/drm_atomic.h>  #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h>  #include <drm/drm_fourcc.h>  #include <drm/drm_gem_framebuffer_helper.h>  #include <drm/drm_vblank.h> @@ -53,10 +54,30 @@ static void pre_mul_alpha_blend(struct vkms_frame_info *frame_info,  	}  } -static bool check_y_limit(struct vkms_frame_info *frame_info, int y) +static int get_y_pos(struct vkms_frame_info *frame_info, int y)  { -	if (y >= frame_info->dst.y1 && y < frame_info->dst.y2) -		return true; +	if (frame_info->rotation & DRM_MODE_REFLECT_Y) +		return drm_rect_height(&frame_info->rotated) - y - 1; + +	switch (frame_info->rotation & DRM_MODE_ROTATE_MASK) { +	case DRM_MODE_ROTATE_90: +		return frame_info->rotated.x2 - y - 1; +	case DRM_MODE_ROTATE_270: +		return y + frame_info->rotated.x1; +	default: +		return y; +	} +} + +static bool check_limit(struct vkms_frame_info *frame_info, int pos) +{ +	if (drm_rotation_90_or_270(frame_info->rotation)) { +		if (pos >= 0 && pos < drm_rect_width(&frame_info->rotated)) +			return true; +	} else { +		if (pos >= frame_info->rotated.y1 && pos < frame_info->rotated.y2) +			return true; +	}  	return false;  } @@ -86,6 +107,7 @@ static void blend(struct vkms_writeback_job *wb,  {  	struct vkms_plane_state **plane = crtc_state->active_planes;  	u32 n_active_planes = crtc_state->num_active_planes; +	int y_pos;  	const struct pixel_argb_u16 background_color = { .a = 0xffff }; @@ -96,10 +118,12 @@ static void blend(struct vkms_writeback_job *wb,  		/* The active planes are composed associatively in z-order. */  		for (size_t i = 0; i < n_active_planes; i++) { -			if (!check_y_limit(plane[i]->frame_info, y)) +			y_pos = get_y_pos(plane[i]->frame_info, y); + +			if (!check_limit(plane[i]->frame_info, y_pos))  				continue; -			plane[i]->plane_read(stage_buffer, plane[i]->frame_info, y); +			vkms_compose_row(stage_buffer, plane[i], y_pos);  			pre_mul_alpha_blend(plane[i]->frame_info, stage_buffer,  					    output_buffer);  		} @@ -107,7 +131,7 @@ static void blend(struct vkms_writeback_job *wb,  		*crc32 = crc32_le(*crc32, (void *)output_buffer->pixels, row_size);  		if (wb) -			wb->wb_write(&wb->wb_frame_info, output_buffer, y); +			wb->wb_write(&wb->wb_frame_info, output_buffer, y_pos);  	}  } @@ -118,7 +142,7 @@ static int check_format_funcs(struct vkms_crtc_state *crtc_state,  	u32 n_active_planes = crtc_state->num_active_planes;  	for (size_t i = 0; i < n_active_planes; i++) -		if (!planes[i]->plane_read) +		if (!planes[i]->pixel_read)  			return -1;  	if (active_wb && !active_wb->wb_write) diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c index 57bbd32e9beb..515f6772b866 100644 --- a/drivers/gpu/drm/vkms/vkms_crtc.c +++ b/drivers/gpu/drm/vkms/vkms_crtc.c @@ -161,7 +161,6 @@ static void vkms_atomic_crtc_reset(struct drm_crtc *crtc)  static const struct drm_crtc_funcs vkms_crtc_funcs = {  	.set_config             = drm_atomic_helper_set_config, -	.destroy                = drm_crtc_cleanup,  	.page_flip              = drm_atomic_helper_page_flip,  	.reset                  = vkms_atomic_crtc_reset,  	.atomic_duplicate_state = vkms_atomic_crtc_duplicate_state, @@ -282,8 +281,8 @@ int vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,  	struct vkms_output *vkms_out = drm_crtc_to_vkms_output(crtc);  	int ret; -	ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor, -					&vkms_crtc_funcs, NULL); +	ret = drmm_crtc_init_with_planes(dev, crtc, primary, cursor, +					 &vkms_crtc_funcs, NULL);  	if (ret) {  		DRM_ERROR("Failed to init CRTC\n");  		return ret; diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index 6d3a2d57d992..e3c9c9571c8d 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -133,8 +133,12 @@ static const struct drm_mode_config_helper_funcs vkms_mode_config_helpers = {  static int vkms_modeset_init(struct vkms_device *vkmsdev)  {  	struct drm_device *dev = &vkmsdev->drm; +	int ret; + +	ret = drmm_mode_config_init(dev); +	if (ret) +		return ret; -	drm_mode_config_init(dev);  	dev->mode_config.funcs = &vkms_mode_funcs;  	dev->mode_config.min_width = XRES_MIN;  	dev->mode_config.min_height = YRES_MIN; diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 4a248567efb2..5f1a0a44a78c 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -26,7 +26,9 @@  struct vkms_frame_info {  	struct drm_framebuffer *fb;  	struct drm_rect src, dst; +	struct drm_rect rotated;  	struct iosys_map map[DRM_FORMAT_MAX_PLANES]; +	unsigned int rotation;  	unsigned int offset;  	unsigned int pitch;  	unsigned int cpp; @@ -56,8 +58,7 @@ struct vkms_writeback_job {  struct vkms_plane_state {  	struct drm_shadow_plane_state base;  	struct vkms_frame_info *frame_info; -	void (*plane_read)(struct line_buffer *buffer, -			   const struct vkms_frame_info *frame_info, int y); +	void (*pixel_read)(u8 *src_buffer, struct pixel_argb_u16 *out_pixel);  };  struct vkms_plane { @@ -155,6 +156,7 @@ int vkms_verify_crc_source(struct drm_crtc *crtc, const char *source_name,  /* Composer Support */  void vkms_composer_worker(struct work_struct *work);  void vkms_set_composer(struct vkms_output *out, bool enabled); +void vkms_compose_row(struct line_buffer *stage_buffer, struct vkms_plane_state *plane, int y);  /* Writeback */  int vkms_enable_writeback_connector(struct vkms_device *vkmsdev); diff --git a/drivers/gpu/drm/vkms/vkms_formats.c b/drivers/gpu/drm/vkms/vkms_formats.c index d4950688b3f1..5945da0beba6 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.c +++ b/drivers/gpu/drm/vkms/vkms_formats.c @@ -2,6 +2,8 @@  #include <linux/kernel.h>  #include <linux/minmax.h> + +#include <drm/drm_blend.h>  #include <drm/drm_rect.h>  #include <drm/drm_fixed.h> @@ -37,104 +39,93 @@ static void *packed_pixels_addr(const struct vkms_frame_info *frame_info,  static void *get_packed_src_addr(const struct vkms_frame_info *frame_info, int y)  {  	int x_src = frame_info->src.x1 >> 16; -	int y_src = y - frame_info->dst.y1 + (frame_info->src.y1 >> 16); +	int y_src = y - frame_info->rotated.y1 + (frame_info->src.y1 >> 16);  	return packed_pixels_addr(frame_info, x_src, y_src);  } -static void ARGB8888_to_argb_u16(struct line_buffer *stage_buffer, -				 const struct vkms_frame_info *frame_info, int y) +static int get_x_position(const struct vkms_frame_info *frame_info, int limit, int x)  { -	struct pixel_argb_u16 *out_pixels = stage_buffer->pixels; -	u8 *src_pixels = get_packed_src_addr(frame_info, y); -	int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), -			    stage_buffer->n_pixels); - -	for (size_t x = 0; x < x_limit; x++, src_pixels += 4) { -		/* -		 * The 257 is the "conversion ratio". This number is obtained by the -		 * (2^16 - 1) / (2^8 - 1) division. Which, in this case, tries to get -		 * the best color value in a pixel format with more possibilities. -		 * A similar idea applies to others RGB color conversions. -		 */ -		out_pixels[x].a = (u16)src_pixels[3] * 257; -		out_pixels[x].r = (u16)src_pixels[2] * 257; -		out_pixels[x].g = (u16)src_pixels[1] * 257; -		out_pixels[x].b = (u16)src_pixels[0] * 257; -	} +	if (frame_info->rotation & (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_270)) +		return limit - x - 1; +	return x;  } -static void XRGB8888_to_argb_u16(struct line_buffer *stage_buffer, -				 const struct vkms_frame_info *frame_info, int y) +static void ARGB8888_to_argb_u16(u8 *src_pixels, struct pixel_argb_u16 *out_pixel)  { -	struct pixel_argb_u16 *out_pixels = stage_buffer->pixels; -	u8 *src_pixels = get_packed_src_addr(frame_info, y); -	int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), -			    stage_buffer->n_pixels); +	/* +	 * The 257 is the "conversion ratio". This number is obtained by the +	 * (2^16 - 1) / (2^8 - 1) division. Which, in this case, tries to get +	 * the best color value in a pixel format with more possibilities. +	 * A similar idea applies to others RGB color conversions. +	 */ +	out_pixel->a = (u16)src_pixels[3] * 257; +	out_pixel->r = (u16)src_pixels[2] * 257; +	out_pixel->g = (u16)src_pixels[1] * 257; +	out_pixel->b = (u16)src_pixels[0] * 257; +} -	for (size_t x = 0; x < x_limit; x++, src_pixels += 4) { -		out_pixels[x].a = (u16)0xffff; -		out_pixels[x].r = (u16)src_pixels[2] * 257; -		out_pixels[x].g = (u16)src_pixels[1] * 257; -		out_pixels[x].b = (u16)src_pixels[0] * 257; -	} +static void XRGB8888_to_argb_u16(u8 *src_pixels, struct pixel_argb_u16 *out_pixel) +{ +	out_pixel->a = (u16)0xffff; +	out_pixel->r = (u16)src_pixels[2] * 257; +	out_pixel->g = (u16)src_pixels[1] * 257; +	out_pixel->b = (u16)src_pixels[0] * 257;  } -static void ARGB16161616_to_argb_u16(struct line_buffer *stage_buffer, -				     const struct vkms_frame_info *frame_info, -				     int y) +static void ARGB16161616_to_argb_u16(u8 *src_pixels, struct pixel_argb_u16 *out_pixel)  { -	struct pixel_argb_u16 *out_pixels = stage_buffer->pixels; -	u16 *src_pixels = get_packed_src_addr(frame_info, y); -	int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), -			    stage_buffer->n_pixels); +	u16 *pixels = (u16 *)src_pixels; -	for (size_t x = 0; x < x_limit; x++, src_pixels += 4) { -		out_pixels[x].a = le16_to_cpu(src_pixels[3]); -		out_pixels[x].r = le16_to_cpu(src_pixels[2]); -		out_pixels[x].g = le16_to_cpu(src_pixels[1]); -		out_pixels[x].b = le16_to_cpu(src_pixels[0]); -	} +	out_pixel->a = le16_to_cpu(pixels[3]); +	out_pixel->r = le16_to_cpu(pixels[2]); +	out_pixel->g = le16_to_cpu(pixels[1]); +	out_pixel->b = le16_to_cpu(pixels[0]);  } -static void XRGB16161616_to_argb_u16(struct line_buffer *stage_buffer, -				     const struct vkms_frame_info *frame_info, -				     int y) +static void XRGB16161616_to_argb_u16(u8 *src_pixels, struct pixel_argb_u16 *out_pixel)  { -	struct pixel_argb_u16 *out_pixels = stage_buffer->pixels; -	u16 *src_pixels = get_packed_src_addr(frame_info, y); -	int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), -			    stage_buffer->n_pixels); +	u16 *pixels = (u16 *)src_pixels; -	for (size_t x = 0; x < x_limit; x++, src_pixels += 4) { -		out_pixels[x].a = (u16)0xffff; -		out_pixels[x].r = le16_to_cpu(src_pixels[2]); -		out_pixels[x].g = le16_to_cpu(src_pixels[1]); -		out_pixels[x].b = le16_to_cpu(src_pixels[0]); -	} +	out_pixel->a = (u16)0xffff; +	out_pixel->r = le16_to_cpu(pixels[2]); +	out_pixel->g = le16_to_cpu(pixels[1]); +	out_pixel->b = le16_to_cpu(pixels[0]);  } -static void RGB565_to_argb_u16(struct line_buffer *stage_buffer, -			       const struct vkms_frame_info *frame_info, int y) +static void RGB565_to_argb_u16(u8 *src_pixels, struct pixel_argb_u16 *out_pixel)  { -	struct pixel_argb_u16 *out_pixels = stage_buffer->pixels; -	u16 *src_pixels = get_packed_src_addr(frame_info, y); -	int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), -			       stage_buffer->n_pixels); +	u16 *pixels = (u16 *)src_pixels;  	s64 fp_rb_ratio = drm_fixp_div(drm_int2fixp(65535), drm_int2fixp(31));  	s64 fp_g_ratio = drm_fixp_div(drm_int2fixp(65535), drm_int2fixp(63)); -	for (size_t x = 0; x < x_limit; x++, src_pixels++) { -		u16 rgb_565 = le16_to_cpu(*src_pixels); -		s64 fp_r = drm_int2fixp((rgb_565 >> 11) & 0x1f); -		s64 fp_g = drm_int2fixp((rgb_565 >> 5) & 0x3f); -		s64 fp_b = drm_int2fixp(rgb_565 & 0x1f); +	u16 rgb_565 = le16_to_cpu(*pixels); +	s64 fp_r = drm_int2fixp((rgb_565 >> 11) & 0x1f); +	s64 fp_g = drm_int2fixp((rgb_565 >> 5) & 0x3f); +	s64 fp_b = drm_int2fixp(rgb_565 & 0x1f); + +	out_pixel->a = (u16)0xffff; +	out_pixel->r = drm_fixp2int_round(drm_fixp_mul(fp_r, fp_rb_ratio)); +	out_pixel->g = drm_fixp2int_round(drm_fixp_mul(fp_g, fp_g_ratio)); +	out_pixel->b = drm_fixp2int_round(drm_fixp_mul(fp_b, fp_rb_ratio)); +} + +void vkms_compose_row(struct line_buffer *stage_buffer, struct vkms_plane_state *plane, int y) +{ +	struct pixel_argb_u16 *out_pixels = stage_buffer->pixels; +	struct vkms_frame_info *frame_info = plane->frame_info; +	u8 *src_pixels = get_packed_src_addr(frame_info, y); +	int limit = min_t(size_t, drm_rect_width(&frame_info->dst), stage_buffer->n_pixels); + +	for (size_t x = 0; x < limit; x++, src_pixels += frame_info->cpp) { +		int x_pos = get_x_position(frame_info, limit, x); + +		if (drm_rotation_90_or_270(frame_info->rotation)) +			src_pixels = get_packed_src_addr(frame_info, x + frame_info->rotated.y1) +				+ frame_info->cpp * y; -		out_pixels[x].a = (u16)0xffff; -		out_pixels[x].r = drm_fixp2int(drm_fixp_mul(fp_r, fp_rb_ratio)); -		out_pixels[x].g = drm_fixp2int(drm_fixp_mul(fp_g, fp_g_ratio)); -		out_pixels[x].b = drm_fixp2int(drm_fixp_mul(fp_b, fp_rb_ratio)); +		plane->pixel_read(src_pixels, &out_pixels[x_pos]);  	}  } @@ -241,15 +232,15 @@ static void argb_u16_to_RGB565(struct vkms_frame_info *frame_info,  		s64 fp_g = drm_int2fixp(in_pixels[x].g);  		s64 fp_b = drm_int2fixp(in_pixels[x].b); -		u16 r = drm_fixp2int(drm_fixp_div(fp_r, fp_rb_ratio)); -		u16 g = drm_fixp2int(drm_fixp_div(fp_g, fp_g_ratio)); -		u16 b = drm_fixp2int(drm_fixp_div(fp_b, fp_rb_ratio)); +		u16 r = drm_fixp2int_round(drm_fixp_div(fp_r, fp_rb_ratio)); +		u16 g = drm_fixp2int_round(drm_fixp_div(fp_g, fp_g_ratio)); +		u16 b = drm_fixp2int_round(drm_fixp_div(fp_b, fp_rb_ratio));  		*dst_pixels = cpu_to_le16(r << 11 | g << 5 | b);  	}  } -void *get_frame_to_line_function(u32 format) +void *get_pixel_conversion_function(u32 format)  {  	switch (format) {  	case DRM_FORMAT_ARGB8888: diff --git a/drivers/gpu/drm/vkms/vkms_formats.h b/drivers/gpu/drm/vkms/vkms_formats.h index 43b7c1979018..c5b113495d0c 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.h +++ b/drivers/gpu/drm/vkms/vkms_formats.h @@ -5,7 +5,7 @@  #include "vkms_drv.h" -void *get_frame_to_line_function(u32 format); +void *get_pixel_conversion_function(u32 format);  void *get_line_to_frame_function(u32 format); diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index c41cec7dcb70..e5c625ab8e3e 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -4,6 +4,7 @@  #include <drm/drm_atomic.h>  #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h>  #include <drm/drm_fourcc.h>  #include <drm/drm_gem_atomic_helper.h>  #include <drm/drm_gem_framebuffer_helper.h> @@ -12,12 +13,6 @@  #include "vkms_formats.h"  static const u32 vkms_formats[] = { -	DRM_FORMAT_XRGB8888, -	DRM_FORMAT_XRGB16161616, -	DRM_FORMAT_RGB565 -}; - -static const u32 vkms_plane_formats[] = {  	DRM_FORMAT_ARGB8888,  	DRM_FORMAT_XRGB8888,  	DRM_FORMAT_XRGB16161616, @@ -117,13 +112,23 @@ static void vkms_plane_atomic_update(struct drm_plane *plane,  	frame_info = vkms_plane_state->frame_info;  	memcpy(&frame_info->src, &new_state->src, sizeof(struct drm_rect));  	memcpy(&frame_info->dst, &new_state->dst, sizeof(struct drm_rect)); +	memcpy(&frame_info->rotated, &new_state->dst, sizeof(struct drm_rect));  	frame_info->fb = fb;  	memcpy(&frame_info->map, &shadow_plane_state->data, sizeof(frame_info->map));  	drm_framebuffer_get(frame_info->fb); +	frame_info->rotation = drm_rotation_simplify(new_state->rotation, DRM_MODE_ROTATE_0 | +						     DRM_MODE_ROTATE_90 | +						     DRM_MODE_ROTATE_270 | +						     DRM_MODE_REFLECT_X | +						     DRM_MODE_REFLECT_Y); + +	drm_rect_rotate(&frame_info->rotated, drm_rect_width(&frame_info->rotated), +			drm_rect_height(&frame_info->rotated), frame_info->rotation); +  	frame_info->offset = fb->offsets[0];  	frame_info->pitch = fb->pitches[0];  	frame_info->cpp = fb->format->cpp[0]; -	vkms_plane_state->plane_read = get_frame_to_line_function(fmt); +	vkms_plane_state->pixel_read = get_pixel_conversion_function(fmt);  }  static int vkms_plane_atomic_check(struct drm_plane *plane, @@ -185,7 +190,7 @@ static void vkms_cleanup_fb(struct drm_plane *plane,  	drm_gem_fb_vunmap(fb, shadow_plane_state->map);  } -static const struct drm_plane_helper_funcs vkms_primary_helper_funcs = { +static const struct drm_plane_helper_funcs vkms_plane_helper_funcs = {  	.atomic_update		= vkms_plane_atomic_update,  	.atomic_check		= vkms_plane_atomic_check,  	.prepare_fb		= vkms_prepare_fb, @@ -196,38 +201,19 @@ struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,  				   enum drm_plane_type type, int index)  {  	struct drm_device *dev = &vkmsdev->drm; -	const struct drm_plane_helper_funcs *funcs;  	struct vkms_plane *plane; -	const u32 *formats; -	int nformats; - -	switch (type) { -	case DRM_PLANE_TYPE_PRIMARY: -		formats = vkms_formats; -		nformats = ARRAY_SIZE(vkms_formats); -		funcs = &vkms_primary_helper_funcs; -		break; -	case DRM_PLANE_TYPE_CURSOR: -	case DRM_PLANE_TYPE_OVERLAY: -		formats = vkms_plane_formats; -		nformats = ARRAY_SIZE(vkms_plane_formats); -		funcs = &vkms_primary_helper_funcs; -		break; -	default: -		formats = vkms_formats; -		nformats = ARRAY_SIZE(vkms_formats); -		funcs = &vkms_primary_helper_funcs; -		break; -	}  	plane = drmm_universal_plane_alloc(dev, struct vkms_plane, base, 1 << index,  					   &vkms_plane_funcs, -					   formats, nformats, +					   vkms_formats, ARRAY_SIZE(vkms_formats),  					   NULL, type, NULL);  	if (IS_ERR(plane))  		return plane; -	drm_plane_helper_add(&plane->base, funcs); +	drm_plane_helper_add(&plane->base, &vkms_plane_helper_funcs); + +	drm_plane_create_rotation_property(&plane->base, DRM_MODE_ROTATE_0, +					   DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK);  	return plane;  } |