]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
drm/komeda: Add d71 layer
[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
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 u32 to_rot_ctrl(u32 rot)
75 {
76         u32 lr_ctrl = 0;
77
78         switch (rot & DRM_MODE_ROTATE_MASK) {
79         case DRM_MODE_ROTATE_0:
80                 lr_ctrl |= L_ROT(L_ROT_R0);
81                 break;
82         case DRM_MODE_ROTATE_90:
83                 lr_ctrl |= L_ROT(L_ROT_R90);
84                 break;
85         case DRM_MODE_ROTATE_180:
86                 lr_ctrl |= L_ROT(L_ROT_R180);
87                 break;
88         case DRM_MODE_ROTATE_270:
89                 lr_ctrl |= L_ROT(L_ROT_R270);
90                 break;
91         }
92
93         if (rot & DRM_MODE_REFLECT_X)
94                 lr_ctrl |= L_HFLIP;
95         if (rot & DRM_MODE_REFLECT_Y)
96                 lr_ctrl |= L_VFLIP;
97
98         return lr_ctrl;
99 }
100
101 static void d71_layer_disable(struct komeda_component *c)
102 {
103         malidp_write32_mask(c->reg, BLK_CONTROL, L_EN, 0);
104 }
105
106 static void d71_layer_update(struct komeda_component *c,
107                              struct komeda_component_state *state)
108 {
109         struct komeda_layer_state *st = to_layer_st(state);
110         struct drm_plane_state *plane_st = state->plane->state;
111         struct drm_framebuffer *fb = plane_st->fb;
112         struct komeda_fb *kfb = to_kfb(fb);
113         u32 __iomem *reg = c->reg;
114         u32 ctrl_mask = L_EN | L_ROT(L_ROT_R270) | L_HFLIP | L_VFLIP | L_TBU_EN;
115         u32 ctrl = L_EN | to_rot_ctrl(st->rot);
116         int i;
117
118         for (i = 0; i < fb->format->num_planes; i++) {
119                 malidp_write32(reg,
120                                BLK_P0_PTR_LOW + i * LAYER_PER_PLANE_REGS * 4,
121                                lower_32_bits(st->addr[i]));
122                 malidp_write32(reg,
123                                BLK_P0_PTR_HIGH + i * LAYER_PER_PLANE_REGS * 4,
124                                upper_32_bits(st->addr[i]));
125                 if (i >= 2)
126                         break;
127
128                 malidp_write32(reg,
129                                BLK_P0_STRIDE + i * LAYER_PER_PLANE_REGS * 4,
130                                fb->pitches[i] & 0xFFFF);
131         }
132
133         malidp_write32(reg, LAYER_FMT, kfb->format_caps->hw_id);
134         malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize, st->vsize));
135
136         malidp_write32_mask(reg, BLK_CONTROL, ctrl_mask, ctrl);
137 }
138
139 static struct komeda_component_funcs d71_layer_funcs = {
140         .update         = d71_layer_update,
141         .disable        = d71_layer_disable,
142 };
143
144 static int d71_layer_init(struct d71_dev *d71,
145                           struct block_header *blk, u32 __iomem *reg)
146 {
147         struct komeda_component *c;
148         struct komeda_layer *layer;
149         u32 pipe_id, layer_id, layer_info;
150
151         get_resources_id(blk->block_info, &pipe_id, &layer_id);
152         c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*layer),
153                                  layer_id,
154                                  BLOCK_INFO_INPUT_ID(blk->block_info),
155                                  &d71_layer_funcs, 0,
156                                  get_valid_inputs(blk),
157                                  1, reg, "LPU%d_LAYER%d", pipe_id, layer_id);
158         if (IS_ERR(c)) {
159                 DRM_ERROR("Failed to add layer component\n");
160                 return PTR_ERR(c);
161         }
162
163         layer = to_layer(c);
164         layer_info = malidp_read32(reg, LAYER_INFO);
165
166         if (layer_info & L_INFO_RF)
167                 layer->layer_type = KOMEDA_FMT_RICH_LAYER;
168         else
169                 layer->layer_type = KOMEDA_FMT_SIMPLE_LAYER;
170
171         set_range(&layer->hsize_in, 4, d71->max_line_size);
172         set_range(&layer->vsize_in, 4, d71->max_vsize);
173
174         malidp_write32(reg, LAYER_PALPHA, D71_PALPHA_DEF_MAP);
175
176         layer->supported_rots = DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK;
177
178         return 0;
179 }
180
181 static int d71_wb_layer_init(struct d71_dev *d71,
182                              struct block_header *blk, u32 __iomem *reg)
183 {
184         DRM_DEBUG("Detect D71_Wb_Layer.\n");
185
186         return 0;
187 }
188
189 static int d71_compiz_init(struct d71_dev *d71,
190                            struct block_header *blk, u32 __iomem *reg)
191 {
192         DRM_DEBUG("Detect D71_compiz.\n");
193
194         return 0;
195 }
196
197 static int d71_improc_init(struct d71_dev *d71,
198                            struct block_header *blk, u32 __iomem *reg)
199 {
200         DRM_DEBUG("Detect D71_improc.\n");
201
202         return 0;
203 }
204
205 static int d71_timing_ctrlr_init(struct d71_dev *d71,
206                                  struct block_header *blk, u32 __iomem *reg)
207 {
208         DRM_DEBUG("Detect D71_timing_ctrlr.\n");
209
210         return 0;
211 }
212
213 int d71_probe_block(struct d71_dev *d71,
214                     struct block_header *blk, u32 __iomem *reg)
215 {
216         struct d71_pipeline *pipe;
217         int blk_id = BLOCK_INFO_BLK_ID(blk->block_info);
218
219         int err = 0;
220
221         switch (BLOCK_INFO_BLK_TYPE(blk->block_info)) {
222         case D71_BLK_TYPE_GCU:
223                 break;
224
225         case D71_BLK_TYPE_LPU:
226                 pipe = d71->pipes[blk_id];
227                 pipe->lpu_addr = reg;
228                 break;
229
230         case D71_BLK_TYPE_LPU_LAYER:
231                 err = d71_layer_init(d71, blk, reg);
232                 break;
233
234         case D71_BLK_TYPE_LPU_WB_LAYER:
235                 err = d71_wb_layer_init(d71, blk, reg);
236                 break;
237
238         case D71_BLK_TYPE_CU:
239                 pipe = d71->pipes[blk_id];
240                 pipe->cu_addr = reg;
241                 err = d71_compiz_init(d71, blk, reg);
242                 break;
243
244         case D71_BLK_TYPE_CU_SPLITTER:
245         case D71_BLK_TYPE_CU_SCALER:
246         case D71_BLK_TYPE_CU_MERGER:
247                 break;
248
249         case D71_BLK_TYPE_DOU:
250                 pipe = d71->pipes[blk_id];
251                 pipe->dou_addr = reg;
252                 break;
253
254         case D71_BLK_TYPE_DOU_IPS:
255                 err = d71_improc_init(d71, blk, reg);
256                 break;
257
258         case D71_BLK_TYPE_DOU_FT_COEFF:
259                 pipe = d71->pipes[blk_id];
260                 pipe->dou_ft_coeff_addr = reg;
261                 break;
262
263         case D71_BLK_TYPE_DOU_BS:
264                 err = d71_timing_ctrlr_init(d71, blk, reg);
265                 break;
266
267         case D71_BLK_TYPE_GLB_LT_COEFF:
268                 break;
269
270         case D71_BLK_TYPE_GLB_SCL_COEFF:
271                 d71->glb_scl_coeff_addr[blk_id] = reg;
272                 break;
273
274         default:
275                 DRM_ERROR("Unknown block (block_info: 0x%x) is found\n",
276                           blk->block_info);
277                 err = -EINVAL;
278                 break;
279         }
280
281         return err;
282 }