]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
drm/komeda: Rename main engine clk name "mclk" to "aclk"
[linux.git] / drivers / gpu / drm / arm / display / komeda / d71 / d71_component.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
4  * Author: James.Qian.Wang <james.qian.wang@arm.com>
5  *
6  */
7
8 #include <drm/drm_print.h>
9 #include "d71_dev.h"
10 #include "komeda_kms.h"
11 #include "malidp_io.h"
12 #include "komeda_framebuffer.h"
13 #include "komeda_color_mgmt.h"
14
15 static void get_resources_id(u32 hw_id, u32 *pipe_id, u32 *comp_id)
16 {
17         u32 id = BLOCK_INFO_BLK_ID(hw_id);
18         u32 pipe = id;
19
20         switch (BLOCK_INFO_BLK_TYPE(hw_id)) {
21         case D71_BLK_TYPE_LPU_WB_LAYER:
22                 id = KOMEDA_COMPONENT_WB_LAYER;
23                 break;
24         case D71_BLK_TYPE_CU_SPLITTER:
25                 id = KOMEDA_COMPONENT_SPLITTER;
26                 break;
27         case D71_BLK_TYPE_CU_SCALER:
28                 pipe = id / D71_PIPELINE_MAX_SCALERS;
29                 id %= D71_PIPELINE_MAX_SCALERS;
30                 id += KOMEDA_COMPONENT_SCALER0;
31                 break;
32         case D71_BLK_TYPE_CU:
33                 id += KOMEDA_COMPONENT_COMPIZ0;
34                 break;
35         case D71_BLK_TYPE_LPU_LAYER:
36                 pipe = id / D71_PIPELINE_MAX_LAYERS;
37                 id %= D71_PIPELINE_MAX_LAYERS;
38                 id += KOMEDA_COMPONENT_LAYER0;
39                 break;
40         case D71_BLK_TYPE_DOU_IPS:
41                 id += KOMEDA_COMPONENT_IPS0;
42                 break;
43         case D71_BLK_TYPE_CU_MERGER:
44                 id = KOMEDA_COMPONENT_MERGER;
45                 break;
46         case D71_BLK_TYPE_DOU:
47                 id = KOMEDA_COMPONENT_TIMING_CTRLR;
48                 break;
49         default:
50                 id = 0xFFFFFFFF;
51         }
52
53         if (comp_id)
54                 *comp_id = id;
55
56         if (pipe_id)
57                 *pipe_id = pipe;
58 }
59
60 static u32 get_valid_inputs(struct block_header *blk)
61 {
62         u32 valid_inputs = 0, comp_id;
63         int i;
64
65         for (i = 0; i < PIPELINE_INFO_N_VALID_INPUTS(blk->pipeline_info); i++) {
66                 get_resources_id(blk->input_ids[i], NULL, &comp_id);
67                 if (comp_id == 0xFFFFFFFF)
68                         continue;
69                 valid_inputs |= BIT(comp_id);
70         }
71
72         return valid_inputs;
73 }
74
75 static void get_values_from_reg(void __iomem *reg, u32 offset,
76                                 u32 count, u32 *val)
77 {
78         u32 i, addr;
79
80         for (i = 0; i < count; i++) {
81                 addr = offset + (i << 2);
82                 /* 0xA4 is WO register */
83                 if (addr != 0xA4)
84                         val[i] = malidp_read32(reg, addr);
85                 else
86                         val[i] = 0xDEADDEAD;
87         }
88 }
89
90 static void dump_block_header(struct seq_file *sf, void __iomem *reg)
91 {
92         struct block_header hdr;
93         u32 i, n_input, n_output;
94
95         d71_read_block_header(reg, &hdr);
96         seq_printf(sf, "BLOCK_INFO:\t\t0x%X\n", hdr.block_info);
97         seq_printf(sf, "PIPELINE_INFO:\t\t0x%X\n", hdr.pipeline_info);
98
99         n_output = PIPELINE_INFO_N_OUTPUTS(hdr.pipeline_info);
100         n_input  = PIPELINE_INFO_N_VALID_INPUTS(hdr.pipeline_info);
101
102         for (i = 0; i < n_input; i++)
103                 seq_printf(sf, "VALID_INPUT_ID%u:\t0x%X\n",
104                            i, hdr.input_ids[i]);
105
106         for (i = 0; i < n_output; i++)
107                 seq_printf(sf, "OUTPUT_ID%u:\t\t0x%X\n",
108                            i, hdr.output_ids[i]);
109 }
110
111 static u32 to_rot_ctrl(u32 rot)
112 {
113         u32 lr_ctrl = 0;
114
115         switch (rot & DRM_MODE_ROTATE_MASK) {
116         case DRM_MODE_ROTATE_0:
117                 lr_ctrl |= L_ROT(L_ROT_R0);
118                 break;
119         case DRM_MODE_ROTATE_90:
120                 lr_ctrl |= L_ROT(L_ROT_R90);
121                 break;
122         case DRM_MODE_ROTATE_180:
123                 lr_ctrl |= L_ROT(L_ROT_R180);
124                 break;
125         case DRM_MODE_ROTATE_270:
126                 lr_ctrl |= L_ROT(L_ROT_R270);
127                 break;
128         }
129
130         if (rot & DRM_MODE_REFLECT_X)
131                 lr_ctrl |= L_HFLIP;
132         if (rot & DRM_MODE_REFLECT_Y)
133                 lr_ctrl |= L_VFLIP;
134
135         return lr_ctrl;
136 }
137
138 static u32 to_ad_ctrl(u64 modifier)
139 {
140         u32 afbc_ctrl = AD_AEN;
141
142         if (!modifier)
143                 return 0;
144
145         if ((modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) ==
146             AFBC_FORMAT_MOD_BLOCK_SIZE_32x8)
147                 afbc_ctrl |= AD_WB;
148
149         if (modifier & AFBC_FORMAT_MOD_YTR)
150                 afbc_ctrl |= AD_YT;
151         if (modifier & AFBC_FORMAT_MOD_SPLIT)
152                 afbc_ctrl |= AD_BS;
153         if (modifier & AFBC_FORMAT_MOD_TILED)
154                 afbc_ctrl |= AD_TH;
155
156         return afbc_ctrl;
157 }
158
159 static inline u32 to_d71_input_id(struct komeda_component_output *output)
160 {
161         struct komeda_component *comp = output->component;
162
163         return comp ? (comp->hw_id + output->output_port) : 0;
164 }
165
166 static void d71_layer_update_fb(struct komeda_component *c,
167                                 struct komeda_fb *kfb,
168                                 dma_addr_t *addr)
169 {
170         struct drm_framebuffer *fb = &kfb->base;
171         const struct drm_format_info *info = fb->format;
172         u32 __iomem *reg = c->reg;
173         int block_h;
174
175         if (info->num_planes > 2)
176                 malidp_write64(reg, BLK_P2_PTR_LOW, addr[2]);
177
178         if (info->num_planes > 1) {
179                 block_h = drm_format_info_block_height(info, 1);
180                 malidp_write32(reg, BLK_P1_STRIDE, fb->pitches[1] * block_h);
181                 malidp_write64(reg, BLK_P1_PTR_LOW, addr[1]);
182         }
183
184         block_h = drm_format_info_block_height(info, 0);
185         malidp_write32(reg, BLK_P0_STRIDE, fb->pitches[0] * block_h);
186         malidp_write64(reg, BLK_P0_PTR_LOW, addr[0]);
187         malidp_write32(reg, LAYER_FMT, kfb->format_caps->hw_id);
188 }
189
190 static void d71_layer_disable(struct komeda_component *c)
191 {
192         malidp_write32_mask(c->reg, BLK_CONTROL, L_EN, 0);
193 }
194
195 static void d71_layer_update(struct komeda_component *c,
196                              struct komeda_component_state *state)
197 {
198         struct komeda_layer_state *st = to_layer_st(state);
199         struct drm_plane_state *plane_st = state->plane->state;
200         struct drm_framebuffer *fb = plane_st->fb;
201         struct komeda_fb *kfb = to_kfb(fb);
202         u32 __iomem *reg = c->reg;
203         u32 ctrl_mask = L_EN | L_ROT(L_ROT_R270) | L_HFLIP | L_VFLIP | L_TBU_EN;
204         u32 ctrl = L_EN | to_rot_ctrl(st->rot);
205
206         d71_layer_update_fb(c, kfb, st->addr);
207
208         malidp_write32(reg, AD_CONTROL, to_ad_ctrl(fb->modifier));
209         if (fb->modifier) {
210                 u64 addr;
211
212                 malidp_write32(reg, LAYER_AD_H_CROP, HV_CROP(st->afbc_crop_l,
213                                                              st->afbc_crop_r));
214                 malidp_write32(reg, LAYER_AD_V_CROP, HV_CROP(st->afbc_crop_t,
215                                                              st->afbc_crop_b));
216                 /* afbc 1.2 wants payload, afbc 1.0/1.1 wants end_addr */
217                 if (fb->modifier & AFBC_FORMAT_MOD_TILED)
218                         addr = st->addr[0] + kfb->offset_payload;
219                 else
220                         addr = st->addr[0] + kfb->afbc_size - 1;
221
222                 malidp_write32(reg, BLK_P1_PTR_LOW, lower_32_bits(addr));
223                 malidp_write32(reg, BLK_P1_PTR_HIGH, upper_32_bits(addr));
224         }
225
226         if (fb->format->is_yuv) {
227                 u32 upsampling = 0;
228
229                 switch (kfb->format_caps->fourcc) {
230                 case DRM_FORMAT_YUYV:
231                         upsampling = fb->modifier ? LR_CHI422_BILINEAR :
232                                      LR_CHI422_REPLICATION;
233                         break;
234                 case DRM_FORMAT_UYVY:
235                         upsampling = LR_CHI422_REPLICATION;
236                         break;
237                 case DRM_FORMAT_NV12:
238                 case DRM_FORMAT_YUV420_8BIT:
239                 case DRM_FORMAT_YUV420_10BIT:
240                 case DRM_FORMAT_YUV420:
241                 case DRM_FORMAT_P010:
242                 /* these fmt support MPGE/JPEG both, here perfer JPEG*/
243                         upsampling = LR_CHI420_JPEG;
244                         break;
245                 case DRM_FORMAT_X0L2:
246                         upsampling = LR_CHI420_JPEG;
247                         break;
248                 default:
249                         break;
250                 }
251
252                 malidp_write32(reg, LAYER_R_CONTROL, upsampling);
253                 malidp_write_group(reg, LAYER_YUV_RGB_COEFF0,
254                                    KOMEDA_N_YUV2RGB_COEFFS,
255                                    komeda_select_yuv2rgb_coeffs(
256                                         plane_st->color_encoding,
257                                         plane_st->color_range));
258         }
259
260         malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize, st->vsize));
261
262         if (kfb->is_va)
263                 ctrl |= L_TBU_EN;
264         malidp_write32_mask(reg, BLK_CONTROL, ctrl_mask, ctrl);
265 }
266
267 static void d71_layer_dump(struct komeda_component *c, struct seq_file *sf)
268 {
269         u32 v[15], i;
270         bool rich, rgb2rgb;
271         char *prefix;
272
273         get_values_from_reg(c->reg, LAYER_INFO, 1, &v[14]);
274         if (v[14] & 0x1) {
275                 rich = true;
276                 prefix = "LR_";
277         } else {
278                 rich = false;
279                 prefix = "LS_";
280         }
281
282         rgb2rgb = !!(v[14] & L_INFO_CM);
283
284         dump_block_header(sf, c->reg);
285
286         seq_printf(sf, "%sLAYER_INFO:\t\t0x%X\n", prefix, v[14]);
287
288         get_values_from_reg(c->reg, 0xD0, 1, v);
289         seq_printf(sf, "%sCONTROL:\t\t0x%X\n", prefix, v[0]);
290         if (rich) {
291                 get_values_from_reg(c->reg, 0xD4, 1, v);
292                 seq_printf(sf, "LR_RICH_CONTROL:\t0x%X\n", v[0]);
293         }
294         get_values_from_reg(c->reg, 0xD8, 4, v);
295         seq_printf(sf, "%sFORMAT:\t\t0x%X\n", prefix, v[0]);
296         seq_printf(sf, "%sIT_COEFFTAB:\t\t0x%X\n", prefix, v[1]);
297         seq_printf(sf, "%sIN_SIZE:\t\t0x%X\n", prefix, v[2]);
298         seq_printf(sf, "%sPALPHA:\t\t0x%X\n", prefix, v[3]);
299
300         get_values_from_reg(c->reg, 0x100, 3, v);
301         seq_printf(sf, "%sP0_PTR_LOW:\t\t0x%X\n", prefix, v[0]);
302         seq_printf(sf, "%sP0_PTR_HIGH:\t\t0x%X\n", prefix, v[1]);
303         seq_printf(sf, "%sP0_STRIDE:\t\t0x%X\n", prefix, v[2]);
304
305         get_values_from_reg(c->reg, 0x110, 2, v);
306         seq_printf(sf, "%sP1_PTR_LOW:\t\t0x%X\n", prefix, v[0]);
307         seq_printf(sf, "%sP1_PTR_HIGH:\t\t0x%X\n", prefix, v[1]);
308         if (rich) {
309                 get_values_from_reg(c->reg, 0x118, 1, v);
310                 seq_printf(sf, "LR_P1_STRIDE:\t\t0x%X\n", v[0]);
311
312                 get_values_from_reg(c->reg, 0x120, 2, v);
313                 seq_printf(sf, "LR_P2_PTR_LOW:\t\t0x%X\n", v[0]);
314                 seq_printf(sf, "LR_P2_PTR_HIGH:\t\t0x%X\n", v[1]);
315
316                 get_values_from_reg(c->reg, 0x130, 12, v);
317                 for (i = 0; i < 12; i++)
318                         seq_printf(sf, "LR_YUV_RGB_COEFF%u:\t0x%X\n", i, v[i]);
319         }
320
321         if (rgb2rgb) {
322                 get_values_from_reg(c->reg, LAYER_RGB_RGB_COEFF0, 12, v);
323                 for (i = 0; i < 12; i++)
324                         seq_printf(sf, "LS_RGB_RGB_COEFF%u:\t0x%X\n", i, v[i]);
325         }
326
327         get_values_from_reg(c->reg, 0x160, 3, v);
328         seq_printf(sf, "%sAD_CONTROL:\t\t0x%X\n", prefix, v[0]);
329         seq_printf(sf, "%sAD_H_CROP:\t\t0x%X\n", prefix, v[1]);
330         seq_printf(sf, "%sAD_V_CROP:\t\t0x%X\n", prefix, v[2]);
331 }
332
333 static const struct komeda_component_funcs d71_layer_funcs = {
334         .update         = d71_layer_update,
335         .disable        = d71_layer_disable,
336         .dump_register  = d71_layer_dump,
337 };
338
339 static int d71_layer_init(struct d71_dev *d71,
340                           struct block_header *blk, u32 __iomem *reg)
341 {
342         struct komeda_component *c;
343         struct komeda_layer *layer;
344         u32 pipe_id, layer_id, layer_info;
345
346         get_resources_id(blk->block_info, &pipe_id, &layer_id);
347         c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*layer),
348                                  layer_id,
349                                  BLOCK_INFO_INPUT_ID(blk->block_info),
350                                  &d71_layer_funcs, 0,
351                                  get_valid_inputs(blk),
352                                  1, reg, "LPU%d_LAYER%d", pipe_id, layer_id);
353         if (IS_ERR(c)) {
354                 DRM_ERROR("Failed to add layer component\n");
355                 return PTR_ERR(c);
356         }
357
358         layer = to_layer(c);
359         layer_info = malidp_read32(reg, LAYER_INFO);
360
361         if (layer_info & L_INFO_RF)
362                 layer->layer_type = KOMEDA_FMT_RICH_LAYER;
363         else
364                 layer->layer_type = KOMEDA_FMT_SIMPLE_LAYER;
365
366         set_range(&layer->hsize_in, 4, d71->max_line_size);
367         set_range(&layer->vsize_in, 4, d71->max_vsize);
368
369         malidp_write32(reg, LAYER_PALPHA, D71_PALPHA_DEF_MAP);
370
371         layer->supported_rots = DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK;
372
373         return 0;
374 }
375
376 static void d71_wb_layer_update(struct komeda_component *c,
377                                 struct komeda_component_state *state)
378 {
379         struct komeda_layer_state *st = to_layer_st(state);
380         struct drm_connector_state *conn_st = state->wb_conn->state;
381         struct komeda_fb *kfb = to_kfb(conn_st->writeback_job->fb);
382         u32 ctrl = L_EN | LW_OFM, mask = L_EN | LW_OFM | LW_TBU_EN;
383         u32 __iomem *reg = c->reg;
384
385         d71_layer_update_fb(c, kfb, st->addr);
386
387         if (kfb->is_va)
388                 ctrl |= LW_TBU_EN;
389
390         malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize, st->vsize));
391         malidp_write32(reg, BLK_INPUT_ID0, to_d71_input_id(&state->inputs[0]));
392         malidp_write32_mask(reg, BLK_CONTROL, mask, ctrl);
393 }
394
395 static void d71_wb_layer_dump(struct komeda_component *c, struct seq_file *sf)
396 {
397         u32 v[12], i;
398
399         dump_block_header(sf, c->reg);
400
401         get_values_from_reg(c->reg, 0x80, 1, v);
402         seq_printf(sf, "LW_INPUT_ID0:\t\t0x%X\n", v[0]);
403
404         get_values_from_reg(c->reg, 0xD0, 3, v);
405         seq_printf(sf, "LW_CONTROL:\t\t0x%X\n", v[0]);
406         seq_printf(sf, "LW_PROG_LINE:\t\t0x%X\n", v[1]);
407         seq_printf(sf, "LW_FORMAT:\t\t0x%X\n", v[2]);
408
409         get_values_from_reg(c->reg, 0xE0, 1, v);
410         seq_printf(sf, "LW_IN_SIZE:\t\t0x%X\n", v[0]);
411
412         for (i = 0; i < 2; i++) {
413                 get_values_from_reg(c->reg, 0x100 + i * 0x10, 3, v);
414                 seq_printf(sf, "LW_P%u_PTR_LOW:\t\t0x%X\n", i, v[0]);
415                 seq_printf(sf, "LW_P%u_PTR_HIGH:\t\t0x%X\n", i, v[1]);
416                 seq_printf(sf, "LW_P%u_STRIDE:\t\t0x%X\n", i, v[2]);
417         }
418
419         get_values_from_reg(c->reg, 0x130, 12, v);
420         for (i = 0; i < 12; i++)
421                 seq_printf(sf, "LW_RGB_YUV_COEFF%u:\t0x%X\n", i, v[i]);
422 }
423
424 static void d71_wb_layer_disable(struct komeda_component *c)
425 {
426         malidp_write32(c->reg, BLK_INPUT_ID0, 0);
427         malidp_write32_mask(c->reg, BLK_CONTROL, L_EN, 0);
428 }
429
430 static const struct komeda_component_funcs d71_wb_layer_funcs = {
431         .update         = d71_wb_layer_update,
432         .disable        = d71_wb_layer_disable,
433         .dump_register  = d71_wb_layer_dump,
434 };
435
436 static int d71_wb_layer_init(struct d71_dev *d71,
437                              struct block_header *blk, u32 __iomem *reg)
438 {
439         struct komeda_component *c;
440         struct komeda_layer *wb_layer;
441         u32 pipe_id, layer_id;
442
443         get_resources_id(blk->block_info, &pipe_id, &layer_id);
444
445         c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*wb_layer),
446                                  layer_id, BLOCK_INFO_INPUT_ID(blk->block_info),
447                                  &d71_wb_layer_funcs,
448                                  1, get_valid_inputs(blk), 0, reg,
449                                  "LPU%d_LAYER_WR", pipe_id);
450         if (IS_ERR(c)) {
451                 DRM_ERROR("Failed to add wb_layer component\n");
452                 return PTR_ERR(c);
453         }
454
455         wb_layer = to_layer(c);
456         wb_layer->layer_type = KOMEDA_FMT_WB_LAYER;
457
458         set_range(&wb_layer->hsize_in, D71_MIN_LINE_SIZE, d71->max_line_size);
459         set_range(&wb_layer->vsize_in, D71_MIN_VERTICAL_SIZE, d71->max_vsize);
460
461         return 0;
462 }
463
464 static void d71_component_disable(struct komeda_component *c)
465 {
466         u32 __iomem *reg = c->reg;
467         u32 i;
468
469         malidp_write32(reg, BLK_CONTROL, 0);
470
471         for (i = 0; i < c->max_active_inputs; i++) {
472                 malidp_write32(reg, BLK_INPUT_ID0 + (i << 2), 0);
473
474                 /* Besides clearing the input ID to zero, D71 compiz also has
475                  * input enable bit in CU_INPUTx_CONTROL which need to be
476                  * cleared.
477                  */
478                 if (has_bit(c->id, KOMEDA_PIPELINE_COMPIZS))
479                         malidp_write32(reg, CU_INPUT0_CONTROL +
480                                        i * CU_PER_INPUT_REGS * 4,
481                                        CU_INPUT_CTRL_ALPHA(0xFF));
482         }
483 }
484
485 static void compiz_enable_input(u32 __iomem *id_reg,
486                                 u32 __iomem *cfg_reg,
487                                 u32 input_hw_id,
488                                 struct komeda_compiz_input_cfg *cin)
489 {
490         u32 ctrl = CU_INPUT_CTRL_EN;
491         u8 blend = cin->pixel_blend_mode;
492
493         if (blend == DRM_MODE_BLEND_PIXEL_NONE)
494                 ctrl |= CU_INPUT_CTRL_PAD;
495         else if (blend == DRM_MODE_BLEND_PREMULTI)
496                 ctrl |= CU_INPUT_CTRL_PMUL;
497
498         ctrl |= CU_INPUT_CTRL_ALPHA(cin->layer_alpha);
499
500         malidp_write32(id_reg, BLK_INPUT_ID0, input_hw_id);
501
502         malidp_write32(cfg_reg, CU_INPUT0_SIZE,
503                        HV_SIZE(cin->hsize, cin->vsize));
504         malidp_write32(cfg_reg, CU_INPUT0_OFFSET,
505                        HV_OFFSET(cin->hoffset, cin->voffset));
506         malidp_write32(cfg_reg, CU_INPUT0_CONTROL, ctrl);
507 }
508
509 static void d71_compiz_update(struct komeda_component *c,
510                               struct komeda_component_state *state)
511 {
512         struct komeda_compiz_state *st = to_compiz_st(state);
513         u32 __iomem *reg = c->reg;
514         u32 __iomem *id_reg, *cfg_reg;
515         u32 index, input_hw_id;
516
517         for_each_changed_input(state, index) {
518                 id_reg = reg + index;
519                 cfg_reg = reg + index * CU_PER_INPUT_REGS;
520                 input_hw_id = to_d71_input_id(&state->inputs[index]);
521                 if (state->active_inputs & BIT(index)) {
522                         compiz_enable_input(id_reg, cfg_reg,
523                                             input_hw_id, &st->cins[index]);
524                 } else {
525                         malidp_write32(id_reg, BLK_INPUT_ID0, 0);
526                         malidp_write32(cfg_reg, CU_INPUT0_CONTROL, 0);
527                 }
528         }
529
530         malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize));
531 }
532
533 static void d71_compiz_dump(struct komeda_component *c, struct seq_file *sf)
534 {
535         u32 v[8], i;
536
537         dump_block_header(sf, c->reg);
538
539         get_values_from_reg(c->reg, 0x80, 5, v);
540         for (i = 0; i < 5; i++)
541                 seq_printf(sf, "CU_INPUT_ID%u:\t\t0x%X\n", i, v[i]);
542
543         get_values_from_reg(c->reg, 0xA0, 5, v);
544         seq_printf(sf, "CU_IRQ_RAW_STATUS:\t0x%X\n", v[0]);
545         seq_printf(sf, "CU_IRQ_CLEAR:\t\t0x%X\n", v[1]);
546         seq_printf(sf, "CU_IRQ_MASK:\t\t0x%X\n", v[2]);
547         seq_printf(sf, "CU_IRQ_STATUS:\t\t0x%X\n", v[3]);
548         seq_printf(sf, "CU_STATUS:\t\t0x%X\n", v[4]);
549
550         get_values_from_reg(c->reg, 0xD0, 2, v);
551         seq_printf(sf, "CU_CONTROL:\t\t0x%X\n", v[0]);
552         seq_printf(sf, "CU_SIZE:\t\t0x%X\n", v[1]);
553
554         get_values_from_reg(c->reg, 0xDC, 1, v);
555         seq_printf(sf, "CU_BG_COLOR:\t\t0x%X\n", v[0]);
556
557         for (i = 0, v[4] = 0xE0; i < 5; i++, v[4] += 0x10) {
558                 get_values_from_reg(c->reg, v[4], 3, v);
559                 seq_printf(sf, "CU_INPUT%u_SIZE:\t\t0x%X\n", i, v[0]);
560                 seq_printf(sf, "CU_INPUT%u_OFFSET:\t0x%X\n", i, v[1]);
561                 seq_printf(sf, "CU_INPUT%u_CONTROL:\t0x%X\n", i, v[2]);
562         }
563
564         get_values_from_reg(c->reg, 0x130, 2, v);
565         seq_printf(sf, "CU_USER_LOW:\t\t0x%X\n", v[0]);
566         seq_printf(sf, "CU_USER_HIGH:\t\t0x%X\n", v[1]);
567 }
568
569 static const struct komeda_component_funcs d71_compiz_funcs = {
570         .update         = d71_compiz_update,
571         .disable        = d71_component_disable,
572         .dump_register  = d71_compiz_dump,
573 };
574
575 static int d71_compiz_init(struct d71_dev *d71,
576                            struct block_header *blk, u32 __iomem *reg)
577 {
578         struct komeda_component *c;
579         struct komeda_compiz *compiz;
580         u32 pipe_id, comp_id;
581
582         get_resources_id(blk->block_info, &pipe_id, &comp_id);
583
584         c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*compiz),
585                                  comp_id,
586                                  BLOCK_INFO_INPUT_ID(blk->block_info),
587                                  &d71_compiz_funcs,
588                                  CU_NUM_INPUT_IDS, get_valid_inputs(blk),
589                                  CU_NUM_OUTPUT_IDS, reg,
590                                  "CU%d", pipe_id);
591         if (IS_ERR(c))
592                 return PTR_ERR(c);
593
594         compiz = to_compiz(c);
595
596         set_range(&compiz->hsize, D71_MIN_LINE_SIZE, d71->max_line_size);
597         set_range(&compiz->vsize, D71_MIN_VERTICAL_SIZE, d71->max_vsize);
598
599         return 0;
600 }
601
602 static void d71_scaler_update_filter_lut(u32 __iomem *reg, u32 hsize_in,
603                                          u32 vsize_in, u32 hsize_out,
604                                          u32 vsize_out)
605 {
606         u32 val = 0;
607
608         if (hsize_in <= hsize_out)
609                 val  |= 0x62;
610         else if (hsize_in <= (hsize_out + hsize_out / 2))
611                 val |= 0x63;
612         else if (hsize_in <= hsize_out * 2)
613                 val |= 0x64;
614         else if (hsize_in <= hsize_out * 2 + (hsize_out * 3) / 4)
615                 val |= 0x65;
616         else
617                 val |= 0x66;
618
619         if (vsize_in <= vsize_out)
620                 val  |= SC_VTSEL(0x6A);
621         else if (vsize_in <= (vsize_out + vsize_out / 2))
622                 val |= SC_VTSEL(0x6B);
623         else if (vsize_in <= vsize_out * 2)
624                 val |= SC_VTSEL(0x6C);
625         else if (vsize_in <= vsize_out * 2 + vsize_out * 3 / 4)
626                 val |= SC_VTSEL(0x6D);
627         else
628                 val |= SC_VTSEL(0x6E);
629
630         malidp_write32(reg, SC_COEFFTAB, val);
631 }
632
633 static void d71_scaler_update(struct komeda_component *c,
634                               struct komeda_component_state *state)
635 {
636         struct komeda_scaler_state *st = to_scaler_st(state);
637         u32 __iomem *reg = c->reg;
638         u32 init_ph, delta_ph, ctrl;
639
640         d71_scaler_update_filter_lut(reg, st->hsize_in, st->vsize_in,
641                                      st->hsize_out, st->vsize_out);
642
643         malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize_in, st->vsize_in));
644         malidp_write32(reg, SC_OUT_SIZE, HV_SIZE(st->hsize_out, st->vsize_out));
645
646         init_ph = (st->hsize_in << 15) / st->hsize_out;
647         malidp_write32(reg, SC_H_INIT_PH, init_ph);
648
649         delta_ph = (st->hsize_in << 16) / st->hsize_out;
650         malidp_write32(reg, SC_H_DELTA_PH, delta_ph);
651
652         init_ph = (st->vsize_in << 15) / st->vsize_out;
653         malidp_write32(reg, SC_V_INIT_PH, init_ph);
654
655         delta_ph = (st->vsize_in << 16) / st->vsize_out;
656         malidp_write32(reg, SC_V_DELTA_PH, delta_ph);
657
658         ctrl = 0;
659         ctrl |= st->en_scaling ? SC_CTRL_SCL : 0;
660         ctrl |= st->en_alpha ? SC_CTRL_AP : 0;
661         ctrl |= st->en_img_enhancement ? SC_CTRL_IENH : 0;
662
663         malidp_write32(reg, BLK_CONTROL, ctrl);
664         malidp_write32(reg, BLK_INPUT_ID0, to_d71_input_id(&state->inputs[0]));
665 }
666
667 static void d71_scaler_dump(struct komeda_component *c, struct seq_file *sf)
668 {
669         u32 v[9];
670
671         dump_block_header(sf, c->reg);
672
673         get_values_from_reg(c->reg, 0x80, 1, v);
674         seq_printf(sf, "SC_INPUT_ID0:\t\t0x%X\n", v[0]);
675
676         get_values_from_reg(c->reg, 0xD0, 1, v);
677         seq_printf(sf, "SC_CONTROL:\t\t0x%X\n", v[0]);
678
679         get_values_from_reg(c->reg, 0xDC, 9, v);
680         seq_printf(sf, "SC_COEFFTAB:\t\t0x%X\n", v[0]);
681         seq_printf(sf, "SC_IN_SIZE:\t\t0x%X\n", v[1]);
682         seq_printf(sf, "SC_OUT_SIZE:\t\t0x%X\n", v[2]);
683         seq_printf(sf, "SC_H_CROP:\t\t0x%X\n", v[3]);
684         seq_printf(sf, "SC_V_CROP:\t\t0x%X\n", v[4]);
685         seq_printf(sf, "SC_H_INIT_PH:\t\t0x%X\n", v[5]);
686         seq_printf(sf, "SC_H_DELTA_PH:\t\t0x%X\n", v[6]);
687         seq_printf(sf, "SC_V_INIT_PH:\t\t0x%X\n", v[7]);
688         seq_printf(sf, "SC_V_DELTA_PH:\t\t0x%X\n", v[8]);
689 }
690
691 static const struct komeda_component_funcs d71_scaler_funcs = {
692         .update         = d71_scaler_update,
693         .disable        = d71_component_disable,
694         .dump_register  = d71_scaler_dump,
695 };
696
697 static int d71_scaler_init(struct d71_dev *d71,
698                            struct block_header *blk, u32 __iomem *reg)
699 {
700         struct komeda_component *c;
701         struct komeda_scaler *scaler;
702         u32 pipe_id, comp_id;
703
704         get_resources_id(blk->block_info, &pipe_id, &comp_id);
705
706         c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*scaler),
707                                  comp_id, BLOCK_INFO_INPUT_ID(blk->block_info),
708                                  &d71_scaler_funcs,
709                                  1, get_valid_inputs(blk), 1, reg,
710                                  "CU%d_SCALER%d",
711                                  pipe_id, BLOCK_INFO_BLK_ID(blk->block_info));
712
713         if (IS_ERR(c)) {
714                 DRM_ERROR("Failed to initialize scaler");
715                 return PTR_ERR(c);
716         }
717
718         scaler = to_scaler(c);
719         set_range(&scaler->hsize, 4, d71->max_line_size);
720         set_range(&scaler->vsize, 4, 4096);
721         scaler->max_downscaling = 6;
722         scaler->max_upscaling = 64;
723
724         malidp_write32(c->reg, BLK_CONTROL, 0);
725
726         return 0;
727 }
728
729 static int d71_downscaling_clk_check(struct komeda_pipeline *pipe,
730                                      struct drm_display_mode *mode,
731                                      unsigned long aclk_rate,
732                                      struct komeda_data_flow_cfg *dflow)
733 {
734         u32 h_in = dflow->in_w;
735         u32 v_in = dflow->in_h;
736         u32 v_out = dflow->out_h;
737         u64 fraction, denominator;
738
739         /* D71 downscaling must satisfy the following equation
740          *
741          *   ACLK                   h_in * v_in
742          * ------- >= ---------------------------------------------
743          *  PXLCLK     (h_total - (1 + 2 * v_in / v_out)) * v_out
744          *
745          * In only horizontal downscaling situation, the right side should be
746          * multiplied by (h_total - 3) / (h_active - 3), then equation becomes
747          *
748          *   ACLK          h_in
749          * ------- >= ----------------
750          *  PXLCLK     (h_active - 3)
751          *
752          * To avoid precision lost the equation 1 will be convert to:
753          *
754          *   ACLK             h_in * v_in
755          * ------- >= -----------------------------------
756          *  PXLCLK     (h_total -1 ) * v_out -  2 * v_in
757          */
758         if (v_in == v_out) {
759                 fraction = h_in;
760                 denominator = mode->hdisplay - 3;
761         } else {
762                 fraction = h_in * v_in;
763                 denominator = (mode->htotal - 1) * v_out -  2 * v_in;
764         }
765
766         return aclk_rate * denominator >= mode->clock * 1000 * fraction ?
767                0 : -EINVAL;
768 }
769
770 static void d71_improc_update(struct komeda_component *c,
771                               struct komeda_component_state *state)
772 {
773         struct komeda_improc_state *st = to_improc_st(state);
774         u32 __iomem *reg = c->reg;
775         u32 index, input_hw_id;
776
777         for_each_changed_input(state, index) {
778                 input_hw_id = state->active_inputs & BIT(index) ?
779                               to_d71_input_id(&state->inputs[index]) : 0;
780                 malidp_write32(reg, BLK_INPUT_ID0 + index * 4, input_hw_id);
781         }
782
783         malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize));
784 }
785
786 static void d71_improc_dump(struct komeda_component *c, struct seq_file *sf)
787 {
788         u32 v[12], i;
789
790         dump_block_header(sf, c->reg);
791
792         get_values_from_reg(c->reg, 0x80, 2, v);
793         seq_printf(sf, "IPS_INPUT_ID0:\t\t0x%X\n", v[0]);
794         seq_printf(sf, "IPS_INPUT_ID1:\t\t0x%X\n", v[1]);
795
796         get_values_from_reg(c->reg, 0xC0, 1, v);
797         seq_printf(sf, "IPS_INFO:\t\t0x%X\n", v[0]);
798
799         get_values_from_reg(c->reg, 0xD0, 3, v);
800         seq_printf(sf, "IPS_CONTROL:\t\t0x%X\n", v[0]);
801         seq_printf(sf, "IPS_SIZE:\t\t0x%X\n", v[1]);
802         seq_printf(sf, "IPS_DEPTH:\t\t0x%X\n", v[2]);
803
804         get_values_from_reg(c->reg, 0x130, 12, v);
805         for (i = 0; i < 12; i++)
806                 seq_printf(sf, "IPS_RGB_RGB_COEFF%u:\t0x%X\n", i, v[i]);
807
808         get_values_from_reg(c->reg, 0x170, 12, v);
809         for (i = 0; i < 12; i++)
810                 seq_printf(sf, "IPS_RGB_YUV_COEFF%u:\t0x%X\n", i, v[i]);
811 }
812
813 static const struct komeda_component_funcs d71_improc_funcs = {
814         .update         = d71_improc_update,
815         .disable        = d71_component_disable,
816         .dump_register  = d71_improc_dump,
817 };
818
819 static int d71_improc_init(struct d71_dev *d71,
820                            struct block_header *blk, u32 __iomem *reg)
821 {
822         struct komeda_component *c;
823         struct komeda_improc *improc;
824         u32 pipe_id, comp_id, value;
825
826         get_resources_id(blk->block_info, &pipe_id, &comp_id);
827
828         c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*improc),
829                                  comp_id,
830                                  BLOCK_INFO_INPUT_ID(blk->block_info),
831                                  &d71_improc_funcs, IPS_NUM_INPUT_IDS,
832                                  get_valid_inputs(blk),
833                                  IPS_NUM_OUTPUT_IDS, reg, "DOU%d_IPS", pipe_id);
834         if (IS_ERR(c)) {
835                 DRM_ERROR("Failed to add improc component\n");
836                 return PTR_ERR(c);
837         }
838
839         improc = to_improc(c);
840         improc->supported_color_depths = BIT(8) | BIT(10);
841         improc->supported_color_formats = DRM_COLOR_FORMAT_RGB444 |
842                                           DRM_COLOR_FORMAT_YCRCB444 |
843                                           DRM_COLOR_FORMAT_YCRCB422;
844         value = malidp_read32(reg, BLK_INFO);
845         if (value & IPS_INFO_CHD420)
846                 improc->supported_color_formats |= DRM_COLOR_FORMAT_YCRCB420;
847
848         improc->supports_csc = true;
849         improc->supports_gamma = true;
850
851         return 0;
852 }
853
854 static void d71_timing_ctrlr_disable(struct komeda_component *c)
855 {
856         malidp_write32_mask(c->reg, BLK_CONTROL, BS_CTRL_EN, 0);
857 }
858
859 static void d71_timing_ctrlr_update(struct komeda_component *c,
860                                     struct komeda_component_state *state)
861 {
862         struct drm_crtc_state *crtc_st = state->crtc->state;
863         u32 __iomem *reg = c->reg;
864         struct videomode vm;
865         u32 value;
866
867         drm_display_mode_to_videomode(&crtc_st->adjusted_mode, &vm);
868
869         malidp_write32(reg, BS_ACTIVESIZE, HV_SIZE(vm.hactive, vm.vactive));
870         malidp_write32(reg, BS_HINTERVALS, BS_H_INTVALS(vm.hfront_porch,
871                                                         vm.hback_porch));
872         malidp_write32(reg, BS_VINTERVALS, BS_V_INTVALS(vm.vfront_porch,
873                                                         vm.vback_porch));
874
875         value = BS_SYNC_VSW(vm.vsync_len) | BS_SYNC_HSW(vm.hsync_len);
876         value |= vm.flags & DISPLAY_FLAGS_VSYNC_HIGH ? BS_SYNC_VSP : 0;
877         value |= vm.flags & DISPLAY_FLAGS_HSYNC_HIGH ? BS_SYNC_HSP : 0;
878         malidp_write32(reg, BS_SYNC, value);
879
880         malidp_write32(reg, BS_PROG_LINE, D71_DEFAULT_PREPRETCH_LINE - 1);
881         malidp_write32(reg, BS_PREFETCH_LINE, D71_DEFAULT_PREPRETCH_LINE);
882
883         /* configure bs control register */
884         value = BS_CTRL_EN | BS_CTRL_VM;
885
886         malidp_write32(reg, BLK_CONTROL, value);
887 }
888
889 static void d71_timing_ctrlr_dump(struct komeda_component *c,
890                                   struct seq_file *sf)
891 {
892         u32 v[8], i;
893
894         dump_block_header(sf, c->reg);
895
896         get_values_from_reg(c->reg, 0xC0, 1, v);
897         seq_printf(sf, "BS_INFO:\t\t0x%X\n", v[0]);
898
899         get_values_from_reg(c->reg, 0xD0, 8, v);
900         seq_printf(sf, "BS_CONTROL:\t\t0x%X\n", v[0]);
901         seq_printf(sf, "BS_PROG_LINE:\t\t0x%X\n", v[1]);
902         seq_printf(sf, "BS_PREFETCH_LINE:\t0x%X\n", v[2]);
903         seq_printf(sf, "BS_BG_COLOR:\t\t0x%X\n", v[3]);
904         seq_printf(sf, "BS_ACTIVESIZE:\t\t0x%X\n", v[4]);
905         seq_printf(sf, "BS_HINTERVALS:\t\t0x%X\n", v[5]);
906         seq_printf(sf, "BS_VINTERVALS:\t\t0x%X\n", v[6]);
907         seq_printf(sf, "BS_SYNC:\t\t0x%X\n", v[7]);
908
909         get_values_from_reg(c->reg, 0x100, 3, v);
910         seq_printf(sf, "BS_DRIFT_TO:\t\t0x%X\n", v[0]);
911         seq_printf(sf, "BS_FRAME_TO:\t\t0x%X\n", v[1]);
912         seq_printf(sf, "BS_TE_TO:\t\t0x%X\n", v[2]);
913
914         get_values_from_reg(c->reg, 0x110, 3, v);
915         for (i = 0; i < 3; i++)
916                 seq_printf(sf, "BS_T%u_INTERVAL:\t\t0x%X\n", i, v[i]);
917
918         get_values_from_reg(c->reg, 0x120, 5, v);
919         for (i = 0; i < 2; i++) {
920                 seq_printf(sf, "BS_CRC%u_LOW:\t\t0x%X\n", i, v[i << 1]);
921                 seq_printf(sf, "BS_CRC%u_HIGH:\t\t0x%X\n", i, v[(i << 1) + 1]);
922         }
923         seq_printf(sf, "BS_USER:\t\t0x%X\n", v[4]);
924 }
925
926 static const struct komeda_component_funcs d71_timing_ctrlr_funcs = {
927         .update         = d71_timing_ctrlr_update,
928         .disable        = d71_timing_ctrlr_disable,
929         .dump_register  = d71_timing_ctrlr_dump,
930 };
931
932 static int d71_timing_ctrlr_init(struct d71_dev *d71,
933                                  struct block_header *blk, u32 __iomem *reg)
934 {
935         struct komeda_component *c;
936         struct komeda_timing_ctrlr *ctrlr;
937         u32 pipe_id, comp_id;
938
939         get_resources_id(blk->block_info, &pipe_id, &comp_id);
940
941         c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*ctrlr),
942                                  KOMEDA_COMPONENT_TIMING_CTRLR,
943                                  BLOCK_INFO_INPUT_ID(blk->block_info),
944                                  &d71_timing_ctrlr_funcs,
945                                  1, BIT(KOMEDA_COMPONENT_IPS0 + pipe_id),
946                                  BS_NUM_OUTPUT_IDS, reg, "DOU%d_BS", pipe_id);
947         if (IS_ERR(c)) {
948                 DRM_ERROR("Failed to add display_ctrl component\n");
949                 return PTR_ERR(c);
950         }
951
952         ctrlr = to_ctrlr(c);
953
954         ctrlr->supports_dual_link = true;
955
956         return 0;
957 }
958
959 int d71_probe_block(struct d71_dev *d71,
960                     struct block_header *blk, u32 __iomem *reg)
961 {
962         struct d71_pipeline *pipe;
963         int blk_id = BLOCK_INFO_BLK_ID(blk->block_info);
964
965         int err = 0;
966
967         switch (BLOCK_INFO_BLK_TYPE(blk->block_info)) {
968         case D71_BLK_TYPE_GCU:
969                 break;
970
971         case D71_BLK_TYPE_LPU:
972                 pipe = d71->pipes[blk_id];
973                 pipe->lpu_addr = reg;
974                 break;
975
976         case D71_BLK_TYPE_LPU_LAYER:
977                 err = d71_layer_init(d71, blk, reg);
978                 break;
979
980         case D71_BLK_TYPE_LPU_WB_LAYER:
981                 err = d71_wb_layer_init(d71, blk, reg);
982                 break;
983
984         case D71_BLK_TYPE_CU:
985                 pipe = d71->pipes[blk_id];
986                 pipe->cu_addr = reg;
987                 err = d71_compiz_init(d71, blk, reg);
988                 break;
989
990         case D71_BLK_TYPE_CU_SCALER:
991                 err = d71_scaler_init(d71, blk, reg);
992                 break;
993
994         case D71_BLK_TYPE_CU_SPLITTER:
995         case D71_BLK_TYPE_CU_MERGER:
996                 break;
997
998         case D71_BLK_TYPE_DOU:
999                 pipe = d71->pipes[blk_id];
1000                 pipe->dou_addr = reg;
1001                 break;
1002
1003         case D71_BLK_TYPE_DOU_IPS:
1004                 err = d71_improc_init(d71, blk, reg);
1005                 break;
1006
1007         case D71_BLK_TYPE_DOU_FT_COEFF:
1008                 pipe = d71->pipes[blk_id];
1009                 pipe->dou_ft_coeff_addr = reg;
1010                 break;
1011
1012         case D71_BLK_TYPE_DOU_BS:
1013                 err = d71_timing_ctrlr_init(d71, blk, reg);
1014                 break;
1015
1016         case D71_BLK_TYPE_GLB_LT_COEFF:
1017                 break;
1018
1019         case D71_BLK_TYPE_GLB_SCL_COEFF:
1020                 d71->glb_scl_coeff_addr[blk_id] = reg;
1021                 break;
1022
1023         default:
1024                 DRM_ERROR("Unknown block (block_info: 0x%x) is found\n",
1025                           blk->block_info);
1026                 err = -EINVAL;
1027                 break;
1028         }
1029
1030         return err;
1031 }
1032
1033 const struct komeda_pipeline_funcs d71_pipeline_funcs = {
1034         .downscaling_clk_check = d71_downscaling_clk_check,
1035 };