Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[sfrench/cifs-2.6.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
14 static void get_resources_id(u32 hw_id, u32 *pipe_id, u32 *comp_id)
15 {
16         u32 id = BLOCK_INFO_BLK_ID(hw_id);
17         u32 pipe = id;
18
19         switch (BLOCK_INFO_BLK_TYPE(hw_id)) {
20         case D71_BLK_TYPE_LPU_WB_LAYER:
21                 id = KOMEDA_COMPONENT_WB_LAYER;
22                 break;
23         case D71_BLK_TYPE_CU_SPLITTER:
24                 id = KOMEDA_COMPONENT_SPLITTER;
25                 break;
26         case D71_BLK_TYPE_CU_SCALER:
27                 pipe = id / D71_PIPELINE_MAX_SCALERS;
28                 id %= D71_PIPELINE_MAX_SCALERS;
29                 id += KOMEDA_COMPONENT_SCALER0;
30                 break;
31         case D71_BLK_TYPE_CU:
32                 id += KOMEDA_COMPONENT_COMPIZ0;
33                 break;
34         case D71_BLK_TYPE_LPU_LAYER:
35                 pipe = id / D71_PIPELINE_MAX_LAYERS;
36                 id %= D71_PIPELINE_MAX_LAYERS;
37                 id += KOMEDA_COMPONENT_LAYER0;
38                 break;
39         case D71_BLK_TYPE_DOU_IPS:
40                 id += KOMEDA_COMPONENT_IPS0;
41                 break;
42         case D71_BLK_TYPE_CU_MERGER:
43                 id = KOMEDA_COMPONENT_MERGER;
44                 break;
45         case D71_BLK_TYPE_DOU:
46                 id = KOMEDA_COMPONENT_TIMING_CTRLR;
47                 break;
48         default:
49                 id = 0xFFFFFFFF;
50         }
51
52         if (comp_id)
53                 *comp_id = id;
54
55         if (pipe_id)
56                 *pipe_id = pipe;
57 }
58
59 static u32 get_valid_inputs(struct block_header *blk)
60 {
61         u32 valid_inputs = 0, comp_id;
62         int i;
63
64         for (i = 0; i < PIPELINE_INFO_N_VALID_INPUTS(blk->pipeline_info); i++) {
65                 get_resources_id(blk->input_ids[i], NULL, &comp_id);
66                 if (comp_id == 0xFFFFFFFF)
67                         continue;
68                 valid_inputs |= BIT(comp_id);
69         }
70
71         return valid_inputs;
72 }
73
74 static void get_values_from_reg(void __iomem *reg, u32 offset,
75                                 u32 count, u32 *val)
76 {
77         u32 i, addr;
78
79         for (i = 0; i < count; i++) {
80                 addr = offset + (i << 2);
81                 /* 0xA4 is WO register */
82                 if (addr != 0xA4)
83                         val[i] = malidp_read32(reg, addr);
84                 else
85                         val[i] = 0xDEADDEAD;
86         }
87 }
88
89 static void dump_block_header(struct seq_file *sf, void __iomem *reg)
90 {
91         struct block_header hdr;
92         u32 i, n_input, n_output;
93
94         d71_read_block_header(reg, &hdr);
95         seq_printf(sf, "BLOCK_INFO:\t\t0x%X\n", hdr.block_info);
96         seq_printf(sf, "PIPELINE_INFO:\t\t0x%X\n", hdr.pipeline_info);
97
98         n_output = PIPELINE_INFO_N_OUTPUTS(hdr.pipeline_info);
99         n_input  = PIPELINE_INFO_N_VALID_INPUTS(hdr.pipeline_info);
100
101         for (i = 0; i < n_input; i++)
102                 seq_printf(sf, "VALID_INPUT_ID%u:\t0x%X\n",
103                            i, hdr.input_ids[i]);
104
105         for (i = 0; i < n_output; i++)
106                 seq_printf(sf, "OUTPUT_ID%u:\t\t0x%X\n",
107                            i, hdr.output_ids[i]);
108 }
109
110 static u32 to_rot_ctrl(u32 rot)
111 {
112         u32 lr_ctrl = 0;
113
114         switch (rot & DRM_MODE_ROTATE_MASK) {
115         case DRM_MODE_ROTATE_0:
116                 lr_ctrl |= L_ROT(L_ROT_R0);
117                 break;
118         case DRM_MODE_ROTATE_90:
119                 lr_ctrl |= L_ROT(L_ROT_R90);
120                 break;
121         case DRM_MODE_ROTATE_180:
122                 lr_ctrl |= L_ROT(L_ROT_R180);
123                 break;
124         case DRM_MODE_ROTATE_270:
125                 lr_ctrl |= L_ROT(L_ROT_R270);
126                 break;
127         }
128
129         if (rot & DRM_MODE_REFLECT_X)
130                 lr_ctrl |= L_HFLIP;
131         if (rot & DRM_MODE_REFLECT_Y)
132                 lr_ctrl |= L_VFLIP;
133
134         return lr_ctrl;
135 }
136
137 static inline u32 to_d71_input_id(struct komeda_component_output *output)
138 {
139         struct komeda_component *comp = output->component;
140
141         return comp ? (comp->hw_id + output->output_port) : 0;
142 }
143
144 static void d71_layer_disable(struct komeda_component *c)
145 {
146         malidp_write32_mask(c->reg, BLK_CONTROL, L_EN, 0);
147 }
148
149 static void d71_layer_update(struct komeda_component *c,
150                              struct komeda_component_state *state)
151 {
152         struct komeda_layer_state *st = to_layer_st(state);
153         struct drm_plane_state *plane_st = state->plane->state;
154         struct drm_framebuffer *fb = plane_st->fb;
155         struct komeda_fb *kfb = to_kfb(fb);
156         u32 __iomem *reg = c->reg;
157         u32 ctrl_mask = L_EN | L_ROT(L_ROT_R270) | L_HFLIP | L_VFLIP | L_TBU_EN;
158         u32 ctrl = L_EN | to_rot_ctrl(st->rot);
159         int i;
160
161         for (i = 0; i < fb->format->num_planes; i++) {
162                 malidp_write32(reg,
163                                BLK_P0_PTR_LOW + i * LAYER_PER_PLANE_REGS * 4,
164                                lower_32_bits(st->addr[i]));
165                 malidp_write32(reg,
166                                BLK_P0_PTR_HIGH + i * LAYER_PER_PLANE_REGS * 4,
167                                upper_32_bits(st->addr[i]));
168                 if (i >= 2)
169                         break;
170
171                 malidp_write32(reg,
172                                BLK_P0_STRIDE + i * LAYER_PER_PLANE_REGS * 4,
173                                fb->pitches[i] & 0xFFFF);
174         }
175
176         malidp_write32(reg, LAYER_FMT, kfb->format_caps->hw_id);
177         malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize, st->vsize));
178
179         malidp_write32_mask(reg, BLK_CONTROL, ctrl_mask, ctrl);
180 }
181
182 static void d71_layer_dump(struct komeda_component *c, struct seq_file *sf)
183 {
184         u32 v[15], i;
185         bool rich, rgb2rgb;
186         char *prefix;
187
188         get_values_from_reg(c->reg, LAYER_INFO, 1, &v[14]);
189         if (v[14] & 0x1) {
190                 rich = true;
191                 prefix = "LR_";
192         } else {
193                 rich = false;
194                 prefix = "LS_";
195         }
196
197         rgb2rgb = !!(v[14] & L_INFO_CM);
198
199         dump_block_header(sf, c->reg);
200
201         seq_printf(sf, "%sLAYER_INFO:\t\t0x%X\n", prefix, v[14]);
202
203         get_values_from_reg(c->reg, 0xD0, 1, v);
204         seq_printf(sf, "%sCONTROL:\t\t0x%X\n", prefix, v[0]);
205         if (rich) {
206                 get_values_from_reg(c->reg, 0xD4, 1, v);
207                 seq_printf(sf, "LR_RICH_CONTROL:\t0x%X\n", v[0]);
208         }
209         get_values_from_reg(c->reg, 0xD8, 4, v);
210         seq_printf(sf, "%sFORMAT:\t\t0x%X\n", prefix, v[0]);
211         seq_printf(sf, "%sIT_COEFFTAB:\t\t0x%X\n", prefix, v[1]);
212         seq_printf(sf, "%sIN_SIZE:\t\t0x%X\n", prefix, v[2]);
213         seq_printf(sf, "%sPALPHA:\t\t0x%X\n", prefix, v[3]);
214
215         get_values_from_reg(c->reg, 0x100, 3, v);
216         seq_printf(sf, "%sP0_PTR_LOW:\t\t0x%X\n", prefix, v[0]);
217         seq_printf(sf, "%sP0_PTR_HIGH:\t\t0x%X\n", prefix, v[1]);
218         seq_printf(sf, "%sP0_STRIDE:\t\t0x%X\n", prefix, v[2]);
219
220         get_values_from_reg(c->reg, 0x110, 2, v);
221         seq_printf(sf, "%sP1_PTR_LOW:\t\t0x%X\n", prefix, v[0]);
222         seq_printf(sf, "%sP1_PTR_HIGH:\t\t0x%X\n", prefix, v[1]);
223         if (rich) {
224                 get_values_from_reg(c->reg, 0x118, 1, v);
225                 seq_printf(sf, "LR_P1_STRIDE:\t\t0x%X\n", v[0]);
226
227                 get_values_from_reg(c->reg, 0x120, 2, v);
228                 seq_printf(sf, "LR_P2_PTR_LOW:\t\t0x%X\n", v[0]);
229                 seq_printf(sf, "LR_P2_PTR_HIGH:\t\t0x%X\n", v[1]);
230
231                 get_values_from_reg(c->reg, 0x130, 12, v);
232                 for (i = 0; i < 12; i++)
233                         seq_printf(sf, "LR_YUV_RGB_COEFF%u:\t0x%X\n", i, v[i]);
234         }
235
236         if (rgb2rgb) {
237                 get_values_from_reg(c->reg, LAYER_RGB_RGB_COEFF0, 12, v);
238                 for (i = 0; i < 12; i++)
239                         seq_printf(sf, "LS_RGB_RGB_COEFF%u:\t0x%X\n", i, v[i]);
240         }
241
242         get_values_from_reg(c->reg, 0x160, 3, v);
243         seq_printf(sf, "%sAD_CONTROL:\t\t0x%X\n", prefix, v[0]);
244         seq_printf(sf, "%sAD_H_CROP:\t\t0x%X\n", prefix, v[1]);
245         seq_printf(sf, "%sAD_V_CROP:\t\t0x%X\n", prefix, v[2]);
246 }
247
248 static const struct komeda_component_funcs d71_layer_funcs = {
249         .update         = d71_layer_update,
250         .disable        = d71_layer_disable,
251         .dump_register  = d71_layer_dump,
252 };
253
254 static int d71_layer_init(struct d71_dev *d71,
255                           struct block_header *blk, u32 __iomem *reg)
256 {
257         struct komeda_component *c;
258         struct komeda_layer *layer;
259         u32 pipe_id, layer_id, layer_info;
260
261         get_resources_id(blk->block_info, &pipe_id, &layer_id);
262         c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*layer),
263                                  layer_id,
264                                  BLOCK_INFO_INPUT_ID(blk->block_info),
265                                  &d71_layer_funcs, 0,
266                                  get_valid_inputs(blk),
267                                  1, reg, "LPU%d_LAYER%d", pipe_id, layer_id);
268         if (IS_ERR(c)) {
269                 DRM_ERROR("Failed to add layer component\n");
270                 return PTR_ERR(c);
271         }
272
273         layer = to_layer(c);
274         layer_info = malidp_read32(reg, LAYER_INFO);
275
276         if (layer_info & L_INFO_RF)
277                 layer->layer_type = KOMEDA_FMT_RICH_LAYER;
278         else
279                 layer->layer_type = KOMEDA_FMT_SIMPLE_LAYER;
280
281         set_range(&layer->hsize_in, 4, d71->max_line_size);
282         set_range(&layer->vsize_in, 4, d71->max_vsize);
283
284         malidp_write32(reg, LAYER_PALPHA, D71_PALPHA_DEF_MAP);
285
286         layer->supported_rots = DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK;
287
288         return 0;
289 }
290
291 static int d71_wb_layer_init(struct d71_dev *d71,
292                              struct block_header *blk, u32 __iomem *reg)
293 {
294         DRM_DEBUG("Detect D71_Wb_Layer.\n");
295
296         return 0;
297 }
298
299 static void d71_component_disable(struct komeda_component *c)
300 {
301         u32 __iomem *reg = c->reg;
302         u32 i;
303
304         malidp_write32(reg, BLK_CONTROL, 0);
305
306         for (i = 0; i < c->max_active_inputs; i++)
307                 malidp_write32(reg, BLK_INPUT_ID0 + (i << 2), 0);
308 }
309
310 static void compiz_enable_input(u32 __iomem *id_reg,
311                                 u32 __iomem *cfg_reg,
312                                 u32 input_hw_id,
313                                 struct komeda_compiz_input_cfg *cin)
314 {
315         u32 ctrl = CU_INPUT_CTRL_EN;
316         u8 blend = cin->pixel_blend_mode;
317
318         if (blend == DRM_MODE_BLEND_PIXEL_NONE)
319                 ctrl |= CU_INPUT_CTRL_PAD;
320         else if (blend == DRM_MODE_BLEND_PREMULTI)
321                 ctrl |= CU_INPUT_CTRL_PMUL;
322
323         ctrl |= CU_INPUT_CTRL_ALPHA(cin->layer_alpha);
324
325         malidp_write32(id_reg, BLK_INPUT_ID0, input_hw_id);
326
327         malidp_write32(cfg_reg, CU_INPUT0_SIZE,
328                        HV_SIZE(cin->hsize, cin->vsize));
329         malidp_write32(cfg_reg, CU_INPUT0_OFFSET,
330                        HV_OFFSET(cin->hoffset, cin->voffset));
331         malidp_write32(cfg_reg, CU_INPUT0_CONTROL, ctrl);
332 }
333
334 static void d71_compiz_update(struct komeda_component *c,
335                               struct komeda_component_state *state)
336 {
337         struct komeda_compiz_state *st = to_compiz_st(state);
338         u32 __iomem *reg = c->reg;
339         u32 __iomem *id_reg, *cfg_reg;
340         u32 index, input_hw_id;
341
342         for_each_changed_input(state, index) {
343                 id_reg = reg + index;
344                 cfg_reg = reg + index * CU_PER_INPUT_REGS;
345                 input_hw_id = to_d71_input_id(&state->inputs[index]);
346                 if (state->active_inputs & BIT(index)) {
347                         compiz_enable_input(id_reg, cfg_reg,
348                                             input_hw_id, &st->cins[index]);
349                 } else {
350                         malidp_write32(id_reg, BLK_INPUT_ID0, 0);
351                         malidp_write32(cfg_reg, CU_INPUT0_CONTROL, 0);
352                 }
353         }
354
355         malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize));
356 }
357
358 static void d71_compiz_dump(struct komeda_component *c, struct seq_file *sf)
359 {
360         u32 v[8], i;
361
362         dump_block_header(sf, c->reg);
363
364         get_values_from_reg(c->reg, 0x80, 5, v);
365         for (i = 0; i < 5; i++)
366                 seq_printf(sf, "CU_INPUT_ID%u:\t\t0x%X\n", i, v[i]);
367
368         get_values_from_reg(c->reg, 0xA0, 5, v);
369         seq_printf(sf, "CU_IRQ_RAW_STATUS:\t0x%X\n", v[0]);
370         seq_printf(sf, "CU_IRQ_CLEAR:\t\t0x%X\n", v[1]);
371         seq_printf(sf, "CU_IRQ_MASK:\t\t0x%X\n", v[2]);
372         seq_printf(sf, "CU_IRQ_STATUS:\t\t0x%X\n", v[3]);
373         seq_printf(sf, "CU_STATUS:\t\t0x%X\n", v[4]);
374
375         get_values_from_reg(c->reg, 0xD0, 2, v);
376         seq_printf(sf, "CU_CONTROL:\t\t0x%X\n", v[0]);
377         seq_printf(sf, "CU_SIZE:\t\t0x%X\n", v[1]);
378
379         get_values_from_reg(c->reg, 0xDC, 1, v);
380         seq_printf(sf, "CU_BG_COLOR:\t\t0x%X\n", v[0]);
381
382         for (i = 0, v[4] = 0xE0; i < 5; i++, v[4] += 0x10) {
383                 get_values_from_reg(c->reg, v[4], 3, v);
384                 seq_printf(sf, "CU_INPUT%u_SIZE:\t\t0x%X\n", i, v[0]);
385                 seq_printf(sf, "CU_INPUT%u_OFFSET:\t0x%X\n", i, v[1]);
386                 seq_printf(sf, "CU_INPUT%u_CONTROL:\t0x%X\n", i, v[2]);
387         }
388
389         get_values_from_reg(c->reg, 0x130, 2, v);
390         seq_printf(sf, "CU_USER_LOW:\t\t0x%X\n", v[0]);
391         seq_printf(sf, "CU_USER_HIGH:\t\t0x%X\n", v[1]);
392 }
393
394 static const struct komeda_component_funcs d71_compiz_funcs = {
395         .update         = d71_compiz_update,
396         .disable        = d71_component_disable,
397         .dump_register  = d71_compiz_dump,
398 };
399
400 static int d71_compiz_init(struct d71_dev *d71,
401                            struct block_header *blk, u32 __iomem *reg)
402 {
403         struct komeda_component *c;
404         struct komeda_compiz *compiz;
405         u32 pipe_id, comp_id;
406
407         get_resources_id(blk->block_info, &pipe_id, &comp_id);
408
409         c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*compiz),
410                                  comp_id,
411                                  BLOCK_INFO_INPUT_ID(blk->block_info),
412                                  &d71_compiz_funcs,
413                                  CU_NUM_INPUT_IDS, get_valid_inputs(blk),
414                                  CU_NUM_OUTPUT_IDS, reg,
415                                  "CU%d", pipe_id);
416         if (IS_ERR(c))
417                 return PTR_ERR(c);
418
419         compiz = to_compiz(c);
420
421         set_range(&compiz->hsize, D71_MIN_LINE_SIZE, d71->max_line_size);
422         set_range(&compiz->vsize, D71_MIN_VERTICAL_SIZE, d71->max_vsize);
423
424         return 0;
425 }
426
427 static void d71_improc_update(struct komeda_component *c,
428                               struct komeda_component_state *state)
429 {
430         struct komeda_improc_state *st = to_improc_st(state);
431         u32 __iomem *reg = c->reg;
432         u32 index, input_hw_id;
433
434         for_each_changed_input(state, index) {
435                 input_hw_id = state->active_inputs & BIT(index) ?
436                               to_d71_input_id(&state->inputs[index]) : 0;
437                 malidp_write32(reg, BLK_INPUT_ID0 + index * 4, input_hw_id);
438         }
439
440         malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize));
441 }
442
443 static void d71_improc_dump(struct komeda_component *c, struct seq_file *sf)
444 {
445         u32 v[12], i;
446
447         dump_block_header(sf, c->reg);
448
449         get_values_from_reg(c->reg, 0x80, 2, v);
450         seq_printf(sf, "IPS_INPUT_ID0:\t\t0x%X\n", v[0]);
451         seq_printf(sf, "IPS_INPUT_ID1:\t\t0x%X\n", v[1]);
452
453         get_values_from_reg(c->reg, 0xC0, 1, v);
454         seq_printf(sf, "IPS_INFO:\t\t0x%X\n", v[0]);
455
456         get_values_from_reg(c->reg, 0xD0, 3, v);
457         seq_printf(sf, "IPS_CONTROL:\t\t0x%X\n", v[0]);
458         seq_printf(sf, "IPS_SIZE:\t\t0x%X\n", v[1]);
459         seq_printf(sf, "IPS_DEPTH:\t\t0x%X\n", v[2]);
460
461         get_values_from_reg(c->reg, 0x130, 12, v);
462         for (i = 0; i < 12; i++)
463                 seq_printf(sf, "IPS_RGB_RGB_COEFF%u:\t0x%X\n", i, v[i]);
464
465         get_values_from_reg(c->reg, 0x170, 12, v);
466         for (i = 0; i < 12; i++)
467                 seq_printf(sf, "IPS_RGB_YUV_COEFF%u:\t0x%X\n", i, v[i]);
468 }
469
470 static const struct komeda_component_funcs d71_improc_funcs = {
471         .update         = d71_improc_update,
472         .disable        = d71_component_disable,
473         .dump_register  = d71_improc_dump,
474 };
475
476 static int d71_improc_init(struct d71_dev *d71,
477                            struct block_header *blk, u32 __iomem *reg)
478 {
479         struct komeda_component *c;
480         struct komeda_improc *improc;
481         u32 pipe_id, comp_id, value;
482
483         get_resources_id(blk->block_info, &pipe_id, &comp_id);
484
485         c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*improc),
486                                  comp_id,
487                                  BLOCK_INFO_INPUT_ID(blk->block_info),
488                                  &d71_improc_funcs, IPS_NUM_INPUT_IDS,
489                                  get_valid_inputs(blk),
490                                  IPS_NUM_OUTPUT_IDS, reg, "DOU%d_IPS", pipe_id);
491         if (IS_ERR(c)) {
492                 DRM_ERROR("Failed to add improc component\n");
493                 return PTR_ERR(c);
494         }
495
496         improc = to_improc(c);
497         improc->supported_color_depths = BIT(8) | BIT(10);
498         improc->supported_color_formats = DRM_COLOR_FORMAT_RGB444 |
499                                           DRM_COLOR_FORMAT_YCRCB444 |
500                                           DRM_COLOR_FORMAT_YCRCB422;
501         value = malidp_read32(reg, BLK_INFO);
502         if (value & IPS_INFO_CHD420)
503                 improc->supported_color_formats |= DRM_COLOR_FORMAT_YCRCB420;
504
505         improc->supports_csc = true;
506         improc->supports_gamma = true;
507
508         return 0;
509 }
510
511 static void d71_timing_ctrlr_disable(struct komeda_component *c)
512 {
513         malidp_write32_mask(c->reg, BLK_CONTROL, BS_CTRL_EN, 0);
514 }
515
516 static void d71_timing_ctrlr_update(struct komeda_component *c,
517                                     struct komeda_component_state *state)
518 {
519         struct drm_crtc_state *crtc_st = state->crtc->state;
520         u32 __iomem *reg = c->reg;
521         struct videomode vm;
522         u32 value;
523
524         drm_display_mode_to_videomode(&crtc_st->adjusted_mode, &vm);
525
526         malidp_write32(reg, BS_ACTIVESIZE, HV_SIZE(vm.hactive, vm.vactive));
527         malidp_write32(reg, BS_HINTERVALS, BS_H_INTVALS(vm.hfront_porch,
528                                                         vm.hback_porch));
529         malidp_write32(reg, BS_VINTERVALS, BS_V_INTVALS(vm.vfront_porch,
530                                                         vm.vback_porch));
531
532         value = BS_SYNC_VSW(vm.vsync_len) | BS_SYNC_HSW(vm.hsync_len);
533         value |= vm.flags & DISPLAY_FLAGS_VSYNC_HIGH ? BS_SYNC_VSP : 0;
534         value |= vm.flags & DISPLAY_FLAGS_HSYNC_HIGH ? BS_SYNC_HSP : 0;
535         malidp_write32(reg, BS_SYNC, value);
536
537         malidp_write32(reg, BS_PROG_LINE, D71_DEFAULT_PREPRETCH_LINE - 1);
538         malidp_write32(reg, BS_PREFETCH_LINE, D71_DEFAULT_PREPRETCH_LINE);
539
540         /* configure bs control register */
541         value = BS_CTRL_EN | BS_CTRL_VM;
542
543         malidp_write32(reg, BLK_CONTROL, value);
544 }
545
546 static void d71_timing_ctrlr_dump(struct komeda_component *c,
547                                   struct seq_file *sf)
548 {
549         u32 v[8], i;
550
551         dump_block_header(sf, c->reg);
552
553         get_values_from_reg(c->reg, 0xC0, 1, v);
554         seq_printf(sf, "BS_INFO:\t\t0x%X\n", v[0]);
555
556         get_values_from_reg(c->reg, 0xD0, 8, v);
557         seq_printf(sf, "BS_CONTROL:\t\t0x%X\n", v[0]);
558         seq_printf(sf, "BS_PROG_LINE:\t\t0x%X\n", v[1]);
559         seq_printf(sf, "BS_PREFETCH_LINE:\t0x%X\n", v[2]);
560         seq_printf(sf, "BS_BG_COLOR:\t\t0x%X\n", v[3]);
561         seq_printf(sf, "BS_ACTIVESIZE:\t\t0x%X\n", v[4]);
562         seq_printf(sf, "BS_HINTERVALS:\t\t0x%X\n", v[5]);
563         seq_printf(sf, "BS_VINTERVALS:\t\t0x%X\n", v[6]);
564         seq_printf(sf, "BS_SYNC:\t\t0x%X\n", v[7]);
565
566         get_values_from_reg(c->reg, 0x100, 3, v);
567         seq_printf(sf, "BS_DRIFT_TO:\t\t0x%X\n", v[0]);
568         seq_printf(sf, "BS_FRAME_TO:\t\t0x%X\n", v[1]);
569         seq_printf(sf, "BS_TE_TO:\t\t0x%X\n", v[2]);
570
571         get_values_from_reg(c->reg, 0x110, 3, v);
572         for (i = 0; i < 3; i++)
573                 seq_printf(sf, "BS_T%u_INTERVAL:\t\t0x%X\n", i, v[i]);
574
575         get_values_from_reg(c->reg, 0x120, 5, v);
576         for (i = 0; i < 2; i++) {
577                 seq_printf(sf, "BS_CRC%u_LOW:\t\t0x%X\n", i, v[i << 1]);
578                 seq_printf(sf, "BS_CRC%u_HIGH:\t\t0x%X\n", i, v[(i << 1) + 1]);
579         }
580         seq_printf(sf, "BS_USER:\t\t0x%X\n", v[4]);
581 }
582
583 static const struct komeda_component_funcs d71_timing_ctrlr_funcs = {
584         .update         = d71_timing_ctrlr_update,
585         .disable        = d71_timing_ctrlr_disable,
586         .dump_register  = d71_timing_ctrlr_dump,
587 };
588
589 static int d71_timing_ctrlr_init(struct d71_dev *d71,
590                                  struct block_header *blk, u32 __iomem *reg)
591 {
592         struct komeda_component *c;
593         struct komeda_timing_ctrlr *ctrlr;
594         u32 pipe_id, comp_id;
595
596         get_resources_id(blk->block_info, &pipe_id, &comp_id);
597
598         c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*ctrlr),
599                                  KOMEDA_COMPONENT_TIMING_CTRLR,
600                                  BLOCK_INFO_INPUT_ID(blk->block_info),
601                                  &d71_timing_ctrlr_funcs,
602                                  1, BIT(KOMEDA_COMPONENT_IPS0 + pipe_id),
603                                  BS_NUM_OUTPUT_IDS, reg, "DOU%d_BS", pipe_id);
604         if (IS_ERR(c)) {
605                 DRM_ERROR("Failed to add display_ctrl component\n");
606                 return PTR_ERR(c);
607         }
608
609         ctrlr = to_ctrlr(c);
610
611         ctrlr->supports_dual_link = true;
612
613         return 0;
614 }
615
616 int d71_probe_block(struct d71_dev *d71,
617                     struct block_header *blk, u32 __iomem *reg)
618 {
619         struct d71_pipeline *pipe;
620         int blk_id = BLOCK_INFO_BLK_ID(blk->block_info);
621
622         int err = 0;
623
624         switch (BLOCK_INFO_BLK_TYPE(blk->block_info)) {
625         case D71_BLK_TYPE_GCU:
626                 break;
627
628         case D71_BLK_TYPE_LPU:
629                 pipe = d71->pipes[blk_id];
630                 pipe->lpu_addr = reg;
631                 break;
632
633         case D71_BLK_TYPE_LPU_LAYER:
634                 err = d71_layer_init(d71, blk, reg);
635                 break;
636
637         case D71_BLK_TYPE_LPU_WB_LAYER:
638                 err = d71_wb_layer_init(d71, blk, reg);
639                 break;
640
641         case D71_BLK_TYPE_CU:
642                 pipe = d71->pipes[blk_id];
643                 pipe->cu_addr = reg;
644                 err = d71_compiz_init(d71, blk, reg);
645                 break;
646
647         case D71_BLK_TYPE_CU_SPLITTER:
648         case D71_BLK_TYPE_CU_SCALER:
649         case D71_BLK_TYPE_CU_MERGER:
650                 break;
651
652         case D71_BLK_TYPE_DOU:
653                 pipe = d71->pipes[blk_id];
654                 pipe->dou_addr = reg;
655                 break;
656
657         case D71_BLK_TYPE_DOU_IPS:
658                 err = d71_improc_init(d71, blk, reg);
659                 break;
660
661         case D71_BLK_TYPE_DOU_FT_COEFF:
662                 pipe = d71->pipes[blk_id];
663                 pipe->dou_ft_coeff_addr = reg;
664                 break;
665
666         case D71_BLK_TYPE_DOU_BS:
667                 err = d71_timing_ctrlr_init(d71, blk, reg);
668                 break;
669
670         case D71_BLK_TYPE_GLB_LT_COEFF:
671                 break;
672
673         case D71_BLK_TYPE_GLB_SCL_COEFF:
674                 d71->glb_scl_coeff_addr[blk_id] = reg;
675                 break;
676
677         default:
678                 DRM_ERROR("Unknown block (block_info: 0x%x) is found\n",
679                           blk->block_info);
680                 err = -EINVAL;
681                 break;
682         }
683
684         return err;
685 }