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