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 #include <linux/of.h> 8 #include <linux/seq_file.h> 9 10 #include <drm/drm_print.h> 11 12 #include "komeda_dev.h" 13 #include "komeda_pipeline.h" 14 15 /** komeda_pipeline_add - Add a pipeline to &komeda_dev */ 16 struct komeda_pipeline * 17 komeda_pipeline_add(struct komeda_dev *mdev, size_t size, 18 const struct komeda_pipeline_funcs *funcs) 19 { 20 struct komeda_pipeline *pipe; 21 22 if (mdev->n_pipelines + 1 > KOMEDA_MAX_PIPELINES) { 23 DRM_ERROR("Exceed max support %d pipelines.\n", 24 KOMEDA_MAX_PIPELINES); 25 return ERR_PTR(-ENOSPC); 26 } 27 28 if (size < sizeof(*pipe)) { 29 DRM_ERROR("Request pipeline size too small.\n"); 30 return ERR_PTR(-EINVAL); 31 } 32 33 pipe = devm_kzalloc(mdev->dev, size, GFP_KERNEL); 34 if (!pipe) 35 return ERR_PTR(-ENOMEM); 36 37 pipe->mdev = mdev; 38 pipe->id = mdev->n_pipelines; 39 pipe->funcs = funcs; 40 41 mdev->pipelines[mdev->n_pipelines] = pipe; 42 mdev->n_pipelines++; 43 44 return pipe; 45 } 46 47 void komeda_pipeline_destroy(struct komeda_dev *mdev, 48 struct komeda_pipeline *pipe) 49 { 50 struct komeda_component *c; 51 int i; 52 unsigned long avail_comps = pipe->avail_comps; 53 54 for_each_set_bit(i, &avail_comps, 32) { 55 c = komeda_pipeline_get_component(pipe, i); 56 komeda_component_destroy(mdev, c); 57 } 58 59 clk_put(pipe->pxlclk); 60 61 of_node_put(pipe->of_output_links[0]); 62 of_node_put(pipe->of_output_links[1]); 63 of_node_put(pipe->of_output_port); 64 of_node_put(pipe->of_node); 65 66 devm_kfree(mdev->dev, pipe); 67 } 68 69 static struct komeda_component ** 70 komeda_pipeline_get_component_pos(struct komeda_pipeline *pipe, int id) 71 { 72 struct komeda_dev *mdev = pipe->mdev; 73 struct komeda_pipeline *temp = NULL; 74 struct komeda_component **pos = NULL; 75 76 switch (id) { 77 case KOMEDA_COMPONENT_LAYER0: 78 case KOMEDA_COMPONENT_LAYER1: 79 case KOMEDA_COMPONENT_LAYER2: 80 case KOMEDA_COMPONENT_LAYER3: 81 pos = to_cpos(pipe->layers[id - KOMEDA_COMPONENT_LAYER0]); 82 break; 83 case KOMEDA_COMPONENT_WB_LAYER: 84 pos = to_cpos(pipe->wb_layer); 85 break; 86 case KOMEDA_COMPONENT_COMPIZ0: 87 case KOMEDA_COMPONENT_COMPIZ1: 88 temp = mdev->pipelines[id - KOMEDA_COMPONENT_COMPIZ0]; 89 if (!temp) { 90 DRM_ERROR("compiz-%d doesn't exist.\n", id); 91 return NULL; 92 } 93 pos = to_cpos(temp->compiz); 94 break; 95 case KOMEDA_COMPONENT_SCALER0: 96 case KOMEDA_COMPONENT_SCALER1: 97 pos = to_cpos(pipe->scalers[id - KOMEDA_COMPONENT_SCALER0]); 98 break; 99 case KOMEDA_COMPONENT_SPLITTER: 100 pos = to_cpos(pipe->splitter); 101 break; 102 case KOMEDA_COMPONENT_MERGER: 103 pos = to_cpos(pipe->merger); 104 break; 105 case KOMEDA_COMPONENT_IPS0: 106 case KOMEDA_COMPONENT_IPS1: 107 temp = mdev->pipelines[id - KOMEDA_COMPONENT_IPS0]; 108 if (!temp) { 109 DRM_ERROR("ips-%d doesn't exist.\n", id); 110 return NULL; 111 } 112 pos = to_cpos(temp->improc); 113 break; 114 case KOMEDA_COMPONENT_TIMING_CTRLR: 115 pos = to_cpos(pipe->ctrlr); 116 break; 117 default: 118 pos = NULL; 119 DRM_ERROR("Unknown pipeline resource ID: %d.\n", id); 120 break; 121 } 122 123 return pos; 124 } 125 126 struct komeda_component * 127 komeda_pipeline_get_component(struct komeda_pipeline *pipe, int id) 128 { 129 struct komeda_component **pos = NULL; 130 struct komeda_component *c = NULL; 131 132 pos = komeda_pipeline_get_component_pos(pipe, id); 133 if (pos) 134 c = *pos; 135 136 return c; 137 } 138 139 struct komeda_component * 140 komeda_pipeline_get_first_component(struct komeda_pipeline *pipe, 141 u32 comp_mask) 142 { 143 struct komeda_component *c = NULL; 144 unsigned long comp_mask_local = (unsigned long)comp_mask; 145 int id; 146 147 id = find_first_bit(&comp_mask_local, 32); 148 if (id < 32) 149 c = komeda_pipeline_get_component(pipe, id); 150 151 return c; 152 } 153 154 static struct komeda_component * 155 komeda_component_pickup_input(struct komeda_component *c, u32 avail_comps) 156 { 157 u32 avail_inputs = c->supported_inputs & (avail_comps); 158 159 return komeda_pipeline_get_first_component(c->pipeline, avail_inputs); 160 } 161 162 /** komeda_component_add - Add a component to &komeda_pipeline */ 163 struct komeda_component * 164 komeda_component_add(struct komeda_pipeline *pipe, 165 size_t comp_sz, u32 id, u32 hw_id, 166 const struct komeda_component_funcs *funcs, 167 u8 max_active_inputs, u32 supported_inputs, 168 u8 max_active_outputs, u32 __iomem *reg, 169 const char *name_fmt, ...) 170 { 171 struct komeda_component **pos; 172 struct komeda_component *c; 173 int idx, *num = NULL; 174 175 if (max_active_inputs > KOMEDA_COMPONENT_N_INPUTS) { 176 WARN(1, "please large KOMEDA_COMPONENT_N_INPUTS to %d.\n", 177 max_active_inputs); 178 return ERR_PTR(-ENOSPC); 179 } 180 181 pos = komeda_pipeline_get_component_pos(pipe, id); 182 if (!pos || (*pos)) 183 return ERR_PTR(-EINVAL); 184 185 if (has_bit(id, KOMEDA_PIPELINE_LAYERS)) { 186 idx = id - KOMEDA_COMPONENT_LAYER0; 187 num = &pipe->n_layers; 188 if (idx != pipe->n_layers) { 189 DRM_ERROR("please add Layer by id sequence.\n"); 190 return ERR_PTR(-EINVAL); 191 } 192 } else if (has_bit(id, KOMEDA_PIPELINE_SCALERS)) { 193 idx = id - KOMEDA_COMPONENT_SCALER0; 194 num = &pipe->n_scalers; 195 if (idx != pipe->n_scalers) { 196 DRM_ERROR("please add Scaler by id sequence.\n"); 197 return ERR_PTR(-EINVAL); 198 } 199 } 200 201 c = devm_kzalloc(pipe->mdev->dev, comp_sz, GFP_KERNEL); 202 if (!c) 203 return ERR_PTR(-ENOMEM); 204 205 c->id = id; 206 c->hw_id = hw_id; 207 c->reg = reg; 208 c->pipeline = pipe; 209 c->max_active_inputs = max_active_inputs; 210 c->max_active_outputs = max_active_outputs; 211 c->supported_inputs = supported_inputs; 212 c->funcs = funcs; 213 214 if (name_fmt) { 215 va_list args; 216 217 va_start(args, name_fmt); 218 vsnprintf(c->name, sizeof(c->name), name_fmt, args); 219 va_end(args); 220 } 221 222 if (num) 223 *num = *num + 1; 224 225 pipe->avail_comps |= BIT(c->id); 226 *pos = c; 227 228 return c; 229 } 230 231 void komeda_component_destroy(struct komeda_dev *mdev, 232 struct komeda_component *c) 233 { 234 devm_kfree(mdev->dev, c); 235 } 236 237 static void komeda_component_dump(struct komeda_component *c) 238 { 239 if (!c) 240 return; 241 242 DRM_DEBUG(" %s: ID %d-0x%08lx.\n", 243 c->name, c->id, BIT(c->id)); 244 DRM_DEBUG(" max_active_inputs:%d, supported_inputs: 0x%08x.\n", 245 c->max_active_inputs, c->supported_inputs); 246 DRM_DEBUG(" max_active_outputs:%d, supported_outputs: 0x%08x.\n", 247 c->max_active_outputs, c->supported_outputs); 248 } 249 250 static void komeda_pipeline_dump(struct komeda_pipeline *pipe) 251 { 252 struct komeda_component *c; 253 int id; 254 unsigned long avail_comps = pipe->avail_comps; 255 256 DRM_INFO("Pipeline-%d: n_layers: %d, n_scalers: %d, output: %s.\n", 257 pipe->id, pipe->n_layers, pipe->n_scalers, 258 pipe->dual_link ? "dual-link" : "single-link"); 259 DRM_INFO(" output_link[0]: %s.\n", 260 pipe->of_output_links[0] ? 261 pipe->of_output_links[0]->full_name : "none"); 262 DRM_INFO(" output_link[1]: %s.\n", 263 pipe->of_output_links[1] ? 264 pipe->of_output_links[1]->full_name : "none"); 265 266 for_each_set_bit(id, &avail_comps, 32) { 267 c = komeda_pipeline_get_component(pipe, id); 268 269 komeda_component_dump(c); 270 } 271 } 272 273 static void komeda_component_verify_inputs(struct komeda_component *c) 274 { 275 struct komeda_pipeline *pipe = c->pipeline; 276 struct komeda_component *input; 277 int id; 278 unsigned long supported_inputs = c->supported_inputs; 279 280 for_each_set_bit(id, &supported_inputs, 32) { 281 input = komeda_pipeline_get_component(pipe, id); 282 if (!input) { 283 c->supported_inputs &= ~(BIT(id)); 284 DRM_WARN("Can not find input(ID-%d) for component: %s.\n", 285 id, c->name); 286 continue; 287 } 288 289 input->supported_outputs |= BIT(c->id); 290 } 291 } 292 293 static struct komeda_layer * 294 komeda_get_layer_split_right_layer(struct komeda_pipeline *pipe, 295 struct komeda_layer *left) 296 { 297 int index = left->base.id - KOMEDA_COMPONENT_LAYER0; 298 int i; 299 300 for (i = index + 1; i < pipe->n_layers; i++) 301 if (left->layer_type == pipe->layers[i]->layer_type) 302 return pipe->layers[i]; 303 return NULL; 304 } 305 306 static void komeda_pipeline_assemble(struct komeda_pipeline *pipe) 307 { 308 struct komeda_component *c; 309 struct komeda_layer *layer; 310 int i, id; 311 unsigned long avail_comps = pipe->avail_comps; 312 313 for_each_set_bit(id, &avail_comps, 32) { 314 c = komeda_pipeline_get_component(pipe, id); 315 komeda_component_verify_inputs(c); 316 } 317 /* calculate right layer for the layer split */ 318 for (i = 0; i < pipe->n_layers; i++) { 319 layer = pipe->layers[i]; 320 321 layer->right = komeda_get_layer_split_right_layer(pipe, layer); 322 } 323 324 if (pipe->dual_link && !pipe->ctrlr->supports_dual_link) { 325 pipe->dual_link = false; 326 DRM_WARN("PIPE-%d doesn't support dual-link, ignore DT dual-link configuration.\n", 327 pipe->id); 328 } 329 } 330 331 /* if pipeline_A accept another pipeline_B's component as input, treat 332 * pipeline_B as slave of pipeline_A. 333 */ 334 struct komeda_pipeline * 335 komeda_pipeline_get_slave(struct komeda_pipeline *master) 336 { 337 struct komeda_component *slave; 338 339 slave = komeda_component_pickup_input(&master->compiz->base, 340 KOMEDA_PIPELINE_COMPIZS); 341 342 return slave ? slave->pipeline : NULL; 343 } 344 345 int komeda_assemble_pipelines(struct komeda_dev *mdev) 346 { 347 struct komeda_pipeline *pipe; 348 int i; 349 350 for (i = 0; i < mdev->n_pipelines; i++) { 351 pipe = mdev->pipelines[i]; 352 353 komeda_pipeline_assemble(pipe); 354 komeda_pipeline_dump(pipe); 355 } 356 357 return 0; 358 } 359 360 void komeda_pipeline_dump_register(struct komeda_pipeline *pipe, 361 struct seq_file *sf) 362 { 363 struct komeda_component *c; 364 u32 id; 365 unsigned long avail_comps; 366 367 seq_printf(sf, "\n======== Pipeline-%d ==========\n", pipe->id); 368 369 if (pipe->funcs && pipe->funcs->dump_register) 370 pipe->funcs->dump_register(pipe, sf); 371 372 avail_comps = pipe->avail_comps; 373 for_each_set_bit(id, &avail_comps, 32) { 374 c = komeda_pipeline_get_component(pipe, id); 375 376 seq_printf(sf, "\n------%s------\n", c->name); 377 if (c->funcs->dump_register) 378 c->funcs->dump_register(c, sf); 379 } 380 } 381