Update to 6.4 RC5

This commit is contained in:
ferrreo 2023-06-06 17:53:04 +01:00
parent 8d7ed18c6a
commit 22e99d6027
13 changed files with 4436 additions and 20285 deletions

390
config

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,912 +0,0 @@
From 9cab14aa7f6828572f808d1bea60def5f883522c Mon Sep 17 00:00:00 2001
From: Peter Jung <admin@ptr1337.dev>
Date: Sun, 22 Jan 2023 23:10:03 +0100
Subject: [PATCH 08/16] hdr
Signed-off-by: Peter Jung <admin@ptr1337.dev>
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 110 ++++++++---
.../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 57 ++++++
.../gpu/drm/amd/display/dc/core/dc_resource.c | 100 ++++------
drivers/gpu/drm/amd/display/dc/dc_stream.h | 2 +-
drivers/gpu/drm/amd/display/dc/dc_types.h | 14 --
drivers/gpu/drm/display/drm_hdmi_helper.c | 8 +-
drivers/gpu/drm/drm_atomic.c | 2 +
drivers/gpu/drm/drm_connector.c | 181 ++++++++++--------
.../gpu/drm/i915/display/intel_connector.c | 4 +-
drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +-
include/drm/display/drm_dp.h | 2 +-
include/drm/drm_connector.h | 57 +++---
12 files changed, 327 insertions(+), 212 deletions(-)
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 93dee3d1a483..b5eb33a97590 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -5172,21 +5172,46 @@ get_aspect_ratio(const struct drm_display_mode *mode_in)
}
static enum dc_color_space
-get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing)
+get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing,
+ const struct drm_connector_state *connector_state)
{
enum dc_color_space color_space = COLOR_SPACE_SRGB;
- switch (dc_crtc_timing->pixel_encoding) {
- case PIXEL_ENCODING_YCBCR422:
- case PIXEL_ENCODING_YCBCR444:
- case PIXEL_ENCODING_YCBCR420:
- {
+ switch (connector_state->colorspace) {
+ case DRM_MODE_COLORIMETRY_BT601_YCC:
+ if (dc_crtc_timing->flags.Y_ONLY)
+ color_space = COLOR_SPACE_YCBCR601_LIMITED;
+ else
+ color_space = COLOR_SPACE_YCBCR601;
+ break;
+ case DRM_MODE_COLORIMETRY_BT709_YCC:
+ if (dc_crtc_timing->flags.Y_ONLY)
+ color_space = COLOR_SPACE_YCBCR709_LIMITED;
+ else
+ color_space = COLOR_SPACE_YCBCR709;
+ break;
+ case DRM_MODE_COLORIMETRY_OPRGB:
+ color_space = COLOR_SPACE_ADOBERGB;
+ break;
+ case DRM_MODE_COLORIMETRY_BT2020_RGB:
+ if (dc_crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB)
+ color_space = COLOR_SPACE_2020_RGB_FULLRANGE;
+ else
+ color_space = COLOR_SPACE_2020_YCBCR;
+ break;
+ case DRM_MODE_COLORIMETRY_BT2020_YCC:
+ color_space = COLOR_SPACE_2020_YCBCR;
+ break;
+ case DRM_MODE_COLORIMETRY_DEFAULT: // ITU601
+ default:
+ if (dc_crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB) {
+ color_space = COLOR_SPACE_SRGB;
/*
* 27030khz is the separation point between HDTV and SDTV
* according to HDMI spec, we use YCbCr709 and YCbCr601
* respectively
*/
- if (dc_crtc_timing->pix_clk_100hz > 270300) {
+ } else if (dc_crtc_timing->pix_clk_100hz > 270300) {
if (dc_crtc_timing->flags.Y_ONLY)
color_space =
COLOR_SPACE_YCBCR709_LIMITED;
@@ -5199,21 +5224,30 @@ get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing)
else
color_space = COLOR_SPACE_YCBCR601;
}
-
- }
- break;
- case PIXEL_ENCODING_RGB:
- color_space = COLOR_SPACE_SRGB;
- break;
-
- default:
- WARN_ON(1);
break;
}
return color_space;
}
+static enum display_content_type
+get_output_content_type(const struct drm_connector_state *connector_state)
+{
+ switch (connector_state->content_type) {
+ default:
+ case DRM_MODE_CONTENT_TYPE_NO_DATA:
+ return DISPLAY_CONTENT_TYPE_NO_DATA;
+ case DRM_MODE_CONTENT_TYPE_GRAPHICS:
+ return DISPLAY_CONTENT_TYPE_GRAPHICS;
+ case DRM_MODE_CONTENT_TYPE_PHOTO:
+ return DISPLAY_CONTENT_TYPE_PHOTO;
+ case DRM_MODE_CONTENT_TYPE_CINEMA:
+ return DISPLAY_CONTENT_TYPE_CINEMA;
+ case DRM_MODE_CONTENT_TYPE_GAME:
+ return DISPLAY_CONTENT_TYPE_GAME;
+ }
+}
+
static bool adjust_colour_depth_from_display_info(
struct dc_crtc_timing *timing_out,
const struct drm_display_info *info)
@@ -5307,6 +5341,7 @@ static void fill_stream_properties_from_drm_display_mode(
if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) {
drm_hdmi_avi_infoframe_from_display_mode(&avi_frame, (struct drm_connector *)connector, mode_in);
timing_out->vic = avi_frame.video_code;
+ drm_hdmi_avi_infoframe_colorimetry(&avi_frame, connector_state);
drm_hdmi_vendor_infoframe_from_display_mode(&hv_frame, (struct drm_connector *)connector, mode_in);
timing_out->hdmi_vic = hv_frame.vic;
}
@@ -5346,7 +5381,8 @@ static void fill_stream_properties_from_drm_display_mode(
}
}
- stream->output_color_space = get_output_color_space(timing_out);
+ stream->output_color_space = get_output_color_space(timing_out, connector_state);
+ stream->content_type = get_output_content_type(connector_state);
}
static void fill_audio_info(struct audio_info *audio_info,
@@ -5786,15 +5822,14 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
{
struct drm_display_mode *preferred_mode = NULL;
struct drm_connector *drm_connector;
- const struct drm_connector_state *con_state =
- dm_state ? &dm_state->base : NULL;
+ const struct drm_connector_state *con_state = &dm_state->base;
struct dc_stream_state *stream = NULL;
struct drm_display_mode mode;
struct drm_display_mode saved_mode;
struct drm_display_mode *freesync_mode = NULL;
bool native_mode_found = false;
bool recalculate_timing = false;
- bool scale = dm_state ? (dm_state->scaling != RMX_OFF) : false;
+ bool scale = dm_state->scaling != RMX_OFF;
int mode_refresh;
int preferred_refresh = 0;
enum color_transfer_func tf = TRANSFER_FUNC_UNKNOWN;
@@ -5875,7 +5910,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
if (recalculate_timing)
drm_mode_set_crtcinfo(&saved_mode, 0);
- else if (!dm_state)
+ else
drm_mode_set_crtcinfo(&mode, 0);
/*
@@ -6404,7 +6439,9 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec
goto fail;
}
- stream = create_validate_stream_for_sink(aconnector, mode, NULL, NULL);
+ stream = create_validate_stream_for_sink(aconnector, mode,
+ to_dm_connector_state(connector->state),
+ NULL);
if (stream) {
dc_stream_release(stream);
result = MODE_OK;
@@ -6498,6 +6535,14 @@ amdgpu_dm_connector_atomic_check(struct drm_connector *conn,
if (!crtc)
return 0;
+ if (new_con_state->colorspace != old_con_state->colorspace) {
+ new_crtc_state = drm_atomic_get_crtc_state(state, crtc);
+ if (IS_ERR(new_crtc_state))
+ return PTR_ERR(new_crtc_state);
+
+ new_crtc_state->mode_changed = true;
+ }
+
if (!drm_connector_atomic_hdr_metadata_equal(old_con_state, new_con_state)) {
struct dc_info_packet hdr_infopacket;
@@ -6520,7 +6565,7 @@ amdgpu_dm_connector_atomic_check(struct drm_connector *conn,
* set is permissible, however. So only force a
* modeset if we're entering or exiting HDR.
*/
- new_crtc_state->mode_changed =
+ new_crtc_state->mode_changed = new_crtc_state->mode_changed ||
!old_con_state->hdr_output_metadata ||
!new_con_state->hdr_output_metadata;
}
@@ -7041,6 +7086,12 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
return amdgpu_dm_connector->num_modes;
}
+static const u32 supported_colorspaces =
+ BIT(DRM_MODE_COLORIMETRY_BT709_YCC) |
+ BIT(DRM_MODE_COLORIMETRY_OPRGB) |
+ BIT(DRM_MODE_COLORIMETRY_BT2020_RGB) |
+ BIT(DRM_MODE_COLORIMETRY_BT2020_YCC);
+
void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
struct amdgpu_dm_connector *aconnector,
int connector_type,
@@ -7109,7 +7160,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
drm_connector_attach_max_bpc_property(&aconnector->base, 8, 16);
/* This defaults to the max in the range, but we want 8bpc for non-edp. */
- aconnector->base.state->max_bpc = (connector_type == DRM_MODE_CONNECTOR_eDP) ? 16 : 8;
+ aconnector->base.state->max_bpc = 16;
aconnector->base.state->max_requested_bpc = aconnector->base.state->max_bpc;
if (connector_type == DRM_MODE_CONNECTOR_eDP &&
@@ -7118,6 +7169,17 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
adev->mode_info.abm_level_property, 0);
}
+ drm_connector_attach_content_type_property(&aconnector->base);
+
+ if (connector_type == DRM_MODE_CONNECTOR_HDMIA) {
+ if (!drm_mode_create_hdmi_colorspace_property(&aconnector->base, supported_colorspaces))
+ drm_connector_attach_colorspace_property(&aconnector->base);
+ } else if (connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
+ connector_type == DRM_MODE_CONNECTOR_eDP) {
+ if (!drm_mode_create_dp_colorspace_property(&aconnector->base, supported_colorspaces))
+ drm_connector_attach_colorspace_property(&aconnector->base);
+ }
+
if (connector_type == DRM_MODE_CONNECTOR_HDMIA ||
connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
connector_type == DRM_MODE_CONNECTOR_eDP) {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
index 461037a3dd75..d95d1c9f4805 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
@@ -935,6 +935,61 @@ static int amdgpu_current_bpc_show(struct seq_file *m, void *data)
}
DEFINE_SHOW_ATTRIBUTE(amdgpu_current_bpc);
+/*
+ * Returns the current bpc for the crtc.
+ * Example usage: cat /sys/kernel/debug/dri/0/crtc-0/amdgpu_current_colorspace
+ */
+static int amdgpu_current_colorspace_show(struct seq_file *m, void *data)
+{
+ struct drm_crtc *crtc = m->private;
+ struct drm_device *dev = crtc->dev;
+ struct dm_crtc_state *dm_crtc_state = NULL;
+ int res = -ENODEV;
+
+ mutex_lock(&dev->mode_config.mutex);
+ drm_modeset_lock(&crtc->mutex, NULL);
+ if (crtc->state == NULL)
+ goto unlock;
+
+ dm_crtc_state = to_dm_crtc_state(crtc->state);
+ if (dm_crtc_state->stream == NULL)
+ goto unlock;
+
+ switch (dm_crtc_state->stream->output_color_space) {
+ case COLOR_SPACE_SRGB:
+ seq_printf(m, "RGB");
+ break;
+ case COLOR_SPACE_YCBCR601:
+ case COLOR_SPACE_YCBCR601_LIMITED:
+ seq_printf(m, "BT601_YCC");
+ break;
+ case COLOR_SPACE_YCBCR709:
+ case COLOR_SPACE_YCBCR709_LIMITED:
+ seq_printf(m, "BT709_YCC");
+ break;
+ case COLOR_SPACE_ADOBERGB:
+ seq_printf(m, "opRGB");
+ break;
+ case COLOR_SPACE_2020_RGB_FULLRANGE:
+ seq_printf(m, "BT2020_RGB");
+ break;
+ case COLOR_SPACE_2020_YCBCR:
+ seq_printf(m, "BT2020_YCC");
+ break;
+ default:
+ goto unlock;
+ }
+ res = 0;
+
+unlock:
+ drm_modeset_unlock(&crtc->mutex);
+ mutex_unlock(&dev->mode_config.mutex);
+
+ return res;
+}
+DEFINE_SHOW_ATTRIBUTE(amdgpu_current_colorspace);
+
+
/*
* Example usage:
* Disable dsc passthrough, i.e.,: have dsc decoding at converver, not external RX
@@ -3326,6 +3381,8 @@ void crtc_debugfs_init(struct drm_crtc *crtc)
#endif
debugfs_create_file("amdgpu_current_bpc", 0644, crtc->debugfs_entry,
crtc, &amdgpu_current_bpc_fops);
+ debugfs_create_file("amdgpu_current_colorspace", 0644, crtc->debugfs_entry,
+ crtc, &amdgpu_current_colorspace_fops);
}
/*
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index da164685547d..e00fadf9d0ff 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -2943,14 +2943,9 @@ static void set_avi_info_frame(
uint32_t pixel_encoding = 0;
enum scanning_type scan_type = SCANNING_TYPE_NODATA;
enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA;
- bool itc = false;
- uint8_t itc_value = 0;
- uint8_t cn0_cn1 = 0;
- unsigned int cn0_cn1_value = 0;
uint8_t *check_sum = NULL;
uint8_t byte_index = 0;
union hdmi_info_packet hdmi_info;
- union display_content_support support = {0};
unsigned int vic = pipe_ctx->stream->timing.vic;
unsigned int rid = pipe_ctx->stream->timing.rid;
unsigned int fr_ind = pipe_ctx->stream->timing.fr_index;
@@ -3010,23 +3005,32 @@ static void set_avi_info_frame(
hdmi_info.bits.S0_S1 = scan_type;
/* C0, C1 : Colorimetry */
- if (color_space == COLOR_SPACE_YCBCR709 ||
- color_space == COLOR_SPACE_YCBCR709_LIMITED)
+ switch (color_space) {
+ case COLOR_SPACE_YCBCR709:
+ case COLOR_SPACE_YCBCR709_LIMITED:
hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709;
- else if (color_space == COLOR_SPACE_YCBCR601 ||
- color_space == COLOR_SPACE_YCBCR601_LIMITED)
+ break;
+ case COLOR_SPACE_YCBCR601:
+ case COLOR_SPACE_YCBCR601_LIMITED:
hdmi_info.bits.C0_C1 = COLORIMETRY_ITU601;
- else {
- hdmi_info.bits.C0_C1 = COLORIMETRY_NO_DATA;
- }
- if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE ||
- color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE ||
- color_space == COLOR_SPACE_2020_YCBCR) {
+ break;
+ case COLOR_SPACE_2020_RGB_FULLRANGE:
+ case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR;
hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED;
- } else if (color_space == COLOR_SPACE_ADOBERGB) {
+ break;
+ case COLOR_SPACE_2020_YCBCR:
+ hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_BT2020YCC;
+ hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED;
+ break;
+ case COLOR_SPACE_ADOBERGB:
hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_ADOBERGB;
hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED;
+ break;
+ case COLOR_SPACE_SRGB:
+ default:
+ hdmi_info.bits.C0_C1 = COLORIMETRY_NO_DATA;
+ break;
}
if (pixel_encoding && color_space == COLOR_SPACE_2020_YCBCR &&
@@ -3054,49 +3058,27 @@ static void set_avi_info_frame(
/* Active Format Aspect ratio - same as Picture Aspect Ratio. */
hdmi_info.bits.R0_R3 = ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE;
- /* TODO: un-hardcode cn0_cn1 and itc */
-
- cn0_cn1 = 0;
- cn0_cn1_value = 0;
-
- itc = true;
- itc_value = 1;
-
- support = stream->content_support;
-
- if (itc) {
- if (!support.bits.valid_content_type) {
- cn0_cn1_value = 0;
- } else {
- if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GRAPHICS) {
- if (support.bits.graphics_content == 1) {
- cn0_cn1_value = 0;
- }
- } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_PHOTO) {
- if (support.bits.photo_content == 1) {
- cn0_cn1_value = 1;
- } else {
- cn0_cn1_value = 0;
- itc_value = 0;
- }
- } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_CINEMA) {
- if (support.bits.cinema_content == 1) {
- cn0_cn1_value = 2;
- } else {
- cn0_cn1_value = 0;
- itc_value = 0;
- }
- } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GAME) {
- if (support.bits.game_content == 1) {
- cn0_cn1_value = 3;
- } else {
- cn0_cn1_value = 0;
- itc_value = 0;
- }
- }
- }
- hdmi_info.bits.CN0_CN1 = cn0_cn1_value;
- hdmi_info.bits.ITC = itc_value;
+ switch (stream->content_type) {
+ case DISPLAY_CONTENT_TYPE_NO_DATA:
+ hdmi_info.bits.CN0_CN1 = 0;
+ hdmi_info.bits.ITC = 0;
+ break;
+ case DISPLAY_CONTENT_TYPE_GRAPHICS:
+ hdmi_info.bits.CN0_CN1 = 0;
+ hdmi_info.bits.ITC = 1;
+ break;
+ case DISPLAY_CONTENT_TYPE_PHOTO:
+ hdmi_info.bits.CN0_CN1 = 1;
+ hdmi_info.bits.ITC = 1;
+ break;
+ case DISPLAY_CONTENT_TYPE_CINEMA:
+ hdmi_info.bits.CN0_CN1 = 2;
+ hdmi_info.bits.ITC = 1;
+ break;
+ case DISPLAY_CONTENT_TYPE_GAME:
+ hdmi_info.bits.CN0_CN1 = 3;
+ hdmi_info.bits.ITC = 1;
+ break;
}
if (stream->qs_bit == 1) {
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h
index dfd3df1d2f7e..f78d49e33a6e 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
@@ -182,7 +182,6 @@ struct dc_stream_state {
*/
struct link_encoder *link_enc;
struct dc_panel_patch sink_patches;
- union display_content_support content_support;
struct dc_crtc_timing timing;
struct dc_crtc_timing_adjust adjust;
struct dc_info_packet vrr_infopacket;
@@ -205,6 +204,7 @@ struct dc_stream_state {
struct dc_csc_transform csc_color_matrix;
enum dc_color_space output_color_space;
+ enum display_content_type content_type;
enum dc_dither_option dither_option;
enum view_3d_format view_format;
diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
index dc78e2404b48..fdf58a2e3a75 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
@@ -174,18 +174,6 @@ struct dc_edid {
#define AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS 20
-union display_content_support {
- unsigned int raw;
- struct {
- unsigned int valid_content_type :1;
- unsigned int game_content :1;
- unsigned int cinema_content :1;
- unsigned int photo_content :1;
- unsigned int graphics_content :1;
- unsigned int reserved :27;
- } bits;
-};
-
struct dc_panel_patch {
unsigned int dppowerup_delay;
unsigned int extra_t12_ms;
@@ -218,8 +206,6 @@ struct dc_edid_caps {
uint32_t audio_latency;
uint32_t video_latency;
- union display_content_support content_support;
-
uint8_t qs_bit;
uint8_t qy_bit;
diff --git a/drivers/gpu/drm/display/drm_hdmi_helper.c b/drivers/gpu/drm/display/drm_hdmi_helper.c
index 0264abe55278..c1e6851b2606 100644
--- a/drivers/gpu/drm/display/drm_hdmi_helper.c
+++ b/drivers/gpu/drm/display/drm_hdmi_helper.c
@@ -44,10 +44,8 @@ int drm_hdmi_infoframe_set_hdr_metadata(struct hdmi_drm_infoframe *frame,
/* Sink EOTF is Bit map while infoframe is absolute values */
if (!is_eotf_supported(hdr_metadata->hdmi_metadata_type1.eotf,
- connector->hdr_sink_metadata.hdmi_type1.eotf)) {
- DRM_DEBUG_KMS("EOTF Not Supported\n");
- return -EINVAL;
- }
+ connector->hdr_sink_metadata.hdmi_type1.eotf))
+ DRM_DEBUG_KMS("Unknown EOTF %d\n", hdr_metadata->hdmi_metadata_type1.eotf);
err = hdmi_drm_infoframe_init(frame);
if (err < 0)
@@ -105,7 +103,7 @@ EXPORT_SYMBOL(drm_hdmi_infoframe_set_hdr_metadata);
#define HDMI_COLORIMETRY_DCI_P3_RGB_THEATER (C(3) | EC(7) | ACE(1))
static const u32 hdmi_colorimetry_val[] = {
- [DRM_MODE_COLORIMETRY_NO_DATA] = HDMI_COLORIMETRY_NO_DATA,
+ [DRM_MODE_COLORIMETRY_DEFAULT] = HDMI_COLORIMETRY_NO_DATA,
[DRM_MODE_COLORIMETRY_SMPTE_170M_YCC] = HDMI_COLORIMETRY_SMPTE_170M_YCC,
[DRM_MODE_COLORIMETRY_BT709_YCC] = HDMI_COLORIMETRY_BT709_YCC,
[DRM_MODE_COLORIMETRY_XVYCC_601] = HDMI_COLORIMETRY_XVYCC_601,
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index f197f59f6d99..d6d04c4ccfc0 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1070,6 +1070,8 @@ static void drm_atomic_connector_print_state(struct drm_printer *p,
drm_printf(p, "connector[%u]: %s\n", connector->base.id, connector->name);
drm_printf(p, "\tcrtc=%s\n", state->crtc ? state->crtc->name : "(null)");
drm_printf(p, "\tself_refresh_aware=%d\n", state->self_refresh_aware);
+ drm_printf(p, "\tmax_requested_bpc=%d\n", state->max_requested_bpc);
+ drm_printf(p, "\tcolorspace=%s\n", drm_get_colorspace_name(state->colorspace));
if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
if (state->writeback_job && state->writeback_job->fb)
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 547356e00341..e99d397cd228 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1016,64 +1016,72 @@ static const struct drm_prop_enum_list drm_dp_subconnector_enum_list[] = {
DRM_ENUM_NAME_FN(drm_get_dp_subconnector_name,
drm_dp_subconnector_enum_list)
-static const struct drm_prop_enum_list hdmi_colorspaces[] = {
- /* For Default case, driver will set the colorspace */
- { DRM_MODE_COLORIMETRY_DEFAULT, "Default" },
- /* Standard Definition Colorimetry based on CEA 861 */
- { DRM_MODE_COLORIMETRY_SMPTE_170M_YCC, "SMPTE_170M_YCC" },
- { DRM_MODE_COLORIMETRY_BT709_YCC, "BT709_YCC" },
- /* Standard Definition Colorimetry based on IEC 61966-2-4 */
- { DRM_MODE_COLORIMETRY_XVYCC_601, "XVYCC_601" },
- /* High Definition Colorimetry based on IEC 61966-2-4 */
- { DRM_MODE_COLORIMETRY_XVYCC_709, "XVYCC_709" },
- /* Colorimetry based on IEC 61966-2-1/Amendment 1 */
- { DRM_MODE_COLORIMETRY_SYCC_601, "SYCC_601" },
- /* Colorimetry based on IEC 61966-2-5 [33] */
- { DRM_MODE_COLORIMETRY_OPYCC_601, "opYCC_601" },
- /* Colorimetry based on IEC 61966-2-5 */
- { DRM_MODE_COLORIMETRY_OPRGB, "opRGB" },
- /* Colorimetry based on ITU-R BT.2020 */
- { DRM_MODE_COLORIMETRY_BT2020_CYCC, "BT2020_CYCC" },
- /* Colorimetry based on ITU-R BT.2020 */
- { DRM_MODE_COLORIMETRY_BT2020_RGB, "BT2020_RGB" },
- /* Colorimetry based on ITU-R BT.2020 */
- { DRM_MODE_COLORIMETRY_BT2020_YCC, "BT2020_YCC" },
- /* Added as part of Additional Colorimetry Extension in 861.G */
- { DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65, "DCI-P3_RGB_D65" },
- { DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER, "DCI-P3_RGB_Theater" },
+static const char * const colorspace_names[] = {
+ [DRM_MODE_COLORIMETRY_DEFAULT] = "Default",
+ [DRM_MODE_COLORIMETRY_SMPTE_170M_YCC] = "SMPTE_170M_YCC",
+ [DRM_MODE_COLORIMETRY_BT709_YCC] = "BT709_YCC",
+ [DRM_MODE_COLORIMETRY_XVYCC_601] = "XVYCC_601",
+ [DRM_MODE_COLORIMETRY_XVYCC_709] = "XVYCC_709",
+ [DRM_MODE_COLORIMETRY_SYCC_601] = "SYCC_601",
+ [DRM_MODE_COLORIMETRY_OPYCC_601] = "opYCC_601",
+ [DRM_MODE_COLORIMETRY_OPRGB] = "opRGB",
+ [DRM_MODE_COLORIMETRY_BT2020_CYCC] = "BT2020_CYCC",
+ [DRM_MODE_COLORIMETRY_BT2020_RGB] = "BT2020_RGB",
+ [DRM_MODE_COLORIMETRY_BT2020_YCC] = "BT2020_YCC",
+ [DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65] = "P3_RGB_D65",
+ [DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER] = "P3_RGB_Theater",
+ [DRM_MODE_COLORIMETRY_RGB_WIDE_FIXED] = "RGB_WIDE_FIXED",
+ [DRM_MODE_COLORIMETRY_RGB_WIDE_FLOAT] = "RGB_WIDE_FLOAT",
+ [DRM_MODE_COLORIMETRY_BT601_YCC] = "BT601_YCC",
};
+/**
+ * drm_get_color_encoding_name - return a string for color encoding
+ * @encoding: color encoding to compute name of
+ *
+ * In contrast to the other drm_get_*_name functions this one here returns a
+ * const pointer and hence is threadsafe.
+ */
+const char *drm_get_colorspace_name(enum drm_colorspace colorspace)
+{
+ if (WARN_ON(colorspace >= ARRAY_SIZE(colorspace_names)))
+ return "unknown";
+
+ return colorspace_names[colorspace];
+}
+
+static const u32 hdmi_colorspaces =
+ BIT(DRM_MODE_COLORIMETRY_SMPTE_170M_YCC) |
+ BIT(DRM_MODE_COLORIMETRY_BT709_YCC) |
+ BIT(DRM_MODE_COLORIMETRY_XVYCC_601) |
+ BIT(DRM_MODE_COLORIMETRY_XVYCC_709) |
+ BIT(DRM_MODE_COLORIMETRY_SYCC_601) |
+ BIT(DRM_MODE_COLORIMETRY_OPYCC_601) |
+ BIT(DRM_MODE_COLORIMETRY_OPRGB) |
+ BIT(DRM_MODE_COLORIMETRY_BT2020_CYCC) |
+ BIT(DRM_MODE_COLORIMETRY_BT2020_RGB) |
+ BIT(DRM_MODE_COLORIMETRY_BT2020_YCC) |
+ BIT(DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65) |
+ BIT(DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER);
+
/*
* As per DP 1.4a spec, 2.2.5.7.5 VSC SDP Payload for Pixel Encoding/Colorimetry
* Format Table 2-120
*/
-static const struct drm_prop_enum_list dp_colorspaces[] = {
- /* For Default case, driver will set the colorspace */
- { DRM_MODE_COLORIMETRY_DEFAULT, "Default" },
- { DRM_MODE_COLORIMETRY_RGB_WIDE_FIXED, "RGB_Wide_Gamut_Fixed_Point" },
- /* Colorimetry based on scRGB (IEC 61966-2-2) */
- { DRM_MODE_COLORIMETRY_RGB_WIDE_FLOAT, "RGB_Wide_Gamut_Floating_Point" },
- /* Colorimetry based on IEC 61966-2-5 */
- { DRM_MODE_COLORIMETRY_OPRGB, "opRGB" },
- /* Colorimetry based on SMPTE RP 431-2 */
- { DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65, "DCI-P3_RGB_D65" },
- /* Colorimetry based on ITU-R BT.2020 */
- { DRM_MODE_COLORIMETRY_BT2020_RGB, "BT2020_RGB" },
- { DRM_MODE_COLORIMETRY_BT601_YCC, "BT601_YCC" },
- { DRM_MODE_COLORIMETRY_BT709_YCC, "BT709_YCC" },
- /* Standard Definition Colorimetry based on IEC 61966-2-4 */
- { DRM_MODE_COLORIMETRY_XVYCC_601, "XVYCC_601" },
- /* High Definition Colorimetry based on IEC 61966-2-4 */
- { DRM_MODE_COLORIMETRY_XVYCC_709, "XVYCC_709" },
- /* Colorimetry based on IEC 61966-2-1/Amendment 1 */
- { DRM_MODE_COLORIMETRY_SYCC_601, "SYCC_601" },
- /* Colorimetry based on IEC 61966-2-5 [33] */
- { DRM_MODE_COLORIMETRY_OPYCC_601, "opYCC_601" },
- /* Colorimetry based on ITU-R BT.2020 */
- { DRM_MODE_COLORIMETRY_BT2020_CYCC, "BT2020_CYCC" },
- /* Colorimetry based on ITU-R BT.2020 */
- { DRM_MODE_COLORIMETRY_BT2020_YCC, "BT2020_YCC" },
-};
+static const u32 dp_colorspaces =
+ BIT(DRM_MODE_COLORIMETRY_RGB_WIDE_FIXED) |
+ BIT(DRM_MODE_COLORIMETRY_RGB_WIDE_FLOAT) |
+ BIT(DRM_MODE_COLORIMETRY_OPRGB) |
+ BIT(DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65) |
+ BIT(DRM_MODE_COLORIMETRY_BT2020_RGB) |
+ BIT(DRM_MODE_COLORIMETRY_BT601_YCC) |
+ BIT(DRM_MODE_COLORIMETRY_BT709_YCC) |
+ BIT(DRM_MODE_COLORIMETRY_XVYCC_601) |
+ BIT(DRM_MODE_COLORIMETRY_XVYCC_709) |
+ BIT(DRM_MODE_COLORIMETRY_SYCC_601) |
+ BIT(DRM_MODE_COLORIMETRY_OPYCC_601) |
+ BIT(DRM_MODE_COLORIMETRY_BT2020_CYCC) |
+ BIT(DRM_MODE_COLORIMETRY_BT2020_YCC);
/**
* DOC: standard connector properties
@@ -1975,33 +1983,58 @@ EXPORT_SYMBOL(drm_mode_create_aspect_ratio_property);
* drm_mode_create_dp_colorspace_property() is used for DP connector.
*/
-/**
- * drm_mode_create_hdmi_colorspace_property - create hdmi colorspace property
- * @connector: connector to create the Colorspace property on.
- *
- * Called by a driver the first time it's needed, must be attached to desired
- * HDMI connectors.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_create_hdmi_colorspace_property(struct drm_connector *connector)
+static int drm_mode_create_colorspace_property(struct drm_connector *connector,
+ u32 supported_colorspaces)
{
struct drm_device *dev = connector->dev;
+ u32 colorspaces = supported_colorspaces | BIT(DRM_MODE_COLORIMETRY_DEFAULT);
+ struct drm_prop_enum_list enum_list[DRM_MODE_COLORIMETRY_MAX];
+ int i, len;
if (connector->colorspace_property)
return 0;
+ if (WARN_ON(supported_colorspaces == 0 ||
+ (supported_colorspaces & -BIT(DRM_MODE_COLORIMETRY_MAX)) != 0))
+ return -EINVAL;
+
+ len = 0;
+ for (i = 0; i < DRM_MODE_COLORIMETRY_MAX; i++) {
+ if ((colorspaces & BIT(i)) == 0)
+ continue;
+
+ enum_list[len].type = i;
+ enum_list[len].name = colorspace_names[i];
+ len++;
+ }
+
connector->colorspace_property =
drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, "Colorspace",
- hdmi_colorspaces,
- ARRAY_SIZE(hdmi_colorspaces));
+ enum_list,
+ len);
if (!connector->colorspace_property)
return -ENOMEM;
return 0;
}
+/**
+ * drm_mode_create_hdmi_colorspace_property - create hdmi colorspace property
+ * @connector: connector to create the Colorspace property on.
+ *
+ * Called by a driver the first time it's needed, must be attached to desired
+ * HDMI connectors.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_create_hdmi_colorspace_property(struct drm_connector *connector,
+ u32 supported_colorspaces)
+{
+ u32 colorspaces = supported_colorspaces & hdmi_colorspaces;
+
+ return drm_mode_create_colorspace_property(connector, colorspaces);
+}
EXPORT_SYMBOL(drm_mode_create_hdmi_colorspace_property);
/**
@@ -2014,22 +2047,12 @@ EXPORT_SYMBOL(drm_mode_create_hdmi_colorspace_property);
* Returns:
* Zero on success, negative errno on failure.
*/
-int drm_mode_create_dp_colorspace_property(struct drm_connector *connector)
+int drm_mode_create_dp_colorspace_property(struct drm_connector *connector,
+ u32 supported_colorspaces)
{
- struct drm_device *dev = connector->dev;
+ u32 colorspaces = supported_colorspaces & dp_colorspaces;
- if (connector->colorspace_property)
- return 0;
-
- connector->colorspace_property =
- drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, "Colorspace",
- dp_colorspaces,
- ARRAY_SIZE(dp_colorspaces));
-
- if (!connector->colorspace_property)
- return -ENOMEM;
-
- return 0;
+ return drm_mode_create_colorspace_property(connector, colorspaces);
}
EXPORT_SYMBOL(drm_mode_create_dp_colorspace_property);
diff --git a/drivers/gpu/drm/i915/display/intel_connector.c b/drivers/gpu/drm/i915/display/intel_connector.c
index 6205ddd3ded0..843a669afd59 100644
--- a/drivers/gpu/drm/i915/display/intel_connector.c
+++ b/drivers/gpu/drm/i915/display/intel_connector.c
@@ -283,14 +283,14 @@ intel_attach_aspect_ratio_property(struct drm_connector *connector)
void
intel_attach_hdmi_colorspace_property(struct drm_connector *connector)
{
- if (!drm_mode_create_hdmi_colorspace_property(connector))
+ if (!drm_mode_create_hdmi_colorspace_property(connector, 0xffffffff))
drm_connector_attach_colorspace_property(connector);
}
void
intel_attach_dp_colorspace_property(struct drm_connector *connector)
{
- if (!drm_mode_create_dp_colorspace_property(connector))
+ if (!drm_mode_create_dp_colorspace_property(connector, 0xffffffff))
drm_connector_attach_colorspace_property(connector);
}
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 55744216392b..280d11648712 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -618,7 +618,7 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
if (ret)
return ret;
- ret = drm_mode_create_hdmi_colorspace_property(connector);
+ ret = drm_mode_create_hdmi_colorspace_property(connector, 0xffffffff);
if (ret)
return ret;
diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index e934aab357be..4fc5120392e3 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -1617,7 +1617,7 @@ enum dp_pixelformat {
*
* This enum is used to indicate DP VSC SDP Colorimetry formats.
* It is based on DP 1.4 spec [Table 2-117: VSC SDP Payload for DB16 through
- * DB18] and a name of enum member follows DRM_MODE_COLORIMETRY definition.
+ * DB18] and a name of enum member follows &enum drm_colorimetry definition.
*
* @DP_COLORIMETRY_DEFAULT: sRGB (IEC 61966-2-1) or
* ITU-R BT.601 colorimetry format
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 565cf9d3c550..68f26a3ebb99 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -30,6 +30,7 @@
#include <linux/notifier.h>
#include <drm/drm_mode_object.h>
#include <drm/drm_util.h>
+#include <drm/drm_property.h>
#include <uapi/drm/drm_mode.h>
@@ -371,29 +372,30 @@ enum drm_privacy_screen_status {
* a colorspace property which will be created and exposed to
* userspace.
*/
-
-/* For Default case, driver will set the colorspace */
-#define DRM_MODE_COLORIMETRY_DEFAULT 0
-/* CEA 861 Normal Colorimetry options */
-#define DRM_MODE_COLORIMETRY_NO_DATA 0
-#define DRM_MODE_COLORIMETRY_SMPTE_170M_YCC 1
-#define DRM_MODE_COLORIMETRY_BT709_YCC 2
-/* CEA 861 Extended Colorimetry Options */
-#define DRM_MODE_COLORIMETRY_XVYCC_601 3
-#define DRM_MODE_COLORIMETRY_XVYCC_709 4
-#define DRM_MODE_COLORIMETRY_SYCC_601 5
-#define DRM_MODE_COLORIMETRY_OPYCC_601 6
-#define DRM_MODE_COLORIMETRY_OPRGB 7
-#define DRM_MODE_COLORIMETRY_BT2020_CYCC 8
-#define DRM_MODE_COLORIMETRY_BT2020_RGB 9
-#define DRM_MODE_COLORIMETRY_BT2020_YCC 10
-/* Additional Colorimetry extension added as part of CTA 861.G */
-#define DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65 11
-#define DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER 12
-/* Additional Colorimetry Options added for DP 1.4a VSC Colorimetry Format */
-#define DRM_MODE_COLORIMETRY_RGB_WIDE_FIXED 13
-#define DRM_MODE_COLORIMETRY_RGB_WIDE_FLOAT 14
-#define DRM_MODE_COLORIMETRY_BT601_YCC 15
+enum drm_colorspace {
+ /* For Default case, driver will set the colorspace */
+ DRM_MODE_COLORIMETRY_DEFAULT,
+ /* CEA 861 Normal Colorimetry options */
+ DRM_MODE_COLORIMETRY_SMPTE_170M_YCC,
+ DRM_MODE_COLORIMETRY_BT709_YCC,
+ /* CEA 861 Extended Colorimetry Options */
+ DRM_MODE_COLORIMETRY_XVYCC_601,
+ DRM_MODE_COLORIMETRY_XVYCC_709,
+ DRM_MODE_COLORIMETRY_SYCC_601,
+ DRM_MODE_COLORIMETRY_OPYCC_601,
+ DRM_MODE_COLORIMETRY_OPRGB,
+ DRM_MODE_COLORIMETRY_BT2020_CYCC,
+ DRM_MODE_COLORIMETRY_BT2020_RGB,
+ DRM_MODE_COLORIMETRY_BT2020_YCC,
+ /* Additional Colorimetry extension added as part of CTA 861.G */
+ DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65,
+ DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER,
+ /* Additional Colorimetry Options added for DP 1.4a VSC Colorimetry Format */
+ DRM_MODE_COLORIMETRY_RGB_WIDE_FIXED,
+ DRM_MODE_COLORIMETRY_RGB_WIDE_FLOAT,
+ DRM_MODE_COLORIMETRY_BT601_YCC,
+ DRM_MODE_COLORIMETRY_MAX
+};
/**
* enum drm_bus_flags - bus_flags info for &drm_display_info
@@ -828,7 +830,7 @@ struct drm_connector_state {
* colorspace change on Sink. This is most commonly used to switch
* to wider color gamuts like BT2020.
*/
- u32 colorspace;
+ enum drm_colorspace colorspace;
/**
* @writeback_job: Writeback job for writeback connectors
@@ -1835,8 +1837,10 @@ int drm_connector_attach_hdr_output_metadata_property(struct drm_connector *conn
bool drm_connector_atomic_hdr_metadata_equal(struct drm_connector_state *old_state,
struct drm_connector_state *new_state);
int drm_mode_create_aspect_ratio_property(struct drm_device *dev);
-int drm_mode_create_hdmi_colorspace_property(struct drm_connector *connector);
-int drm_mode_create_dp_colorspace_property(struct drm_connector *connector);
+int drm_mode_create_hdmi_colorspace_property(struct drm_connector *connector,
+ u32 supported_colorspaces);
+int drm_mode_create_dp_colorspace_property(struct drm_connector *connector,
+ u32 supported_colorspaces);
int drm_mode_create_content_type_property(struct drm_device *dev);
int drm_mode_create_suggested_offset_properties(struct drm_device *dev);
@@ -1919,6 +1923,7 @@ void drm_connector_list_iter_end(struct drm_connector_list_iter *iter);
bool drm_connector_has_possible_encoder(struct drm_connector *connector,
struct drm_encoder *encoder);
+const char *drm_get_colorspace_name(enum drm_colorspace colorspace);
/**
* drm_for_each_connector_iter - connector_list iterator macro
--
2.39.2

View File

@ -1,139 +0,0 @@
From d750d1480362781e208b3cc64640c0be127afcc9 Mon Sep 17 00:00:00 2001
From: "Daniel J. Ogorchock" <djogorchock@gmail.com>
Date: Fri, 3 Feb 2023 16:51:18 -0500
Subject: HID: nintendo: fix rumble rate limiter
It's been discovered that BT controller disconnect events correlate to
erratic input report timestamp deltas.
In experimentation, it's been found that ensuring that multiple
timestamp deltas are consistent prior to transmitting a rumble packet
drastically reduces the occurence rate of BT disconnects.
Alter the joycon_enforce_subcmd_rate() function to use this new
approach.
Signed-off-by: Daniel J. Ogorchock <djogorchock@gmail.com>
Reviewed-by: Silvan Jegen <s.jegen@gmail.com
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
drivers/hid/hid-nintendo.c | 75 ++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 69 insertions(+), 6 deletions(-)
diff --git a/drivers/hid/hid-nintendo.c b/drivers/hid/hid-nintendo.c
index 2b781cc9082b4..250f5d2f888ab 100644
--- a/drivers/hid/hid-nintendo.c
+++ b/drivers/hid/hid-nintendo.c
@@ -433,7 +433,9 @@ struct joycon_ctlr {
u8 usb_ack_match;
u8 subcmd_ack_match;
bool received_input_report;
+ unsigned int last_input_report_msecs;
unsigned int last_subcmd_sent_msecs;
+ unsigned int consecutive_valid_report_deltas;
/* factory calibration data */
struct joycon_stick_cal left_stick_cal_x;
@@ -543,19 +545,54 @@ static void joycon_wait_for_input_report(struct joycon_ctlr *ctlr)
* Sending subcommands and/or rumble data at too high a rate can cause bluetooth
* controller disconnections.
*/
+#define JC_INPUT_REPORT_MIN_DELTA 8
+#define JC_INPUT_REPORT_MAX_DELTA 17
+#define JC_SUBCMD_TX_OFFSET_MS 4
+#define JC_SUBCMD_VALID_DELTA_REQ 3
+#define JC_SUBCMD_RATE_MAX_ATTEMPTS 500
+#define JC_SUBCMD_RATE_LIMITER_USB_MS 20
+#define JC_SUBCMD_RATE_LIMITER_BT_MS 60
+#define JC_SUBCMD_RATE_LIMITER_MS(ctlr) ((ctlr)->hdev->bus == BUS_USB ? JC_SUBCMD_RATE_LIMITER_USB_MS : JC_SUBCMD_RATE_LIMITER_BT_MS)
static void joycon_enforce_subcmd_rate(struct joycon_ctlr *ctlr)
{
- static const unsigned int max_subcmd_rate_ms = 25;
- unsigned int current_ms = jiffies_to_msecs(jiffies);
- unsigned int delta_ms = current_ms - ctlr->last_subcmd_sent_msecs;
+ unsigned int current_ms;
+ unsigned long subcmd_delta;
+ int consecutive_valid_deltas = 0;
+ int attempts = 0;
+ unsigned long flags;
+
+ if (unlikely(ctlr->ctlr_state != JOYCON_CTLR_STATE_READ))
+ return;
- while (delta_ms < max_subcmd_rate_ms &&
- ctlr->ctlr_state == JOYCON_CTLR_STATE_READ) {
+ do {
joycon_wait_for_input_report(ctlr);
current_ms = jiffies_to_msecs(jiffies);
- delta_ms = current_ms - ctlr->last_subcmd_sent_msecs;
+ subcmd_delta = current_ms - ctlr->last_subcmd_sent_msecs;
+
+ spin_lock_irqsave(&ctlr->lock, flags);
+ consecutive_valid_deltas = ctlr->consecutive_valid_report_deltas;
+ spin_unlock_irqrestore(&ctlr->lock, flags);
+
+ attempts++;
+ } while ((consecutive_valid_deltas < JC_SUBCMD_VALID_DELTA_REQ ||
+ subcmd_delta < JC_SUBCMD_RATE_LIMITER_MS(ctlr)) &&
+ ctlr->ctlr_state == JOYCON_CTLR_STATE_READ &&
+ attempts < JC_SUBCMD_RATE_MAX_ATTEMPTS);
+
+ if (attempts >= JC_SUBCMD_RATE_MAX_ATTEMPTS) {
+ hid_warn(ctlr->hdev, "%s: exceeded max attempts", __func__);
+ return;
}
+
ctlr->last_subcmd_sent_msecs = current_ms;
+
+ /*
+ * Wait a short time after receiving an input report before
+ * transmitting. This should reduce odds of a TX coinciding with an RX.
+ * Minimizing concurrent BT traffic with the controller seems to lower
+ * the rate of disconnections.
+ */
+ msleep(JC_SUBCMD_TX_OFFSET_MS);
}
static int joycon_hid_send_sync(struct joycon_ctlr *ctlr, u8 *data, size_t len,
@@ -1223,6 +1260,7 @@ static void joycon_parse_report(struct joycon_ctlr *ctlr,
u8 tmp;
u32 btns;
unsigned long msecs = jiffies_to_msecs(jiffies);
+ unsigned long report_delta_ms = msecs - ctlr->last_input_report_msecs;
spin_lock_irqsave(&ctlr->lock, flags);
if (IS_ENABLED(CONFIG_NINTENDO_FF) && rep->vibrator_report &&
@@ -1364,6 +1402,31 @@ static void joycon_parse_report(struct joycon_ctlr *ctlr,
input_sync(dev);
+ spin_lock_irqsave(&ctlr->lock, flags);
+ ctlr->last_input_report_msecs = msecs;
+ /*
+ * Was this input report a reasonable time delta compared to the prior
+ * report? We use this information to decide when a safe time is to send
+ * rumble packets or subcommand packets.
+ */
+ if (report_delta_ms >= JC_INPUT_REPORT_MIN_DELTA &&
+ report_delta_ms <= JC_INPUT_REPORT_MAX_DELTA) {
+ if (ctlr->consecutive_valid_report_deltas < JC_SUBCMD_VALID_DELTA_REQ)
+ ctlr->consecutive_valid_report_deltas++;
+ } else {
+ ctlr->consecutive_valid_report_deltas = 0;
+ }
+ /*
+ * Our consecutive valid report tracking is only relevant for
+ * bluetooth-connected controllers. For USB devices, we're beholden to
+ * USB's underlying polling rate anyway. Always set to the consecutive
+ * delta requirement.
+ */
+ if (ctlr->hdev->bus == BUS_USB)
+ ctlr->consecutive_valid_report_deltas = JC_SUBCMD_VALID_DELTA_REQ;
+
+ spin_unlock_irqrestore(&ctlr->lock, flags);
+
/*
* Immediately after receiving a report is the most reliable time to
* send a subcommand to the controller. Wake any subcommand senders
--
cgit

View File

@ -1,64 +0,0 @@
From bcba9f32c13a29edf7e996371eebe7eb5ff9f854 Mon Sep 17 00:00:00 2001
From: "Daniel J. Ogorchock" <djogorchock@gmail.com>
Date: Fri, 3 Feb 2023 16:51:17 -0500
Subject: HID: nintendo: prevent rumble queue overruns
Make sure that we never throw out the most recent rumble setting,
opting to overwrite the prior queue head instead. This prevents
instances where we could get rumble stuck on if there were an overrun at
the wrong time.
Signed-off-by: Daniel J. Ogorchock <djogorchock@gmail.com>
Reviewed-by: Silvan Jegen <s.jegen@gmail.com
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
drivers/hid/hid-nintendo.c | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/drivers/hid/hid-nintendo.c b/drivers/hid/hid-nintendo.c
index 5bfc0c4504608..2b781cc9082b4 100644
--- a/drivers/hid/hid-nintendo.c
+++ b/drivers/hid/hid-nintendo.c
@@ -1527,6 +1527,7 @@ static int joycon_set_rumble(struct joycon_ctlr *ctlr, u16 amp_r, u16 amp_l,
u16 freq_l_low;
u16 freq_l_high;
unsigned long flags;
+ int next_rq_head;
spin_lock_irqsave(&ctlr->lock, flags);
freq_r_low = ctlr->rumble_rl_freq;
@@ -1547,8 +1548,21 @@ static int joycon_set_rumble(struct joycon_ctlr *ctlr, u16 amp_r, u16 amp_l,
joycon_encode_rumble(data, freq_l_low, freq_l_high, amp);
spin_lock_irqsave(&ctlr->lock, flags);
- if (++ctlr->rumble_queue_head >= JC_RUMBLE_QUEUE_SIZE)
- ctlr->rumble_queue_head = 0;
+
+ next_rq_head = ctlr->rumble_queue_head + 1;
+ if (next_rq_head >= JC_RUMBLE_QUEUE_SIZE)
+ next_rq_head = 0;
+
+ /* Did we overrun the circular buffer?
+ * If so, be sure we keep the latest intended rumble state.
+ */
+ if (next_rq_head == ctlr->rumble_queue_tail) {
+ hid_dbg(ctlr->hdev, "rumble queue is full");
+ /* overwrite the prior value at the end of the circular buf */
+ next_rq_head = ctlr->rumble_queue_head;
+ }
+
+ ctlr->rumble_queue_head = next_rq_head;
memcpy(ctlr->rumble_data[ctlr->rumble_queue_head], data,
JC_RUMBLE_DATA_SIZE);
@@ -2128,7 +2142,7 @@ static int nintendo_hid_probe(struct hid_device *hdev,
ctlr->hdev = hdev;
ctlr->ctlr_state = JOYCON_CTLR_STATE_INIT;
- ctlr->rumble_queue_head = JC_RUMBLE_QUEUE_SIZE - 1;
+ ctlr->rumble_queue_head = 0;
ctlr->rumble_queue_tail = 0;
hid_set_drvdata(hdev, ctlr);
mutex_init(&ctlr->output_mutex);
--
cgit

View File

@ -2,4 +2,4 @@
echo "Pika Kernel - Building"
make -j`nproc` bindeb-pkg LOCALVERSION=-pikaos KDEB_PKGVERSION=$(make kernelversion)-3
make -j`nproc` bindeb-pkg LOCALVERSION=-pikaos KDEB_PKGVERSION=$(make kernelversion)-4

View File

@ -7,16 +7,8 @@ echo "Pika Kernel - Applying patches"
patch -Np1 < "../patches/0001-cachy-all.patch"
# orig patch from cachy
patch -Np1 < "../patches/0002-eevdf.patch"
# HDR patch - Currently broken against 6.3
#patch -Np1 < "../patches/0004-hdr.patch"
# Nintendo controller rumble patch
patch -Np1 < "../patches/0006-Nintendo-controller-one.patch"
# Nintendo controller BT patch
patch -Np1 < "../patches/0006-Nintendo-controller-two.patch"
# Nobara patches are here: https://github.com/sammilucia/nobara-kernel-fork
# Extra Leigon laptop goodies
patch -Np1 < "../patches/0001-Add-legion-laptop-v0.1.patch"
# Allow setting custom pollrates for usb devices
patch -Np1 < "../patches/0001-Allow-to-set-custom-USB-pollrate-for-specific-device.patch"
patch -Np1 < "../patches/0003-Allow-to-set-custom-USB-pollrate-for-specific-device.patch"
# Allow pre polaris cards to use the amdgpu kernel module
patch -Np1 < "../patches/amdgpu-si-cik-default.patch"
patch -Np1 < "../patches/0004-amdgpu-si-cik-default.patch"

View File

@ -12,7 +12,7 @@ rsync -azP --exclude '*.deb' ferreo@direct.pika-os.com:/srv/www/pikappa/ ./outpu
echo "Pika Kernel - Repo rsync pull complete"
# Remove our existing package from the repo - only for current version so we can update it
reprepro -V --basedir ./output/repo/ removefilter lunar 'Package (% linux-*-6.3.0-pikaos*)'
reprepro -V --basedir ./output/repo/ removefilter lunar 'Package (% linux-*-6.4.0-pikaos*)'
echo "Pika Kernel - Repo clean complete"
# Add the new package to the repo

View File

@ -2,7 +2,7 @@
echo "Pika Kernel - Getting source"
wget -nv https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.3.tar.xz
tar -xf ./linux-6.3.tar.xz
wget -nv https://git.kernel.org/torvalds/t/linux-6.4-rc5.tar.gz
tar -xf ./linux-6.4-rc5.tar.gz
cd linux-6.3
cd linux-6.4-rc5