]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
drm/komeda: Refine function to_d71_input_id
[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_state *st, int idx)
160 {
161         struct komeda_component_output *input = &st->inputs[idx];
162
163         /* if input is not active, set hw input_id(0) to disable it */
164         if (has_bit(idx, st->active_inputs))
165                 return input->component->hw_id + input->output_port;
166         else
167                 return 0;
168 }
169
170 static void d71_layer_update_fb(struct komeda_component *c,
171                                 struct komeda_fb *kfb,
172                                 dma_addr_t *addr)
173 {
174         struct drm_framebuffer *fb = &kfb->base;
175         const struct drm_format_info *info = fb->format;
176         u32 __iomem *reg = c->reg;
177         int block_h;
178
179         if (info->num_planes > 2)
180                 malidp_write64(reg, BLK_P2_PTR_LOW, addr[2]);
181
182         if (info->num_planes > 1) {
183                 block_h = drm_format_info_block_height(info, 1);
184                 malidp_write32(reg, BLK_P1_STRIDE, fb->pitches[1] * block_h);
185                 malidp_write64(reg, BLK_P1_PTR_LOW, addr[1]);
186         }
187
188         block_h = drm_format_info_block_height(info, 0);
189         malidp_write32(reg, BLK_P0_STRIDE, fb->pitches[0] * block_h);
190         malidp_write64(reg, BLK_P0_PTR_LOW, addr[0]);
191         malidp_write32(reg, LAYER_FMT, kfb->format_caps->hw_id);
192 }
193
194 static void d71_layer_disable(struct komeda_component *c)
195 {
196         malidp_write32_mask(c->reg, BLK_CONTROL, L_EN, 0);
197 }
198
199 static void d71_layer_update(struct komeda_component *c,
200                              struct komeda_component_state *state)
201 {
202         struct komeda_layer_state *st = to_layer_st(state);
203         struct drm_plane_state *plane_st = state->plane->state;
204         struct drm_framebuffer *fb = plane_st->fb;
205         struct komeda_fb *kfb = to_kfb(fb);
206         u32 __iomem *reg = c->reg;
207         u32 ctrl_mask = L_EN | L_ROT(L_ROT_R270) | L_HFLIP | L_VFLIP | L_TBU_EN;
208         u32 ctrl = L_EN | to_rot_ctrl(st->rot);
209
210         d71_layer_update_fb(c, kfb, st->addr);
211
212         malidp_write32(reg, AD_CONTROL, to_ad_ctrl(fb->modifier));
213         if (fb->modifier) {
214                 u64 addr;
215
216                 malidp_write32(reg, LAYER_AD_H_CROP, HV_CROP(st->afbc_crop_l,
217                                                              st->afbc_crop_r));
218                 malidp_write32(reg, LAYER_AD_V_CROP, HV_CROP(st->afbc_crop_t,
219                                                              st->afbc_crop_b));
220                 /* afbc 1.2 wants payload, afbc 1.0/1.1 wants end_addr */
221                 if (fb->modifier & AFBC_FORMAT_MOD_TILED)
222                         addr = st->addr[0] + kfb->offset_payload;
223                 else
224                         addr = st->addr[0] + kfb->afbc_size - 1;
225
226                 malidp_write32(reg, BLK_P1_PTR_LOW, lower_32_bits(addr));
227                 malidp_write32(reg, BLK_P1_PTR_HIGH, upper_32_bits(addr));
228         }
229
230         if (fb->format->is_yuv) {
231                 u32 upsampling = 0;
232
233                 switch (kfb->format_caps->fourcc) {
234                 case DRM_FORMAT_YUYV:
235                         upsampling = fb->modifier ? LR_CHI422_BILINEAR :
236                                      LR_CHI422_REPLICATION;
237                         break;
238                 case DRM_FORMAT_UYVY:
239                         upsampling = LR_CHI422_REPLICATION;
240                         break;
241                 case DRM_FORMAT_NV12:
242                 case DRM_FORMAT_YUV420_8BIT:
243                 case DRM_FORMAT_YUV420_10BIT:
244                 case DRM_FORMAT_YUV420:
245                 case DRM_FORMAT_P010:
246                 /* these fmt support MPGE/JPEG both, here perfer JPEG*/
247                         upsampling = LR_CHI420_JPEG;
248                         break;
249                 case DRM_FORMAT_X0L2:
250                         upsampling = LR_CHI420_JPEG;
251                         break;
252                 default:
253                         break;
254                 }
255
256                 malidp_write32(reg, LAYER_R_CONTROL, upsampling);
257                 malidp_write_group(reg, LAYER_YUV_RGB_COEFF0,
258                                    KOMEDA_N_YUV2RGB_COEFFS,
259                                    komeda_select_yuv2rgb_coeffs(
260                                         plane_st->color_encoding,
261                                         plane_st->color_range));
262         }
263
264         malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize, st->vsize));
265
266         if (kfb->is_va)
267                 ctrl |= L_TBU_EN;
268         malidp_write32_mask(reg, BLK_CONTROL, ctrl_mask, ctrl);
269 }
270
271 static void d71_layer_dump(struct komeda_component *c, struct seq_file *sf)
272 {
273         u32 v[15], i;
274         bool rich, rgb2rgb;
275         char *prefix;
276
277         get_values_from_reg(c->reg, LAYER_INFO, 1, &v[14]);
278         if (v[14] & 0x1) {
279                 rich = true;
280                 prefix = "LR_";
281         } else {
282                 rich = false;
283                 prefix = "LS_";
284         }
285
286         rgb2rgb = !!(v[14] & L_INFO_CM);
287
288         dump_block_header(sf, c->reg);
289
290         seq_printf(sf, "%sLAYER_INFO:\t\t0x%X\n", prefix, v[14]);
291
292         get_values_from_reg(c->reg, 0xD0, 1, v);
293         seq_printf(sf, "%sCONTROL:\t\t0x%X\n", prefix, v[0]);
294         if (rich) {
295                 get_values_from_reg(c->reg, 0xD4, 1, v);
296                 seq_printf(sf, "LR_RICH_CONTROL:\t0x%X\n", v[0]);
297         }
298         get_values_from_reg(c->reg, 0xD8, 4, v);
299         seq_printf(sf, "%sFORMAT:\t\t0x%X\n", prefix, v[0]);
300         seq_printf(sf, "%sIT_COEFFTAB:\t\t0x%X\n", prefix, v[1]);
301         seq_printf(sf, "%sIN_SIZE:\t\t0x%X\n", prefix, v[2]);
302         seq_printf(sf, "%sPALPHA:\t\t0x%X\n", prefix, v[3]);
303
304         get_values_from_reg(c->reg, 0x100, 3, v);
305         seq_printf(sf, "%sP0_PTR_LOW:\t\t0x%X\n", prefix, v[0]);
306         seq_printf(sf, "%sP0_PTR_HIGH:\t\t0x%X\n", prefix, v[1]);
307         seq_printf(sf, "%sP0_STRIDE:\t\t0x%X\n", prefix, v[2]);
308
309         get_values_from_reg(c->reg, 0x110, 2, v);
310         seq_printf(sf, "%sP1_PTR_LOW:\t\t0x%X\n", prefix, v[0]);
311         seq_printf(sf, "%sP1_PTR_HIGH:\t\t0x%X\n", prefix, v[1]);
312         if (rich) {
313                 get_values_from_reg(c->reg, 0x118, 1, v);
314                 seq_printf(sf, "LR_P1_STRIDE:\t\t0x%X\n", v[0]);
315
316                 get_values_from_reg(c->reg, 0x120, 2, v);
317                 seq_printf(sf, "LR_P2_PTR_LOW:\t\t0x%X\n", v[0]);
318                 seq_printf(sf, "LR_P2_PTR_HIGH:\t\t0x%X\n", v[1]);
319
320                 get_values_from_reg(c->reg, 0x130, 12, v);
321                 for (i = 0; i < 12; i++)
322                         seq_printf(sf, "LR_YUV_RGB_COEFF%u:\t0x%X\n", i, v[i]);
323         }
324
325         if (rgb2rgb) {
326                 get_values_from_reg(c->reg, LAYER_RGB_RGB_COEFF0, 12, v);
327                 for (i = 0; i < 12; i++)
328                         seq_printf(sf, "LS_RGB_RGB_COEFF%u:\t0x%X\n", i, v[i]);
329         }
330
331         get_values_from_reg(c->reg, 0x160, 3, v);
332         seq_printf(sf, "%sAD_CONTROL:\t\t0x%X\n", prefix, v[0]);
333         seq_printf(sf, "%sAD_H_CROP:\t\t0x%X\n", prefix, v[1]);
334         seq_printf(sf, "%sAD_V_CROP:\t\t0x%X\n", prefix, v[2]);
335 }
336
337 static const struct komeda_component_funcs d71_layer_funcs = {
338         .update         = d71_layer_update,
339         .disable        = d71_layer_disable,
340         .dump_register  = d71_layer_dump,
341 };
342
343 static int d71_layer_init(struct d71_dev *d71,
344                           struct block_header *blk, u32 __iomem *reg)
345 {
346         struct komeda_component *c;
347         struct komeda_layer *layer;
348         u32 pipe_id, layer_id, layer_info;
349
350         get_resources_id(blk->block_info, &pipe_id, &layer_id);
351         c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*layer),
352                                  layer_id,
353                                  BLOCK_INFO_INPUT_ID(blk->block_info),
354                                  &d71_layer_funcs, 0,
355                                  get_valid_inputs(blk),
356                                  1, reg, "LPU%d_LAYER%d", pipe_id, layer_id);
357         if (IS_ERR(c)) {
358                 DRM_ERROR("Failed to add layer component\n");
359                 return PTR_ERR(c);
360         }
361
362         layer = to_layer(c);
363         layer_info = malidp_read32(reg, LAYER_INFO);
364
365         if (layer_info & L_INFO_RF)
366                 layer->layer_type = KOMEDA_FMT_RICH_LAYER;
367         else
368                 layer->layer_type = KOMEDA_FMT_SIMPLE_LAYER;
369
370         set_range(&layer->hsize_in, 4, d71->max_line_size);
371         set_range(&layer->vsize_in, 4, d71->max_vsize);
372
373         malidp_write32(reg, LAYER_PALPHA, D71_PALPHA_DEF_MAP);
374
375         layer->supported_rots = DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK;
376
377         return 0;
378 }
379
380 static void d71_wb_layer_update(struct komeda_component *c,
381                                 struct komeda_component_state *state)
382 {
383         struct komeda_layer_state *st = to_layer_st(state);
384         struct drm_connector_state *conn_st = state->wb_conn->state;
385         struct komeda_fb *kfb = to_kfb(conn_st->writeback_job->fb);
386         u32 ctrl = L_EN | LW_OFM, mask = L_EN | LW_OFM | LW_TBU_EN;
387         u32 __iomem *reg = c->reg;
388
389         d71_layer_update_fb(c, kfb, st->addr);
390
391         if (kfb->is_va)
392                 ctrl |= LW_TBU_EN;
393
394         malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize, st->vsize));
395         malidp_write32(reg, BLK_INPUT_ID0, to_d71_input_id(state, 0));
396         malidp_write32_mask(reg, BLK_CONTROL, mask, ctrl);
397 }
398
399 static void d71_wb_layer_dump(struct komeda_component *c, struct seq_file *sf)
400 {
401         u32 v[12], i;
402
403         dump_block_header(sf, c->reg);
404
405         get_values_from_reg(c->reg, 0x80, 1, v);
406         seq_printf(sf, "LW_INPUT_ID0:\t\t0x%X\n", v[0]);
407
408         get_values_from_reg(c->reg, 0xD0, 3, v);
409         seq_printf(sf, "LW_CONTROL:\t\t0x%X\n", v[0]);
410         seq_printf(sf, "LW_PROG_LINE:\t\t0x%X\n", v[1]);
411         seq_printf(sf, "LW_FORMAT:\t\t0x%X\n", v[2]);
412
413         get_values_from_reg(c->reg, 0xE0, 1, v);
414         seq_printf(sf, "LW_IN_SIZE:\t\t0x%X\n", v[0]);
415
416         for (i = 0; i < 2; i++) {
417                 get_values_from_reg(c->reg, 0x100 + i * 0x10, 3, v);
418                 seq_printf(sf, "LW_P%u_PTR_LOW:\t\t0x%X\n", i, v[0]);
419                 seq_printf(sf, "LW_P%u_PTR_HIGH:\t\t0x%X\n", i, v[1]);
420                 seq_printf(sf, "LW_P%u_STRIDE:\t\t0x%X\n", i, v[2]);
421         }
422
423         get_values_from_reg(c->reg, 0x130, 12, v);
424         for (i = 0; i < 12; i++)
425                 seq_printf(sf, "LW_RGB_YUV_COEFF%u:\t0x%X\n", i, v[i]);
426 }
427
428 static void d71_wb_layer_disable(struct komeda_component *c)
429 {
430         malidp_write32(c->reg, BLK_INPUT_ID0, 0);
431         malidp_write32_mask(c->reg, BLK_CONTROL, L_EN, 0);
432 }
433
434 static const struct komeda_component_funcs d71_wb_layer_funcs = {
435         .update         = d71_wb_layer_update,
436         .disable        = d71_wb_layer_disable,
437         .dump_register  = d71_wb_layer_dump,
438 };
439
440 static int d71_wb_layer_init(struct d71_dev *d71,
441                              struct block_header *blk, u32 __iomem *reg)
442 {
443         struct komeda_component *c;
444         struct komeda_layer *wb_layer;
445         u32 pipe_id, layer_id;
446
447         get_resources_id(blk->block_info, &pipe_id, &layer_id);
448
449         c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*wb_layer),
450                                  layer_id, BLOCK_INFO_INPUT_ID(blk->block_info),
451                                  &d71_wb_layer_funcs,
452                                  1, get_valid_inputs(blk), 0, reg,
453                                  "LPU%d_LAYER_WR", pipe_id);
454         if (IS_ERR(c)) {
455                 DRM_ERROR("Failed to add wb_layer component\n");
456                 return PTR_ERR(c);
457         }
458
459         wb_layer = to_layer(c);
460         wb_layer->layer_type = KOMEDA_FMT_WB_LAYER;
461
462         set_range(&wb_layer->hsize_in, D71_MIN_LINE_SIZE, d71->max_line_size);
463         set_range(&wb_layer->vsize_in, D71_MIN_VERTICAL_SIZE, d71->max_vsize);
464
465         return 0;
466 }
467
468 static void d71_component_disable(struct komeda_component *c)
469 {
470         u32 __iomem *reg = c->reg;
471         u32 i;
472
473         malidp_write32(reg, BLK_CONTROL, 0);
474
475         for (i = 0; i < c->max_active_inputs; i++) {
476                 malidp_write32(reg, BLK_INPUT_ID0 + (i << 2), 0);
477
478                 /* Besides clearing the input ID to zero, D71 compiz also has
479                  * input enable bit in CU_INPUTx_CONTROL which need to be
480                  * cleared.
481                  */
482                 if (has_bit(c->id, KOMEDA_PIPELINE_COMPIZS))
483                         malidp_write32(reg, CU_INPUT0_CONTROL +
484                                        i * CU_PER_INPUT_REGS * 4,
485                                        CU_INPUT_CTRL_ALPHA(0xFF));
486         }
487 }
488
489 static void compiz_enable_input(u32 __iomem *id_reg,
490                                 u32 __iomem *cfg_reg,
491                                 u32 input_hw_id,
492                                 struct komeda_compiz_input_cfg *cin)
493 {
494         u32 ctrl = CU_INPUT_CTRL_EN;
495         u8 blend = cin->pixel_blend_mode;
496
497         if (blend == DRM_MODE_BLEND_PIXEL_NONE)
498                 ctrl |= CU_INPUT_CTRL_PAD;
499         else if (blend == DRM_MODE_BLEND_PREMULTI)
500                 ctrl |= CU_INPUT_CTRL_PMUL;
501
502         ctrl |= CU_INPUT_CTRL_ALPHA(cin->layer_alpha);
503
504         malidp_write32(id_reg, BLK_INPUT_ID0, input_hw_id);
505
506         malidp_write32(cfg_reg, CU_INPUT0_SIZE,
507                        HV_SIZE(cin->hsize, cin->vsize));
508         malidp_write32(cfg_reg, CU_INPUT0_OFFSET,
509                        HV_OFFSET(cin->hoffset, cin->voffset));
510         malidp_write32(cfg_reg, CU_INPUT0_CONTROL, ctrl);
511 }
512
513 static void d71_compiz_update(struct komeda_component *c,
514                               struct komeda_component_state *state)
515 {
516         struct komeda_compiz_state *st = to_compiz_st(state);
517         u32 __iomem *reg = c->reg;
518         u32 __iomem *id_reg, *cfg_reg;
519         u32 index;
520
521         for_each_changed_input(state, index) {
522                 id_reg = reg + index;
523                 cfg_reg = reg + index * CU_PER_INPUT_REGS;
524                 if (state->active_inputs & BIT(index)) {
525                         compiz_enable_input(id_reg, cfg_reg,
526                                             to_d71_input_id(state, index),
527                                             &st->cins[index]);
528                 } else {
529                         malidp_write32(id_reg, BLK_INPUT_ID0, 0);
530                         malidp_write32(cfg_reg, CU_INPUT0_CONTROL, 0);
531                 }
532         }
533
534         malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize));
535 }
536
537 static void d71_compiz_dump(struct komeda_component *c, struct seq_file *sf)
538 {
539         u32 v[8], i;
540
541         dump_block_header(sf, c->reg);
542
543         get_values_from_reg(c->reg, 0x80, 5, v);
544         for (i = 0; i < 5; i++)
545                 seq_printf(sf, "CU_INPUT_ID%u:\t\t0x%X\n", i, v[i]);
546
547         get_values_from_reg(c->reg, 0xA0, 5, v);
548         seq_printf(sf, "CU_IRQ_RAW_STATUS:\t0x%X\n", v[0]);
549         seq_printf(sf, "CU_IRQ_CLEAR:\t\t0x%X\n", v[1]);
550         seq_printf(sf, "CU_IRQ_MASK:\t\t0x%X\n", v[2]);
551         seq_printf(sf, "CU_IRQ_STATUS:\t\t0x%X\n", v[3]);
552         seq_printf(sf, "CU_STATUS:\t\t0x%X\n", v[4]);
553
554         get_values_from_reg(c->reg, 0xD0, 2, v);
555         seq_printf(sf, "CU_CONTROL:\t\t0x%X\n", v[0]);
556         seq_printf(sf, "CU_SIZE:\t\t0x%X\n", v[1]);
557
558         get_values_from_reg(c->reg, 0xDC, 1, v);
559         seq_printf(sf, "CU_BG_COLOR:\t\t0x%X\n", v[0]);
560
561         for (i = 0, v[4] = 0xE0; i < 5; i++, v[4] += 0x10) {
562                 get_values_from_reg(c->reg, v[4], 3, v);
563                 seq_printf(sf, "CU_INPUT%u_SIZE:\t\t0x%X\n", i, v[0]);
564                 seq_printf(sf, "CU_INPUT%u_OFFSET:\t0x%X\n", i, v[1]);
565                 seq_printf(sf, "CU_INPUT%u_CONTROL:\t0x%X\n", i, v[2]);
566         }
567
568         get_values_from_reg(c->reg, 0x130, 2, v);
569         seq_printf(sf, "CU_USER_LOW:\t\t0x%X\n", v[0]);
570         seq_printf(sf, "CU_USER_HIGH:\t\t0x%X\n", v[1]);
571 }
572
573 static const struct komeda_component_funcs d71_compiz_funcs = {
574         .update         = d71_compiz_update,
575         .disable        = d71_component_disable,
576         .dump_register  = d71_compiz_dump,
577 };
578
579 static int d71_compiz_init(struct d71_dev *d71,
580                            struct block_header *blk, u32 __iomem *reg)
581 {
582         struct komeda_component *c;
583         struct komeda_compiz *compiz;
584         u32 pipe_id, comp_id;
585
586         get_resources_id(blk->block_info, &pipe_id, &comp_id);
587
588         c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*compiz),
589                                  comp_id,
590                                  BLOCK_INFO_INPUT_ID(blk->block_info),
591                                  &d71_compiz_funcs,
592                                  CU_NUM_INPUT_IDS, get_valid_inputs(blk),
593                                  CU_NUM_OUTPUT_IDS, reg,
594                                  "CU%d", pipe_id);
595         if (IS_ERR(c))
596                 return PTR_ERR(c);
597
598         compiz = to_compiz(c);
599
600         set_range(&compiz->hsize, D71_MIN_LINE_SIZE, d71->max_line_size);
601         set_range(&compiz->vsize, D71_MIN_VERTICAL_SIZE, d71->max_vsize);
602
603         return 0;
604 }
605
606 static void d71_scaler_update_filter_lut(u32 __iomem *reg, u32 hsize_in,
607                                          u32 vsize_in, u32 hsize_out,
608                                          u32 vsize_out)
609 {
610         u32 val = 0;
611
612         if (hsize_in <= hsize_out)
613                 val  |= 0x62;
614         else if (hsize_in <= (hsize_out + hsize_out / 2))
615                 val |= 0x63;
616         else if (hsize_in <= hsize_out * 2)
617                 val |= 0x64;
618         else if (hsize_in <= hsize_out * 2 + (hsize_out * 3) / 4)
619                 val |= 0x65;
620         else
621                 val |= 0x66;
622
623         if (vsize_in <= vsize_out)
624                 val  |= SC_VTSEL(0x6A);
625         else if (vsize_in <= (vsize_out + vsize_out / 2))
626                 val |= SC_VTSEL(0x6B);
627         else if (vsize_in <= vsize_out * 2)
628                 val |= SC_VTSEL(0x6C);
629         else if (vsize_in <= vsize_out * 2 + vsize_out * 3 / 4)
630                 val |= SC_VTSEL(0x6D);
631         else
632                 val |= SC_VTSEL(0x6E);
633
634         malidp_write32(reg, SC_COEFFTAB, val);
635 }
636
637 static void d71_scaler_update(struct komeda_component *c,
638                               struct komeda_component_state *state)
639 {
640         struct komeda_scaler_state *st = to_scaler_st(state);
641         u32 __iomem *reg = c->reg;
642         u32 init_ph, delta_ph, ctrl;
643
644         d71_scaler_update_filter_lut(reg, st->hsize_in, st->vsize_in,
645                                      st->hsize_out, st->vsize_out);
646
647         malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize_in, st->vsize_in));
648         malidp_write32(reg, SC_OUT_SIZE, HV_SIZE(st->hsize_out, st->vsize_out));
649         malidp_write32(reg, SC_H_CROP, HV_CROP(st->left_crop, st->right_crop));
650
651         /* for right part, HW only sample the valid pixel which means the pixels
652          * in left_crop will be jumpped, and the first sample pixel is:
653          *
654          * dst_a = st->total_hsize_out - st->hsize_out + st->left_crop + 0.5;
655          *
656          * Then the corresponding texel in src is:
657          *
658          * h_delta_phase = st->total_hsize_in / st->total_hsize_out;
659          * src_a = dst_A * h_delta_phase;
660          *
661          * and h_init_phase is src_a deduct the real source start src_S;
662          *
663          * src_S = st->total_hsize_in - st->hsize_in;
664          * h_init_phase = src_a - src_S;
665          *
666          * And HW precision for the initial/delta_phase is 16:16 fixed point,
667          * the following is the simplified formula
668          */
669         if (st->right_part) {
670                 u32 dst_a = st->total_hsize_out - st->hsize_out + st->left_crop;
671
672                 if (st->en_img_enhancement)
673                         dst_a -= 1;
674
675                 init_ph = ((st->total_hsize_in * (2 * dst_a + 1) -
676                             2 * st->total_hsize_out * (st->total_hsize_in -
677                             st->hsize_in)) << 15) / st->total_hsize_out;
678         } else {
679                 init_ph = (st->total_hsize_in << 15) / st->total_hsize_out;
680         }
681
682         malidp_write32(reg, SC_H_INIT_PH, init_ph);
683
684         delta_ph = (st->total_hsize_in << 16) / st->total_hsize_out;
685         malidp_write32(reg, SC_H_DELTA_PH, delta_ph);
686
687         init_ph = (st->total_vsize_in << 15) / st->vsize_out;
688         malidp_write32(reg, SC_V_INIT_PH, init_ph);
689
690         delta_ph = (st->total_vsize_in << 16) / st->vsize_out;
691         malidp_write32(reg, SC_V_DELTA_PH, delta_ph);
692
693         ctrl = 0;
694         ctrl |= st->en_scaling ? SC_CTRL_SCL : 0;
695         ctrl |= st->en_alpha ? SC_CTRL_AP : 0;
696         ctrl |= st->en_img_enhancement ? SC_CTRL_IENH : 0;
697         /* If we use the hardware splitter we shouldn't set SC_CTRL_LS */
698         if (st->en_split &&
699             state->inputs[0].component->id != KOMEDA_COMPONENT_SPLITTER)
700                 ctrl |= SC_CTRL_LS;
701
702         malidp_write32(reg, BLK_CONTROL, ctrl);
703         malidp_write32(reg, BLK_INPUT_ID0, to_d71_input_id(state, 0));
704 }
705
706 static void d71_scaler_dump(struct komeda_component *c, struct seq_file *sf)
707 {
708         u32 v[9];
709
710         dump_block_header(sf, c->reg);
711
712         get_values_from_reg(c->reg, 0x80, 1, v);
713         seq_printf(sf, "SC_INPUT_ID0:\t\t0x%X\n", v[0]);
714
715         get_values_from_reg(c->reg, 0xD0, 1, v);
716         seq_printf(sf, "SC_CONTROL:\t\t0x%X\n", v[0]);
717
718         get_values_from_reg(c->reg, 0xDC, 9, v);
719         seq_printf(sf, "SC_COEFFTAB:\t\t0x%X\n", v[0]);
720         seq_printf(sf, "SC_IN_SIZE:\t\t0x%X\n", v[1]);
721         seq_printf(sf, "SC_OUT_SIZE:\t\t0x%X\n", v[2]);
722         seq_printf(sf, "SC_H_CROP:\t\t0x%X\n", v[3]);
723         seq_printf(sf, "SC_V_CROP:\t\t0x%X\n", v[4]);
724         seq_printf(sf, "SC_H_INIT_PH:\t\t0x%X\n", v[5]);
725         seq_printf(sf, "SC_H_DELTA_PH:\t\t0x%X\n", v[6]);
726         seq_printf(sf, "SC_V_INIT_PH:\t\t0x%X\n", v[7]);
727         seq_printf(sf, "SC_V_DELTA_PH:\t\t0x%X\n", v[8]);
728 }
729
730 static const struct komeda_component_funcs d71_scaler_funcs = {
731         .update         = d71_scaler_update,
732         .disable        = d71_component_disable,
733         .dump_register  = d71_scaler_dump,
734 };
735
736 static int d71_scaler_init(struct d71_dev *d71,
737                            struct block_header *blk, u32 __iomem *reg)
738 {
739         struct komeda_component *c;
740         struct komeda_scaler *scaler;
741         u32 pipe_id, comp_id;
742
743         get_resources_id(blk->block_info, &pipe_id, &comp_id);
744
745         c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*scaler),
746                                  comp_id, BLOCK_INFO_INPUT_ID(blk->block_info),
747                                  &d71_scaler_funcs,
748                                  1, get_valid_inputs(blk), 1, reg,
749                                  "CU%d_SCALER%d",
750                                  pipe_id, BLOCK_INFO_BLK_ID(blk->block_info));
751
752         if (IS_ERR(c)) {
753                 DRM_ERROR("Failed to initialize scaler");
754                 return PTR_ERR(c);
755         }
756
757         scaler = to_scaler(c);
758         set_range(&scaler->hsize, 4, 2048);
759         set_range(&scaler->vsize, 4, 4096);
760         scaler->max_downscaling = 6;
761         scaler->max_upscaling = 64;
762         scaler->scaling_split_overlap = 8;
763         scaler->enh_split_overlap = 1;
764
765         malidp_write32(c->reg, BLK_CONTROL, 0);
766
767         return 0;
768 }
769
770 static int d71_downscaling_clk_check(struct komeda_pipeline *pipe,
771                                      struct drm_display_mode *mode,
772                                      unsigned long aclk_rate,
773                                      struct komeda_data_flow_cfg *dflow)
774 {
775         u32 h_in = dflow->in_w;
776         u32 v_in = dflow->in_h;
777         u32 v_out = dflow->out_h;
778         u64 fraction, denominator;
779
780         /* D71 downscaling must satisfy the following equation
781          *
782          *   ACLK                   h_in * v_in
783          * ------- >= ---------------------------------------------
784          *  PXLCLK     (h_total - (1 + 2 * v_in / v_out)) * v_out
785          *
786          * In only horizontal downscaling situation, the right side should be
787          * multiplied by (h_total - 3) / (h_active - 3), then equation becomes
788          *
789          *   ACLK          h_in
790          * ------- >= ----------------
791          *  PXLCLK     (h_active - 3)
792          *
793          * To avoid precision lost the equation 1 will be convert to:
794          *
795          *   ACLK             h_in * v_in
796          * ------- >= -----------------------------------
797          *  PXLCLK     (h_total -1 ) * v_out -  2 * v_in
798          */
799         if (v_in == v_out) {
800                 fraction = h_in;
801                 denominator = mode->hdisplay - 3;
802         } else {
803                 fraction = h_in * v_in;
804                 denominator = (mode->htotal - 1) * v_out -  2 * v_in;
805         }
806
807         return aclk_rate * denominator >= mode->clock * 1000 * fraction ?
808                0 : -EINVAL;
809 }
810
811 static void d71_merger_update(struct komeda_component *c,
812                               struct komeda_component_state *state)
813 {
814         struct komeda_merger_state *st = to_merger_st(state);
815         u32 __iomem *reg = c->reg;
816         u32 index;
817
818         for_each_changed_input(state, index)
819                 malidp_write32(reg, MG_INPUT_ID0 + index * 4,
820                                to_d71_input_id(state, index));
821
822         malidp_write32(reg, MG_SIZE, HV_SIZE(st->hsize_merged,
823                                              st->vsize_merged));
824         malidp_write32(reg, BLK_CONTROL, BLK_CTRL_EN);
825 }
826
827 static void d71_merger_dump(struct komeda_component *c, struct seq_file *sf)
828 {
829         u32 v;
830
831         dump_block_header(sf, c->reg);
832
833         get_values_from_reg(c->reg, MG_INPUT_ID0, 1, &v);
834         seq_printf(sf, "MG_INPUT_ID0:\t\t0x%X\n", v);
835
836         get_values_from_reg(c->reg, MG_INPUT_ID1, 1, &v);
837         seq_printf(sf, "MG_INPUT_ID1:\t\t0x%X\n", v);
838
839         get_values_from_reg(c->reg, BLK_CONTROL, 1, &v);
840         seq_printf(sf, "MG_CONTROL:\t\t0x%X\n", v);
841
842         get_values_from_reg(c->reg, MG_SIZE, 1, &v);
843         seq_printf(sf, "MG_SIZE:\t\t0x%X\n", v);
844 }
845
846 static const struct komeda_component_funcs d71_merger_funcs = {
847         .update         = d71_merger_update,
848         .disable        = d71_component_disable,
849         .dump_register  = d71_merger_dump,
850 };
851
852 static int d71_merger_init(struct d71_dev *d71,
853                            struct block_header *blk, u32 __iomem *reg)
854 {
855         struct komeda_component *c;
856         struct komeda_merger *merger;
857         u32 pipe_id, comp_id;
858
859         get_resources_id(blk->block_info, &pipe_id, &comp_id);
860
861         c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*merger),
862                                  comp_id,
863                                  BLOCK_INFO_INPUT_ID(blk->block_info),
864                                  &d71_merger_funcs,
865                                  MG_NUM_INPUTS_IDS, get_valid_inputs(blk),
866                                  MG_NUM_OUTPUTS_IDS, reg,
867                                  "CU%d_MERGER", pipe_id);
868
869         if (IS_ERR(c)) {
870                 DRM_ERROR("Failed to initialize merger.\n");
871                 return PTR_ERR(c);
872         }
873
874         merger = to_merger(c);
875
876         set_range(&merger->hsize_merged, 4, 4032);
877         set_range(&merger->vsize_merged, 4, 4096);
878
879         return 0;
880 }
881
882 static void d71_improc_update(struct komeda_component *c,
883                               struct komeda_component_state *state)
884 {
885         struct komeda_improc_state *st = to_improc_st(state);
886         u32 __iomem *reg = c->reg;
887         u32 index;
888
889         for_each_changed_input(state, index)
890                 malidp_write32(reg, BLK_INPUT_ID0 + index * 4,
891                                to_d71_input_id(state, index));
892
893         malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize));
894 }
895
896 static void d71_improc_dump(struct komeda_component *c, struct seq_file *sf)
897 {
898         u32 v[12], i;
899
900         dump_block_header(sf, c->reg);
901
902         get_values_from_reg(c->reg, 0x80, 2, v);
903         seq_printf(sf, "IPS_INPUT_ID0:\t\t0x%X\n", v[0]);
904         seq_printf(sf, "IPS_INPUT_ID1:\t\t0x%X\n", v[1]);
905
906         get_values_from_reg(c->reg, 0xC0, 1, v);
907         seq_printf(sf, "IPS_INFO:\t\t0x%X\n", v[0]);
908
909         get_values_from_reg(c->reg, 0xD0, 3, v);
910         seq_printf(sf, "IPS_CONTROL:\t\t0x%X\n", v[0]);
911         seq_printf(sf, "IPS_SIZE:\t\t0x%X\n", v[1]);
912         seq_printf(sf, "IPS_DEPTH:\t\t0x%X\n", v[2]);
913
914         get_values_from_reg(c->reg, 0x130, 12, v);
915         for (i = 0; i < 12; i++)
916                 seq_printf(sf, "IPS_RGB_RGB_COEFF%u:\t0x%X\n", i, v[i]);
917
918         get_values_from_reg(c->reg, 0x170, 12, v);
919         for (i = 0; i < 12; i++)
920                 seq_printf(sf, "IPS_RGB_YUV_COEFF%u:\t0x%X\n", i, v[i]);
921 }
922
923 static const struct komeda_component_funcs d71_improc_funcs = {
924         .update         = d71_improc_update,
925         .disable        = d71_component_disable,
926         .dump_register  = d71_improc_dump,
927 };
928
929 static int d71_improc_init(struct d71_dev *d71,
930                            struct block_header *blk, u32 __iomem *reg)
931 {
932         struct komeda_component *c;
933         struct komeda_improc *improc;
934         u32 pipe_id, comp_id, value;
935
936         get_resources_id(blk->block_info, &pipe_id, &comp_id);
937
938         c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*improc),
939                                  comp_id,
940                                  BLOCK_INFO_INPUT_ID(blk->block_info),
941                                  &d71_improc_funcs, IPS_NUM_INPUT_IDS,
942                                  get_valid_inputs(blk),
943                                  IPS_NUM_OUTPUT_IDS, reg, "DOU%d_IPS", pipe_id);
944         if (IS_ERR(c)) {
945                 DRM_ERROR("Failed to add improc component\n");
946                 return PTR_ERR(c);
947         }
948
949         improc = to_improc(c);
950         improc->supported_color_depths = BIT(8) | BIT(10);
951         improc->supported_color_formats = DRM_COLOR_FORMAT_RGB444 |
952                                           DRM_COLOR_FORMAT_YCRCB444 |
953                                           DRM_COLOR_FORMAT_YCRCB422;
954         value = malidp_read32(reg, BLK_INFO);
955         if (value & IPS_INFO_CHD420)
956                 improc->supported_color_formats |= DRM_COLOR_FORMAT_YCRCB420;
957
958         improc->supports_csc = true;
959         improc->supports_gamma = true;
960
961         return 0;
962 }
963
964 static void d71_timing_ctrlr_disable(struct komeda_component *c)
965 {
966         malidp_write32_mask(c->reg, BLK_CONTROL, BS_CTRL_EN, 0);
967 }
968
969 static void d71_timing_ctrlr_update(struct komeda_component *c,
970                                     struct komeda_component_state *state)
971 {
972         struct drm_crtc_state *crtc_st = state->crtc->state;
973         u32 __iomem *reg = c->reg;
974         struct videomode vm;
975         u32 value;
976
977         drm_display_mode_to_videomode(&crtc_st->adjusted_mode, &vm);
978
979         malidp_write32(reg, BS_ACTIVESIZE, HV_SIZE(vm.hactive, vm.vactive));
980         malidp_write32(reg, BS_HINTERVALS, BS_H_INTVALS(vm.hfront_porch,
981                                                         vm.hback_porch));
982         malidp_write32(reg, BS_VINTERVALS, BS_V_INTVALS(vm.vfront_porch,
983                                                         vm.vback_porch));
984
985         value = BS_SYNC_VSW(vm.vsync_len) | BS_SYNC_HSW(vm.hsync_len);
986         value |= vm.flags & DISPLAY_FLAGS_VSYNC_HIGH ? BS_SYNC_VSP : 0;
987         value |= vm.flags & DISPLAY_FLAGS_HSYNC_HIGH ? BS_SYNC_HSP : 0;
988         malidp_write32(reg, BS_SYNC, value);
989
990         malidp_write32(reg, BS_PROG_LINE, D71_DEFAULT_PREPRETCH_LINE - 1);
991         malidp_write32(reg, BS_PREFETCH_LINE, D71_DEFAULT_PREPRETCH_LINE);
992
993         /* configure bs control register */
994         value = BS_CTRL_EN | BS_CTRL_VM;
995
996         malidp_write32(reg, BLK_CONTROL, value);
997 }
998
999 static void d71_timing_ctrlr_dump(struct komeda_component *c,
1000                                   struct seq_file *sf)
1001 {
1002         u32 v[8], i;
1003
1004         dump_block_header(sf, c->reg);
1005
1006         get_values_from_reg(c->reg, 0xC0, 1, v);
1007         seq_printf(sf, "BS_INFO:\t\t0x%X\n", v[0]);
1008
1009         get_values_from_reg(c->reg, 0xD0, 8, v);
1010         seq_printf(sf, "BS_CONTROL:\t\t0x%X\n", v[0]);
1011         seq_printf(sf, "BS_PROG_LINE:\t\t0x%X\n", v[1]);
1012         seq_printf(sf, "BS_PREFETCH_LINE:\t0x%X\n", v[2]);
1013         seq_printf(sf, "BS_BG_COLOR:\t\t0x%X\n", v[3]);
1014         seq_printf(sf, "BS_ACTIVESIZE:\t\t0x%X\n", v[4]);
1015         seq_printf(sf, "BS_HINTERVALS:\t\t0x%X\n", v[5]);
1016         seq_printf(sf, "BS_VINTERVALS:\t\t0x%X\n", v[6]);
1017         seq_printf(sf, "BS_SYNC:\t\t0x%X\n", v[7]);
1018
1019         get_values_from_reg(c->reg, 0x100, 3, v);
1020         seq_printf(sf, "BS_DRIFT_TO:\t\t0x%X\n", v[0]);
1021         seq_printf(sf, "BS_FRAME_TO:\t\t0x%X\n", v[1]);
1022         seq_printf(sf, "BS_TE_TO:\t\t0x%X\n", v[2]);
1023
1024         get_values_from_reg(c->reg, 0x110, 3, v);
1025         for (i = 0; i < 3; i++)
1026                 seq_printf(sf, "BS_T%u_INTERVAL:\t\t0x%X\n", i, v[i]);
1027
1028         get_values_from_reg(c->reg, 0x120, 5, v);
1029         for (i = 0; i < 2; i++) {
1030                 seq_printf(sf, "BS_CRC%u_LOW:\t\t0x%X\n", i, v[i << 1]);
1031                 seq_printf(sf, "BS_CRC%u_HIGH:\t\t0x%X\n", i, v[(i << 1) + 1]);
1032         }
1033         seq_printf(sf, "BS_USER:\t\t0x%X\n", v[4]);
1034 }
1035
1036 static const struct komeda_component_funcs d71_timing_ctrlr_funcs = {
1037         .update         = d71_timing_ctrlr_update,
1038         .disable        = d71_timing_ctrlr_disable,
1039         .dump_register  = d71_timing_ctrlr_dump,
1040 };
1041
1042 static int d71_timing_ctrlr_init(struct d71_dev *d71,
1043                                  struct block_header *blk, u32 __iomem *reg)
1044 {
1045         struct komeda_component *c;
1046         struct komeda_timing_ctrlr *ctrlr;
1047         u32 pipe_id, comp_id;
1048
1049         get_resources_id(blk->block_info, &pipe_id, &comp_id);
1050
1051         c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*ctrlr),
1052                                  KOMEDA_COMPONENT_TIMING_CTRLR,
1053                                  BLOCK_INFO_INPUT_ID(blk->block_info),
1054                                  &d71_timing_ctrlr_funcs,
1055                                  1, BIT(KOMEDA_COMPONENT_IPS0 + pipe_id),
1056                                  BS_NUM_OUTPUT_IDS, reg, "DOU%d_BS", pipe_id);
1057         if (IS_ERR(c)) {
1058                 DRM_ERROR("Failed to add display_ctrl component\n");
1059                 return PTR_ERR(c);
1060         }
1061
1062         ctrlr = to_ctrlr(c);
1063
1064         ctrlr->supports_dual_link = true;
1065
1066         return 0;
1067 }
1068
1069 int d71_probe_block(struct d71_dev *d71,
1070                     struct block_header *blk, u32 __iomem *reg)
1071 {
1072         struct d71_pipeline *pipe;
1073         int blk_id = BLOCK_INFO_BLK_ID(blk->block_info);
1074
1075         int err = 0;
1076
1077         switch (BLOCK_INFO_BLK_TYPE(blk->block_info)) {
1078         case D71_BLK_TYPE_GCU:
1079                 break;
1080
1081         case D71_BLK_TYPE_LPU:
1082                 pipe = d71->pipes[blk_id];
1083                 pipe->lpu_addr = reg;
1084                 break;
1085
1086         case D71_BLK_TYPE_LPU_LAYER:
1087                 err = d71_layer_init(d71, blk, reg);
1088                 break;
1089
1090         case D71_BLK_TYPE_LPU_WB_LAYER:
1091                 err = d71_wb_layer_init(d71, blk, reg);
1092                 break;
1093
1094         case D71_BLK_TYPE_CU:
1095                 pipe = d71->pipes[blk_id];
1096                 pipe->cu_addr = reg;
1097                 err = d71_compiz_init(d71, blk, reg);
1098                 break;
1099
1100         case D71_BLK_TYPE_CU_SCALER:
1101                 err = d71_scaler_init(d71, blk, reg);
1102                 break;
1103
1104         case D71_BLK_TYPE_CU_SPLITTER:
1105                 break;
1106
1107         case D71_BLK_TYPE_CU_MERGER:
1108                 err = d71_merger_init(d71, blk, reg);
1109                 break;
1110
1111         case D71_BLK_TYPE_DOU:
1112                 pipe = d71->pipes[blk_id];
1113                 pipe->dou_addr = reg;
1114                 break;
1115
1116         case D71_BLK_TYPE_DOU_IPS:
1117                 err = d71_improc_init(d71, blk, reg);
1118                 break;
1119
1120         case D71_BLK_TYPE_DOU_FT_COEFF:
1121                 pipe = d71->pipes[blk_id];
1122                 pipe->dou_ft_coeff_addr = reg;
1123                 break;
1124
1125         case D71_BLK_TYPE_DOU_BS:
1126                 err = d71_timing_ctrlr_init(d71, blk, reg);
1127                 break;
1128
1129         case D71_BLK_TYPE_GLB_LT_COEFF:
1130                 break;
1131
1132         case D71_BLK_TYPE_GLB_SCL_COEFF:
1133                 d71->glb_scl_coeff_addr[blk_id] = reg;
1134                 break;
1135
1136         default:
1137                 DRM_ERROR("Unknown block (block_info: 0x%x) is found\n",
1138                           blk->block_info);
1139                 err = -EINVAL;
1140                 break;
1141         }
1142
1143         return err;
1144 }
1145
1146 const struct komeda_pipeline_funcs d71_pipeline_funcs = {
1147         .downscaling_clk_check = d71_downscaling_clk_check,
1148 };