1
2
3
4
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
15static 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
60static 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
75static 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
83 if (addr != 0xA4)
84 val[i] = malidp_read32(reg, addr);
85 else
86 val[i] = 0xDEADDEAD;
87 }
88}
89
90static 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
111static 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
138static 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
159static 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
164 if (has_bit(idx, st->active_inputs))
165 return input->component->hw_id + input->output_port;
166 else
167 return 0;
168}
169
170static 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
194static void d71_layer_disable(struct komeda_component *c)
195{
196 malidp_write32_mask(c->reg, BLK_CONTROL, L_EN, 0);
197}
198
199static 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
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
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
271static 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
337static 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
343static 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
380static 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
399static 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
428static 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
434static 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
440static 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
468static 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
479
480
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
489static 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
513static 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
537static 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
573static 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
579static 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
606static 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
637static 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
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
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
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
706static 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
730static 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
736static 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
770static 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
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
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
811static void d71_splitter_update(struct komeda_component *c,
812 struct komeda_component_state *state)
813{
814 struct komeda_splitter_state *st = to_splitter_st(state);
815 u32 __iomem *reg = c->reg;
816
817 malidp_write32(reg, BLK_INPUT_ID0, to_d71_input_id(state, 0));
818 malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize));
819 malidp_write32(reg, SP_OVERLAP_SIZE, st->overlap & 0x1FFF);
820 malidp_write32(reg, BLK_CONTROL, BLK_CTRL_EN);
821}
822
823static void d71_splitter_dump(struct komeda_component *c, struct seq_file *sf)
824{
825 u32 v[3];
826
827 dump_block_header(sf, c->reg);
828
829 get_values_from_reg(c->reg, BLK_INPUT_ID0, 1, v);
830 seq_printf(sf, "SP_INPUT_ID0:\t\t0x%X\n", v[0]);
831
832 get_values_from_reg(c->reg, BLK_CONTROL, 3, v);
833 seq_printf(sf, "SP_CONTROL:\t\t0x%X\n", v[0]);
834 seq_printf(sf, "SP_SIZE:\t\t0x%X\n", v[1]);
835 seq_printf(sf, "SP_OVERLAP_SIZE:\t0x%X\n", v[2]);
836}
837
838static const struct komeda_component_funcs d71_splitter_funcs = {
839 .update = d71_splitter_update,
840 .disable = d71_component_disable,
841 .dump_register = d71_splitter_dump,
842};
843
844static int d71_splitter_init(struct d71_dev *d71,
845 struct block_header *blk, u32 __iomem *reg)
846{
847 struct komeda_component *c;
848 struct komeda_splitter *splitter;
849 u32 pipe_id, comp_id;
850
851 get_resources_id(blk->block_info, &pipe_id, &comp_id);
852
853 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*splitter),
854 comp_id,
855 BLOCK_INFO_INPUT_ID(blk->block_info),
856 &d71_splitter_funcs,
857 1, get_valid_inputs(blk), 2, reg,
858 "CU%d_SPLITTER", pipe_id);
859
860 if (IS_ERR(c)) {
861 DRM_ERROR("Failed to initialize splitter");
862 return -1;
863 }
864
865 splitter = to_splitter(c);
866
867 set_range(&splitter->hsize, 4, d71->max_line_size);
868 set_range(&splitter->vsize, 4, d71->max_vsize);
869
870 return 0;
871}
872
873static void d71_merger_update(struct komeda_component *c,
874 struct komeda_component_state *state)
875{
876 struct komeda_merger_state *st = to_merger_st(state);
877 u32 __iomem *reg = c->reg;
878 u32 index;
879
880 for_each_changed_input(state, index)
881 malidp_write32(reg, MG_INPUT_ID0 + index * 4,
882 to_d71_input_id(state, index));
883
884 malidp_write32(reg, MG_SIZE, HV_SIZE(st->hsize_merged,
885 st->vsize_merged));
886 malidp_write32(reg, BLK_CONTROL, BLK_CTRL_EN);
887}
888
889static void d71_merger_dump(struct komeda_component *c, struct seq_file *sf)
890{
891 u32 v;
892
893 dump_block_header(sf, c->reg);
894
895 get_values_from_reg(c->reg, MG_INPUT_ID0, 1, &v);
896 seq_printf(sf, "MG_INPUT_ID0:\t\t0x%X\n", v);
897
898 get_values_from_reg(c->reg, MG_INPUT_ID1, 1, &v);
899 seq_printf(sf, "MG_INPUT_ID1:\t\t0x%X\n", v);
900
901 get_values_from_reg(c->reg, BLK_CONTROL, 1, &v);
902 seq_printf(sf, "MG_CONTROL:\t\t0x%X\n", v);
903
904 get_values_from_reg(c->reg, MG_SIZE, 1, &v);
905 seq_printf(sf, "MG_SIZE:\t\t0x%X\n", v);
906}
907
908static const struct komeda_component_funcs d71_merger_funcs = {
909 .update = d71_merger_update,
910 .disable = d71_component_disable,
911 .dump_register = d71_merger_dump,
912};
913
914static int d71_merger_init(struct d71_dev *d71,
915 struct block_header *blk, u32 __iomem *reg)
916{
917 struct komeda_component *c;
918 struct komeda_merger *merger;
919 u32 pipe_id, comp_id;
920
921 get_resources_id(blk->block_info, &pipe_id, &comp_id);
922
923 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*merger),
924 comp_id,
925 BLOCK_INFO_INPUT_ID(blk->block_info),
926 &d71_merger_funcs,
927 MG_NUM_INPUTS_IDS, get_valid_inputs(blk),
928 MG_NUM_OUTPUTS_IDS, reg,
929 "CU%d_MERGER", pipe_id);
930
931 if (IS_ERR(c)) {
932 DRM_ERROR("Failed to initialize merger.\n");
933 return PTR_ERR(c);
934 }
935
936 merger = to_merger(c);
937
938 set_range(&merger->hsize_merged, 4, 4032);
939 set_range(&merger->vsize_merged, 4, 4096);
940
941 return 0;
942}
943
944static void d71_improc_update(struct komeda_component *c,
945 struct komeda_component_state *state)
946{
947 struct komeda_improc_state *st = to_improc_st(state);
948 u32 __iomem *reg = c->reg;
949 u32 index;
950
951 for_each_changed_input(state, index)
952 malidp_write32(reg, BLK_INPUT_ID0 + index * 4,
953 to_d71_input_id(state, index));
954
955 malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize));
956}
957
958static void d71_improc_dump(struct komeda_component *c, struct seq_file *sf)
959{
960 u32 v[12], i;
961
962 dump_block_header(sf, c->reg);
963
964 get_values_from_reg(c->reg, 0x80, 2, v);
965 seq_printf(sf, "IPS_INPUT_ID0:\t\t0x%X\n", v[0]);
966 seq_printf(sf, "IPS_INPUT_ID1:\t\t0x%X\n", v[1]);
967
968 get_values_from_reg(c->reg, 0xC0, 1, v);
969 seq_printf(sf, "IPS_INFO:\t\t0x%X\n", v[0]);
970
971 get_values_from_reg(c->reg, 0xD0, 3, v);
972 seq_printf(sf, "IPS_CONTROL:\t\t0x%X\n", v[0]);
973 seq_printf(sf, "IPS_SIZE:\t\t0x%X\n", v[1]);
974 seq_printf(sf, "IPS_DEPTH:\t\t0x%X\n", v[2]);
975
976 get_values_from_reg(c->reg, 0x130, 12, v);
977 for (i = 0; i < 12; i++)
978 seq_printf(sf, "IPS_RGB_RGB_COEFF%u:\t0x%X\n", i, v[i]);
979
980 get_values_from_reg(c->reg, 0x170, 12, v);
981 for (i = 0; i < 12; i++)
982 seq_printf(sf, "IPS_RGB_YUV_COEFF%u:\t0x%X\n", i, v[i]);
983}
984
985static const struct komeda_component_funcs d71_improc_funcs = {
986 .update = d71_improc_update,
987 .disable = d71_component_disable,
988 .dump_register = d71_improc_dump,
989};
990
991static int d71_improc_init(struct d71_dev *d71,
992 struct block_header *blk, u32 __iomem *reg)
993{
994 struct komeda_component *c;
995 struct komeda_improc *improc;
996 u32 pipe_id, comp_id, value;
997
998 get_resources_id(blk->block_info, &pipe_id, &comp_id);
999
1000 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*improc),
1001 comp_id,
1002 BLOCK_INFO_INPUT_ID(blk->block_info),
1003 &d71_improc_funcs, IPS_NUM_INPUT_IDS,
1004 get_valid_inputs(blk),
1005 IPS_NUM_OUTPUT_IDS, reg, "DOU%d_IPS", pipe_id);
1006 if (IS_ERR(c)) {
1007 DRM_ERROR("Failed to add improc component\n");
1008 return PTR_ERR(c);
1009 }
1010
1011 improc = to_improc(c);
1012 improc->supported_color_depths = BIT(8) | BIT(10);
1013 improc->supported_color_formats = DRM_COLOR_FORMAT_RGB444 |
1014 DRM_COLOR_FORMAT_YCRCB444 |
1015 DRM_COLOR_FORMAT_YCRCB422;
1016 value = malidp_read32(reg, BLK_INFO);
1017 if (value & IPS_INFO_CHD420)
1018 improc->supported_color_formats |= DRM_COLOR_FORMAT_YCRCB420;
1019
1020 improc->supports_csc = true;
1021 improc->supports_gamma = true;
1022
1023 return 0;
1024}
1025
1026static void d71_timing_ctrlr_disable(struct komeda_component *c)
1027{
1028 malidp_write32_mask(c->reg, BLK_CONTROL, BS_CTRL_EN, 0);
1029}
1030
1031static void d71_timing_ctrlr_update(struct komeda_component *c,
1032 struct komeda_component_state *state)
1033{
1034 struct drm_crtc_state *crtc_st = state->crtc->state;
1035 u32 __iomem *reg = c->reg;
1036 struct videomode vm;
1037 u32 value;
1038
1039 drm_display_mode_to_videomode(&crtc_st->adjusted_mode, &vm);
1040
1041 malidp_write32(reg, BS_ACTIVESIZE, HV_SIZE(vm.hactive, vm.vactive));
1042 malidp_write32(reg, BS_HINTERVALS, BS_H_INTVALS(vm.hfront_porch,
1043 vm.hback_porch));
1044 malidp_write32(reg, BS_VINTERVALS, BS_V_INTVALS(vm.vfront_porch,
1045 vm.vback_porch));
1046
1047 value = BS_SYNC_VSW(vm.vsync_len) | BS_SYNC_HSW(vm.hsync_len);
1048 value |= vm.flags & DISPLAY_FLAGS_VSYNC_HIGH ? BS_SYNC_VSP : 0;
1049 value |= vm.flags & DISPLAY_FLAGS_HSYNC_HIGH ? BS_SYNC_HSP : 0;
1050 malidp_write32(reg, BS_SYNC, value);
1051
1052 malidp_write32(reg, BS_PROG_LINE, D71_DEFAULT_PREPRETCH_LINE - 1);
1053 malidp_write32(reg, BS_PREFETCH_LINE, D71_DEFAULT_PREPRETCH_LINE);
1054
1055
1056 value = BS_CTRL_EN | BS_CTRL_VM;
1057
1058 malidp_write32(reg, BLK_CONTROL, value);
1059}
1060
1061static void d71_timing_ctrlr_dump(struct komeda_component *c,
1062 struct seq_file *sf)
1063{
1064 u32 v[8], i;
1065
1066 dump_block_header(sf, c->reg);
1067
1068 get_values_from_reg(c->reg, 0xC0, 1, v);
1069 seq_printf(sf, "BS_INFO:\t\t0x%X\n", v[0]);
1070
1071 get_values_from_reg(c->reg, 0xD0, 8, v);
1072 seq_printf(sf, "BS_CONTROL:\t\t0x%X\n", v[0]);
1073 seq_printf(sf, "BS_PROG_LINE:\t\t0x%X\n", v[1]);
1074 seq_printf(sf, "BS_PREFETCH_LINE:\t0x%X\n", v[2]);
1075 seq_printf(sf, "BS_BG_COLOR:\t\t0x%X\n", v[3]);
1076 seq_printf(sf, "BS_ACTIVESIZE:\t\t0x%X\n", v[4]);
1077 seq_printf(sf, "BS_HINTERVALS:\t\t0x%X\n", v[5]);
1078 seq_printf(sf, "BS_VINTERVALS:\t\t0x%X\n", v[6]);
1079 seq_printf(sf, "BS_SYNC:\t\t0x%X\n", v[7]);
1080
1081 get_values_from_reg(c->reg, 0x100, 3, v);
1082 seq_printf(sf, "BS_DRIFT_TO:\t\t0x%X\n", v[0]);
1083 seq_printf(sf, "BS_FRAME_TO:\t\t0x%X\n", v[1]);
1084 seq_printf(sf, "BS_TE_TO:\t\t0x%X\n", v[2]);
1085
1086 get_values_from_reg(c->reg, 0x110, 3, v);
1087 for (i = 0; i < 3; i++)
1088 seq_printf(sf, "BS_T%u_INTERVAL:\t\t0x%X\n", i, v[i]);
1089
1090 get_values_from_reg(c->reg, 0x120, 5, v);
1091 for (i = 0; i < 2; i++) {
1092 seq_printf(sf, "BS_CRC%u_LOW:\t\t0x%X\n", i, v[i << 1]);
1093 seq_printf(sf, "BS_CRC%u_HIGH:\t\t0x%X\n", i, v[(i << 1) + 1]);
1094 }
1095 seq_printf(sf, "BS_USER:\t\t0x%X\n", v[4]);
1096}
1097
1098static const struct komeda_component_funcs d71_timing_ctrlr_funcs = {
1099 .update = d71_timing_ctrlr_update,
1100 .disable = d71_timing_ctrlr_disable,
1101 .dump_register = d71_timing_ctrlr_dump,
1102};
1103
1104static int d71_timing_ctrlr_init(struct d71_dev *d71,
1105 struct block_header *blk, u32 __iomem *reg)
1106{
1107 struct komeda_component *c;
1108 struct komeda_timing_ctrlr *ctrlr;
1109 u32 pipe_id, comp_id;
1110
1111 get_resources_id(blk->block_info, &pipe_id, &comp_id);
1112
1113 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*ctrlr),
1114 KOMEDA_COMPONENT_TIMING_CTRLR,
1115 BLOCK_INFO_INPUT_ID(blk->block_info),
1116 &d71_timing_ctrlr_funcs,
1117 1, BIT(KOMEDA_COMPONENT_IPS0 + pipe_id),
1118 BS_NUM_OUTPUT_IDS, reg, "DOU%d_BS", pipe_id);
1119 if (IS_ERR(c)) {
1120 DRM_ERROR("Failed to add display_ctrl component\n");
1121 return PTR_ERR(c);
1122 }
1123
1124 ctrlr = to_ctrlr(c);
1125
1126 ctrlr->supports_dual_link = true;
1127
1128 return 0;
1129}
1130
1131int d71_probe_block(struct d71_dev *d71,
1132 struct block_header *blk, u32 __iomem *reg)
1133{
1134 struct d71_pipeline *pipe;
1135 int blk_id = BLOCK_INFO_BLK_ID(blk->block_info);
1136
1137 int err = 0;
1138
1139 switch (BLOCK_INFO_BLK_TYPE(blk->block_info)) {
1140 case D71_BLK_TYPE_GCU:
1141 break;
1142
1143 case D71_BLK_TYPE_LPU:
1144 pipe = d71->pipes[blk_id];
1145 pipe->lpu_addr = reg;
1146 break;
1147
1148 case D71_BLK_TYPE_LPU_LAYER:
1149 err = d71_layer_init(d71, blk, reg);
1150 break;
1151
1152 case D71_BLK_TYPE_LPU_WB_LAYER:
1153 err = d71_wb_layer_init(d71, blk, reg);
1154 break;
1155
1156 case D71_BLK_TYPE_CU:
1157 pipe = d71->pipes[blk_id];
1158 pipe->cu_addr = reg;
1159 err = d71_compiz_init(d71, blk, reg);
1160 break;
1161
1162 case D71_BLK_TYPE_CU_SCALER:
1163 err = d71_scaler_init(d71, blk, reg);
1164 break;
1165
1166 case D71_BLK_TYPE_CU_SPLITTER:
1167 err = d71_splitter_init(d71, blk, reg);
1168 break;
1169
1170 case D71_BLK_TYPE_CU_MERGER:
1171 err = d71_merger_init(d71, blk, reg);
1172 break;
1173
1174 case D71_BLK_TYPE_DOU:
1175 pipe = d71->pipes[blk_id];
1176 pipe->dou_addr = reg;
1177 break;
1178
1179 case D71_BLK_TYPE_DOU_IPS:
1180 err = d71_improc_init(d71, blk, reg);
1181 break;
1182
1183 case D71_BLK_TYPE_DOU_FT_COEFF:
1184 pipe = d71->pipes[blk_id];
1185 pipe->dou_ft_coeff_addr = reg;
1186 break;
1187
1188 case D71_BLK_TYPE_DOU_BS:
1189 err = d71_timing_ctrlr_init(d71, blk, reg);
1190 break;
1191
1192 case D71_BLK_TYPE_GLB_LT_COEFF:
1193 break;
1194
1195 case D71_BLK_TYPE_GLB_SCL_COEFF:
1196 d71->glb_scl_coeff_addr[blk_id] = reg;
1197 break;
1198
1199 default:
1200 DRM_ERROR("Unknown block (block_info: 0x%x) is found\n",
1201 blk->block_info);
1202 err = -EINVAL;
1203 break;
1204 }
1205
1206 return err;
1207}
1208
1209const struct komeda_pipeline_funcs d71_pipeline_funcs = {
1210 .downscaling_clk_check = d71_downscaling_clk_check,
1211};
1212