blob: c19ee82fded4d983288ed58978dceaad4992f25a [file] [log] [blame]
Lloyd Atkinson8772e202016-09-26 17:52:16 -04001/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
14
Alan Kwong748e833d2016-10-26 12:34:48 -040015#include <linux/debugfs.h>
16
Lloyd Atkinson8772e202016-09-26 17:52:16 -040017#include "sde_vbif.h"
18#include "sde_hw_vbif.h"
19#include "sde_trace.h"
20
21/**
22 * _sde_vbif_wait_for_xin_halt - wait for the xin to halt
23 * @vbif: Pointer to hardware vbif driver
24 * @xin_id: Client interface identifier
25 * @return: 0 if success; error code otherwise
26 */
27static int _sde_vbif_wait_for_xin_halt(struct sde_hw_vbif *vbif, u32 xin_id)
28{
29 ktime_t timeout;
30 bool status;
31 int rc;
32
33 if (!vbif || !vbif->cap || !vbif->ops.get_halt_ctrl) {
34 SDE_ERROR("invalid arguments vbif %d\n", vbif != 0);
35 return -EINVAL;
36 }
37
38 timeout = ktime_add_us(ktime_get(), vbif->cap->xin_halt_timeout);
39 for (;;) {
40 status = vbif->ops.get_halt_ctrl(vbif, xin_id);
41 if (status)
42 break;
43 if (ktime_compare_safe(ktime_get(), timeout) > 0) {
44 status = vbif->ops.get_halt_ctrl(vbif, xin_id);
45 break;
46 }
47 usleep_range(501, 1000);
48 }
49
50 if (!status) {
51 rc = -ETIMEDOUT;
52 SDE_ERROR("VBIF %d client %d not halting. TIMEDOUT.\n",
53 vbif->idx - VBIF_0, xin_id);
54 } else {
55 rc = 0;
56 SDE_DEBUG("VBIF %d client %d is halted\n",
57 vbif->idx - VBIF_0, xin_id);
58 }
59
60 return rc;
61}
62
Harsh Sahuea808372017-09-12 22:41:01 -070063int sde_vbif_halt_plane_xin(struct sde_kms *sde_kms, u32 xin_id, u32 clk_ctrl)
64{
65 struct sde_hw_vbif *vbif = NULL;
66 struct sde_hw_mdp *mdp;
67 bool forced_on = false;
68 bool status;
69 int rc = 0;
70
71 if (!sde_kms) {
72 SDE_ERROR("invalid argument\n");
73 return -EINVAL;
74 }
75
76 vbif = sde_kms->hw_vbif[VBIF_RT];
77 mdp = sde_kms->hw_mdp;
78 if (!vbif || !mdp || !vbif->ops.get_halt_ctrl ||
79 !vbif->ops.set_halt_ctrl ||
80 !mdp->ops.setup_clk_force_ctrl) {
81 SDE_ERROR("invalid vbif or mdp arguments\n");
82 return -EINVAL;
83 }
84
Lloyd Atkinson1753a982017-11-30 15:32:47 -050085 mutex_lock(&vbif->mutex);
86
87 SDE_EVT32_VERBOSE(vbif->idx, xin_id);
88
Harsh Sahuea808372017-09-12 22:41:01 -070089 /*
90 * If status is 0, then make sure client clock is not gated
91 * while halting by forcing it ON only if it was not previously
92 * forced on. If status is 1 then its already halted.
93 */
94 status = vbif->ops.get_halt_ctrl(vbif, xin_id);
Lloyd Atkinson1753a982017-11-30 15:32:47 -050095 if (status) {
96 mutex_unlock(&vbif->mutex);
Harsh Sahuea808372017-09-12 22:41:01 -070097 return 0;
Lloyd Atkinson1753a982017-11-30 15:32:47 -050098 }
99
100 forced_on = mdp->ops.setup_clk_force_ctrl(mdp, clk_ctrl, true);
Harsh Sahuea808372017-09-12 22:41:01 -0700101
102 /* send halt request for unused plane's xin client */
103 vbif->ops.set_halt_ctrl(vbif, xin_id, true);
104
105 rc = _sde_vbif_wait_for_xin_halt(vbif, xin_id);
106 if (rc) {
107 SDE_ERROR(
108 "wait failed for pipe halt:xin_id %u, clk_ctrl %u, rc %u\n",
109 xin_id, clk_ctrl, rc);
110 SDE_EVT32(xin_id, clk_ctrl, rc, SDE_EVTLOG_ERROR);
Harsh Sahuea808372017-09-12 22:41:01 -0700111 }
112
113 /* open xin client to enable transactions */
114 vbif->ops.set_halt_ctrl(vbif, xin_id, false);
115 if (forced_on)
116 mdp->ops.setup_clk_force_ctrl(mdp, clk_ctrl, false);
117
Lloyd Atkinson1753a982017-11-30 15:32:47 -0500118 mutex_unlock(&vbif->mutex);
119
Lloyd Atkinson89e6f2f2017-11-10 18:37:43 -0500120 return rc;
Harsh Sahuea808372017-09-12 22:41:01 -0700121}
122
Lloyd Atkinson8772e202016-09-26 17:52:16 -0400123/**
124 * _sde_vbif_apply_dynamic_ot_limit - determine OT based on usecase parameters
125 * @vbif: Pointer to hardware vbif driver
126 * @ot_lim: Pointer to OT limit to be modified
127 * @params: Pointer to usecase parameters
128 */
129static void _sde_vbif_apply_dynamic_ot_limit(struct sde_hw_vbif *vbif,
130 u32 *ot_lim, struct sde_vbif_set_ot_params *params)
131{
132 u64 pps;
133 const struct sde_vbif_dynamic_ot_tbl *tbl;
134 u32 i;
135
136 if (!vbif || !(vbif->cap->features & BIT(SDE_VBIF_QOS_OTLIM)))
137 return;
138
139 /* Dynamic OT setting done only for WFD */
140 if (!params->is_wfd)
141 return;
142
143 pps = params->frame_rate;
144 pps *= params->width;
145 pps *= params->height;
146
147 tbl = params->rd ? &vbif->cap->dynamic_ot_rd_tbl :
148 &vbif->cap->dynamic_ot_wr_tbl;
149
150 for (i = 0; i < tbl->count; i++) {
151 if (pps <= tbl->cfg[i].pps) {
152 *ot_lim = tbl->cfg[i].ot_limit;
153 break;
154 }
155 }
156
157 SDE_DEBUG("vbif:%d xin:%d w:%d h:%d fps:%d pps:%llu ot:%u\n",
158 vbif->idx - VBIF_0, params->xin_id,
159 params->width, params->height, params->frame_rate,
160 pps, *ot_lim);
161}
162
163/**
164 * _sde_vbif_get_ot_limit - get OT based on usecase & configuration parameters
165 * @vbif: Pointer to hardware vbif driver
166 * @params: Pointer to usecase parameters
167 * @return: OT limit
168 */
169static u32 _sde_vbif_get_ot_limit(struct sde_hw_vbif *vbif,
170 struct sde_vbif_set_ot_params *params)
171{
172 u32 ot_lim = 0;
173 u32 val;
174
175 if (!vbif || !vbif->cap) {
176 SDE_ERROR("invalid arguments vbif %d\n", vbif != 0);
177 return -EINVAL;
178 }
179
180 if (vbif->cap->default_ot_wr_limit && !params->rd)
181 ot_lim = vbif->cap->default_ot_wr_limit;
182 else if (vbif->cap->default_ot_rd_limit && params->rd)
183 ot_lim = vbif->cap->default_ot_rd_limit;
184
185 /*
186 * If default ot is not set from dt/catalog,
187 * then do not configure it.
188 */
189 if (ot_lim == 0)
190 goto exit;
191
192 /* Modify the limits if the target and the use case requires it */
193 _sde_vbif_apply_dynamic_ot_limit(vbif, &ot_lim, params);
194
195 if (vbif && vbif->ops.get_limit_conf) {
196 val = vbif->ops.get_limit_conf(vbif,
197 params->xin_id, params->rd);
198 if (val == ot_lim)
199 ot_lim = 0;
200 }
201
202exit:
203 SDE_DEBUG("vbif:%d xin:%d ot_lim:%d\n",
204 vbif->idx - VBIF_0, params->xin_id, ot_lim);
205 return ot_lim;
206}
207
208/**
209 * sde_vbif_set_ot_limit - set OT based on usecase & configuration parameters
210 * @vbif: Pointer to hardware vbif driver
211 * @params: Pointer to usecase parameters
212 *
213 * Note this function would block waiting for bus halt.
214 */
215void sde_vbif_set_ot_limit(struct sde_kms *sde_kms,
216 struct sde_vbif_set_ot_params *params)
217{
218 struct sde_hw_vbif *vbif = NULL;
219 struct sde_hw_mdp *mdp;
220 bool forced_on = false;
221 u32 ot_lim;
222 int ret, i;
223
224 if (!sde_kms) {
225 SDE_ERROR("invalid arguments\n");
226 return;
227 }
228 mdp = sde_kms->hw_mdp;
229
230 for (i = 0; i < ARRAY_SIZE(sde_kms->hw_vbif); i++) {
231 if (sde_kms->hw_vbif[i] &&
Clarence Ipff4609e2017-10-06 13:36:24 -0400232 sde_kms->hw_vbif[i]->idx == params->vbif_idx) {
Lloyd Atkinson8772e202016-09-26 17:52:16 -0400233 vbif = sde_kms->hw_vbif[i];
Clarence Ipff4609e2017-10-06 13:36:24 -0400234 break;
235 }
Lloyd Atkinson8772e202016-09-26 17:52:16 -0400236 }
237
238 if (!vbif || !mdp) {
239 SDE_DEBUG("invalid arguments vbif %d mdp %d\n",
Clarence Ipff4609e2017-10-06 13:36:24 -0400240 vbif != NULL, mdp != NULL);
Lloyd Atkinson8772e202016-09-26 17:52:16 -0400241 return;
242 }
243
244 if (!mdp->ops.setup_clk_force_ctrl ||
245 !vbif->ops.set_limit_conf ||
246 !vbif->ops.set_halt_ctrl)
247 return;
248
Lloyd Atkinson1753a982017-11-30 15:32:47 -0500249 mutex_lock(&vbif->mutex);
250
251 SDE_EVT32_VERBOSE(vbif->idx, params->xin_id);
252
Veera Sundaram Sankaran79525402017-07-31 14:17:23 -0700253 /* set write_gather_en for all write clients */
254 if (vbif->ops.set_write_gather_en && !params->rd)
255 vbif->ops.set_write_gather_en(vbif, params->xin_id);
256
Lloyd Atkinson8772e202016-09-26 17:52:16 -0400257 ot_lim = _sde_vbif_get_ot_limit(vbif, params) & 0xFF;
258
259 if (ot_lim == 0)
260 goto exit;
261
262 trace_sde_perf_set_ot(params->num, params->xin_id, ot_lim,
263 params->vbif_idx);
264
265 forced_on = mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, true);
266
267 vbif->ops.set_limit_conf(vbif, params->xin_id, params->rd, ot_lim);
268
269 vbif->ops.set_halt_ctrl(vbif, params->xin_id, true);
270
271 ret = _sde_vbif_wait_for_xin_halt(vbif, params->xin_id);
272 if (ret)
Lloyd Atkinson5d40d312016-09-06 08:34:13 -0400273 SDE_EVT32(vbif->idx, params->xin_id);
Lloyd Atkinson8772e202016-09-26 17:52:16 -0400274
275 vbif->ops.set_halt_ctrl(vbif, params->xin_id, false);
276
277 if (forced_on)
278 mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, false);
279exit:
Lloyd Atkinson1753a982017-11-30 15:32:47 -0500280 mutex_unlock(&vbif->mutex);
Lloyd Atkinson8772e202016-09-26 17:52:16 -0400281 return;
282}
Alan Kwong748e833d2016-10-26 12:34:48 -0400283
Clarence Ipff4609e2017-10-06 13:36:24 -0400284bool sde_vbif_set_xin_halt(struct sde_kms *sde_kms,
285 struct sde_vbif_set_xin_halt_params *params)
286{
287 struct sde_hw_vbif *vbif = NULL;
288 struct sde_hw_mdp *mdp;
289 bool forced_on = false;
290 int ret, i;
291
292 if (!sde_kms || !params) {
293 SDE_ERROR("invalid arguments\n");
294 return false;
295 }
296 mdp = sde_kms->hw_mdp;
297
298 for (i = 0; i < ARRAY_SIZE(sde_kms->hw_vbif); i++) {
299 if (sde_kms->hw_vbif[i] &&
300 sde_kms->hw_vbif[i]->idx == params->vbif_idx) {
301 vbif = sde_kms->hw_vbif[i];
302 break;
303 }
304 }
305
306 if (!vbif || !mdp) {
307 SDE_DEBUG("invalid arguments vbif %d mdp %d\n",
308 vbif != NULL, mdp != NULL);
309 return false;
310 }
311
312 if (!mdp->ops.setup_clk_force_ctrl ||
313 !vbif->ops.set_halt_ctrl)
314 return false;
315
Lloyd Atkinson1753a982017-11-30 15:32:47 -0500316 mutex_lock(&vbif->mutex);
317
318 SDE_EVT32_VERBOSE(vbif->idx, params->xin_id);
319
Clarence Ipff4609e2017-10-06 13:36:24 -0400320 if (params->enable) {
321 forced_on = mdp->ops.setup_clk_force_ctrl(mdp,
322 params->clk_ctrl, true);
323
324 vbif->ops.set_halt_ctrl(vbif, params->xin_id, true);
325
326 ret = _sde_vbif_wait_for_xin_halt(vbif, params->xin_id);
327 if (ret)
328 SDE_EVT32(vbif->idx, params->xin_id, SDE_EVTLOG_ERROR);
329 } else {
330 vbif->ops.set_halt_ctrl(vbif, params->xin_id, false);
331
332 if (params->forced_on)
333 mdp->ops.setup_clk_force_ctrl(mdp,
334 params->clk_ctrl, false);
335 }
336
Lloyd Atkinson1753a982017-11-30 15:32:47 -0500337 mutex_unlock(&vbif->mutex);
338
Clarence Ipff4609e2017-10-06 13:36:24 -0400339 return forced_on;
340}
341
Alan Kwonga62eeb82017-04-19 08:57:55 -0700342void sde_vbif_set_qos_remap(struct sde_kms *sde_kms,
343 struct sde_vbif_set_qos_params *params)
344{
345 struct sde_hw_vbif *vbif = NULL;
346 struct sde_hw_mdp *mdp;
347 bool forced_on = false;
348 const struct sde_vbif_qos_tbl *qos_tbl;
349 int i;
350
351 if (!sde_kms || !params || !sde_kms->hw_mdp) {
352 SDE_ERROR("invalid arguments\n");
353 return;
354 }
355 mdp = sde_kms->hw_mdp;
356
357 for (i = 0; i < ARRAY_SIZE(sde_kms->hw_vbif); i++) {
358 if (sde_kms->hw_vbif[i] &&
359 sde_kms->hw_vbif[i]->idx == params->vbif_idx) {
360 vbif = sde_kms->hw_vbif[i];
361 break;
362 }
363 }
364
365 if (!vbif || !vbif->cap) {
366 SDE_ERROR("invalid vbif %d\n", params->vbif_idx);
367 return;
368 }
369
370 if (!vbif->ops.set_qos_remap || !mdp->ops.setup_clk_force_ctrl) {
371 SDE_DEBUG("qos remap not supported\n");
372 return;
373 }
374
375 qos_tbl = params->is_rt ? &vbif->cap->qos_rt_tbl :
376 &vbif->cap->qos_nrt_tbl;
377
378 if (!qos_tbl->npriority_lvl || !qos_tbl->priority_lvl) {
379 SDE_DEBUG("qos tbl not defined\n");
380 return;
381 }
382
Lloyd Atkinson1753a982017-11-30 15:32:47 -0500383 mutex_lock(&vbif->mutex);
384
Alan Kwonga62eeb82017-04-19 08:57:55 -0700385 forced_on = mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, true);
386
387 for (i = 0; i < qos_tbl->npriority_lvl; i++) {
388 SDE_DEBUG("vbif:%d xin:%d lvl:%d/%d\n",
389 params->vbif_idx, params->xin_id, i,
390 qos_tbl->priority_lvl[i]);
391 vbif->ops.set_qos_remap(vbif, params->xin_id, i,
392 qos_tbl->priority_lvl[i]);
393 }
394
395 if (forced_on)
396 mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, false);
Lloyd Atkinson1753a982017-11-30 15:32:47 -0500397
398 mutex_unlock(&vbif->mutex);
Alan Kwonga62eeb82017-04-19 08:57:55 -0700399}
400
Clarence Ip980405d2017-08-08 18:33:44 -0400401void sde_vbif_clear_errors(struct sde_kms *sde_kms)
402{
403 struct sde_hw_vbif *vbif;
404 u32 i, pnd, src;
405
406 if (!sde_kms) {
407 SDE_ERROR("invalid argument\n");
408 return;
409 }
410
411 for (i = 0; i < ARRAY_SIZE(sde_kms->hw_vbif); i++) {
412 vbif = sde_kms->hw_vbif[i];
413 if (vbif && vbif->ops.clear_errors) {
Lloyd Atkinson1753a982017-11-30 15:32:47 -0500414 mutex_lock(&vbif->mutex);
Clarence Ip980405d2017-08-08 18:33:44 -0400415 vbif->ops.clear_errors(vbif, &pnd, &src);
416 if (pnd || src) {
417 SDE_EVT32(i, pnd, src);
418 SDE_DEBUG("VBIF %d: pnd 0x%X, src 0x%X\n",
419 vbif->idx - VBIF_0, pnd, src);
420 }
Lloyd Atkinson1753a982017-11-30 15:32:47 -0500421 mutex_unlock(&vbif->mutex);
Clarence Ip980405d2017-08-08 18:33:44 -0400422 }
423 }
424}
425
Clarence Ip7f0de632017-05-31 14:59:14 -0400426void sde_vbif_init_memtypes(struct sde_kms *sde_kms)
427{
428 struct sde_hw_vbif *vbif;
429 int i, j;
430
431 if (!sde_kms) {
432 SDE_ERROR("invalid argument\n");
433 return;
434 }
435
436 for (i = 0; i < ARRAY_SIZE(sde_kms->hw_vbif); i++) {
437 vbif = sde_kms->hw_vbif[i];
438 if (vbif && vbif->cap && vbif->ops.set_mem_type) {
Lloyd Atkinson1753a982017-11-30 15:32:47 -0500439 mutex_lock(&vbif->mutex);
Clarence Ip7f0de632017-05-31 14:59:14 -0400440 for (j = 0; j < vbif->cap->memtype_count; j++)
441 vbif->ops.set_mem_type(
442 vbif, j, vbif->cap->memtype[j]);
Lloyd Atkinson1753a982017-11-30 15:32:47 -0500443 mutex_unlock(&vbif->mutex);
Clarence Ip7f0de632017-05-31 14:59:14 -0400444 }
445 }
446}
447
Alan Kwong748e833d2016-10-26 12:34:48 -0400448#ifdef CONFIG_DEBUG_FS
449void sde_debugfs_vbif_destroy(struct sde_kms *sde_kms)
450{
451 debugfs_remove_recursive(sde_kms->debugfs_vbif);
452 sde_kms->debugfs_vbif = NULL;
453}
454
455int sde_debugfs_vbif_init(struct sde_kms *sde_kms, struct dentry *debugfs_root)
456{
457 char vbif_name[32];
458 struct dentry *debugfs_vbif;
459 int i, j;
460
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -0700461 sde_kms->debugfs_vbif = debugfs_create_dir("vbif", debugfs_root);
Alan Kwong748e833d2016-10-26 12:34:48 -0400462 if (!sde_kms->debugfs_vbif) {
463 SDE_ERROR("failed to create vbif debugfs\n");
464 return -EINVAL;
465 }
466
467 for (i = 0; i < sde_kms->catalog->vbif_count; i++) {
468 struct sde_vbif_cfg *vbif = &sde_kms->catalog->vbif[i];
469
470 snprintf(vbif_name, sizeof(vbif_name), "%d", vbif->id);
471
472 debugfs_vbif = debugfs_create_dir(vbif_name,
473 sde_kms->debugfs_vbif);
474
Lloyd Atkinson8de415a2017-05-23 11:31:16 -0400475 debugfs_create_u32("features", 0600, debugfs_vbif,
Alan Kwong748e833d2016-10-26 12:34:48 -0400476 (u32 *)&vbif->features);
477
Lloyd Atkinson8de415a2017-05-23 11:31:16 -0400478 debugfs_create_u32("xin_halt_timeout", 0400, debugfs_vbif,
Alan Kwong748e833d2016-10-26 12:34:48 -0400479 (u32 *)&vbif->xin_halt_timeout);
480
Lloyd Atkinson8de415a2017-05-23 11:31:16 -0400481 debugfs_create_u32("default_rd_ot_limit", 0400, debugfs_vbif,
Alan Kwong748e833d2016-10-26 12:34:48 -0400482 (u32 *)&vbif->default_ot_rd_limit);
483
Lloyd Atkinson8de415a2017-05-23 11:31:16 -0400484 debugfs_create_u32("default_wr_ot_limit", 0400, debugfs_vbif,
Alan Kwong748e833d2016-10-26 12:34:48 -0400485 (u32 *)&vbif->default_ot_wr_limit);
486
487 for (j = 0; j < vbif->dynamic_ot_rd_tbl.count; j++) {
488 struct sde_vbif_dynamic_ot_cfg *cfg =
489 &vbif->dynamic_ot_rd_tbl.cfg[j];
490
491 snprintf(vbif_name, sizeof(vbif_name),
492 "dynamic_ot_rd_%d_pps", j);
Lloyd Atkinson8de415a2017-05-23 11:31:16 -0400493 debugfs_create_u64(vbif_name, 0400, debugfs_vbif,
Alan Kwong748e833d2016-10-26 12:34:48 -0400494 (u64 *)&cfg->pps);
495 snprintf(vbif_name, sizeof(vbif_name),
496 "dynamic_ot_rd_%d_ot_limit", j);
Lloyd Atkinson8de415a2017-05-23 11:31:16 -0400497 debugfs_create_u32(vbif_name, 0400, debugfs_vbif,
Alan Kwong748e833d2016-10-26 12:34:48 -0400498 (u32 *)&cfg->ot_limit);
499 }
500
501 for (j = 0; j < vbif->dynamic_ot_wr_tbl.count; j++) {
502 struct sde_vbif_dynamic_ot_cfg *cfg =
503 &vbif->dynamic_ot_wr_tbl.cfg[j];
504
505 snprintf(vbif_name, sizeof(vbif_name),
506 "dynamic_ot_wr_%d_pps", j);
Lloyd Atkinson8de415a2017-05-23 11:31:16 -0400507 debugfs_create_u64(vbif_name, 0400, debugfs_vbif,
Alan Kwong748e833d2016-10-26 12:34:48 -0400508 (u64 *)&cfg->pps);
509 snprintf(vbif_name, sizeof(vbif_name),
510 "dynamic_ot_wr_%d_ot_limit", j);
Lloyd Atkinson8de415a2017-05-23 11:31:16 -0400511 debugfs_create_u32(vbif_name, 0400, debugfs_vbif,
Alan Kwong748e833d2016-10-26 12:34:48 -0400512 (u32 *)&cfg->ot_limit);
513 }
514 }
515
516 return 0;
517}
518#endif