blob: ae01bafa44a1bda3c631a508849132863affd42e [file] [log] [blame]
Benjamin Chan1b94f952017-01-23 17:42:30 -05001/* Copyright (c) 2012, 2015-2017, The Linux Foundation. All rights reserved.
Adrian Salido-Moreno5c150382016-04-06 09:29:37 -07002 *
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) "%s: " fmt, __func__
14
15#include <linux/errno.h>
16#include <linux/file.h>
17#include <linux/spinlock.h>
18#include <linux/types.h>
19#include <linux/major.h>
20#include <linux/debugfs.h>
21#include <linux/clk.h>
22#include <linux/slab.h>
23#include <linux/io.h>
24#include <linux/iopoll.h>
25#include <linux/msm-bus.h>
26#include <linux/msm-bus-board.h>
27#include <linux/regulator/consumer.h>
28
29#define CREATE_TRACE_POINTS
30#include "sde_rotator_base.h"
31#include "sde_rotator_util.h"
32#include "sde_rotator_trace.h"
Benjamin Chan1b94f952017-01-23 17:42:30 -050033#include "sde_rotator_debug.h"
Adrian Salido-Moreno5c150382016-04-06 09:29:37 -070034
35static inline u64 fudge_factor(u64 val, u32 numer, u32 denom)
36{
37 u64 result = (val * (u64)numer);
38
39 do_div(result, denom);
40 return result;
41}
42
43static inline u64 apply_fudge_factor(u64 val,
44 struct sde_mult_factor *factor)
45{
46 return fudge_factor(val, factor->numer, factor->denom);
47}
48
49static inline u64 apply_inverse_fudge_factor(u64 val,
50 struct sde_mult_factor *factor)
51{
52 return fudge_factor(val, factor->denom, factor->numer);
53}
54
55static inline bool validate_comp_ratio(struct sde_mult_factor *factor)
56{
57 return factor->numer && factor->denom;
58}
59
60u32 sde_apply_comp_ratio_factor(u32 quota,
61 struct sde_mdp_format_params *fmt,
62 struct sde_mult_factor *factor)
63{
64 struct sde_rot_data_type *mdata = sde_rot_get_mdata();
65
66 if (!mdata || !test_bit(SDE_QOS_OVERHEAD_FACTOR,
67 mdata->sde_qos_map))
68 return quota;
69
70 /* apply compression ratio, only for compressed formats */
71 if (sde_mdp_is_ubwc_format(fmt) &&
72 validate_comp_ratio(factor))
73 quota = apply_inverse_fudge_factor(quota, factor);
74
75 return quota;
76}
77
78#define RES_1080p (1088*1920)
79#define RES_UHD (3840*2160)
80#define XIN_HALT_TIMEOUT_US 0x4000
81
82static int sde_mdp_wait_for_xin_halt(u32 xin_id)
83{
84 void __iomem *vbif_base;
85 u32 status;
86 struct sde_rot_data_type *mdata = sde_rot_get_mdata();
87 u32 idle_mask = BIT(xin_id);
88 int rc;
89
90 vbif_base = mdata->vbif_nrt_io.base;
91
92 rc = readl_poll_timeout(vbif_base + MMSS_VBIF_XIN_HALT_CTRL1,
93 status, (status & idle_mask),
94 1000, XIN_HALT_TIMEOUT_US);
95 if (rc == -ETIMEDOUT) {
96 SDEROT_ERR("VBIF client %d not halting. TIMEDOUT.\n",
97 xin_id);
98 } else {
99 SDEROT_DBG("VBIF client %d is halted\n", xin_id);
100 }
101
102 return rc;
103}
104
105/**
106 * force_on_xin_clk() - enable/disable the force-on for the pipe clock
107 * @bit_off: offset of the bit to enable/disable the force-on.
108 * @reg_off: register offset for the clock control.
109 * @enable: boolean to indicate if the force-on of the clock needs to be
110 * enabled or disabled.
111 *
112 * This function returns:
113 * true - if the clock is forced-on by this function
114 * false - if the clock was already forced on
115 * It is the caller responsibility to check if this function is forcing
116 * the clock on; if so, it will need to remove the force of the clock,
117 * otherwise it should avoid to remove the force-on.
118 * Clocks must be on when calling this function.
119 */
120static bool force_on_xin_clk(u32 bit_off, u32 clk_ctl_reg_off, bool enable)
121{
122 u32 val;
123 u32 force_on_mask;
124 struct sde_rot_data_type *mdata = sde_rot_get_mdata();
125 bool clk_forced_on = false;
126
127 force_on_mask = BIT(bit_off);
128 val = readl_relaxed(mdata->mdp_base + clk_ctl_reg_off);
129
130 clk_forced_on = !(force_on_mask & val);
131
132 if (true == enable)
133 val |= force_on_mask;
134 else
135 val &= ~force_on_mask;
136
137 writel_relaxed(val, mdata->mdp_base + clk_ctl_reg_off);
138
139 return clk_forced_on;
140}
141
Alan Kwongeffb5ee2016-03-12 19:47:45 -0500142u32 sde_mdp_get_ot_limit(u32 width, u32 height, u32 pixfmt, u32 fps, u32 is_rd)
Adrian Salido-Moreno5c150382016-04-06 09:29:37 -0700143{
144 struct sde_rot_data_type *mdata = sde_rot_get_mdata();
Alan Kwongeffb5ee2016-03-12 19:47:45 -0500145 struct sde_mdp_format_params *fmt;
146 u32 ot_lim;
147 u32 is_yuv;
Adrian Salido-Moreno5c150382016-04-06 09:29:37 -0700148 u32 res;
149
Alan Kwongeffb5ee2016-03-12 19:47:45 -0500150 ot_lim = (is_rd) ? mdata->default_ot_rd_limit :
151 mdata->default_ot_wr_limit;
Adrian Salido-Moreno5c150382016-04-06 09:29:37 -0700152
153 /*
154 * If default ot is not set from dt,
155 * then do not configure it.
156 */
157 if (ot_lim == 0)
158 goto exit;
159
160 /* Modify the limits if the target and the use case requires it */
Alan Kwongeffb5ee2016-03-12 19:47:45 -0500161 if (false == test_bit(SDE_QOS_OTLIM, mdata->sde_qos_map))
162 goto exit;
163
164 res = width * height;
165
166 fmt = sde_get_format_params(pixfmt);
167
168 if (!fmt) {
169 SDEROT_WARN("invalid format %8.8x\n", pixfmt);
170 goto exit;
171 }
172
173 is_yuv = sde_mdp_is_yuv_format(fmt);
174
175 SDEROT_DBG("w:%d h:%d fps:%d pixfmt:%8.8x yuv:%d res:%d rd:%d\n",
176 width, height, fps, pixfmt, is_yuv, res, is_rd);
177
178 if (!is_yuv)
179 goto exit;
180
181 if ((res <= RES_1080p) && (fps <= 30))
182 ot_lim = 2;
183 else if ((res <= RES_1080p) && (fps <= 60))
184 ot_lim = 4;
185 else if ((res <= RES_UHD) && (fps <= 30))
186 ot_lim = 8;
187
188exit:
189 SDEROT_DBG("ot_lim=%d\n", ot_lim);
190 return ot_lim;
191}
192
193static u32 get_ot_limit(u32 reg_off, u32 bit_off,
194 struct sde_mdp_set_ot_params *params)
195{
196 struct sde_rot_data_type *mdata = sde_rot_get_mdata();
197 u32 ot_lim;
198 u32 val;
199
200 ot_lim = sde_mdp_get_ot_limit(
201 params->width, params->height,
202 params->fmt, params->fps,
203 params->reg_off_vbif_lim_conf == MMSS_VBIF_RD_LIM_CONF);
204
205 /*
206 * If default ot is not set from dt,
207 * then do not configure it.
208 */
209 if (ot_lim == 0)
210 goto exit;
Adrian Salido-Moreno5c150382016-04-06 09:29:37 -0700211
212 val = SDE_VBIF_READ(mdata, reg_off);
213 val &= (0xFF << bit_off);
214 val = val >> bit_off;
215
216 if (val == ot_lim)
217 ot_lim = 0;
218
219exit:
220 SDEROT_DBG("ot_lim=%d\n", ot_lim);
Benjamin Chan1b94f952017-01-23 17:42:30 -0500221 SDEROT_EVTLOG(params->width, params->height, params->fmt, params->fps,
222 ot_lim);
Adrian Salido-Moreno5c150382016-04-06 09:29:37 -0700223 return ot_lim;
224}
225
226void sde_mdp_set_ot_limit(struct sde_mdp_set_ot_params *params)
227{
228 struct sde_rot_data_type *mdata = sde_rot_get_mdata();
229 u32 ot_lim;
Veera Sundaram Sankaran3e539fe2017-05-10 17:03:32 -0700230 u32 reg_off_vbif_lim_conf = ((params->xin_id / mdata->npriority_lvl)
231 * mdata->npriority_lvl)
232 + params->reg_off_vbif_lim_conf;
233 u32 bit_off_vbif_lim_conf = (params->xin_id % mdata->npriority_lvl) * 8;
Adrian Salido-Moreno5c150382016-04-06 09:29:37 -0700234 u32 reg_val;
Benjamin Chan1b94f952017-01-23 17:42:30 -0500235 u32 sts;
Adrian Salido-Moreno5c150382016-04-06 09:29:37 -0700236 bool forced_on;
237
238 ot_lim = get_ot_limit(
239 reg_off_vbif_lim_conf,
240 bit_off_vbif_lim_conf,
241 params) & 0xFF;
242
243 if (ot_lim == 0)
244 goto exit;
245
Benjamin Chan1b94f952017-01-23 17:42:30 -0500246 if (params->rotsts_base && params->rotsts_busy_mask) {
247 sts = readl_relaxed(params->rotsts_base);
248 if (sts & params->rotsts_busy_mask) {
249 SDEROT_ERR(
250 "Rotator still busy, should not modify VBIF\n");
251 SDEROT_EVTLOG_TOUT_HANDLER(
252 "rot", "vbif_dbg_bus", "panic");
253 }
254 }
255
Adrian Salido-Moreno5c150382016-04-06 09:29:37 -0700256 trace_rot_perf_set_ot(params->num, params->xin_id, ot_lim);
257
258 forced_on = force_on_xin_clk(params->bit_off_mdp_clk_ctrl,
259 params->reg_off_mdp_clk_ctrl, true);
260
261 reg_val = SDE_VBIF_READ(mdata, reg_off_vbif_lim_conf);
262 reg_val &= ~(0xFF << bit_off_vbif_lim_conf);
263 reg_val |= (ot_lim) << bit_off_vbif_lim_conf;
264 SDE_VBIF_WRITE(mdata, reg_off_vbif_lim_conf, reg_val);
265
266 reg_val = SDE_VBIF_READ(mdata, MMSS_VBIF_XIN_HALT_CTRL0);
267 SDE_VBIF_WRITE(mdata, MMSS_VBIF_XIN_HALT_CTRL0,
268 reg_val | BIT(params->xin_id));
269
270 /* this is a polling operation */
271 sde_mdp_wait_for_xin_halt(params->xin_id);
272
273 reg_val = SDE_VBIF_READ(mdata, MMSS_VBIF_XIN_HALT_CTRL0);
274 SDE_VBIF_WRITE(mdata, MMSS_VBIF_XIN_HALT_CTRL0,
275 reg_val & ~BIT(params->xin_id));
276
277 if (forced_on)
278 force_on_xin_clk(params->bit_off_mdp_clk_ctrl,
279 params->reg_off_mdp_clk_ctrl, false);
280
Benjamin Chan1b94f952017-01-23 17:42:30 -0500281 SDEROT_EVTLOG(params->num, params->xin_id, ot_lim);
Adrian Salido-Moreno5c150382016-04-06 09:29:37 -0700282exit:
283 return;
284}
285
Alan Kwong9bdbb082017-06-30 14:20:48 -0400286/*
287 * sde_mdp_set_vbif_memtype - set memtype output for the given xin port
288 * @mdata: pointer to global rotator data
289 * @xin_id: xin identifier
290 * @memtype: memtype output configuration
291 * return: none
292 */
293static void sde_mdp_set_vbif_memtype(struct sde_rot_data_type *mdata,
294 u32 xin_id, u32 memtype)
295{
296 u32 reg_off;
297 u32 bit_off;
298 u32 reg_val;
299
300 /*
301 * Assume 4 bits per bit field, 8 fields per 32-bit register.
302 */
303 if (xin_id >= 8)
304 return;
305
306 reg_off = MMSS_VBIF_NRT_VBIF_OUT_AXI_AMEMTYPE_CONF0;
307
308 bit_off = (xin_id & 0x7) * 4;
309 reg_val = SDE_VBIF_READ(mdata, reg_off);
310 reg_val &= ~(0x7 << bit_off);
311 reg_val |= (memtype & 0x7) << bit_off;
312 SDE_VBIF_WRITE(mdata, reg_off, reg_val);
313}
314
315/*
316 * sde_mdp_init_vbif - initialize static vbif configuration
317 * return: 0 if success; error code otherwise
318 */
319int sde_mdp_init_vbif(void)
320{
321 struct sde_rot_data_type *mdata = sde_rot_get_mdata();
322 int i;
323
324 if (!mdata)
325 return -EINVAL;
326
327 if (mdata->vbif_memtype_count && mdata->vbif_memtype) {
328 for (i = 0; i < mdata->vbif_memtype_count; i++)
329 sde_mdp_set_vbif_memtype(mdata, i,
330 mdata->vbif_memtype[i]);
331
332 SDEROT_DBG("amemtype=0x%x\n", SDE_VBIF_READ(mdata,
333 MMSS_VBIF_NRT_VBIF_OUT_AXI_AMEMTYPE_CONF0));
334 }
335
336 return 0;
337}
338
Adrian Salido-Moreno5c150382016-04-06 09:29:37 -0700339struct reg_bus_client *sde_reg_bus_vote_client_create(char *client_name)
340{
341 struct reg_bus_client *client;
342 struct sde_rot_data_type *sde_res = sde_rot_get_mdata();
343 static u32 id;
344
345 if (client_name == NULL) {
346 SDEROT_ERR("client name is null\n");
347 return ERR_PTR(-EINVAL);
348 }
349
350 client = kzalloc(sizeof(struct reg_bus_client), GFP_KERNEL);
351 if (!client)
352 return ERR_PTR(-ENOMEM);
353
354 mutex_lock(&sde_res->reg_bus_lock);
355 strlcpy(client->name, client_name, MAX_CLIENT_NAME_LEN);
356 client->usecase_ndx = VOTE_INDEX_DISABLE;
357 client->id = id;
358 SDEROT_DBG("bus vote client %s created:%p id :%d\n", client_name,
359 client, id);
360 id++;
361 list_add(&client->list, &sde_res->reg_bus_clist);
362 mutex_unlock(&sde_res->reg_bus_lock);
363
364 return client;
365}
366
367void sde_reg_bus_vote_client_destroy(struct reg_bus_client *client)
368{
369 struct sde_rot_data_type *sde_res = sde_rot_get_mdata();
370
371 if (!client) {
372 SDEROT_ERR("reg bus vote: invalid client handle\n");
373 } else {
374 SDEROT_DBG("bus vote client %s destroyed:%p id:%u\n",
375 client->name, client, client->id);
376 mutex_lock(&sde_res->reg_bus_lock);
377 list_del_init(&client->list);
378 mutex_unlock(&sde_res->reg_bus_lock);
379 kfree(client);
380 }
381}
382
383int sde_update_reg_bus_vote(struct reg_bus_client *bus_client, u32 usecase_ndx)
384{
385 int ret = 0;
386 bool changed = false;
387 u32 max_usecase_ndx = VOTE_INDEX_DISABLE;
388 struct reg_bus_client *client, *temp_client;
389 struct sde_rot_data_type *sde_res = sde_rot_get_mdata();
390
391 if (!sde_res || !sde_res->reg_bus_hdl || !bus_client)
392 return 0;
393
394 mutex_lock(&sde_res->reg_bus_lock);
395 bus_client->usecase_ndx = usecase_ndx;
396 list_for_each_entry_safe(client, temp_client, &sde_res->reg_bus_clist,
397 list) {
398
399 if (client->usecase_ndx < VOTE_INDEX_MAX &&
400 client->usecase_ndx > max_usecase_ndx)
401 max_usecase_ndx = client->usecase_ndx;
402 }
403
404 if (sde_res->reg_bus_usecase_ndx != max_usecase_ndx) {
405 changed = true;
406 sde_res->reg_bus_usecase_ndx = max_usecase_ndx;
407 }
408
409 SDEROT_DBG(
410 "%pS: changed=%d current idx=%d request client %s id:%u idx:%d\n",
411 __builtin_return_address(0), changed, max_usecase_ndx,
412 bus_client->name, bus_client->id, usecase_ndx);
413 if (changed)
414 ret = msm_bus_scale_client_update_request(sde_res->reg_bus_hdl,
415 max_usecase_ndx);
416
417 mutex_unlock(&sde_res->reg_bus_lock);
418 return ret;
419}
420
421static int sde_mdp_parse_dt_handler(struct platform_device *pdev,
422 char *prop_name, u32 *offsets, int len)
423{
424 int rc;
425
426 rc = of_property_read_u32_array(pdev->dev.of_node, prop_name,
427 offsets, len);
428 if (rc) {
429 SDEROT_ERR("Error from prop %s : u32 array read\n", prop_name);
430 return -EINVAL;
431 }
432
433 return 0;
434}
435
436static int sde_mdp_parse_dt_prop_len(struct platform_device *pdev,
437 char *prop_name)
438{
439 int len = 0;
440
441 of_find_property(pdev->dev.of_node, prop_name, &len);
442
443 if (len < 1) {
444 SDEROT_INFO("prop %s : doesn't exist in device tree\n",
445 prop_name);
446 return 0;
447 }
448
449 len = len/sizeof(u32);
450
451 return len;
452}
453
Alan Kwong9bdbb082017-06-30 14:20:48 -0400454static void sde_mdp_parse_vbif_memtype(struct platform_device *pdev,
455 struct sde_rot_data_type *mdata)
456{
457 int rc;
458
459 mdata->vbif_memtype_count = sde_mdp_parse_dt_prop_len(pdev,
460 "qcom,mdss-rot-vbif-memtype");
461 mdata->vbif_memtype = kzalloc(sizeof(u32) *
462 mdata->vbif_memtype_count, GFP_KERNEL);
463 if (!mdata->vbif_memtype) {
464 mdata->vbif_memtype_count = 0;
465 return;
466 }
467
468 rc = sde_mdp_parse_dt_handler(pdev,
469 "qcom,mdss-rot-vbif-memtype", mdata->vbif_memtype,
470 mdata->vbif_memtype_count);
471 if (rc) {
472 SDEROT_DBG("vbif memtype not found\n");
473 kfree(mdata->vbif_memtype);
474 mdata->vbif_memtype = NULL;
475 mdata->vbif_memtype_count = 0;
476 return;
477 }
478}
479
Adrian Salido-Moreno5c150382016-04-06 09:29:37 -0700480static void sde_mdp_parse_vbif_qos(struct platform_device *pdev,
481 struct sde_rot_data_type *mdata)
482{
483 int rc;
484
485 mdata->vbif_rt_qos = NULL;
486
487 mdata->npriority_lvl = sde_mdp_parse_dt_prop_len(pdev,
488 "qcom,mdss-rot-vbif-qos-setting");
489 mdata->vbif_nrt_qos = kzalloc(sizeof(u32) *
490 mdata->npriority_lvl, GFP_KERNEL);
Alan Kwong9bdbb082017-06-30 14:20:48 -0400491 if (!mdata->vbif_nrt_qos) {
492 mdata->npriority_lvl = 0;
Adrian Salido-Moreno5c150382016-04-06 09:29:37 -0700493 return;
Alan Kwong9bdbb082017-06-30 14:20:48 -0400494 }
Adrian Salido-Moreno5c150382016-04-06 09:29:37 -0700495
496 rc = sde_mdp_parse_dt_handler(pdev,
497 "qcom,mdss-rot-vbif-qos-setting", mdata->vbif_nrt_qos,
498 mdata->npriority_lvl);
499 if (rc) {
500 SDEROT_DBG("vbif setting not found\n");
Alan Kwong9bdbb082017-06-30 14:20:48 -0400501 kfree(mdata->vbif_nrt_qos);
502 mdata->vbif_nrt_qos = NULL;
503 mdata->npriority_lvl = 0;
Adrian Salido-Moreno5c150382016-04-06 09:29:37 -0700504 return;
505 }
506}
507
Veera Sundaram Sankaran3f0141e2017-05-10 18:19:29 -0700508static void sde_mdp_parse_cdp_setting(struct platform_device *pdev,
509 struct sde_rot_data_type *mdata)
510{
511 int rc;
512 u32 len, data[SDE_ROT_OP_MAX] = {0};
513
514 len = sde_mdp_parse_dt_prop_len(pdev,
515 "qcom,mdss-rot-cdp-setting");
516 if (len == SDE_ROT_OP_MAX) {
517 rc = sde_mdp_parse_dt_handler(pdev,
518 "qcom,mdss-rot-cdp-setting", data, len);
519 if (rc) {
520 SDEROT_ERR("invalid CDP setting\n");
521 goto end;
522 }
523
524 set_bit(SDE_QOS_CDP, mdata->sde_qos_map);
525 mdata->enable_cdp[SDE_ROT_RD] = data[SDE_ROT_RD];
526 mdata->enable_cdp[SDE_ROT_WR] = data[SDE_ROT_WR];
527 return;
528 }
529end:
530 clear_bit(SDE_QOS_CDP, mdata->sde_qos_map);
531}
532
Veera Sundaram Sankaranf13fb322017-05-11 15:42:28 -0700533static void sde_mdp_parse_rot_lut_setting(struct platform_device *pdev,
534 struct sde_rot_data_type *mdata)
535{
536 int rc;
537 u32 len, data[4];
538
539 len = sde_mdp_parse_dt_prop_len(pdev, "qcom,mdss-rot-qos-lut");
540 if (len == 4) {
541 rc = sde_mdp_parse_dt_handler(pdev,
542 "qcom,mdss-rot-qos-lut", data, len);
543 if (!rc) {
544 mdata->lut_cfg[SDE_ROT_RD].creq_lut_0 = data[0];
545 mdata->lut_cfg[SDE_ROT_RD].creq_lut_1 = data[1];
546 mdata->lut_cfg[SDE_ROT_WR].creq_lut_0 = data[2];
547 mdata->lut_cfg[SDE_ROT_WR].creq_lut_1 = data[3];
548 set_bit(SDE_QOS_LUT, mdata->sde_qos_map);
549 } else {
550 SDEROT_DBG("qos lut setting not found\n");
551 }
552 }
553
554 len = sde_mdp_parse_dt_prop_len(pdev, "qcom,mdss-rot-danger-lut");
555 if (len == SDE_ROT_OP_MAX) {
556 rc = sde_mdp_parse_dt_handler(pdev,
557 "qcom,mdss-rot-danger-lut", data, len);
558 if (!rc) {
559 mdata->lut_cfg[SDE_ROT_RD].danger_lut
560 = data[SDE_ROT_RD];
561 mdata->lut_cfg[SDE_ROT_WR].danger_lut
562 = data[SDE_ROT_WR];
563 set_bit(SDE_QOS_DANGER_LUT, mdata->sde_qos_map);
564 } else {
565 SDEROT_DBG("danger lut setting not found\n");
566 }
567 }
568
569 len = sde_mdp_parse_dt_prop_len(pdev, "qcom,mdss-rot-safe-lut");
570 if (len == SDE_ROT_OP_MAX) {
571 rc = sde_mdp_parse_dt_handler(pdev,
572 "qcom,mdss-rot-safe-lut", data, len);
573 if (!rc) {
574 mdata->lut_cfg[SDE_ROT_RD].safe_lut = data[SDE_ROT_RD];
575 mdata->lut_cfg[SDE_ROT_WR].safe_lut = data[SDE_ROT_WR];
576 set_bit(SDE_QOS_SAFE_LUT, mdata->sde_qos_map);
577 } else {
578 SDEROT_DBG("safe lut setting not found\n");
579 }
580 }
581}
582
583static void sde_mdp_parse_inline_rot_lut_setting(struct platform_device *pdev,
584 struct sde_rot_data_type *mdata)
585{
586 int rc;
587 u32 len, data[4];
588
589 len = sde_mdp_parse_dt_prop_len(pdev, "qcom,mdss-inline-rot-qos-lut");
590 if (len == 4) {
591 rc = sde_mdp_parse_dt_handler(pdev,
592 "qcom,mdss-inline-rot-qos-lut", data, len);
593 if (!rc) {
594 mdata->inline_lut_cfg[SDE_ROT_RD].creq_lut_0 = data[0];
595 mdata->inline_lut_cfg[SDE_ROT_RD].creq_lut_1 = data[1];
596 mdata->inline_lut_cfg[SDE_ROT_WR].creq_lut_0 = data[2];
597 mdata->inline_lut_cfg[SDE_ROT_WR].creq_lut_1 = data[3];
598 set_bit(SDE_INLINE_QOS_LUT, mdata->sde_inline_qos_map);
599 } else {
600 SDEROT_DBG("inline qos lut setting not found\n");
601 }
602 }
603
604 len = sde_mdp_parse_dt_prop_len(pdev,
605 "qcom,mdss-inline-rot-danger-lut");
606 if (len == SDE_ROT_OP_MAX) {
607 rc = sde_mdp_parse_dt_handler(pdev,
608 "qcom,mdss-inline-rot-danger-lut", data, len);
609 if (!rc) {
610 mdata->inline_lut_cfg[SDE_ROT_RD].danger_lut
611 = data[SDE_ROT_RD];
612 mdata->inline_lut_cfg[SDE_ROT_WR].danger_lut
613 = data[SDE_ROT_WR];
614 set_bit(SDE_INLINE_QOS_DANGER_LUT,
615 mdata->sde_inline_qos_map);
616 } else {
617 SDEROT_DBG("inline danger lut setting not found\n");
618 }
619 }
620
621 len = sde_mdp_parse_dt_prop_len(pdev, "qcom,mdss-inline-rot-safe-lut");
622 if (len == SDE_ROT_OP_MAX) {
623 rc = sde_mdp_parse_dt_handler(pdev,
624 "qcom,mdss-inline-rot-safe-lut", data, len);
625 if (!rc) {
626 mdata->inline_lut_cfg[SDE_ROT_RD].safe_lut
627 = data[SDE_ROT_RD];
628 mdata->inline_lut_cfg[SDE_ROT_WR].safe_lut
629 = data[SDE_ROT_WR];
630 set_bit(SDE_INLINE_QOS_SAFE_LUT,
631 mdata->sde_inline_qos_map);
632 } else {
633 SDEROT_DBG("inline safe lut setting not found\n");
634 }
635 }
636}
637
Adrian Salido-Moreno5c150382016-04-06 09:29:37 -0700638static int sde_mdp_parse_dt_misc(struct platform_device *pdev,
639 struct sde_rot_data_type *mdata)
640{
641 int rc;
642 u32 data;
643
644 rc = of_property_read_u32(pdev->dev.of_node, "qcom,mdss-rot-block-size",
645 &data);
646 mdata->rot_block_size = (!rc ? data : 128);
647
648 rc = of_property_read_u32(pdev->dev.of_node,
649 "qcom,mdss-default-ot-rd-limit", &data);
650 mdata->default_ot_rd_limit = (!rc ? data : 0);
651
652 rc = of_property_read_u32(pdev->dev.of_node,
653 "qcom,mdss-default-ot-wr-limit", &data);
654 mdata->default_ot_wr_limit = (!rc ? data : 0);
655
656 rc = of_property_read_u32(pdev->dev.of_node,
657 "qcom,mdss-highest-bank-bit", &(mdata->highest_bank_bit));
658 if (rc)
659 SDEROT_DBG(
660 "Could not read optional property: highest bank bit\n");
661
Veera Sundaram Sankaran3f0141e2017-05-10 18:19:29 -0700662 sde_mdp_parse_cdp_setting(pdev, mdata);
663
Adrian Salido-Moreno5c150382016-04-06 09:29:37 -0700664 sde_mdp_parse_vbif_qos(pdev, mdata);
665
Alan Kwong9bdbb082017-06-30 14:20:48 -0400666 sde_mdp_parse_vbif_memtype(pdev, mdata);
667
Veera Sundaram Sankaranf13fb322017-05-11 15:42:28 -0700668 sde_mdp_parse_rot_lut_setting(pdev, mdata);
669
670 sde_mdp_parse_inline_rot_lut_setting(pdev, mdata);
671
Adrian Salido-Moreno5c150382016-04-06 09:29:37 -0700672 mdata->mdp_base = mdata->sde_io.base + SDE_MDP_OFFSET;
673
674 return 0;
675}
676
Alan Kwong9bdbb082017-06-30 14:20:48 -0400677static void sde_mdp_destroy_dt_misc(struct platform_device *pdev,
678 struct sde_rot_data_type *mdata)
679{
680 kfree(mdata->vbif_memtype);
681 mdata->vbif_memtype = NULL;
682 kfree(mdata->vbif_rt_qos);
683 mdata->vbif_rt_qos = NULL;
684 kfree(mdata->vbif_nrt_qos);
685 mdata->vbif_nrt_qos = NULL;
686}
687
Adrian Salido-Moreno5c150382016-04-06 09:29:37 -0700688#define MDP_REG_BUS_VECTOR_ENTRY(ab_val, ib_val) \
689 { \
690 .src = MSM_BUS_MASTER_AMPSS_M0, \
691 .dst = MSM_BUS_SLAVE_DISPLAY_CFG, \
692 .ab = (ab_val), \
693 .ib = (ib_val), \
694 }
695
696#define BUS_VOTE_19_MHZ 153600000
697#define BUS_VOTE_40_MHZ 320000000
698#define BUS_VOTE_80_MHZ 640000000
699
700static struct msm_bus_vectors mdp_reg_bus_vectors[] = {
701 MDP_REG_BUS_VECTOR_ENTRY(0, 0),
702 MDP_REG_BUS_VECTOR_ENTRY(0, BUS_VOTE_19_MHZ),
703 MDP_REG_BUS_VECTOR_ENTRY(0, BUS_VOTE_40_MHZ),
704 MDP_REG_BUS_VECTOR_ENTRY(0, BUS_VOTE_80_MHZ),
705};
706static struct msm_bus_paths mdp_reg_bus_usecases[ARRAY_SIZE(
707 mdp_reg_bus_vectors)];
708static struct msm_bus_scale_pdata mdp_reg_bus_scale_table = {
709 .usecase = mdp_reg_bus_usecases,
710 .num_usecases = ARRAY_SIZE(mdp_reg_bus_usecases),
711 .name = "sde_reg",
712 .active_only = true,
713};
714
715static int sde_mdp_bus_scale_register(struct sde_rot_data_type *mdata)
716{
717 struct msm_bus_scale_pdata *reg_bus_pdata;
718 int i;
719
720 if (!mdata->reg_bus_hdl) {
721 reg_bus_pdata = &mdp_reg_bus_scale_table;
722 for (i = 0; i < reg_bus_pdata->num_usecases; i++) {
723 mdp_reg_bus_usecases[i].num_paths = 1;
724 mdp_reg_bus_usecases[i].vectors =
725 &mdp_reg_bus_vectors[i];
726 }
727
728 mdata->reg_bus_hdl =
729 msm_bus_scale_register_client(reg_bus_pdata);
730 if (!mdata->reg_bus_hdl) {
731 /* Continue without reg_bus scaling */
732 SDEROT_WARN("reg_bus_client register failed\n");
733 } else
734 SDEROT_DBG("register reg_bus_hdl=%x\n",
735 mdata->reg_bus_hdl);
736 }
737
738 return 0;
739}
740
741static void sde_mdp_bus_scale_unregister(struct sde_rot_data_type *mdata)
742{
743 SDEROT_DBG("unregister reg_bus_hdl=%x\n", mdata->reg_bus_hdl);
744
745 if (mdata->reg_bus_hdl) {
746 msm_bus_scale_unregister_client(mdata->reg_bus_hdl);
747 mdata->reg_bus_hdl = 0;
748 }
749}
750
751static struct sde_rot_data_type *sde_rot_res;
752
753struct sde_rot_data_type *sde_rot_get_mdata(void)
754{
755 return sde_rot_res;
756}
757
758/*
759 * sde_rotator_base_init - initialize base rotator data/resource
760 */
761int sde_rotator_base_init(struct sde_rot_data_type **pmdata,
762 struct platform_device *pdev,
763 const void *drvdata)
764{
765 int rc;
766 struct sde_rot_data_type *mdata;
767
768 mdata = devm_kzalloc(&pdev->dev, sizeof(*mdata), GFP_KERNEL);
769 if (mdata == NULL)
770 return -ENOMEM;
771
772 mdata->pdev = pdev;
773 sde_rot_res = mdata;
774 mutex_init(&mdata->reg_bus_lock);
775 INIT_LIST_HEAD(&mdata->reg_bus_clist);
776
777 rc = sde_rot_ioremap_byname(pdev, &mdata->sde_io, "mdp_phys");
778 if (rc) {
779 SDEROT_ERR("unable to map SDE base\n");
780 goto probe_done;
781 }
782 SDEROT_DBG("SDE ROT HW Base addr=0x%x len=0x%x\n",
783 (int) (unsigned long) mdata->sde_io.base,
784 mdata->sde_io.len);
785
786 rc = sde_rot_ioremap_byname(pdev, &mdata->vbif_nrt_io, "rot_vbif_phys");
787 if (rc) {
788 SDEROT_ERR("unable to map SDE ROT VBIF base\n");
789 goto probe_done;
790 }
791 SDEROT_DBG("SDE ROT VBIF HW Base addr=%p len=0x%x\n",
792 mdata->vbif_nrt_io.base, mdata->vbif_nrt_io.len);
793
794 rc = sde_mdp_parse_dt_misc(pdev, mdata);
795 if (rc) {
796 SDEROT_ERR("Error in device tree : misc\n");
797 goto probe_done;
798 }
799
800 rc = sde_mdp_bus_scale_register(mdata);
801 if (rc) {
802 SDEROT_ERR("unable to register bus scaling\n");
803 goto probe_done;
804 }
805
806 rc = sde_smmu_init(&pdev->dev);
807 if (rc) {
808 SDEROT_ERR("sde smmu init failed %d\n", rc);
809 goto probe_done;
810 }
811
Abhijit Kulkarni298c8232016-09-26 22:32:10 -0700812 mdata->iclient = msm_ion_client_create(mdata->pdev->name);
813 if (IS_ERR_OR_NULL(mdata->iclient)) {
814 SDEROT_ERR("msm_ion_client_create() return error (%pK)\n",
815 mdata->iclient);
816 mdata->iclient = NULL;
817 rc = -EFAULT;
818 goto probe_done;
819 }
820
Adrian Salido-Moreno5c150382016-04-06 09:29:37 -0700821 *pmdata = mdata;
822
823 return 0;
824probe_done:
825 return rc;
826}
827
828/*
829 * sde_rotator_base_destroy - clean up base rotator data/resource
830 */
831void sde_rotator_base_destroy(struct sde_rot_data_type *mdata)
832{
833 struct platform_device *pdev;
834
835 if (!mdata || !mdata->pdev)
836 return;
837
838 pdev = mdata->pdev;
839
840 sde_rot_res = NULL;
841 sde_mdp_bus_scale_unregister(mdata);
Alan Kwong9bdbb082017-06-30 14:20:48 -0400842 sde_mdp_destroy_dt_misc(pdev, mdata);
Adrian Salido-Moreno5c150382016-04-06 09:29:37 -0700843 sde_rot_iounmap(&mdata->vbif_nrt_io);
844 sde_rot_iounmap(&mdata->sde_io);
845 devm_kfree(&pdev->dev, mdata);
846}