Selaa lähdekoodia

disp: msm: dsi: allocate priv info and bit clk list per fps

Currently, in dsi_display_get_modes, priv_info, rates,
front_porches and pixel_clks_khz memory is allocated for each
timing node and the same memory is copied for each supported fps.
The values of front porches calculated to maintain constant fps for
each bit clk rate gets overwritten with the values for last fps in
the dfps list. But the values of front porches should be different
in case where DFPS and dynamic clock are both supported either by
vfp approach or hfp approach. To fix this, allocate memory
separately for each fps.

Change-Id: Ibf753aa8cca8d77b02b20785b5435f1aba05106e
Signed-off-by: Kashish Jain <[email protected]>
Kashish Jain 3 vuotta sitten
vanhempi
sitoutus
c079b51c81
1 muutettua tiedostoa jossa 78 lisäystä ja 1 poistoa
  1. 78 1
      msm/dsi/dsi_display.c

+ 78 - 1
msm/dsi/dsi_display.c

@@ -6868,6 +6868,57 @@ static void _dsi_display_populate_bit_clks(struct dsi_display *display, int star
 	}
 }
 
+static int dsi_display_mode_dyn_clk_cpy(struct dsi_display *display,
+		struct dsi_display_mode *src, struct dsi_display_mode *dst)
+{
+	int rc = 0;
+	u32 count = 0;
+	struct dsi_dyn_clk_caps *dyn_clk_caps;
+	struct msm_dyn_clk_list *bit_clk_list;
+
+	dyn_clk_caps = &(display->panel->dyn_clk_caps);
+	if (!dyn_clk_caps->dyn_clk_support)
+		return rc;
+
+	count = dst->priv_info->bit_clk_list.count;
+	bit_clk_list = &dst->priv_info->bit_clk_list;
+	bit_clk_list->front_porches =
+			kcalloc(count, sizeof(u32), GFP_KERNEL);
+	if (!bit_clk_list->front_porches) {
+		DSI_ERR("failed to allocate space for front porch list\n");
+		rc = -ENOMEM;
+		goto error;
+	}
+
+	bit_clk_list->rates =
+			kcalloc(count, sizeof(u32), GFP_KERNEL);
+	if (!bit_clk_list->rates) {
+		DSI_ERR("failed to allocate space for rates list\n");
+		rc = -ENOMEM;
+		goto error;
+	}
+
+	memcpy(bit_clk_list->rates, src->priv_info->bit_clk_list.rates,
+			count*sizeof(u32));
+
+	bit_clk_list->pixel_clks_khz =
+			kcalloc(count, sizeof(u32), GFP_KERNEL);
+	if (!bit_clk_list->pixel_clks_khz) {
+		DSI_ERR("failed to allocate space for pixel clocks list\n");
+		rc = -ENOMEM;
+		goto error;
+	}
+
+	return rc;
+
+error:
+	kfree(bit_clk_list->rates);
+	kfree(bit_clk_list->front_porches);
+	kfree(bit_clk_list->pixel_clks_khz);
+
+	return rc;
+}
+
 int dsi_display_restore_bit_clk(struct dsi_display *display, struct dsi_display_mode *mode)
 {
 	int i;
@@ -6967,6 +7018,7 @@ int dsi_display_get_modes(struct dsi_display *display,
 		int topology_override = NO_OVERRIDE;
 		bool is_preferred = false;
 		u32 frame_threshold_us = ctrl->ctrl->frame_threshold_time_us;
+		struct msm_dyn_clk_list *bit_clk_list;
 
 		memset(&display_mode, 0, sizeof(display_mode));
 
@@ -7060,10 +7112,24 @@ int dsi_display_get_modes(struct dsi_display *display,
 			 * Qsync min fps for the mode will be populated in the timing info
 			 * in dsi_panel_get_mode function.
 			 */
-			sub_mode->priv_info->qsync_min_fps = sub_mode->timing.qsync_min_fps;
+			display_mode.priv_info->qsync_min_fps = sub_mode->timing.qsync_min_fps;
 			if (!dfps_caps.dfps_support || !support_video_mode)
 				continue;
 
+			sub_mode->priv_info = kmemdup(display_mode.priv_info,
+					sizeof(*sub_mode->priv_info), GFP_KERNEL);
+			if (!sub_mode->priv_info) {
+				rc = -ENOMEM;
+				goto error;
+			}
+
+			rc = dsi_display_mode_dyn_clk_cpy(display,
+					&display_mode, sub_mode);
+			if (rc) {
+				DSI_ERR("unable to copy dyn clock list\n");
+				goto error;
+			}
+
 			sub_mode->mode_idx += (array_idx - 1);
 			curr_refresh_rate = sub_mode->timing.refresh_rate;
 			sub_mode->timing.refresh_rate = dfps_caps.dfps_list[i];
@@ -7086,6 +7152,17 @@ int dsi_display_get_modes(struct dsi_display *display,
 			/* Set first timing sub mode as preferred mode */
 			display->modes[start].is_preferred = true;
 		}
+
+		bit_clk_list = &display_mode.priv_info->bit_clk_list;
+		if (support_video_mode && dfps_caps.dfps_support) {
+			if (dyn_clk_caps->dyn_clk_support) {
+				kfree(bit_clk_list->rates);
+				kfree(bit_clk_list->front_porches);
+				kfree(bit_clk_list->pixel_clks_khz);
+			}
+
+			kfree(display_mode.priv_info);
+		}
 	}
 
 	if (dsc_modes && nondsc_modes)