diff options
author | Shu Zhong <shuz@nvidia.com> | 2016-09-01 16:40:00 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2016-09-09 17:03:46 -0400 |
commit | 21d71493c9327a09f7b752766152c55cfa07f4e5 (patch) | |
tree | 52e467f6d996ba48ec113137872545cf3dabb969 | |
parent | a3e6e6090817f992e3b526cf135ac6e2017b4bba (diff) |
video: tegra: nvdisp: clear and init bw
1) The display driver should explicitly clear its ISO bw
when all heads are disabled.
2) When display comes back, it will use the bw settings for
the max config. These settings will eventually be adjusted
through IMP, if supported by the client.
Bug 1705477
Bug 1753714
Change-Id: Ibdff1440f2b1f8e4ff464a0ef3966a70fc3f2178
Signed-off-by: Shu Zhong <shuz@nvidia.com>
Reviewed-on: http://git-master/r/1213146
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
-rw-r--r-- | drivers/video/tegra/dc/nvdisp/nvdisp.c | 15 | ||||
-rw-r--r-- | drivers/video/tegra/dc/nvdisp/nvdisp.h | 2 | ||||
-rw-r--r-- | drivers/video/tegra/dc/nvdisp/nvdisp_bandwidth.c | 64 |
3 files changed, 47 insertions, 34 deletions
diff --git a/drivers/video/tegra/dc/nvdisp/nvdisp.c b/drivers/video/tegra/dc/nvdisp/nvdisp.c index c71ffc426..6991817c8 100644 --- a/drivers/video/tegra/dc/nvdisp/nvdisp.c +++ b/drivers/video/tegra/dc/nvdisp/nvdisp.c | |||
@@ -1373,8 +1373,9 @@ int tegra_nvdisp_head_disable(struct tegra_dc *dc) | |||
1373 | break; | 1373 | break; |
1374 | } | 1374 | } |
1375 | 1375 | ||
1376 | /* disable hub clock if none of the heads is using it */ | 1376 | /* disable hub clock if none of the heads is using it and clear bw */ |
1377 | if (idx == TEGRA_MAX_DC) { | 1377 | if (idx == TEGRA_MAX_DC) { |
1378 | tegra_nvdisp_clear_bandwidth(dc); | ||
1378 | tegra_disp_clk_disable_unprepare(hubclk); | 1379 | tegra_disp_clk_disable_unprepare(hubclk); |
1379 | hubclk_already_on = false; | 1380 | hubclk_already_on = false; |
1380 | } | 1381 | } |
@@ -1410,22 +1411,14 @@ int tegra_nvdisp_head_enable(struct tegra_dc *dc) | |||
1410 | } | 1411 | } |
1411 | clk_set_parent(hubclk, hubparent_clk); | 1412 | clk_set_parent(hubclk, hubparent_clk); |
1412 | 1413 | ||
1413 | /* | ||
1414 | * WAR for bug 200212319 | ||
1415 | * | ||
1416 | * IMP will ultimately be responsible for setting the required hubclk | ||
1417 | * rate in the kernel, but it's not ready yet. As such, explicitly drive | ||
1418 | * the hubclk rate to 408MHz so that we're not stuck with the rate set | ||
1419 | * by BL. | ||
1420 | */ | ||
1421 | clk_set_rate(hubclk, 408000000); | ||
1422 | |||
1423 | /* set clock status to inuse */ | 1414 | /* set clock status to inuse */ |
1424 | mutex_lock(&tegra_nvdisp_lock); | 1415 | mutex_lock(&tegra_nvdisp_lock); |
1425 | clk_client[dc->ctrl_num].inuse = true; | 1416 | clk_client[dc->ctrl_num].inuse = true; |
1426 | clk_client[dc->ctrl_num].dc = dc; | 1417 | clk_client[dc->ctrl_num].dc = dc; |
1427 | 1418 | ||
1419 | /* turn on hub clock and init bw */ | ||
1428 | if (!hubclk_already_on) { | 1420 | if (!hubclk_already_on) { |
1421 | tegra_nvdisp_init_bandwidth(dc); | ||
1429 | tegra_disp_clk_prepare_enable(hubclk); | 1422 | tegra_disp_clk_prepare_enable(hubclk); |
1430 | hubclk_already_on = true; | 1423 | hubclk_already_on = true; |
1431 | } | 1424 | } |
diff --git a/drivers/video/tegra/dc/nvdisp/nvdisp.h b/drivers/video/tegra/dc/nvdisp/nvdisp.h index 7641161f4..5bf446d31 100644 --- a/drivers/video/tegra/dc/nvdisp/nvdisp.h +++ b/drivers/video/tegra/dc/nvdisp/nvdisp.h | |||
@@ -57,4 +57,6 @@ void tegra_nvdisp_program_bandwidth(struct tegra_dc *dc, u32 proposed_bw, | |||
57 | u32 proposed_latency, u32 proposed_hubclk, bool before_win_udpate); | 57 | u32 proposed_latency, u32 proposed_hubclk, bool before_win_udpate); |
58 | int tegra_nvdisp_negotiate_reserved_bw(struct tegra_dc *dc, u32 proposed_bw, | 58 | int tegra_nvdisp_negotiate_reserved_bw(struct tegra_dc *dc, u32 proposed_bw, |
59 | u32 proposed_latency); | 59 | u32 proposed_latency); |
60 | void tegra_nvdisp_init_bandwidth(struct tegra_dc *dc); | ||
61 | void tegra_nvdisp_clear_bandwidth(struct tegra_dc *dc); | ||
60 | #endif | 62 | #endif |
diff --git a/drivers/video/tegra/dc/nvdisp/nvdisp_bandwidth.c b/drivers/video/tegra/dc/nvdisp/nvdisp_bandwidth.c index e0294cbbe..bdf77d59f 100644 --- a/drivers/video/tegra/dc/nvdisp/nvdisp_bandwidth.c +++ b/drivers/video/tegra/dc/nvdisp/nvdisp_bandwidth.c | |||
@@ -42,8 +42,8 @@ | |||
42 | * - Pitch | 42 | * - Pitch |
43 | * - LUT disabled | 43 | * - LUT disabled |
44 | * | 44 | * |
45 | * NVDISP_BW_MAX_BW_KBPS and NVDISP_BW_TOTAL_MC_LATENCY were calculated with | 45 | * NVDISP_BW_MAX_BW_KBPS, NVDISP_BW_TOTAL_MC_LATENCY, and |
46 | * these settings: | 46 | * NVDISP_BW_REQ_HUBCLK_HZ were calculated with these settings: |
47 | * - 3 active heads: | 47 | * - 3 active heads: |
48 | * - 4096x2160@60p | 48 | * - 4096x2160@60p |
49 | * - 2 active windows on each head: | 49 | * - 2 active windows on each head: |
@@ -73,6 +73,9 @@ | |||
73 | /* Total MC request latency that display can tolerate (usec) */ | 73 | /* Total MC request latency that display can tolerate (usec) */ |
74 | #define NVDISP_BW_TOTAL_MC_LATENCY 1 | 74 | #define NVDISP_BW_TOTAL_MC_LATENCY 1 |
75 | 75 | ||
76 | /* Required hubclk rate for max config (Hz) */ | ||
77 | #define NVDISP_BW_REQ_HUBCLK_HZ 362000000 | ||
78 | |||
76 | /* Output id that we pass to tegra_dc_ext_process_bandwidth_negotiate */ | 79 | /* Output id that we pass to tegra_dc_ext_process_bandwidth_negotiate */ |
77 | #define NVDISP_BW_OUTPUT_ID 0 | 80 | #define NVDISP_BW_OUTPUT_ID 0 |
78 | 81 | ||
@@ -189,6 +192,40 @@ void tegra_nvdisp_program_bandwidth(struct tegra_dc *dc, | |||
189 | } | 192 | } |
190 | } | 193 | } |
191 | 194 | ||
195 | void tegra_nvdisp_init_bandwidth(struct tegra_dc *dc) | ||
196 | { | ||
197 | /* | ||
198 | * Use the max config settings. These values will eventually be adjusted | ||
199 | * through IMP, if the client supports it. | ||
200 | */ | ||
201 | |||
202 | u32 proposed_bw = NVDISP_BW_MAX_BW_KBPS; | ||
203 | u32 proposed_latency = NVDISP_BW_TOTAL_MC_LATENCY; | ||
204 | u32 proposed_hubclk = NVDISP_BW_REQ_HUBCLK_HZ; | ||
205 | bool before_win_update = true; | ||
206 | |||
207 | tegra_nvdisp_negotiate_reserved_bw(dc, proposed_bw, proposed_latency); | ||
208 | tegra_nvdisp_program_bandwidth(dc, | ||
209 | proposed_bw, | ||
210 | proposed_latency, | ||
211 | proposed_hubclk, | ||
212 | before_win_update); | ||
213 | } | ||
214 | |||
215 | void tegra_nvdisp_clear_bandwidth(struct tegra_dc *dc) | ||
216 | { | ||
217 | u32 proposed_bw = 0; | ||
218 | u32 proposed_latency = 1000; | ||
219 | u32 proposed_hubclk = 0; | ||
220 | bool before_win_update = false; | ||
221 | |||
222 | tegra_nvdisp_program_bandwidth(dc, | ||
223 | proposed_bw, | ||
224 | proposed_latency, | ||
225 | proposed_hubclk, | ||
226 | before_win_update); | ||
227 | } | ||
228 | |||
192 | /* | 229 | /* |
193 | * tegra_dc_calc_min_bandwidth - returns the minimum dedicated bw | 230 | * tegra_dc_calc_min_bandwidth - returns the minimum dedicated bw |
194 | * | 231 | * |
@@ -284,7 +321,6 @@ void tegra_nvdisp_isomgr_attach(struct tegra_dc *dc) | |||
284 | */ | 321 | */ |
285 | int tegra_nvdisp_isomgr_register(enum tegra_iso_client client, u32 udedi_bw) | 322 | int tegra_nvdisp_isomgr_register(enum tegra_iso_client client, u32 udedi_bw) |
286 | { | 323 | { |
287 | u32 latency = 0; | ||
288 | int err = 0; | 324 | int err = 0; |
289 | 325 | ||
290 | mutex_lock(&tegra_nvdisp_lock); | 326 | mutex_lock(&tegra_nvdisp_lock); |
@@ -303,26 +339,6 @@ int tegra_nvdisp_isomgr_register(enum tegra_iso_client client, u32 udedi_bw) | |||
303 | */ | 339 | */ |
304 | ihub_bw_info.available_bw = UINT_MAX; | 340 | ihub_bw_info.available_bw = UINT_MAX; |
305 | 341 | ||
306 | /* | ||
307 | * Reserve and realize the max bw at start-up. There's no need to update | ||
308 | * the corresponding fields since these values will be adjusted through | ||
309 | * IMP anyways. | ||
310 | */ | ||
311 | latency = tegra_isomgr_reserve(ihub_bw_info.isomgr_handle, | ||
312 | NVDISP_BW_MAX_BW_KBPS, | ||
313 | NVDISP_BW_TOTAL_MC_LATENCY); | ||
314 | if (latency) { | ||
315 | latency = tegra_isomgr_realize(ihub_bw_info.isomgr_handle); | ||
316 | if (!latency) { | ||
317 | WARN_ONCE(!latency, "tegra_isomgr_realize failed\n"); | ||
318 | err = -ENOENT; | ||
319 | } | ||
320 | } else { | ||
321 | WARN_ONCE(1, "tegra_isomgr_reserve failed\n"); | ||
322 | err = -ENOENT; | ||
323 | } | ||
324 | tegra_dc_set_latency_allowance(NVDISP_BW_MAX_BW_KBPS); | ||
325 | |||
326 | unlock_and_ret: | 342 | unlock_and_ret: |
327 | mutex_unlock(&tegra_nvdisp_lock); | 343 | mutex_unlock(&tegra_nvdisp_lock); |
328 | return err; | 344 | return err; |
@@ -349,6 +365,8 @@ int tegra_nvdisp_negotiate_reserved_bw(struct tegra_dc *dc, u32 proposed_bw, | |||
349 | { | 365 | { |
350 | return -ENOSYS; | 366 | return -ENOSYS; |
351 | } | 367 | } |
368 | void tegra_nvdisp_init_bandwidth(struct tegra_dc *dc) {} | ||
369 | void tegra_nvdisp_clear_bandwidth(struct tegra_dc *dc) {} | ||
352 | long tegra_dc_calc_min_bandwidth(struct tegra_dc *dc) | 370 | long tegra_dc_calc_min_bandwidth(struct tegra_dc *dc) |
353 | { | 371 | { |
354 | return -ENOSYS; | 372 | return -ENOSYS; |