blob: 181f8be09310675990c942420dbc124eaf4320ef [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 "sde_hw_sspp.h"
14#include "sde_hwio.h"
15#include "sde_hw_catalog.h"
16#include "sde_hw_lm.h"
17
18#define SDE_MDP_FETCH_CONFIG_RESET_VALUE 0x00000087
19
20/* SDE_SSPP_SRC */
21#define SSPP_SRC_SIZE 0x00
22#define SSPP_SRC_XY 0x08
23#define SSPP_OUT_SIZE 0x0c
24#define SSPP_OUT_XY 0x10
25#define SSPP_SRC0_ADDR 0x14
26#define SSPP_SRC1_ADDR 0x18
27#define SSPP_SRC2_ADDR 0x1C
28#define SSPP_SRC3_ADDR 0x20
29#define SSPP_SRC_YSTRIDE0 0x24
30#define SSPP_SRC_YSTRIDE1 0x28
31#define SSPP_SRC_FORMAT 0x30
32#define SSPP_SRC_UNPACK_PATTERN 0x34
33#define SSPP_SRC_OP_MODE 0x38
34#define MDSS_MDP_OP_DEINTERLACE BIT(22)
35
36#define MDSS_MDP_OP_DEINTERLACE_ODD BIT(23)
37#define MDSS_MDP_OP_IGC_ROM_1 BIT(18)
38#define MDSS_MDP_OP_IGC_ROM_0 BIT(17)
39#define MDSS_MDP_OP_IGC_EN BIT(16)
40#define MDSS_MDP_OP_FLIP_UD BIT(14)
41#define MDSS_MDP_OP_FLIP_LR BIT(13)
42#define MDSS_MDP_OP_BWC_EN BIT(0)
43#define MDSS_MDP_OP_PE_OVERRIDE BIT(31)
44#define MDSS_MDP_OP_BWC_LOSSLESS (0 << 1)
45#define MDSS_MDP_OP_BWC_Q_HIGH (1 << 1)
46#define MDSS_MDP_OP_BWC_Q_MED (2 << 1)
47
48#define SSPP_SRC_CONSTANT_COLOR 0x3c
49#define SSPP_FETCH_CONFIG 0x048
50#define SSPP_DANGER_LUT 0x60
51#define SSPP_SAFE_LUT 0x64
52#define SSPP_CREQ_LUT 0x68
53#define SSPP_DECIMATION_CONFIG 0xB4
54#define SSPP_SRC_ADDR_SW_STATUS 0x70
55#define SSPP_SW_PIX_EXT_C0_LR 0x100
56#define SSPP_SW_PIX_EXT_C0_TB 0x104
57#define SSPP_SW_PIX_EXT_C0_REQ_PIXELS 0x108
58#define SSPP_SW_PIX_EXT_C1C2_LR 0x110
59#define SSPP_SW_PIX_EXT_C1C2_TB 0x114
60#define SSPP_SW_PIX_EXT_C1C2_REQ_PIXELS 0x118
61#define SSPP_SW_PIX_EXT_C3_LR 0x120
62#define SSPP_SW_PIX_EXT_C3_TB 0x124
63#define SSPP_SW_PIX_EXT_C3_REQ_PIXELS 0x128
64#define SSPP_UBWC_ERROR_STATUS 0x138
65#define SSPP_VIG_OP_MODE 0x200
66
67/* SDE_SSPP_SCALAR_QSEED2 */
68#define SCALE_CONFIG 0x04
69#define COMP0_3_PHASE_STEP_X 0x10
70#define COMP0_3_PHASE_STEP_Y 0x14
71#define COMP1_2_PHASE_STEP_X 0x18
72#define COMP1_2_PHASE_STEP_Y 0x1c
73#define COMP0_3_INIT_PHASE_X 0x20
74#define COMP0_3_INIT_PHASE_Y 0x24
75#define COMP1_2_INIT_PHASE_X 0x28
76#define COMP1_2_INIT_PHASE_Y 0x2C
77#define VIG_0_QSEED2_SHARP 0x30
78
79#define VIG_0_CSC_1_MATRIX_COEFF_0 0x20
80#define VIG_0_CSC_1_COMP_0_PRE_CLAMP 0x34
81#define VIG_0_CSC_1_COMP_0_POST_CLAMP 0x40
82#define VIG_0_CSC_1_COMP_0_PRE_BIAS 0x4C
83#define VIG_0_CSC_1_COMP_0_POST_BIAS 0x60
84
85/*
86 * MDP Solid fill configuration
87 * argb8888
88 */
89#define SSPP_SOLID_FILL 0x4037ff
90
91enum {
92 CSC = 0x1,
93 PA,
94 HIST,
95 SKIN_COL,
96 FOIL,
97 SKY_COL,
98 MEM_PROT_HUE,
99 MEM_PROT_SAT,
100 MEM_PROT_VAL,
101 MEM_PROT_CONT,
102 MEM_PROT_BLEND,
103 PA_SAT_ADJ
104};
105
106static inline int _sspp_subblk_offset(struct sde_hw_pipe *ctx,
107 int s_id,
108 u32 *idx)
109{
110 int rc = 0;
111 const struct sde_sspp_sub_blks *sblk = ctx->cap->sblk;
112
113 switch (s_id) {
114 case SDE_SSPP_SRC:
115 *idx = sblk->src_blk.base;
116 break;
117 case SDE_SSPP_SCALAR_QSEED2:
118 case SDE_SSPP_SCALAR_QSEED3:
119 case SDE_SSPP_SCALAR_RGB:
120 *idx = sblk->scalar_blk.base;
121 break;
122 case SDE_SSPP_CSC:
123 *idx = sblk->csc_blk.base;
124 break;
125 case SDE_SSPP_PA_V1:
126 *idx = sblk->pa_blk.base;
127 break;
128 case SDE_SSPP_HIST_V1:
129 *idx = sblk->hist_lut.base;
130 break;
131 case SDE_SSPP_PCC:
132 *idx = sblk->pcc_blk.base;
133 break;
134 default:
135 rc = -EINVAL;
136 pr_err("Unsupported SSPP sub-blk for this hw\n");
137 }
138
139 return rc;
140}
141
142static void _sspp_setup_opmode(struct sde_hw_pipe *ctx,
143 u32 op, u8 en)
144{
145 struct sde_hw_blk_reg_map *c = &ctx->hw;
146 u32 idx;
147 u32 opmode;
148
149 if (ctx->cap->features == SDE_SSPP_PA_V1) {
150
151 if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
152 return;
153
154 opmode = SDE_REG_READ(c, SSPP_VIG_OP_MODE + idx);
155
156 /* ops */
157 switch (op) {
158 case CSC:
159 if (en)
160 /* CSC_1_EN and CSC_SRC_DATA_FORMAT*/
161 opmode |= BIT(18) | BIT(17);
162 else
163 opmode &= ~BIT(17);
164 break;
165 default:
166 pr_err(" Unsupported operation\n");
167 }
168 SDE_REG_WRITE(c, SSPP_VIG_OP_MODE + idx, opmode);
169 }
170}
171/**
172 * Setup source pixel format, flip,
173 */
174static void sde_hw_sspp_setup_format(struct sde_hw_pipe *ctx,
175 struct sde_hw_pipe_cfg *cfg,
176 u32 flags)
177{
178 struct sde_hw_blk_reg_map *c = &ctx->hw;
179 struct sde_mdp_format_params *fmt;
180 u32 chroma_samp, unpack, src_format;
181 u32 secure = 0;
182 u32 opmode = 0;
183 u32 idx;
184
185 if (!_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
186 return;
187
188 opmode = SDE_REG_READ(c, SSPP_SRC_OP_MODE + idx);
189
190 /* format info */
191 fmt = cfg->src.format;
192 if (WARN_ON(!fmt))
193 return;
194
195 if (flags & SDE_SSPP_SECURE_OVERLAY_SESSION)
196 secure = 0xF;
197
198 if (flags & SDE_SSPP_FLIP_LR)
199 opmode |= MDSS_MDP_OP_FLIP_LR;
200 if (flags & SDE_SSPP_FLIP_UD)
201 opmode |= MDSS_MDP_OP_FLIP_UD;
202
203 chroma_samp = fmt->chroma_sample;
204 if (flags & SDE_SSPP_SOURCE_ROTATED_90) {
205 if (chroma_samp == SDE_MDP_CHROMA_H2V1)
206 chroma_samp = SDE_MDP_CHROMA_H1V2;
207 else if (chroma_samp == SDE_MDP_CHROMA_H1V2)
208 chroma_samp = SDE_MDP_CHROMA_H2V1;
209 }
210
211 src_format = (chroma_samp << 23) | (fmt->fetch_planes << 19) |
212 (fmt->bits[C3_ALPHA] << 6) | (fmt->bits[C2_R_Cr] << 4) |
213 (fmt->bits[C0_G_Y] << 0);
214
215 if (flags & SDE_SSPP_ROT_90)
216 src_format |= BIT(11); /* ROT90 */
217
218 if (fmt->alpha_enable &&
219 fmt->fetch_planes != SDE_MDP_PLANE_INTERLEAVED)
220 src_format |= BIT(8); /* SRCC3_EN */
221
222 unpack = (fmt->element[3] << 24) | (fmt->element[2] << 16) |
223 (fmt->element[1] << 8) | (fmt->element[0] << 0);
224 src_format |= ((fmt->unpack_count - 1) << 12) |
225 (fmt->unpack_tight << 17) |
226 (fmt->unpack_align_msb << 18) |
227 ((fmt->bpp - 1) << 9);
228
229 if (fmt->fetch_mode != SDE_MDP_FETCH_LINEAR) {
230 opmode |= MDSS_MDP_OP_BWC_EN;
231 src_format |= (fmt->fetch_mode & 3) << 30; /*FRAME_FORMAT */
232 SDE_REG_WRITE(c, SSPP_FETCH_CONFIG,
233 SDE_MDP_FETCH_CONFIG_RESET_VALUE |
234 ctx->highest_bank_bit << 18);
235 }
236
237 /* if this is YUV pixel format, enable CSC */
238 if (fmt->is_yuv) {
239 _sspp_setup_opmode(ctx, CSC, 0x0);
240 } else {
241 src_format |= BIT(15);
242 _sspp_setup_opmode(ctx, CSC, 0x1);
243 }
244
245 opmode |= MDSS_MDP_OP_PE_OVERRIDE;
246
247 SDE_REG_WRITE(c, SSPP_SRC_FORMAT + idx, src_format);
248 SDE_REG_WRITE(c, SSPP_SRC_UNPACK_PATTERN + idx, unpack);
249 SDE_REG_WRITE(c, SSPP_SRC_OP_MODE + idx, opmode);
250 SDE_REG_WRITE(c, SSPP_SRC_ADDR_SW_STATUS + idx, secure);
251
252 /* clear previous UBWC error */
253 SDE_REG_WRITE(c, SSPP_UBWC_ERROR_STATUS + idx, BIT(31));
254}
255
256static void sde_hw_sspp_setup_pe_config(struct sde_hw_pipe *ctx,
257 struct sde_hw_pipe_cfg *cfg,
258 struct sde_hw_pixel_ext *pe_ext)
259{
260 struct sde_hw_blk_reg_map *c = &ctx->hw;
261 u8 color;
262 u32 lr_pe[4], tb_pe[4], tot_req_pixels[4];
263 const u32 bytemask = 0xffff;
264 const u8 shortmask = 0xff;
265 u32 idx;
266
267 if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
268 return;
269
270 /* program SW pixel extension override for all pipes*/
271 for (color = 0; color < 4; color++) {
272 /* color 2 has the same set of registers as color 1 */
273 if (color == 2)
274 continue;
275
276 lr_pe[color] = ((pe_ext->right_ftch[color] & bytemask) << 24)|
277 ((pe_ext->right_rpt[color] & bytemask) << 16)|
278 ((pe_ext->left_ftch[color] & bytemask) << 8)|
279 (pe_ext->left_rpt[color] & bytemask);
280
281 tb_pe[color] = ((pe_ext->btm_ftch[color] & bytemask) << 24)|
282 ((pe_ext->btm_rpt[color] & bytemask) << 16)|
283 ((pe_ext->top_ftch[color] & bytemask) << 8)|
284 (pe_ext->top_rpt[color] & bytemask);
285
286 tot_req_pixels[color] = (((cfg->src.height +
287 pe_ext->num_ext_pxls_top[color] +
288 pe_ext->num_ext_pxls_btm[color]) & shortmask) << 16) |
289 ((pe_ext->roi_w[color] +
290 pe_ext->num_ext_pxls_left[color] +
291 pe_ext->num_ext_pxls_right[color]) & shortmask);
292 }
293
294 /* color 0 */
295 SDE_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_LR + idx, lr_pe[0]);
296 SDE_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_TB + idx, tb_pe[0]);
297 SDE_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_REQ_PIXELS + idx,
298 tot_req_pixels[0]);
299
300 /* color 1 and color 2 */
301 SDE_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_LR + idx, lr_pe[1]);
302 SDE_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_TB + idx, tb_pe[1]);
303 SDE_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_REQ_PIXELS + idx,
304 tot_req_pixels[1]);
305
306 /* color 3 */
307 SDE_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_LR + idx, lr_pe[3]);
308 SDE_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_TB + idx, lr_pe[3]);
309 SDE_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_REQ_PIXELS + idx,
310 tot_req_pixels[3]);
311}
312
313static void sde_hw_sspp_setup_scalar(struct sde_hw_pipe *ctx,
314 struct sde_hw_pixel_ext *pe_ext)
315{
316 struct sde_hw_blk_reg_map *c = &ctx->hw;
317 int scale_config;
318 const u8 mask = 0x3;
319 u32 idx;
320
321 if (_sspp_subblk_offset(ctx, SDE_SSPP_SCALAR_QSEED2, &idx))
322 return;
323
324 scale_config = BIT(0) | BIT(1);
325 /* RGB/YUV config */
326 scale_config |= (pe_ext->horz_filter[0] & mask) << 8;
327 scale_config |= (pe_ext->vert_filter[0] & mask) << 10;
328 /* Aplha config*/
329 scale_config |= (pe_ext->horz_filter[3] & mask) << 16;
330 scale_config |= (pe_ext->vert_filter[3] & mask) << 18;
331
332 SDE_REG_WRITE(c, SCALE_CONFIG + idx, scale_config);
333 SDE_REG_WRITE(c, COMP0_3_INIT_PHASE_X + idx,
334 pe_ext->init_phase_x[0]);
335 SDE_REG_WRITE(c, COMP0_3_INIT_PHASE_Y + idx,
336 pe_ext->init_phase_y[0]);
337 SDE_REG_WRITE(c, COMP0_3_PHASE_STEP_X + idx,
338 pe_ext->phase_step_x[0]);
339 SDE_REG_WRITE(c, COMP0_3_PHASE_STEP_Y + idx,
340 pe_ext->phase_step_y[0]);
341
342 SDE_REG_WRITE(c, COMP1_2_INIT_PHASE_X + idx,
343 pe_ext->init_phase_x[1]);
344 SDE_REG_WRITE(c, COMP1_2_INIT_PHASE_Y + idx,
345 pe_ext->init_phase_y[1]);
346 SDE_REG_WRITE(c, COMP1_2_PHASE_STEP_X + idx,
347 pe_ext->phase_step_x[1]);
348 SDE_REG_WRITE(c, COMP1_2_PHASE_STEP_Y + idx,
349 pe_ext->phase_step_y[0]);
350}
351
352/**
353 * sde_hw_sspp_setup_rects()
354 */
355static void sde_hw_sspp_setup_rects(struct sde_hw_pipe *ctx,
356 struct sde_hw_pipe_cfg *cfg,
357 struct sde_hw_pixel_ext *pe_ext)
358{
359 struct sde_hw_blk_reg_map *c = &ctx->hw;
360 u32 src_size, src_xy, dst_size, dst_xy, ystride0, ystride1;
361 u32 decimation = 0;
362 u32 idx;
363
364 if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
365 return;
366
367 /* program pixel extension override */
368 if (!pe_ext)
369 sde_hw_sspp_setup_pe_config(ctx, cfg, pe_ext);
370
371 /* src and dest rect programming */
372 src_xy = (cfg->src_rect.y << 16) |
373 (cfg->src_rect.x);
374 src_size = (cfg->src_rect.h << 16) |
375 (cfg->src_rect.w);
376 dst_xy = (cfg->dst_rect.y << 16) |
377 (cfg->dst_rect.x);
378 dst_size = (cfg->dst_rect.h << 16) |
379 (cfg->dst_rect.w);
380
381 ystride0 = (cfg->src.ystride[0]) |
382 (cfg->src.ystride[1] << 16);
383 ystride1 = (cfg->src.ystride[2]) |
384 (cfg->src.ystride[3] << 16);
385
386 /* program scalar, phase registers, if pipes supporting scaling */
387 if (src_size != dst_size) {
388 if (test_bit(SDE_SSPP_SCALAR_RGB, &ctx->cap->features) ||
389 test_bit(SDE_SSPP_SCALAR_QSEED2, &ctx->cap->features)) {
390 /* program decimation */
391 if (!cfg->horz_decimation)
392 decimation = (cfg->horz_decimation - 1) << 8;
393 if (!cfg->vert_decimation)
394 decimation |= (cfg->vert_decimation - 1);
395
396 sde_hw_sspp_setup_scalar(ctx, pe_ext);
397 }
398 }
399
400 /* Rectangle Register programming */
401 SDE_REG_WRITE(c, SSPP_SRC_SIZE + idx, src_size);
402 SDE_REG_WRITE(c, SSPP_SRC_XY + idx, src_xy);
403 SDE_REG_WRITE(c, SSPP_OUT_SIZE + idx, dst_size);
404 SDE_REG_WRITE(c, SSPP_OUT_XY + idx, dst_xy);
405
406 SDE_REG_WRITE(c, SSPP_SRC_YSTRIDE0 + idx, ystride0);
407 SDE_REG_WRITE(c, SSPP_SRC_YSTRIDE1 + idx, ystride1);
408 SDE_REG_WRITE(c, SSPP_DECIMATION_CONFIG + idx, decimation);
409}
410
411static void sde_hw_sspp_setup_sourceaddress(struct sde_hw_pipe *ctx,
412 struct sde_hw_pipe_cfg *cfg)
413{
414 struct sde_hw_blk_reg_map *c = &ctx->hw;
415 int i;
416 u32 idx;
417
418 if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
419 return;
420
421 for (i = 0; i < cfg->src.num_planes; i++)
422 SDE_REG_WRITE(c, SSPP_SRC0_ADDR + idx + i*0x4,
423 cfg->addr.plane[i]);
424
425}
426
427static void sde_hw_sspp_setup_csc_8bit(struct sde_hw_pipe *ctx,
428 struct sde_csc_cfg *data)
429{
430 struct sde_hw_blk_reg_map *c = &ctx->hw;
431
432 sde_hw_csc_setup(c, VIG_0_CSC_1_MATRIX_COEFF_0, data);
433}
434
435static void sde_hw_sspp_setup_sharpening(struct sde_hw_pipe *ctx,
436 struct sde_hw_sharp_cfg *cfg)
437{
438 struct sde_hw_blk_reg_map *c = &ctx->hw;
439 u32 idx;
440
441 if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
442 return;
443
444 SDE_REG_WRITE(c, VIG_0_QSEED2_SHARP + idx, cfg->strength);
445 SDE_REG_WRITE(c, VIG_0_QSEED2_SHARP + idx + 0x4, cfg->edge_thr);
446 SDE_REG_WRITE(c, VIG_0_QSEED2_SHARP + idx + 0x8, cfg->smooth_thr);
447 SDE_REG_WRITE(c, VIG_0_QSEED2_SHARP + idx + 0xC, cfg->noise_thr);
448}
449
450static void sde_hw_sspp_setup_solidfill(struct sde_hw_pipe *ctx,
451 u32 const_color,
452 u32 flags)
453{
454 struct sde_hw_blk_reg_map *c = &ctx->hw;
455 u32 secure = 0;
456 u32 unpack, src_format, opmode = 0;
457 u32 idx;
458
459 if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
460 return;
461
462 /* format info */
463 src_format = SSPP_SOLID_FILL;
464 unpack = (C3_ALPHA << 24) | (C2_R_Cr << 16) |
465 (C1_B_Cb << 8) | (C0_G_Y << 0);
466 secure = (flags & SDE_SSPP_SECURE_OVERLAY_SESSION) ? 0xF : 0x00;
467 opmode = MDSS_MDP_OP_PE_OVERRIDE;
468
469 SDE_REG_WRITE(c, SSPP_SRC_FORMAT + idx, src_format);
470 SDE_REG_WRITE(c, SSPP_SRC_UNPACK_PATTERN + idx, unpack);
471 SDE_REG_WRITE(c, SSPP_SRC_ADDR_SW_STATUS + idx, secure);
472 SDE_REG_WRITE(c, SSPP_SRC_CONSTANT_COLOR + idx, const_color);
473 SDE_REG_WRITE(c, SSPP_SRC_OP_MODE + idx, opmode);
474}
475
476static void sde_hw_sspp_setup_histogram_v1(struct sde_hw_pipe *ctx,
477 void *cfg)
478{
479
480}
481
482static void sde_hw_sspp_setup_memcolor(struct sde_hw_pipe *ctx,
483 u32 memcolortype, u8 en)
484{
485}
486
487static void sde_hw_sspp_setup_igc(struct sde_hw_pipe *ctx)
488{
489}
490
491void sde_sspp_setup_pa(struct sde_hw_pipe *c)
492{
493}
494
495static void sde_hw_sspp_setup_danger_safe(struct sde_hw_pipe *ctx,
496 u32 danger_lut, u32 safe_lut)
497{
498 struct sde_hw_blk_reg_map *c = &ctx->hw;
499 u32 idx;
500
501 if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
502 return;
503
504 SDE_REG_WRITE(c, SSPP_DANGER_LUT + idx, danger_lut);
505 SDE_REG_WRITE(c, SSPP_SAFE_LUT + idx, safe_lut);
506}
507
508static void sde_hw_sspp_qseed2_coeff(void *ctx)
509{
510}
511
512static void _setup_layer_ops(struct sde_hw_sspp_ops *ops,
513 unsigned long features)
514{
515 if (test_bit(SDE_SSPP_SRC, &features)) {
516 ops->setup_sourceformat = sde_hw_sspp_setup_format;
517 ops->setup_rects = sde_hw_sspp_setup_rects;
518 ops->setup_sourceaddress = sde_hw_sspp_setup_sourceaddress;
519 ops->setup_solidfill = sde_hw_sspp_setup_solidfill;
520 ops->setup_danger_safe = sde_hw_sspp_setup_danger_safe;
521 }
522 if (test_bit(SDE_SSPP_CSC, &features))
523 ops->setup_csc = sde_hw_sspp_setup_csc_8bit;
524
525 if (test_bit(SDE_SSPP_PA_V1, &features)) {
526 ops->setup_sharpening = sde_hw_sspp_setup_sharpening;
527 ops->setup_pa_memcolor = sde_hw_sspp_setup_memcolor;
528 }
529 if (test_bit(SDE_SSPP_HIST_V1, &features))
530 ops->setup_histogram = sde_hw_sspp_setup_histogram_v1;
531
532 if (test_bit(SDE_SSPP_IGC, &features))
533 ops->setup_igc = sde_hw_sspp_setup_igc;
534}
535
536static struct sde_sspp_cfg *_sspp_offset(enum sde_sspp sspp,
537 struct sde_mdss_cfg *m,
538 void __iomem *addr,
539 struct sde_hw_blk_reg_map *b)
540{
541 int i;
542
543 for (i = 0; i < m->sspp_count; i++) {
544 if (sspp == m->sspp[i].id) {
545 b->base_off = addr;
546 b->blk_off = m->sspp[i].base;
547 b->hwversion = m->hwversion;
548 return &m->sspp[i];
549 }
550 }
551
552 return ERR_PTR(-ENOMEM);
553}
554
555struct sde_hw_pipe *sde_hw_sspp_init(enum sde_sspp idx,
556 void __iomem *addr,
557 struct sde_mdss_cfg *m)
558{
559 struct sde_hw_pipe *c;
560 struct sde_sspp_cfg *cfg;
561
562 c = kzalloc(sizeof(*c), GFP_KERNEL);
563 if (!c)
564 return ERR_PTR(-ENOMEM);
565
566 cfg = _sspp_offset(idx, m, addr, &c->hw);
567 if (IS_ERR_OR_NULL(cfg)) {
568 kfree(c);
569 return ERR_PTR(-EINVAL);
570 }
571
572 /* Assign ops */
573 c->idx = idx;
574 c->cap = cfg;
575 _setup_layer_ops(&c->ops, c->cap->features);
576 c->highest_bank_bit = m->mdp[0].highest_bank_bit;
577
578 /*
579 * Perform any default initialization for the sspp blocks
580 */
581 if (test_bit(SDE_SSPP_SCALAR_QSEED2, &cfg->features))
582 sde_hw_sspp_qseed2_coeff(c);
583
584 if (test_bit(SDE_MDP_PANIC_PER_PIPE, &m->mdp[0].features))
585 sde_hw_sspp_setup_danger_safe(c,
586 cfg->sblk->danger_lut,
587 cfg->sblk->safe_lut);
588
589 return c;
590}
591