blob: cf546115ef295ff0891c4bdc782cb265c80bd943 [file] [log] [blame]
Lloyd Atkinson77158732016-10-23 13:02:00 -04001/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
Abhijit Kulkarni94954d52016-06-24 18:27:48 -04002 *
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#include "sde_hwio.h"
14#include "sde_hw_catalog.h"
Clarence Ipc475b082016-06-26 09:27:23 -040015#include "sde_hw_top.h"
Lloyd Atkinson113aefd2016-10-23 13:15:18 -040016#include "sde_dbg.h"
Abhijit Kulkarni94954d52016-06-24 18:27:48 -040017
Clarence Ip110d15c2016-08-16 14:44:41 -040018#define SSPP_SPARE 0x28
Clarence Ip32bcb002017-03-13 12:26:44 -070019#define UBWC_STATIC 0x144
Abhijit Kulkarni43eafcc2016-06-28 17:48:41 -040020
Abhijit Kulkarni43eafcc2016-06-28 17:48:41 -040021#define FLD_SPLIT_DISPLAY_CMD BIT(1)
22#define FLD_SMART_PANEL_FREE_RUN BIT(2)
23#define FLD_INTF_1_SW_TRG_MUX BIT(4)
24#define FLD_INTF_2_SW_TRG_MUX BIT(8)
25#define FLD_TE_LINE_INTER_WATERLEVEL_MASK 0xFFFF
26
Alan Kwongf0fd8512016-10-24 21:39:26 -040027#define DANGER_STATUS 0x360
28#define SAFE_STATUS 0x364
29
Abhijit Kulkarni94954d52016-06-24 18:27:48 -040030#define TE_LINE_INTERVAL 0x3F4
31
Alan Kwong3232ca52016-07-29 02:27:47 -040032#define TRAFFIC_SHAPER_EN BIT(31)
33#define TRAFFIC_SHAPER_RD_CLIENT(num) (0x030 + (num * 4))
34#define TRAFFIC_SHAPER_WR_CLIENT(num) (0x060 + (num * 4))
35#define TRAFFIC_SHAPER_FIXPOINT_FACTOR 4
36
Jeykumar Sankaran5c2f0702017-03-09 18:03:15 -080037#define DCE_SEL 0x450
38
Clarence Ip8e69ad02016-12-09 09:43:57 -050039static void sde_hw_setup_split_pipe(struct sde_hw_mdp *mdp,
Abhijit Kulkarni43eafcc2016-06-28 17:48:41 -040040 struct split_pipe_cfg *cfg)
Abhijit Kulkarni94954d52016-06-24 18:27:48 -040041{
Lloyd Atkinson20c9ecd2017-04-18 10:33:47 -070042 struct sde_hw_blk_reg_map *c;
Abhijit Kulkarni43eafcc2016-06-28 17:48:41 -040043 u32 upper_pipe = 0;
44 u32 lower_pipe = 0;
Abhijit Kulkarni94954d52016-06-24 18:27:48 -040045
Clarence Ip8e69ad02016-12-09 09:43:57 -050046 if (!mdp || !cfg)
47 return;
48
Lloyd Atkinson20c9ecd2017-04-18 10:33:47 -070049 c = &mdp->hw;
50
Abhijit Kulkarni94954d52016-06-24 18:27:48 -040051 if (cfg->en) {
Abhijit Kulkarni94954d52016-06-24 18:27:48 -040052 if (cfg->mode == INTF_MODE_CMD) {
Abhijit Kulkarni43eafcc2016-06-28 17:48:41 -040053 lower_pipe = FLD_SPLIT_DISPLAY_CMD;
54 /* interface controlling sw trigger */
55 if (cfg->intf == INTF_2)
56 lower_pipe |= FLD_INTF_1_SW_TRG_MUX;
57 else
58 lower_pipe |= FLD_INTF_2_SW_TRG_MUX;
Abhijit Kulkarni94954d52016-06-24 18:27:48 -040059
Abhijit Kulkarni43eafcc2016-06-28 17:48:41 -040060 /* free run */
Clarence Ip8e69ad02016-12-09 09:43:57 -050061 if (cfg->pp_split_slave != INTF_MAX)
Abhijit Kulkarni43eafcc2016-06-28 17:48:41 -040062 lower_pipe = FLD_SMART_PANEL_FREE_RUN;
63
64 upper_pipe = lower_pipe;
65 } else {
66 if (cfg->intf == INTF_2) {
67 lower_pipe = FLD_INTF_1_SW_TRG_MUX;
68 upper_pipe = FLD_INTF_2_SW_TRG_MUX;
69 } else {
70 lower_pipe = FLD_INTF_2_SW_TRG_MUX;
71 upper_pipe = FLD_INTF_1_SW_TRG_MUX;
72 }
73 }
Abhijit Kulkarni94954d52016-06-24 18:27:48 -040074 }
75
Clarence Ip8e69ad02016-12-09 09:43:57 -050076 SDE_REG_WRITE(c, SSPP_SPARE, cfg->split_flush_en ? 0x1 : 0x0);
Clarence Ip110d15c2016-08-16 14:44:41 -040077 SDE_REG_WRITE(c, SPLIT_DISPLAY_LOWER_PIPE_CTRL, lower_pipe);
78 SDE_REG_WRITE(c, SPLIT_DISPLAY_UPPER_PIPE_CTRL, upper_pipe);
79 SDE_REG_WRITE(c, SPLIT_DISPLAY_EN, cfg->en & 0x1);
Abhijit Kulkarni94954d52016-06-24 18:27:48 -040080}
81
Clarence Ip8e69ad02016-12-09 09:43:57 -050082static void sde_hw_setup_pp_split(struct sde_hw_mdp *mdp,
83 struct split_pipe_cfg *cfg)
84{
85 u32 ppb_config = 0x0;
86 u32 ppb_control = 0x0;
87
88 if (!mdp || !cfg)
89 return;
90
91 if (cfg->en && cfg->pp_split_slave != INTF_MAX) {
92 ppb_config |= (cfg->pp_split_slave - INTF_0 + 1) << 20;
93 ppb_config |= BIT(16); /* split enable */
94 ppb_control = BIT(5); /* horz split*/
95 }
96 if (cfg->pp_split_index) {
97 SDE_REG_WRITE(&mdp->hw, PPB0_CONFIG, 0x0);
98 SDE_REG_WRITE(&mdp->hw, PPB0_CNTL, 0x0);
99 SDE_REG_WRITE(&mdp->hw, PPB1_CONFIG, ppb_config);
100 SDE_REG_WRITE(&mdp->hw, PPB1_CNTL, ppb_control);
101 } else {
102 SDE_REG_WRITE(&mdp->hw, PPB0_CONFIG, ppb_config);
103 SDE_REG_WRITE(&mdp->hw, PPB0_CNTL, ppb_control);
104 SDE_REG_WRITE(&mdp->hw, PPB1_CONFIG, 0x0);
105 SDE_REG_WRITE(&mdp->hw, PPB1_CNTL, 0x0);
106 }
107}
108
Alan Kwongdcc96ff2016-07-29 03:06:44 -0400109static void sde_hw_setup_cdm_output(struct sde_hw_mdp *mdp,
110 struct cdm_output_cfg *cfg)
111{
Lloyd Atkinson20c9ecd2017-04-18 10:33:47 -0700112 struct sde_hw_blk_reg_map *c;
Alan Kwongdcc96ff2016-07-29 03:06:44 -0400113 u32 out_ctl = 0;
114
Lloyd Atkinson20c9ecd2017-04-18 10:33:47 -0700115 if (!mdp || !cfg)
116 return;
117
118 c = &mdp->hw;
119
Alan Kwongdcc96ff2016-07-29 03:06:44 -0400120 if (cfg->wb_en)
121 out_ctl |= BIT(24);
122 else if (cfg->intf_en)
123 out_ctl |= BIT(19);
124
125 SDE_REG_WRITE(c, MDP_OUT_CTL_0, out_ctl);
126}
127
Alan Kwong5d324e42016-07-28 22:56:18 -0400128static bool sde_hw_setup_clk_force_ctrl(struct sde_hw_mdp *mdp,
129 enum sde_clk_ctrl_type clk_ctrl, bool enable)
130{
Lloyd Atkinson20c9ecd2017-04-18 10:33:47 -0700131 struct sde_hw_blk_reg_map *c;
Alan Kwong5d324e42016-07-28 22:56:18 -0400132 u32 reg_off, bit_off;
133 u32 reg_val, new_val;
134 bool clk_forced_on;
135
Lloyd Atkinson20c9ecd2017-04-18 10:33:47 -0700136 if (!mdp)
137 return false;
138
139 c = &mdp->hw;
140
Alan Kwong5d324e42016-07-28 22:56:18 -0400141 if (clk_ctrl <= SDE_CLK_CTRL_NONE || clk_ctrl >= SDE_CLK_CTRL_MAX)
142 return false;
143
144 reg_off = mdp->cap->clk_ctrls[clk_ctrl].reg_off;
145 bit_off = mdp->cap->clk_ctrls[clk_ctrl].bit_off;
146
147 reg_val = SDE_REG_READ(c, reg_off);
148
149 if (enable)
150 new_val = reg_val | BIT(bit_off);
151 else
152 new_val = reg_val & ~BIT(bit_off);
153
154 SDE_REG_WRITE(c, reg_off, new_val);
155
156 clk_forced_on = !(reg_val & BIT(bit_off));
157
158 return clk_forced_on;
159}
160
Alan Kwongf0fd8512016-10-24 21:39:26 -0400161
162static void sde_hw_get_danger_status(struct sde_hw_mdp *mdp,
163 struct sde_danger_safe_status *status)
164{
Lloyd Atkinson20c9ecd2017-04-18 10:33:47 -0700165 struct sde_hw_blk_reg_map *c;
Alan Kwongf0fd8512016-10-24 21:39:26 -0400166 u32 value;
167
Lloyd Atkinson20c9ecd2017-04-18 10:33:47 -0700168 if (!mdp || !status)
169 return;
170
171 c = &mdp->hw;
172
Alan Kwongf0fd8512016-10-24 21:39:26 -0400173 value = SDE_REG_READ(c, DANGER_STATUS);
174 status->mdp = (value >> 0) & 0x3;
175 status->sspp[SSPP_VIG0] = (value >> 4) & 0x3;
176 status->sspp[SSPP_VIG1] = (value >> 6) & 0x3;
177 status->sspp[SSPP_VIG2] = (value >> 8) & 0x3;
178 status->sspp[SSPP_VIG3] = (value >> 10) & 0x3;
179 status->sspp[SSPP_RGB0] = (value >> 12) & 0x3;
180 status->sspp[SSPP_RGB1] = (value >> 14) & 0x3;
181 status->sspp[SSPP_RGB2] = (value >> 16) & 0x3;
182 status->sspp[SSPP_RGB3] = (value >> 18) & 0x3;
183 status->sspp[SSPP_DMA0] = (value >> 20) & 0x3;
184 status->sspp[SSPP_DMA1] = (value >> 22) & 0x3;
185 status->sspp[SSPP_DMA2] = (value >> 28) & 0x3;
186 status->sspp[SSPP_DMA3] = (value >> 30) & 0x3;
187 status->sspp[SSPP_CURSOR0] = (value >> 24) & 0x3;
188 status->sspp[SSPP_CURSOR1] = (value >> 26) & 0x3;
189 status->wb[WB_0] = 0;
190 status->wb[WB_1] = 0;
191 status->wb[WB_2] = (value >> 2) & 0x3;
192 status->wb[WB_3] = 0;
193}
194
195static void sde_hw_get_safe_status(struct sde_hw_mdp *mdp,
196 struct sde_danger_safe_status *status)
197{
Lloyd Atkinson20c9ecd2017-04-18 10:33:47 -0700198 struct sde_hw_blk_reg_map *c;
Alan Kwongf0fd8512016-10-24 21:39:26 -0400199 u32 value;
200
Lloyd Atkinson20c9ecd2017-04-18 10:33:47 -0700201 if (!mdp || !status)
202 return;
203
204 c = &mdp->hw;
205
Alan Kwongf0fd8512016-10-24 21:39:26 -0400206 value = SDE_REG_READ(c, SAFE_STATUS);
207 status->mdp = (value >> 0) & 0x1;
208 status->sspp[SSPP_VIG0] = (value >> 4) & 0x1;
209 status->sspp[SSPP_VIG1] = (value >> 6) & 0x1;
210 status->sspp[SSPP_VIG2] = (value >> 8) & 0x1;
211 status->sspp[SSPP_VIG3] = (value >> 10) & 0x1;
212 status->sspp[SSPP_RGB0] = (value >> 12) & 0x1;
213 status->sspp[SSPP_RGB1] = (value >> 14) & 0x1;
214 status->sspp[SSPP_RGB2] = (value >> 16) & 0x1;
215 status->sspp[SSPP_RGB3] = (value >> 18) & 0x1;
216 status->sspp[SSPP_DMA0] = (value >> 20) & 0x1;
217 status->sspp[SSPP_DMA1] = (value >> 22) & 0x1;
218 status->sspp[SSPP_DMA2] = (value >> 28) & 0x1;
219 status->sspp[SSPP_DMA3] = (value >> 30) & 0x1;
220 status->sspp[SSPP_CURSOR0] = (value >> 24) & 0x1;
221 status->sspp[SSPP_CURSOR1] = (value >> 26) & 0x1;
222 status->wb[WB_0] = 0;
223 status->wb[WB_1] = 0;
224 status->wb[WB_2] = (value >> 2) & 0x1;
225 status->wb[WB_3] = 0;
226}
227
Jeykumar Sankaran5c2f0702017-03-09 18:03:15 -0800228static void sde_hw_setup_dce(struct sde_hw_mdp *mdp, u32 dce_sel)
229{
Lloyd Atkinson20c9ecd2017-04-18 10:33:47 -0700230 struct sde_hw_blk_reg_map *c;
231
232 if (!mdp)
233 return;
234
235 c = &mdp->hw;
Jeykumar Sankaran5c2f0702017-03-09 18:03:15 -0800236
237 SDE_REG_WRITE(c, DCE_SEL, dce_sel);
238}
239
Clarence Ip35348262017-04-28 16:10:46 -0700240void sde_hw_reset_ubwc(struct sde_hw_mdp *mdp, struct sde_mdss_cfg *m)
241{
242 struct sde_hw_blk_reg_map c;
243
244 if (!mdp || !m)
245 return;
246
247 if (!IS_UBWC_20_SUPPORTED(m->ubwc_version))
248 return;
249
250 /* force blk offset to zero to access beginning of register region */
251 c = mdp->hw;
252 c.blk_off = 0x0;
253 SDE_REG_WRITE(&c, UBWC_STATIC, m->mdp[0].ubwc_static);
254}
255
Abhijit Kulkarni94954d52016-06-24 18:27:48 -0400256static void _setup_mdp_ops(struct sde_hw_mdp_ops *ops,
257 unsigned long cap)
258{
Clarence Ip8e69ad02016-12-09 09:43:57 -0500259 ops->setup_split_pipe = sde_hw_setup_split_pipe;
260 ops->setup_pp_split = sde_hw_setup_pp_split;
Alan Kwongdcc96ff2016-07-29 03:06:44 -0400261 ops->setup_cdm_output = sde_hw_setup_cdm_output;
Alan Kwong5d324e42016-07-28 22:56:18 -0400262 ops->setup_clk_force_ctrl = sde_hw_setup_clk_force_ctrl;
Alan Kwongf0fd8512016-10-24 21:39:26 -0400263 ops->get_danger_status = sde_hw_get_danger_status;
264 ops->get_safe_status = sde_hw_get_safe_status;
Jeykumar Sankaran5c2f0702017-03-09 18:03:15 -0800265 ops->setup_dce = sde_hw_setup_dce;
Clarence Ip35348262017-04-28 16:10:46 -0700266 ops->reset_ubwc = sde_hw_reset_ubwc;
Abhijit Kulkarni94954d52016-06-24 18:27:48 -0400267}
268
269static const struct sde_mdp_cfg *_top_offset(enum sde_mdp mdp,
270 const struct sde_mdss_cfg *m,
271 void __iomem *addr,
272 struct sde_hw_blk_reg_map *b)
273{
274 int i;
275
Lloyd Atkinson20c9ecd2017-04-18 10:33:47 -0700276 if (!m || !addr || !b)
277 return ERR_PTR(-EINVAL);
278
Abhijit Kulkarni94954d52016-06-24 18:27:48 -0400279 for (i = 0; i < m->mdp_count; i++) {
280 if (mdp == m->mdp[i].id) {
281 b->base_off = addr;
282 b->blk_off = m->mdp[i].base;
Lloyd Atkinson77158732016-10-23 13:02:00 -0400283 b->length = m->mdp[i].len;
Abhijit Kulkarni94954d52016-06-24 18:27:48 -0400284 b->hwversion = m->hwversion;
Lloyd Atkinsonbb87b5b2016-06-13 18:31:15 -0400285 b->log_mask = SDE_DBG_MASK_TOP;
Abhijit Kulkarni94954d52016-06-24 18:27:48 -0400286 return &m->mdp[i];
287 }
288 }
289
290 return ERR_PTR(-EINVAL);
291}
292
293struct sde_hw_mdp *sde_hw_mdptop_init(enum sde_mdp idx,
294 void __iomem *addr,
295 const struct sde_mdss_cfg *m)
296{
Lloyd Atkinson85ef3fe2016-10-04 09:47:46 -0400297 struct sde_hw_mdp *mdp;
Abhijit Kulkarni94954d52016-06-24 18:27:48 -0400298 const struct sde_mdp_cfg *cfg;
299
Clarence Ip32bcb002017-03-13 12:26:44 -0700300 if (!addr || !m)
301 return ERR_PTR(-EINVAL);
302
Lloyd Atkinson85ef3fe2016-10-04 09:47:46 -0400303 mdp = kzalloc(sizeof(*mdp), GFP_KERNEL);
304 if (!mdp)
Abhijit Kulkarni94954d52016-06-24 18:27:48 -0400305 return ERR_PTR(-ENOMEM);
306
Lloyd Atkinson85ef3fe2016-10-04 09:47:46 -0400307 cfg = _top_offset(idx, m, addr, &mdp->hw);
Abhijit Kulkarni94954d52016-06-24 18:27:48 -0400308 if (IS_ERR_OR_NULL(cfg)) {
Lloyd Atkinson85ef3fe2016-10-04 09:47:46 -0400309 kfree(mdp);
Abhijit Kulkarni94954d52016-06-24 18:27:48 -0400310 return ERR_PTR(-EINVAL);
311 }
312
313 /*
314 * Assign ops
315 */
Lloyd Atkinson85ef3fe2016-10-04 09:47:46 -0400316 mdp->idx = idx;
317 mdp->cap = cfg;
318 _setup_mdp_ops(&mdp->ops, mdp->cap->features);
Abhijit Kulkarni94954d52016-06-24 18:27:48 -0400319
Lloyd Atkinson113aefd2016-10-23 13:15:18 -0400320 sde_dbg_reg_register_dump_range(SDE_DBG_NAME, cfg->name,
321 mdp->hw.blk_off, mdp->hw.blk_off + mdp->hw.length,
322 mdp->hw.xin_id);
Lloyd Atkinsonac4b6e02017-03-23 11:43:48 -0700323 sde_dbg_set_sde_top_offset(mdp->hw.blk_off);
Lloyd Atkinson85ef3fe2016-10-04 09:47:46 -0400324
325 return mdp;
Abhijit Kulkarni94954d52016-06-24 18:27:48 -0400326}
327
328void sde_hw_mdp_destroy(struct sde_hw_mdp *mdp)
329{
Lloyd Atkinsone5c2c0b2016-07-05 12:23:29 -0400330 kfree(mdp);
Abhijit Kulkarni94954d52016-06-24 18:27:48 -0400331}
332