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