diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index 821805dc3a..810ed48a7f 100644 --- a/msm/dsi/dsi_display.c +++ b/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)