Created
August 3, 2021 15:32
-
-
Save darksylinc/8dc3fd06627970a90d8477c9b25f3093 to your computer and use it in GitHub Desktop.
Full RGB Kernel 5.13.7 patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | |
index 2a4cd7d377bf..62c6934a6244 100644 | |
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | |
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | |
@@ -1215,6 +1215,33 @@ static const struct drm_prop_enum_list amdgpu_dither_enum_list[] = | |
{ AMDGPU_FMT_DITHER_ENABLE, "on" }, | |
}; | |
+static const struct drm_prop_enum_list amdgpu_user_pixenc_list[] = { | |
+ { 0, "auto" }, | |
+ { DRM_COLOR_FORMAT_RGB444, "rgb" }, | |
+ { DRM_COLOR_FORMAT_YCRCB444, "ycbcr444" }, | |
+ { DRM_COLOR_FORMAT_YCRCB420, "ycbcr420" }, | |
+}; | |
+ | |
+bool amdgpu_user_pixenc_from_name( | |
+ unsigned int *user_pixenc, | |
+ const char *pixenc_name) | |
+{ | |
+ bool found = false; | |
+ | |
+ if (pixenc_name && (*pixenc_name != '\0')) { | |
+ const int sz = ARRAY_SIZE(amdgpu_user_pixenc_list); | |
+ int i; | |
+ | |
+ for (i = 0; !found && i < sz; ++i) { | |
+ if (strcmp(pixenc_name, amdgpu_user_pixenc_list[i].name) == 0) { | |
+ *user_pixenc = amdgpu_user_pixenc_list[i].type; | |
+ found = true; | |
+ } | |
+ } | |
+ } | |
+ return found; | |
+} | |
+ | |
int amdgpu_display_modeset_create_props(struct amdgpu_device *adev) | |
{ | |
int sz; | |
@@ -1267,6 +1294,14 @@ int amdgpu_display_modeset_create_props(struct amdgpu_device *adev) | |
"abm level", 0, 4); | |
if (!adev->mode_info.abm_level_property) | |
return -ENOMEM; | |
+ | |
+ sz = ARRAY_SIZE(amdgpu_user_pixenc_list); | |
+ adev->mode_info.pixel_encoding_property = | |
+ drm_property_create_enum(adev_to_drm(adev), 0, | |
+ "pixel encoding", | |
+ amdgpu_user_pixenc_list, sz); | |
+ if (!adev->mode_info.pixel_encoding_property) | |
+ return -ENOMEM; | |
} | |
return 0; | |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h | |
index 7b6d83e2b13c..f67ae02fb438 100644 | |
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h | |
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h | |
@@ -50,4 +50,7 @@ amdgpu_lookup_format_info(u32 format, uint64_t modifier); | |
int amdgpu_display_suspend_helper(struct amdgpu_device *adev); | |
int amdgpu_display_resume_helper(struct amdgpu_device *adev); | |
+bool amdgpu_user_pixenc_from_name(unsigned int *user_pixenc, | |
+ const char *pixenc_name); | |
+ | |
#endif | |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | |
index cb0b581bbce7..8c6ede86c524 100644 | |
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | |
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | |
@@ -337,6 +337,8 @@ struct amdgpu_mode_info { | |
struct drm_property *dither_property; | |
/* Adaptive Backlight Modulation (power feature) */ | |
struct drm_property *abm_level_property; | |
+ /* User HDMI pixel encoding override */ | |
+ struct drm_property *pixel_encoding_property; | |
/* hardcoded DFP edid from BIOS */ | |
struct edid *bios_hardcoded_edid; | |
int bios_hardcoded_edid_size; | |
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | |
index eeaae1cf2bc2..287fee85707c 100644 | |
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | |
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | |
@@ -5174,6 +5174,115 @@ static bool adjust_colour_depth_from_display_info( | |
return false; | |
} | |
+/* convert an pixel encoding property value to a dc_pixel_encoding */ | |
+static bool drm_prop_to_dc_pixel_encoding( | |
+ enum dc_pixel_encoding *dc_pixenc, | |
+ unsigned int propval) | |
+{ | |
+ bool ret = false; | |
+ | |
+ switch (propval) { | |
+ case 0: | |
+ *dc_pixenc = PIXEL_ENCODING_UNDEFINED; | |
+ ret = true; | |
+ break; | |
+ case DRM_COLOR_FORMAT_RGB444: | |
+ *dc_pixenc = PIXEL_ENCODING_RGB; | |
+ ret = true; | |
+ break; | |
+ case DRM_COLOR_FORMAT_YCRCB444: | |
+ *dc_pixenc = PIXEL_ENCODING_YCBCR444; | |
+ ret = true; | |
+ break; | |
+ case DRM_COLOR_FORMAT_YCRCB420: | |
+ *dc_pixenc = PIXEL_ENCODING_YCBCR420; | |
+ ret = true; | |
+ break; | |
+ default: | |
+ break; | |
+ } | |
+ return ret; | |
+} | |
+ | |
+/* convert an dc_pixel_encoding to a pixel encoding property value */ | |
+static unsigned int dc_pixel_encoding_to_drm_prop( | |
+ enum dc_pixel_encoding pixel_encoding) | |
+{ | |
+ unsigned int propval = 0; | |
+ | |
+ switch (pixel_encoding) { | |
+ case PIXEL_ENCODING_RGB: | |
+ propval = DRM_COLOR_FORMAT_RGB444; | |
+ break; | |
+ case PIXEL_ENCODING_YCBCR444: | |
+ propval = DRM_COLOR_FORMAT_YCRCB444; | |
+ break; | |
+ case PIXEL_ENCODING_YCBCR420: | |
+ propval = DRM_COLOR_FORMAT_YCRCB420; | |
+ break; | |
+ default: | |
+ break; | |
+ } | |
+ return propval; | |
+} | |
+ | |
+/* | |
+ * Tries to read 'pixel_encoding' from the pixel_encoding DRM property on | |
+ * 'state'. Returns true if a supported, acceptable, non-undefined value is | |
+ * found; false otherwise. Only modifies 'pixel_encoding' if returning true. | |
+ */ | |
+bool get_connector_state_pixel_encoding( | |
+ enum dc_pixel_encoding *pixel_encoding, | |
+ const struct drm_connector_state *state, | |
+ const struct drm_display_info *info, | |
+ const struct drm_display_mode *mode_in) | |
+{ | |
+ bool ret = false; | |
+ struct dm_connector_state *dm_state; | |
+ | |
+ dm_state = to_dm_connector_state(state); | |
+ if (!dm_state) | |
+ return false; | |
+ | |
+ /* check encoding is supported */ | |
+ switch (dm_state->pixel_encoding) { | |
+ case PIXEL_ENCODING_RGB: | |
+ ret = (info->color_formats & DRM_COLOR_FORMAT_RGB444); | |
+ break; | |
+ case PIXEL_ENCODING_YCBCR444: | |
+ ret = (info->color_formats & DRM_COLOR_FORMAT_YCRCB444); | |
+ break; | |
+ case PIXEL_ENCODING_YCBCR420: | |
+ ret = drm_mode_is_420(info, mode_in); | |
+ break; | |
+ default: | |
+ break; | |
+ } | |
+ | |
+ if (ret) | |
+ *pixel_encoding = dm_state->pixel_encoding; | |
+ | |
+ return ret; | |
+} | |
+ | |
+/* | |
+ * Writes 'pixel_encoding' to the pixel_encoding DRM property on 'state', if | |
+ * the enum value is valid and supported; otherwise writes | |
+ * PIXEL_ENCODING_UNDEFINED which corresponds to the "auto" property state. | |
+ */ | |
+void set_connector_state_pixel_encoding( | |
+ const struct drm_connector_state *state, | |
+ enum dc_pixel_encoding pixel_encoding) | |
+{ | |
+ struct dm_connector_state *dm_state; | |
+ | |
+ dm_state = to_dm_connector_state(state); | |
+ if (!dm_state) | |
+ return; | |
+ | |
+ dm_state->pixel_encoding = pixel_encoding; | |
+} | |
+ | |
static void fill_stream_properties_from_drm_display_mode( | |
struct dc_stream_state *stream, | |
const struct drm_display_mode *mode_in, | |
@@ -5195,18 +5304,21 @@ static void fill_stream_properties_from_drm_display_mode( | |
timing_out->h_border_right = 0; | |
timing_out->v_border_top = 0; | |
timing_out->v_border_bottom = 0; | |
- /* TODO: un-hardcode */ | |
- if (drm_mode_is_420_only(info, mode_in) | |
- && stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) | |
- timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420; | |
- else if (drm_mode_is_420_also(info, mode_in) | |
- && aconnector->force_yuv420_output) | |
- timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420; | |
- else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444) | |
- && stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) | |
- timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444; | |
- else | |
- timing_out->pixel_encoding = PIXEL_ENCODING_RGB; | |
+ | |
+ if (!get_connector_state_pixel_encoding(&timing_out->pixel_encoding, | |
+ connector_state, info, mode_in)) { | |
+ /* auto-select a pixel encoding */ | |
+ if (drm_mode_is_420_only(info, mode_in) && | |
+ stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) | |
+ timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420; | |
+ else if (drm_mode_is_420_also(info, mode_in) && aconnector->force_yuv420_output) | |
+ timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420; | |
+ else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444) | |
+ && stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) | |
+ timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444; | |
+ else | |
+ timing_out->pixel_encoding = PIXEL_ENCODING_RGB; | |
+ } | |
timing_out->timing_3d_format = TIMING_3D_FORMAT_NONE; | |
timing_out->display_color_depth = convert_color_depth_from_display_info( | |
@@ -5271,6 +5383,9 @@ static void fill_stream_properties_from_drm_display_mode( | |
adjust_colour_depth_from_display_info(timing_out, info); | |
} | |
} | |
+ | |
+ /* write back final choice of pixel encoding */ | |
+ set_connector_state_pixel_encoding(connector_state, timing_out->pixel_encoding); | |
} | |
static void fill_audio_info(struct audio_info *audio_info, | |
@@ -5946,6 +6061,9 @@ int amdgpu_dm_connector_atomic_set_property(struct drm_connector *connector, | |
} else if (property == adev->mode_info.abm_level_property) { | |
dm_new_state->abm_level = val; | |
ret = 0; | |
+ } else if (property == adev->mode_info.pixel_encoding_property) { | |
+ if (drm_prop_to_dc_pixel_encoding(&dm_new_state->pixel_encoding, val)) | |
+ ret = 0; | |
} | |
return ret; | |
@@ -5991,6 +6109,9 @@ int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector, | |
} else if (property == adev->mode_info.abm_level_property) { | |
*val = dm_state->abm_level; | |
ret = 0; | |
+ } else if (property == adev->mode_info.pixel_encoding_property) { | |
+ *val = dc_pixel_encoding_to_drm_prop(dm_state->pixel_encoding); | |
+ ret = 0; | |
} | |
return ret; | |
@@ -6070,6 +6191,20 @@ void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector) | |
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) | |
state->abm_level = amdgpu_dm_abm_level; | |
+ switch (connector->cmdline_mode.pixel_encoding) { | |
+ case DRM_COLOR_FORMAT_RGB444: | |
+ state->pixel_encoding = PIXEL_ENCODING_RGB; | |
+ break; | |
+ case DRM_COLOR_FORMAT_YCRCB444: | |
+ state->pixel_encoding = PIXEL_ENCODING_YCBCR444; | |
+ break; | |
+ case DRM_COLOR_FORMAT_YCRCB420: | |
+ state->pixel_encoding = PIXEL_ENCODING_YCBCR420; | |
+ break; | |
+ default: | |
+ break; | |
+ } | |
+ | |
__drm_atomic_helper_connector_reset(connector, &state->base); | |
} | |
} | |
@@ -6096,6 +6231,7 @@ amdgpu_dm_connector_atomic_duplicate_state(struct drm_connector *connector) | |
new_state->underscan_vborder = state->underscan_vborder; | |
new_state->vcpi_slots = state->vcpi_slots; | |
new_state->pbn = state->pbn; | |
+ new_state->pixel_encoding = state->pixel_encoding; | |
return &new_state->base; | |
} | |
@@ -7576,6 +7712,12 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, | |
if (adev->dm.hdcp_workqueue) | |
drm_connector_attach_content_protection_property(&aconnector->base, true); | |
#endif | |
+ | |
+ if (adev->mode_info.pixel_encoding_property) { | |
+ drm_object_attach_property(&aconnector->base.base, | |
+ adev->mode_info.pixel_encoding_property, 0); | |
+ DRM_DEBUG_DRIVER("amdgpu: attached pixel encoding drm property"); | |
+ } | |
} | |
} | |
@@ -8636,6 +8778,38 @@ static void amdgpu_dm_crtc_copy_transient_flags(struct drm_crtc_state *crtc_stat | |
stream_state->mode_changed = drm_atomic_crtc_needs_modeset(crtc_state); | |
} | |
+static void update_stream_for_pixel_encoding( | |
+ struct dc_stream_update *stream_update, | |
+ struct drm_connector *connector, | |
+ struct dm_crtc_state *dm_old_crtc_state, | |
+ struct dm_crtc_state *dm_new_crtc_state, | |
+ struct dm_connector_state *dm_new_con_state) | |
+{ | |
+ struct amdgpu_dm_connector *aconnector = | |
+ to_amdgpu_dm_connector(connector); | |
+ struct dc_stream_state *new_stream = NULL; | |
+ | |
+ if (aconnector) | |
+ new_stream = create_validate_stream_for_sink( | |
+ aconnector, | |
+ &dm_new_crtc_state->base.mode, | |
+ dm_new_con_state, | |
+ dm_old_crtc_state->stream); | |
+ if (new_stream) { | |
+ dm_new_crtc_state->stream->timing = | |
+ new_stream->timing; | |
+ stream_update->timing_for_pixel_encoding = | |
+ &dm_new_crtc_state->stream->timing; | |
+ | |
+ dm_new_crtc_state->stream->output_color_space = | |
+ new_stream->output_color_space; | |
+ stream_update->output_color_space = | |
+ &dm_new_crtc_state->stream->output_color_space; | |
+ | |
+ dc_stream_release(new_stream); | |
+ } | |
+} | |
+ | |
/** | |
* amdgpu_dm_atomic_commit_tail() - AMDgpu DM's commit tail implementation. | |
* @state: The atomic state to commit | |
@@ -8848,7 +9022,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) | |
struct dc_stream_update stream_update; | |
struct dc_info_packet hdr_packet; | |
struct dc_stream_status *status = NULL; | |
- bool abm_changed, hdr_changed, scaling_changed; | |
+ bool abm_changed, hdr_changed, scaling_changed, pixenc_changed; | |
memset(&dummy_updates, 0, sizeof(dummy_updates)); | |
memset(&stream_update, 0, sizeof(stream_update)); | |
@@ -8874,7 +9048,10 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) | |
hdr_changed = | |
is_hdr_metadata_different(old_con_state, new_con_state); | |
- if (!scaling_changed && !abm_changed && !hdr_changed) | |
+ pixenc_changed = dm_new_con_state->pixel_encoding != | |
+ dm_old_con_state->pixel_encoding; | |
+ | |
+ if (!scaling_changed && !abm_changed && !hdr_changed && !pixenc_changed) | |
continue; | |
stream_update.stream = dm_new_crtc_state->stream; | |
@@ -8897,6 +9074,13 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) | |
stream_update.hdr_static_metadata = &hdr_packet; | |
} | |
+ if (pixenc_changed) { | |
+ update_stream_for_pixel_encoding(&stream_update, | |
+ connector, | |
+ dm_old_crtc_state, dm_new_crtc_state, | |
+ dm_new_con_state); | |
+ } | |
+ | |
status = dc_stream_get_status(dm_new_crtc_state->stream); | |
WARN_ON(!status); | |
WARN_ON(!status->plane_count); | |
@@ -10044,6 +10228,12 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, | |
if (dm_old_con_state->abm_level != | |
dm_new_con_state->abm_level) | |
new_crtc_state->connectors_changed = true; | |
+ | |
+ if (dm_old_con_state->pixel_encoding != | |
+ dm_new_con_state->pixel_encoding) { | |
+ new_crtc_state->connectors_changed = true; | |
+ new_crtc_state->mode_changed = true; | |
+ } | |
} | |
#if defined(CONFIG_DRM_AMD_DC_DCN) | |
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | |
index c8e5bbbb8bce..cbbb22f06c32 100644 | |
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | |
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | |
@@ -541,6 +541,7 @@ struct dm_connector_state { | |
uint8_t abm_level; | |
int vcpi_slots; | |
uint64_t pbn; | |
+ enum dc_pixel_encoding pixel_encoding; | |
}; | |
struct amdgpu_hdmi_vsdb_info { | |
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c | |
index a869702d77af..3a3317dc8de5 100644 | |
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c | |
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c | |
@@ -2141,6 +2141,11 @@ static enum surface_update_type check_update_surfaces_for_stream( | |
if (stream_update->output_csc_transform || stream_update->output_color_space) | |
su_flags->bits.out_csc = 1; | |
+ | |
+ if (stream_update->timing_for_pixel_encoding) { | |
+ su_flags->bits.pixel_encoding = 1; | |
+ elevate_update_type(&overall_type, UPDATE_TYPE_FULL); | |
+ } | |
} | |
for (i = 0 ; i < surface_count; i++) { | |
@@ -2446,6 +2451,10 @@ static void copy_stream_update_to_stream(struct dc *dc, | |
update->dsc_config = NULL; | |
} | |
} | |
+ | |
+ if (update->timing_for_pixel_encoding) { | |
+ stream->timing = *update->timing_for_pixel_encoding; | |
+ } | |
} | |
static void commit_planes_do_stream_update(struct dc *dc, | |
@@ -2473,7 +2482,8 @@ static void commit_planes_do_stream_update(struct dc *dc, | |
if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) || | |
stream_update->vrr_infopacket || | |
stream_update->vsc_infopacket || | |
- stream_update->vsp_infopacket) { | |
+ stream_update->vsp_infopacket || | |
+ stream_update->timing_for_pixel_encoding) { | |
resource_build_info_frame(pipe_ctx); | |
dc->hwss.update_info_frame(pipe_ctx); | |
} | |
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h | |
index 13dae7238a58..d5f128a69452 100644 | |
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h | |
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h | |
@@ -125,6 +125,7 @@ union stream_update_flags { | |
uint32_t gamut_remap:1; | |
uint32_t wb_update:1; | |
uint32_t dsc_changed : 1; | |
+ uint32_t pixel_encoding:1; | |
} bits; | |
uint32_t raw; | |
@@ -277,6 +278,7 @@ struct dc_stream_update { | |
struct dc_dsc_config *dsc_config; | |
struct dc_transfer_func *func_shaper; | |
struct dc_3dlut *lut3d_func; | |
+ struct dc_crtc_timing *timing_for_pixel_encoding; | |
struct test_pattern *pending_test_pattern; | |
}; | |
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c | |
index 73e4de3c7f49..82d177a5af79 100644 | |
--- a/drivers/gpu/drm/drm_modes.c | |
+++ b/drivers/gpu/drm/drm_modes.c | |
@@ -1590,6 +1590,33 @@ static int drm_mode_parse_panel_orientation(const char *delim, | |
return 0; | |
} | |
+static int drm_mode_parse_pixel_encoding(const char *delim, | |
+ struct drm_cmdline_mode *mode) | |
+{ | |
+ const char *value; | |
+ | |
+ if (*delim != '=') | |
+ return -EINVAL; | |
+ | |
+ value = delim + 1; | |
+ delim = strchr(value, ','); | |
+ if (!delim) | |
+ delim = value + strlen(value); | |
+ | |
+ if (!strncmp(value, "auto", delim - value)) | |
+ mode->pixel_encoding = 0; | |
+ else if (!strncmp(value, "rgb", delim - value)) | |
+ mode->pixel_encoding = DRM_COLOR_FORMAT_RGB444; | |
+ else if (!strncmp(value, "ycbcr444", delim - value)) | |
+ mode->pixel_encoding = DRM_COLOR_FORMAT_YCRCB444; | |
+ else if (!strncmp(value, "ycbcr420", delim - value)) | |
+ mode->pixel_encoding = DRM_COLOR_FORMAT_YCRCB420; | |
+ else | |
+ return -EINVAL; | |
+ | |
+ return 0; | |
+} | |
+ | |
static int drm_mode_parse_cmdline_options(const char *str, | |
bool freestanding, | |
const struct drm_connector *connector, | |
@@ -1659,6 +1686,9 @@ static int drm_mode_parse_cmdline_options(const char *str, | |
} else if (!strncmp(option, "panel_orientation", delim - option)) { | |
if (drm_mode_parse_panel_orientation(delim, mode)) | |
return -EINVAL; | |
+ } else if (!strncmp(option, "pixel_encoding", delim - option)) { | |
+ if (drm_mode_parse_pixel_encoding(delim, mode)) | |
+ return -EINVAL; | |
} else { | |
return -EINVAL; | |
} | |
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h | |
index 1922b278ffad..433dc7a440d3 100644 | |
--- a/include/drm/drm_connector.h | |
+++ b/include/drm/drm_connector.h | |
@@ -1206,6 +1206,13 @@ struct drm_cmdline_mode { | |
* @tv_margins: TV margins to apply to the mode. | |
*/ | |
struct drm_connector_tv_margins tv_margins; | |
+ | |
+ /** | |
+ * @pixel_encoding: | |
+ * | |
+ * Initial pixel encoding. | |
+ */ | |
+ unsigned int pixel_encoding; | |
}; | |
/** |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | |
index 2a4cd7d377bf..62c6934a6244 100644 | |
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | |
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | |
@@ -1215,6 +1215,33 @@ static const struct drm_prop_enum_list amdgpu_dither_enum_list[] = | |
{ AMDGPU_FMT_DITHER_ENABLE, "on" }, | |
}; | |
+static const struct drm_prop_enum_list amdgpu_user_pixenc_list[] = { | |
+ { 0, "auto" }, | |
+ { DRM_COLOR_FORMAT_RGB444, "rgb" }, | |
+ { DRM_COLOR_FORMAT_YCRCB444, "ycbcr444" }, | |
+ { DRM_COLOR_FORMAT_YCRCB420, "ycbcr420" }, | |
+}; | |
+ | |
+bool amdgpu_user_pixenc_from_name( | |
+ unsigned int *user_pixenc, | |
+ const char *pixenc_name) | |
+{ | |
+ bool found = false; | |
+ | |
+ if (pixenc_name && (*pixenc_name != '\0')) { | |
+ const int sz = ARRAY_SIZE(amdgpu_user_pixenc_list); | |
+ int i; | |
+ | |
+ for (i = 0; !found && i < sz; ++i) { | |
+ if (strcmp(pixenc_name, amdgpu_user_pixenc_list[i].name) == 0) { | |
+ *user_pixenc = amdgpu_user_pixenc_list[i].type; | |
+ found = true; | |
+ } | |
+ } | |
+ } | |
+ return found; | |
+} | |
+ | |
int amdgpu_display_modeset_create_props(struct amdgpu_device *adev) | |
{ | |
int sz; | |
@@ -1267,6 +1294,14 @@ int amdgpu_display_modeset_create_props(struct amdgpu_device *adev) | |
"abm level", 0, 4); | |
if (!adev->mode_info.abm_level_property) | |
return -ENOMEM; | |
+ | |
+ sz = ARRAY_SIZE(amdgpu_user_pixenc_list); | |
+ adev->mode_info.pixel_encoding_property = | |
+ drm_property_create_enum(adev_to_drm(adev), 0, | |
+ "pixel encoding", | |
+ amdgpu_user_pixenc_list, sz); | |
+ if (!adev->mode_info.pixel_encoding_property) | |
+ return -ENOMEM; | |
} | |
return 0; | |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h | |
index 7b6d83e2b13c..f67ae02fb438 100644 | |
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h | |
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h | |
@@ -50,4 +50,7 @@ amdgpu_lookup_format_info(u32 format, uint64_t modifier); | |
int amdgpu_display_suspend_helper(struct amdgpu_device *adev); | |
int amdgpu_display_resume_helper(struct amdgpu_device *adev); | |
+bool amdgpu_user_pixenc_from_name(unsigned int *user_pixenc, | |
+ const char *pixenc_name); | |
+ | |
#endif | |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | |
index cb0b581bbce7..8c6ede86c524 100644 | |
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | |
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | |
@@ -337,6 +337,8 @@ struct amdgpu_mode_info { | |
struct drm_property *dither_property; | |
/* Adaptive Backlight Modulation (power feature) */ | |
struct drm_property *abm_level_property; | |
+ /* User HDMI pixel encoding override */ | |
+ struct drm_property *pixel_encoding_property; | |
/* hardcoded DFP edid from BIOS */ | |
struct edid *bios_hardcoded_edid; | |
int bios_hardcoded_edid_size; | |
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | |
index eeaae1cf2bc2..287fee85707c 100644 | |
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | |
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | |
@@ -5174,6 +5174,115 @@ static bool adjust_colour_depth_from_display_info( | |
return false; | |
} | |
+/* convert an pixel encoding property value to a dc_pixel_encoding */ | |
+static bool drm_prop_to_dc_pixel_encoding( | |
+ enum dc_pixel_encoding *dc_pixenc, | |
+ unsigned int propval) | |
+{ | |
+ bool ret = false; | |
+ | |
+ switch (propval) { | |
+ case 0: | |
+ *dc_pixenc = PIXEL_ENCODING_UNDEFINED; | |
+ ret = true; | |
+ break; | |
+ case DRM_COLOR_FORMAT_RGB444: | |
+ *dc_pixenc = PIXEL_ENCODING_RGB; | |
+ ret = true; | |
+ break; | |
+ case DRM_COLOR_FORMAT_YCRCB444: | |
+ *dc_pixenc = PIXEL_ENCODING_YCBCR444; | |
+ ret = true; | |
+ break; | |
+ case DRM_COLOR_FORMAT_YCRCB420: | |
+ *dc_pixenc = PIXEL_ENCODING_YCBCR420; | |
+ ret = true; | |
+ break; | |
+ default: | |
+ break; | |
+ } | |
+ return ret; | |
+} | |
+ | |
+/* convert an dc_pixel_encoding to a pixel encoding property value */ | |
+static unsigned int dc_pixel_encoding_to_drm_prop( | |
+ enum dc_pixel_encoding pixel_encoding) | |
+{ | |
+ unsigned int propval = 0; | |
+ | |
+ switch (pixel_encoding) { | |
+ case PIXEL_ENCODING_RGB: | |
+ propval = DRM_COLOR_FORMAT_RGB444; | |
+ break; | |
+ case PIXEL_ENCODING_YCBCR444: | |
+ propval = DRM_COLOR_FORMAT_YCRCB444; | |
+ break; | |
+ case PIXEL_ENCODING_YCBCR420: | |
+ propval = DRM_COLOR_FORMAT_YCRCB420; | |
+ break; | |
+ default: | |
+ break; | |
+ } | |
+ return propval; | |
+} | |
+ | |
+/* | |
+ * Tries to read 'pixel_encoding' from the pixel_encoding DRM property on | |
+ * 'state'. Returns true if a supported, acceptable, non-undefined value is | |
+ * found; false otherwise. Only modifies 'pixel_encoding' if returning true. | |
+ */ | |
+bool get_connector_state_pixel_encoding( | |
+ enum dc_pixel_encoding *pixel_encoding, | |
+ const struct drm_connector_state *state, | |
+ const struct drm_display_info *info, | |
+ const struct drm_display_mode *mode_in) | |
+{ | |
+ bool ret = false; | |
+ struct dm_connector_state *dm_state; | |
+ | |
+ dm_state = to_dm_connector_state(state); | |
+ if (!dm_state) | |
+ return false; | |
+ | |
+ /* check encoding is supported */ | |
+ switch (dm_state->pixel_encoding) { | |
+ case PIXEL_ENCODING_RGB: | |
+ ret = (info->color_formats & DRM_COLOR_FORMAT_RGB444); | |
+ break; | |
+ case PIXEL_ENCODING_YCBCR444: | |
+ ret = (info->color_formats & DRM_COLOR_FORMAT_YCRCB444); | |
+ break; | |
+ case PIXEL_ENCODING_YCBCR420: | |
+ ret = drm_mode_is_420(info, mode_in); | |
+ break; | |
+ default: | |
+ break; | |
+ } | |
+ | |
+ if (ret) | |
+ *pixel_encoding = dm_state->pixel_encoding; | |
+ | |
+ return ret; | |
+} | |
+ | |
+/* | |
+ * Writes 'pixel_encoding' to the pixel_encoding DRM property on 'state', if | |
+ * the enum value is valid and supported; otherwise writes | |
+ * PIXEL_ENCODING_UNDEFINED which corresponds to the "auto" property state. | |
+ */ | |
+void set_connector_state_pixel_encoding( | |
+ const struct drm_connector_state *state, | |
+ enum dc_pixel_encoding pixel_encoding) | |
+{ | |
+ struct dm_connector_state *dm_state; | |
+ | |
+ dm_state = to_dm_connector_state(state); | |
+ if (!dm_state) | |
+ return; | |
+ | |
+ dm_state->pixel_encoding = pixel_encoding; | |
+} | |
+ | |
static void fill_stream_properties_from_drm_display_mode( | |
struct dc_stream_state *stream, | |
const struct drm_display_mode *mode_in, | |
@@ -5195,18 +5304,21 @@ static void fill_stream_properties_from_drm_display_mode( | |
timing_out->h_border_right = 0; | |
timing_out->v_border_top = 0; | |
timing_out->v_border_bottom = 0; | |
- /* TODO: un-hardcode */ | |
- if (drm_mode_is_420_only(info, mode_in) | |
- && stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) | |
- timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420; | |
- else if (drm_mode_is_420_also(info, mode_in) | |
- && aconnector->force_yuv420_output) | |
- timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420; | |
- else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444) | |
- && stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) | |
- timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444; | |
- else | |
- timing_out->pixel_encoding = PIXEL_ENCODING_RGB; | |
+ | |
+ if (!get_connector_state_pixel_encoding(&timing_out->pixel_encoding, | |
+ connector_state, info, mode_in)) { | |
+ /* auto-select a pixel encoding */ | |
+ if (drm_mode_is_420_only(info, mode_in) && | |
+ stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) | |
+ timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420; | |
+ else if (drm_mode_is_420_also(info, mode_in) && aconnector->force_yuv420_output) | |
+ timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420; | |
+ else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444) | |
+ && stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) | |
+ timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444; | |
+ else | |
+ timing_out->pixel_encoding = PIXEL_ENCODING_RGB; | |
+ } | |
timing_out->timing_3d_format = TIMING_3D_FORMAT_NONE; | |
timing_out->display_color_depth = convert_color_depth_from_display_info( | |
@@ -5271,6 +5383,9 @@ static void fill_stream_properties_from_drm_display_mode( | |
adjust_colour_depth_from_display_info(timing_out, info); | |
} | |
} | |
+ | |
+ /* write back final choice of pixel encoding */ | |
+ set_connector_state_pixel_encoding(connector_state, timing_out->pixel_encoding); | |
} | |
static void fill_audio_info(struct audio_info *audio_info, | |
@@ -5946,6 +6061,9 @@ int amdgpu_dm_connector_atomic_set_property(struct drm_connector *connector, | |
} else if (property == adev->mode_info.abm_level_property) { | |
dm_new_state->abm_level = val; | |
ret = 0; | |
+ } else if (property == adev->mode_info.pixel_encoding_property) { | |
+ if (drm_prop_to_dc_pixel_encoding(&dm_new_state->pixel_encoding, val)) | |
+ ret = 0; | |
} | |
return ret; | |
@@ -5991,6 +6109,9 @@ int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector, | |
} else if (property == adev->mode_info.abm_level_property) { | |
*val = dm_state->abm_level; | |
ret = 0; | |
+ } else if (property == adev->mode_info.pixel_encoding_property) { | |
+ *val = dc_pixel_encoding_to_drm_prop(dm_state->pixel_encoding); | |
+ ret = 0; | |
} | |
return ret; | |
@@ -6070,6 +6191,20 @@ void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector) | |
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) | |
state->abm_level = amdgpu_dm_abm_level; | |
+ switch (connector->cmdline_mode.pixel_encoding) { | |
+ case DRM_COLOR_FORMAT_RGB444: | |
+ state->pixel_encoding = PIXEL_ENCODING_RGB; | |
+ break; | |
+ case DRM_COLOR_FORMAT_YCRCB444: | |
+ state->pixel_encoding = PIXEL_ENCODING_YCBCR444; | |
+ break; | |
+ case DRM_COLOR_FORMAT_YCRCB420: | |
+ state->pixel_encoding = PIXEL_ENCODING_YCBCR420; | |
+ break; | |
+ default: | |
+ break; | |
+ } | |
+ | |
__drm_atomic_helper_connector_reset(connector, &state->base); | |
} | |
} | |
@@ -6096,6 +6231,7 @@ amdgpu_dm_connector_atomic_duplicate_state(struct drm_connector *connector) | |
new_state->underscan_vborder = state->underscan_vborder; | |
new_state->vcpi_slots = state->vcpi_slots; | |
new_state->pbn = state->pbn; | |
+ new_state->pixel_encoding = state->pixel_encoding; | |
return &new_state->base; | |
} | |
@@ -7576,6 +7712,12 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, | |
if (adev->dm.hdcp_workqueue) | |
drm_connector_attach_content_protection_property(&aconnector->base, true); | |
#endif | |
+ | |
+ if (adev->mode_info.pixel_encoding_property) { | |
+ drm_object_attach_property(&aconnector->base.base, | |
+ adev->mode_info.pixel_encoding_property, 0); | |
+ DRM_DEBUG_DRIVER("amdgpu: attached pixel encoding drm property"); | |
+ } | |
} | |
} | |
@@ -8636,6 +8778,38 @@ static void amdgpu_dm_crtc_copy_transient_flags(struct drm_crtc_state *crtc_stat | |
stream_state->mode_changed = drm_atomic_crtc_needs_modeset(crtc_state); | |
} | |
+static void update_stream_for_pixel_encoding( | |
+ struct dc_stream_update *stream_update, | |
+ struct drm_connector *connector, | |
+ struct dm_crtc_state *dm_old_crtc_state, | |
+ struct dm_crtc_state *dm_new_crtc_state, | |
+ struct dm_connector_state *dm_new_con_state) | |
+{ | |
+ struct amdgpu_dm_connector *aconnector = | |
+ to_amdgpu_dm_connector(connector); | |
+ struct dc_stream_state *new_stream = NULL; | |
+ | |
+ if (aconnector) | |
+ new_stream = create_validate_stream_for_sink( | |
+ aconnector, | |
+ &dm_new_crtc_state->base.mode, | |
+ dm_new_con_state, | |
+ dm_old_crtc_state->stream); | |
+ if (new_stream) { | |
+ dm_new_crtc_state->stream->timing = | |
+ new_stream->timing; | |
+ stream_update->timing_for_pixel_encoding = | |
+ &dm_new_crtc_state->stream->timing; | |
+ | |
+ dm_new_crtc_state->stream->output_color_space = | |
+ new_stream->output_color_space; | |
+ stream_update->output_color_space = | |
+ &dm_new_crtc_state->stream->output_color_space; | |
+ | |
+ dc_stream_release(new_stream); | |
+ } | |
+} | |
+ | |
/** | |
* amdgpu_dm_atomic_commit_tail() - AMDgpu DM's commit tail implementation. | |
* @state: The atomic state to commit | |
@@ -8848,7 +9022,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) | |
struct dc_stream_update stream_update; | |
struct dc_info_packet hdr_packet; | |
struct dc_stream_status *status = NULL; | |
- bool abm_changed, hdr_changed, scaling_changed; | |
+ bool abm_changed, hdr_changed, scaling_changed, pixenc_changed; | |
memset(&dummy_updates, 0, sizeof(dummy_updates)); | |
memset(&stream_update, 0, sizeof(stream_update)); | |
@@ -8874,7 +9048,10 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) | |
hdr_changed = | |
is_hdr_metadata_different(old_con_state, new_con_state); | |
- if (!scaling_changed && !abm_changed && !hdr_changed) | |
+ pixenc_changed = dm_new_con_state->pixel_encoding != | |
+ dm_old_con_state->pixel_encoding; | |
+ | |
+ if (!scaling_changed && !abm_changed && !hdr_changed && !pixenc_changed) | |
continue; | |
stream_update.stream = dm_new_crtc_state->stream; | |
@@ -8897,6 +9074,13 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) | |
stream_update.hdr_static_metadata = &hdr_packet; | |
} | |
+ if (pixenc_changed) { | |
+ update_stream_for_pixel_encoding(&stream_update, | |
+ connector, | |
+ dm_old_crtc_state, dm_new_crtc_state, | |
+ dm_new_con_state); | |
+ } | |
+ | |
status = dc_stream_get_status(dm_new_crtc_state->stream); | |
WARN_ON(!status); | |
WARN_ON(!status->plane_count); | |
@@ -10044,6 +10228,12 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, | |
if (dm_old_con_state->abm_level != | |
dm_new_con_state->abm_level) | |
new_crtc_state->connectors_changed = true; | |
+ | |
+ if (dm_old_con_state->pixel_encoding != | |
+ dm_new_con_state->pixel_encoding) { | |
+ new_crtc_state->connectors_changed = true; | |
+ new_crtc_state->mode_changed = true; | |
+ } | |
} | |
#if defined(CONFIG_DRM_AMD_DC_DCN) | |
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | |
index c8e5bbbb8bce..cbbb22f06c32 100644 | |
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | |
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | |
@@ -541,6 +541,7 @@ struct dm_connector_state { | |
uint8_t abm_level; | |
int vcpi_slots; | |
uint64_t pbn; | |
+ enum dc_pixel_encoding pixel_encoding; | |
}; | |
struct amdgpu_hdmi_vsdb_info { | |
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c | |
index a869702d77af..3a3317dc8de5 100644 | |
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c | |
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c | |
@@ -2141,6 +2141,11 @@ static enum surface_update_type check_update_surfaces_for_stream( | |
if (stream_update->output_csc_transform || stream_update->output_color_space) | |
su_flags->bits.out_csc = 1; | |
+ | |
+ if (stream_update->timing_for_pixel_encoding) { | |
+ su_flags->bits.pixel_encoding = 1; | |
+ elevate_update_type(&overall_type, UPDATE_TYPE_FULL); | |
+ } | |
} | |
for (i = 0 ; i < surface_count; i++) { | |
@@ -2446,6 +2451,10 @@ static void copy_stream_update_to_stream(struct dc *dc, | |
update->dsc_config = NULL; | |
} | |
} | |
+ | |
+ if (update->timing_for_pixel_encoding) { | |
+ stream->timing = *update->timing_for_pixel_encoding; | |
+ } | |
} | |
static void commit_planes_do_stream_update(struct dc *dc, | |
@@ -2473,7 +2482,8 @@ static void commit_planes_do_stream_update(struct dc *dc, | |
if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) || | |
stream_update->vrr_infopacket || | |
stream_update->vsc_infopacket || | |
- stream_update->vsp_infopacket) { | |
+ stream_update->vsp_infopacket || | |
+ stream_update->timing_for_pixel_encoding) { | |
resource_build_info_frame(pipe_ctx); | |
dc->hwss.update_info_frame(pipe_ctx); | |
} | |
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h | |
index 13dae7238a58..d5f128a69452 100644 | |
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h | |
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h | |
@@ -125,6 +125,7 @@ union stream_update_flags { | |
uint32_t gamut_remap:1; | |
uint32_t wb_update:1; | |
uint32_t dsc_changed : 1; | |
+ uint32_t pixel_encoding:1; | |
} bits; | |
uint32_t raw; | |
@@ -277,6 +278,7 @@ struct dc_stream_update { | |
struct dc_dsc_config *dsc_config; | |
struct dc_transfer_func *func_shaper; | |
struct dc_3dlut *lut3d_func; | |
+ struct dc_crtc_timing *timing_for_pixel_encoding; | |
struct test_pattern *pending_test_pattern; | |
}; | |
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c | |
index 73e4de3c7f49..82d177a5af79 100644 | |
--- a/drivers/gpu/drm/drm_modes.c | |
+++ b/drivers/gpu/drm/drm_modes.c | |
@@ -1590,6 +1590,33 @@ static int drm_mode_parse_panel_orientation(const char *delim, | |
return 0; | |
} | |
+static int drm_mode_parse_pixel_encoding(const char *delim, | |
+ struct drm_cmdline_mode *mode) | |
+{ | |
+ const char *value; | |
+ | |
+ if (*delim != '=') | |
+ return -EINVAL; | |
+ | |
+ value = delim + 1; | |
+ delim = strchr(value, ','); | |
+ if (!delim) | |
+ delim = value + strlen(value); | |
+ | |
+ if (!strncmp(value, "auto", delim - value)) | |
+ mode->pixel_encoding = 0; | |
+ else if (!strncmp(value, "rgb", delim - value)) | |
+ mode->pixel_encoding = DRM_COLOR_FORMAT_RGB444; | |
+ else if (!strncmp(value, "ycbcr444", delim - value)) | |
+ mode->pixel_encoding = DRM_COLOR_FORMAT_YCRCB444; | |
+ else if (!strncmp(value, "ycbcr420", delim - value)) | |
+ mode->pixel_encoding = DRM_COLOR_FORMAT_YCRCB420; | |
+ else | |
+ return -EINVAL; | |
+ | |
+ return 0; | |
+} | |
+ | |
static int drm_mode_parse_cmdline_options(const char *str, | |
bool freestanding, | |
const struct drm_connector *connector, | |
@@ -1659,6 +1686,9 @@ static int drm_mode_parse_cmdline_options(const char *str, | |
} else if (!strncmp(option, "panel_orientation", delim - option)) { | |
if (drm_mode_parse_panel_orientation(delim, mode)) | |
return -EINVAL; | |
+ } else if (!strncmp(option, "pixel_encoding", delim - option)) { | |
+ if (drm_mode_parse_pixel_encoding(delim, mode)) | |
+ return -EINVAL; | |
} else { | |
return -EINVAL; | |
} | |
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h | |
index 1922b278ffad..433dc7a440d3 100644 | |
--- a/include/drm/drm_connector.h | |
+++ b/include/drm/drm_connector.h | |
@@ -1206,6 +1206,13 @@ struct drm_cmdline_mode { | |
* @tv_margins: TV margins to apply to the mode. | |
*/ | |
struct drm_connector_tv_margins tv_margins; | |
+ | |
+ /** | |
+ * @pixel_encoding: | |
+ * | |
+ * Initial pixel encoding. | |
+ */ | |
+ unsigned int pixel_encoding; | |
}; | |
/** |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment