]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
drm/amd/display: DSC Bit target rate debugfs write entry
authorEryk Brol <eryk.brol@amd.com>
Fri, 19 Jun 2020 18:02:38 +0000 (14:02 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 4 Aug 2020 21:29:27 +0000 (17:29 -0400)
[Why]
We need to be able to specify bits per pixel for DSC on any
connector.

[How]
Overwrite computed DSC target rate in dsc_cfg, with requested value.
Overwrites for both SST and MST connectors, but in different places, but the process is identical. Overwrites only if DSC is decided to be enabled on that connector.

Signed-off-by: Eryk Brol <eryk.brol@amd.com>
Signed-off-by: Mikita Lipski <mikita.lipski@amd.com>
Reviewed-by: Mikita Lipski <Mikita.Lipski@amd.com>
Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c

index 26217e5e800de606af976a9a8edfc19cce5863be..765680b62d6a4d5a00bba200fb045ec5fbbb0cbc 100644 (file)
@@ -4678,6 +4678,9 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
                        if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_slice_height)
                                stream->timing.dsc_cfg.num_slices_v = DIV_ROUND_UP(stream->timing.v_addressable,
                                                                        aconnector->dsc_settings.dsc_slice_height);
+
+                       if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_bits_per_pixel)
+                               stream->timing.dsc_cfg.bits_per_pixel = aconnector->dsc_settings.dsc_bits_per_pixel;
                }
 #endif
        }
index 1a31473d39921db73f1d60cde02e8a5eb5f7f6b8..a8fff3413af339e9bd1faa64b16fb03f58025067 100644 (file)
@@ -346,6 +346,7 @@ struct dsc_preferred_settings {
        bool dsc_clock_en;
        uint32_t dsc_slice_width;
        uint32_t dsc_slice_height;
+       uint32_t dsc_bits_per_pixel;
 };
 
 struct amdgpu_dm_connector {
index b4c470c75cbe32425e7970c616a3d510c1e69442..9260b27659e48ee1480574b9e0355ab3a8df9f2a 100644 (file)
@@ -1423,6 +1423,18 @@ done:
        return size;
 }
 
+/* function: read DSC target rate on the connector in bits per pixel
+ *
+ * The read function: dp_dsc_bits_per_pixel_read
+ * returns target rate of compression in bits per pixel
+ * The return is an integer: 0 or other positive integer
+ *
+ * Access it with the following command:
+ *
+ *     cat /sys/kernel/debug/dri/0/DP-X/dsc_bits_per_pixel
+ *
+ *  0 - means that DSC is disabled
+ */
 static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf,
                                    size_t size, loff_t *pos)
 {
@@ -1480,6 +1492,79 @@ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf,
        return result;
 }
 
+/* function: write DSC target rate in bits per pixel
+ *
+ * The write function: dp_dsc_bits_per_pixel_write
+ * overwrites automatically generated DSC configuration
+ * of DSC target bit rate.
+ *
+ * Also the user has to write bpp in hexidecimal
+ * rather than in decimal.
+ *
+ * Writing DSC settings is done with the following command:
+ * - To force overwrite rate (example sets to 256 bpp x 1/16):
+ *
+ *     echo 0x100 > /sys/kernel/debug/dri/0/DP-X/dsc_bits_per_pixel
+ *
+ *  - To stop overwriting and let driver find the optimal rate,
+ * set the rate to zero:
+ *
+ *     echo 0x0 > /sys/kernel/debug/dri/0/DP-X/dsc_bits_per_pixel
+ *
+ */
+static ssize_t dp_dsc_bits_per_pixel_write(struct file *f, const char __user *buf,
+                                    size_t size, loff_t *pos)
+{
+       struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;
+       struct pipe_ctx *pipe_ctx;
+       int i;
+       char *wr_buf = NULL;
+       uint32_t wr_buf_size = 42;
+       int max_param_num = 1;
+       uint8_t param_nums = 0;
+       long param[1] = {0};
+
+       if (size == 0)
+               return -EINVAL;
+
+       wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);
+
+       if (!wr_buf) {
+               DRM_DEBUG_DRIVER("no memory to allocate write buffer\n");
+               return -ENOSPC;
+       }
+
+       if (parse_write_buffer_into_params(wr_buf, wr_buf_size,
+                                           (long *)param, buf,
+                                           max_param_num,
+                                           &param_nums)) {
+               kfree(wr_buf);
+               return -EINVAL;
+       }
+
+       if (param_nums <= 0) {
+               DRM_DEBUG_DRIVER("user data not be read\n");
+               kfree(wr_buf);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < MAX_PIPES; i++) {
+               pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
+                       if (pipe_ctx && pipe_ctx->stream &&
+                           pipe_ctx->stream->link == aconnector->dc_link)
+                               break;
+       }
+
+       if (!pipe_ctx || !pipe_ctx->stream)
+               goto done;
+
+       aconnector->dsc_settings.dsc_bits_per_pixel = param[0];
+
+done:
+       kfree(wr_buf);
+       return size;
+}
+
 static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf,
                                    size_t size, loff_t *pos)
 {
@@ -1739,6 +1824,7 @@ static const struct file_operations dp_dsc_slice_height_debugfs_fops = {
 static const struct file_operations dp_dsc_bits_per_pixel_debugfs_fops = {
        .owner = THIS_MODULE,
        .read = dp_dsc_bits_per_pixel_read,
+       .write = dp_dsc_bits_per_pixel_write,
        .llseek = default_llseek
 };
 
index 4d74780f21a45c764ee3fe882cf74a813ac2f317..a222335133e0e2527203ac49726c93a7d9ff684d 100644 (file)
@@ -453,6 +453,7 @@ struct dsc_mst_fairness_params {
        bool clock_overwrite;
        uint32_t slice_width_overwrite;
        uint32_t slice_height_overwrite;
+       uint32_t bpp_overwrite;
 };
 
 struct dsc_mst_fairness_vars {
@@ -486,7 +487,12 @@ static void set_dsc_configs_from_fairness_vars(struct dsc_mst_fairness_params *p
                                        params[i].timing,
                                        &params[i].timing->dsc_cfg)) {
                        params[i].timing->flags.DSC = 1;
-                       params[i].timing->dsc_cfg.bits_per_pixel = vars[i].bpp_x16;
+
+                       if (params[i].bpp_overwrite)
+                               params[i].timing->dsc_cfg.bits_per_pixel = params[i].bpp_overwrite;
+                       else
+                               params[i].timing->dsc_cfg.bits_per_pixel = vars[i].bpp_x16;
+
                        if (params[i].slice_width_overwrite)
                                params[i].timing->dsc_cfg.num_slices_h = DIV_ROUND_UP(
                                                                                params[i].timing->h_addressable,
@@ -714,6 +720,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
                        debugfs_overwrite = true;
                params[count].slice_width_overwrite = aconnector->dsc_settings.dsc_slice_width;
                params[count].slice_height_overwrite = aconnector->dsc_settings.dsc_slice_height;
+               params[count].bpp_overwrite = aconnector->dsc_settings.dsc_bits_per_pixel;
                params[count].compression_possible = stream->sink->dsc_caps.dsc_dec_caps.is_dsc_supported;
                dc_dsc_get_policy_for_timing(params[count].timing, &dsc_policy);
                if (!dc_dsc_compute_bandwidth_range(