OSDN Git Service

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 26217e5..765680b 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 1a31473..a8fff34 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 b4c470c..9260b27 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 4d74780..a222335 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(