blob: 47c5cda4e6a53c8ca9c90ce3694702adeaa2c65a [file] [log] [blame]
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001/* Copyright (c) 2015-2016, 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#include <linux/delay.h>
14#include "sde_hwio.h"
Clarence Ipc475b082016-06-26 09:27:23 -040015#include "sde_hw_ctl.h"
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070016
17#define CTL_LAYER(lm) \
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040018 (((lm) == LM_5) ? (0x024) : (((lm) - LM_0) * 0x004))
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070019#define CTL_LAYER_EXT(lm) \
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040020 (0x40 + (((lm) - LM_0) * 0x004))
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070021#define CTL_TOP 0x014
22#define CTL_FLUSH 0x018
23#define CTL_START 0x01C
24#define CTL_PACK_3D 0x020
25#define CTL_SW_RESET 0x030
26#define CTL_LAYER_EXTN_OFFSET 0x40
27
28#define SDE_REG_RESET_TIMEOUT_COUNT 20
29
30static struct sde_ctl_cfg *_ctl_offset(enum sde_ctl ctl,
31 struct sde_mdss_cfg *m,
32 void __iomem *addr,
33 struct sde_hw_blk_reg_map *b)
34{
35 int i;
36
37 for (i = 0; i < m->ctl_count; i++) {
38 if (ctl == m->ctl[i].id) {
39 b->base_off = addr;
40 b->blk_off = m->ctl[i].base;
41 b->hwversion = m->hwversion;
Clarence Ip4ce59322016-06-26 22:27:51 -040042 b->log_mask = SDE_DBG_MASK_CTL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070043 return &m->ctl[i];
44 }
45 }
46 return ERR_PTR(-ENOMEM);
47}
48
49static int _mixer_stages(const struct sde_lm_cfg *mixer, int count,
50 enum sde_lm lm)
51{
52 int i;
53 int stages = -EINVAL;
54
55 for (i = 0; i < count; i++) {
56 if (lm == mixer[i].id) {
57 stages = mixer[i].sblk->maxblendstages;
58 break;
59 }
60 }
61
62 return stages;
63}
64
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040065static inline void sde_hw_ctl_force_start(struct sde_hw_ctl *ctx)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070066{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040067 SDE_REG_WRITE(&ctx->hw, CTL_START, 0x1);
68}
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070069
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040070static inline void sde_hw_ctl_setup_flush(struct sde_hw_ctl *ctx, u32 flushbits)
71{
72 SDE_REG_WRITE(&ctx->hw, CTL_FLUSH, flushbits);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070073}
74
75static inline int sde_hw_ctl_get_bitmask_sspp(struct sde_hw_ctl *ctx,
76 u32 *flushbits, enum sde_sspp sspp)
77{
78 switch (sspp) {
79 case SSPP_VIG0:
80 *flushbits |= BIT(0);
81 break;
82 case SSPP_VIG1:
83 *flushbits |= BIT(1);
84 break;
85 case SSPP_VIG2:
86 *flushbits |= BIT(2);
87 break;
88 case SSPP_VIG3:
89 *flushbits |= BIT(18);
90 break;
91 case SSPP_RGB0:
92 *flushbits |= BIT(3);
93 break;
94 case SSPP_RGB1:
95 *flushbits |= BIT(4);
96 break;
97 case SSPP_RGB2:
98 *flushbits |= BIT(5);
99 break;
100 case SSPP_RGB3:
101 *flushbits |= BIT(19);
102 break;
103 case SSPP_DMA0:
104 *flushbits |= BIT(11);
105 break;
106 case SSPP_DMA1:
107 *flushbits |= BIT(12);
108 break;
109 case SSPP_CURSOR0:
110 *flushbits |= BIT(22);
111 break;
112 case SSPP_CURSOR1:
113 *flushbits |= BIT(23);
114 break;
115 default:
116 return -EINVAL;
117 }
118 return 0;
119}
120
121static inline int sde_hw_ctl_get_bitmask_mixer(struct sde_hw_ctl *ctx,
122 u32 *flushbits, enum sde_lm lm)
123{
124 switch (lm) {
125 case LM_0:
126 *flushbits |= BIT(6);
127 break;
128 case LM_1:
129 *flushbits |= BIT(7);
130 break;
131 case LM_2:
132 *flushbits |= BIT(8);
133 break;
134 case LM_3:
135 *flushbits |= BIT(9);
136 break;
137 case LM_4:
138 *flushbits |= BIT(10);
139 break;
140 case LM_5:
141 *flushbits |= BIT(20);
142 break;
143 default:
144 return -EINVAL;
145 }
146 *flushbits |= BIT(17); /* CTL */
147 return 0;
148}
149
150static inline int sde_hw_ctl_get_bitmask_dspp(struct sde_hw_ctl *ctx,
151 u32 *flushbits, enum sde_dspp dspp)
152{
153 switch (dspp) {
154 case DSPP_0:
155 *flushbits |= BIT(13);
156 break;
157 case DSPP_1:
158 *flushbits |= BIT(14);
159 break;
160 default:
161 return -EINVAL;
162 }
163 return 0;
164}
165
166static inline int sde_hw_ctl_get_bitmask_intf(struct sde_hw_ctl *ctx,
167 u32 *flushbits, enum sde_intf intf)
168{
169 switch (intf) {
170 case INTF_0:
171 *flushbits |= BIT(31);
172 break;
173 case INTF_1:
174 *flushbits |= BIT(30);
175 break;
176 case INTF_2:
177 *flushbits |= BIT(29);
178 break;
179 case INTF_3:
180 *flushbits |= BIT(28);
181 break;
182 default:
183 return -EINVAL;
184 }
185 return 0;
186}
187
188static inline int sde_hw_ctl_get_bitmask_cdm(struct sde_hw_ctl *ctx,
189 u32 *flushbits, enum sde_cdm cdm)
190{
191 switch (cdm) {
192 case CDM_0:
193 *flushbits |= BIT(26);
194 break;
195 default:
196 return -EINVAL;
197 }
198 return 0;
199}
200
201static int sde_hw_ctl_reset_control(struct sde_hw_ctl *ctx)
202{
203 struct sde_hw_blk_reg_map *c = &ctx->hw;
204 int count = SDE_REG_RESET_TIMEOUT_COUNT;
205 int reset;
206
207 SDE_REG_WRITE(c, CTL_SW_RESET, 0x1);
208
209 for (; count > 0; count--) {
210 /* insert small delay to avoid spinning the cpu while waiting */
211 usleep_range(20, 50);
212 reset = SDE_REG_READ(c, CTL_SW_RESET);
213 if (reset == 0)
214 return 0;
215 }
216
217 return -EINVAL;
218}
219
220static void sde_hw_ctl_setup_blendstage(struct sde_hw_ctl *ctx,
221 enum sde_lm lm,
222 struct sde_hw_stage_cfg *cfg)
223{
224 struct sde_hw_blk_reg_map *c = &ctx->hw;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400225 u32 mixercfg, mixercfg_ext = 0;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700226 int i, j;
227 u8 stages;
228 int pipes_per_stage;
229
230 stages = _mixer_stages(ctx->mixer_hw_caps, ctx->mixer_count, lm);
Clarence Ipc475b082016-06-26 09:27:23 -0400231 if (stages < 0)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700232 return;
233
234 if (test_bit(SDE_MIXER_SOURCESPLIT,
235 &ctx->mixer_hw_caps->features))
236 pipes_per_stage = PIPES_PER_STAGE;
237 else
238 pipes_per_stage = 1;
239
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400240 mixercfg = cfg->border_enable << 24; /* BORDER_OUT */
241
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700242 for (i = 0; i <= stages; i++) {
243 for (j = 0; j < pipes_per_stage; j++) {
244 switch (cfg->stage[i][j]) {
245 case SSPP_VIG0:
246 mixercfg |= (i + 1) << 0;
247 mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 0;
248 break;
249 case SSPP_VIG1:
250 mixercfg |= (i + 1) << 3;
251 mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 2;
252 break;
253 case SSPP_VIG2:
254 mixercfg |= (i + 1) << 6;
255 mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 4;
256 break;
257 case SSPP_VIG3:
258 mixercfg |= (i + 1) << 26;
Clarence Ip4c1d9772016-06-26 09:35:38 -0400259 mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 6;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700260 break;
261 case SSPP_RGB0:
262 mixercfg |= (i + 1) << 9;
263 mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 8;
264 break;
265 case SSPP_RGB1:
266 mixercfg |= (i + 1) << 12;
267 mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 10;
268 break;
269 case SSPP_RGB2:
270 mixercfg |= (i + 1) << 15;
271 mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 12;
272 break;
273 case SSPP_RGB3:
274 mixercfg |= (i + 1) << 29;
275 mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 14;
276 break;
277 case SSPP_DMA0:
Clarence Ip4c1d9772016-06-26 09:35:38 -0400278 mixercfg |= (i + 1) << 18;
279 mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 16;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700280 break;
281 case SSPP_DMA1:
Clarence Ip4c1d9772016-06-26 09:35:38 -0400282 mixercfg |= (i + 1) << 21;
283 mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 18;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700284 break;
285 case SSPP_CURSOR0:
286 mixercfg_ext |= (i + 1) << 20;
287 break;
288 case SSPP_CURSOR1:
289 mixercfg_ext |= (i + 1) << 26;
290 break;
291 default:
292 break;
293 }
294 }
295 }
296
297 SDE_REG_WRITE(c, CTL_LAYER(lm), mixercfg);
298 SDE_REG_WRITE(c, CTL_LAYER_EXT(lm), mixercfg_ext);
299}
300
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400301static void sde_hw_ctl_intf_cfg(struct sde_hw_ctl *ctx,
302 struct sde_hw_intf_cfg *cfg)
303{
304 struct sde_hw_blk_reg_map *c = &ctx->hw;
305 u32 intf_cfg = 0;
306
307 intf_cfg |= (cfg->intf & 0xF) << 4;
308
309 if (cfg->wb)
310 intf_cfg |= (cfg->wb & 0x3) + 2;
311
312 if (cfg->mode_3d) {
313 intf_cfg |= BIT(19);
314 intf_cfg |= (cfg->mode_3d - 1) << 20;
315 }
316
317 SDE_REG_WRITE(c, CTL_TOP, intf_cfg);
318}
319
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700320static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops,
321 unsigned long cap)
322{
323 ops->setup_flush = sde_hw_ctl_setup_flush;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400324 ops->setup_start = sde_hw_ctl_force_start;
325 ops->setup_intf_cfg = sde_hw_ctl_intf_cfg;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700326 ops->reset = sde_hw_ctl_reset_control;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400327 ops->setup_blendstage = sde_hw_ctl_setup_blendstage;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700328 ops->get_bitmask_sspp = sde_hw_ctl_get_bitmask_sspp;
329 ops->get_bitmask_mixer = sde_hw_ctl_get_bitmask_mixer;
330 ops->get_bitmask_dspp = sde_hw_ctl_get_bitmask_dspp;
331 ops->get_bitmask_intf = sde_hw_ctl_get_bitmask_intf;
332 ops->get_bitmask_cdm = sde_hw_ctl_get_bitmask_cdm;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700333};
334
335struct sde_hw_ctl *sde_hw_ctl_init(enum sde_ctl idx,
336 void __iomem *addr,
337 struct sde_mdss_cfg *m)
338{
339 struct sde_hw_ctl *c;
340 struct sde_ctl_cfg *cfg;
341
342 c = kzalloc(sizeof(*c), GFP_KERNEL);
343 if (!c)
344 return ERR_PTR(-ENOMEM);
345
346 cfg = _ctl_offset(idx, m, addr, &c->hw);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400347 if (IS_ERR_OR_NULL(cfg)) {
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700348 kfree(c);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400349 pr_err("Error Panic\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700350 return ERR_PTR(-EINVAL);
351 }
352
353 c->caps = cfg;
354 _setup_ctl_ops(&c->ops, c->caps->features);
355 c->idx = idx;
356 c->mixer_count = m->mixer_count;
357 c->mixer_hw_caps = m->mixer;
358
359 return c;
360}
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400361
362void sde_hw_ctl_destroy(struct sde_hw_ctl *ctx)
363{
364 kfree(ctx);
365}