Advertise the supported values and add the conversion matrix of the currently selected values to writeback jobs.
This does not have any effect yet as no YUV/YCbCr formats are advertised. Signed-off-by: Robert Mader <robert.ma...@collabora.com> --- drivers/gpu/drm/vkms/vkms_drv.h | 33 ++++++++--------- drivers/gpu/drm/vkms/vkms_writeback.c | 51 +++++++++++++++++++++++++-- 2 files changed, 66 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 8013c31efe3b..7fa58e17c286 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -81,10 +81,27 @@ struct line_buffer { */ typedef void (*pixel_write_t)(u8 *out_pixel, const struct pixel_argb_u16 *in_pixel); +/** + * struct conversion_matrix - Matrix to use for a specific encoding and range + * + * @matrix: Conversion matrix from yuv to rgb. The matrix is stored in a row-major manner and is + * used to compute rgb values from yuv values: + * [[r],[g],[b]] = @matrix * [[y],[u],[v]] + * OR for yvu formats: + * [[r],[g],[b]] = @matrix * [[y],[v],[u]] + * The values of the matrix are signed fixed-point values with 32 bits fractional part. + * @y_offset: Offset to apply on the y value. + */ +struct conversion_matrix { + s64 matrix[3][3]; + int y_offset; +}; + struct vkms_writeback_job { struct iosys_map data[DRM_FORMAT_MAX_PLANES]; struct vkms_frame_info wb_frame_info; pixel_write_t pixel_write; + struct conversion_matrix conversion_matrix; }; /** @@ -119,22 +136,6 @@ typedef void (*pixel_read_line_t)(const struct vkms_plane_state *plane, int x_st int y_start, enum pixel_read_direction direction, int count, struct pixel_argb_u16 out_pixel[]); -/** - * struct conversion_matrix - Matrix to use for a specific encoding and range - * - * @matrix: Conversion matrix from yuv to rgb. The matrix is stored in a row-major manner and is - * used to compute rgb values from yuv values: - * [[r],[g],[b]] = @matrix * [[y],[u],[v]] - * OR for yvu formats: - * [[r],[g],[b]] = @matrix * [[y],[v],[u]] - * The values of the matrix are signed fixed-point values with 32 bits fractional part. - * @y_offset: Offset to apply on the y value. - */ -struct conversion_matrix { - s64 matrix[3][3]; - int y_offset; -}; - /** * struct vkms_plane_state - Driver specific plane state * @base: base plane state diff --git a/drivers/gpu/drm/vkms/vkms_writeback.c b/drivers/gpu/drm/vkms/vkms_writeback.c index 45d69a3b85f6..59e7a980533c 100644 --- a/drivers/gpu/drm/vkms/vkms_writeback.c +++ b/drivers/gpu/drm/vkms/vkms_writeback.c @@ -14,6 +14,9 @@ #include "vkms_drv.h" #include "vkms_formats.h" +#define DEFAULT_COLOR_ENCODING DRM_COLOR_YCBCR_BT601 +#define DEFAULT_COLOR_RANGE DRM_COLOR_YCBCR_LIMITED_RANGE + static const u32 vkms_wb_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888, @@ -23,9 +26,17 @@ static const u32 vkms_wb_formats[] = { DRM_FORMAT_RGB565 }; +static void vkms_wb_connector_reset(struct drm_connector *connector) +{ + drm_atomic_helper_connector_reset(connector); + + connector->state->writeback_color_encoding = DEFAULT_COLOR_ENCODING; + connector->state->writeback_color_range = DEFAULT_COLOR_RANGE; +} + static const struct drm_connector_funcs vkms_wb_connector_funcs = { .fill_modes = drm_helper_probe_single_connector_modes, - .reset = drm_atomic_helper_connector_reset, + .reset = vkms_wb_connector_reset, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; @@ -60,6 +71,21 @@ static int vkms_wb_atomic_check(struct drm_connector *connector, if (ret < 0) return ret; + if (conn_state->writeback_color_encoding != DRM_COLOR_YCBCR_BT601 && + conn_state->writeback_color_encoding != DRM_COLOR_YCBCR_BT709 && + conn_state->writeback_color_encoding != DRM_COLOR_YCBCR_BT2020) { + DRM_DEBUG_KMS("Invalid color encoding %u\n", + conn_state->writeback_color_encoding); + return -EINVAL; + } + + if (conn_state->writeback_color_range != DRM_COLOR_YCBCR_LIMITED_RANGE && + conn_state->writeback_color_range != DRM_COLOR_YCBCR_FULL_RANGE) { + DRM_DEBUG_KMS("Invalid color range %u\n", + conn_state->writeback_color_range); + return -EINVAL; + } + return 0; } @@ -151,6 +177,10 @@ static void vkms_wb_atomic_commit(struct drm_connector *conn, spin_unlock_irq(&output->composer_lock); drm_writeback_queue_job(wb_conn, connector_state); active_wb->pixel_write = get_pixel_write_function(wb_format); + get_conversion_matrix_from_argb_u16(wb_format, + conn_state->writeback_color_encoding, + conn_state->writeback_color_range, + &active_wb->conversion_matrix); drm_rect_init(&wb_frame_info->src, 0, 0, crtc_width, crtc_height); drm_rect_init(&wb_frame_info->dst, 0, 0, crtc_width, crtc_height); } @@ -179,9 +209,26 @@ int vkms_enable_writeback_connector(struct vkms_device *vkmsdev, drm_connector_helper_add(&wb->base, &vkms_wb_conn_helper_funcs); - return drmm_writeback_connector_init(&vkmsdev->drm, wb, + ret = drmm_writeback_connector_init(&vkmsdev->drm, wb, &vkms_wb_connector_funcs, &vkms_output->wb_encoder, vkms_wb_formats, ARRAY_SIZE(vkms_wb_formats)); + if (ret) + return ret; + + ret = drm_writeback_create_color_properties(wb, + BIT(DRM_COLOR_YCBCR_BT601) | + BIT(DRM_COLOR_YCBCR_BT709) | + BIT(DRM_COLOR_YCBCR_BT2020), + BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | + BIT(DRM_COLOR_YCBCR_FULL_RANGE), + DEFAULT_COLOR_ENCODING, + DEFAULT_COLOR_RANGE); + if (ret) { + DRM_ERROR("adding color properties failed: %d\n", ret); + return ret; + } + + return 0; } -- 2.50.1