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