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 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 clk_put(pipe->aclk); 57 58 of_node_put(pipe->of_output_dev); 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_IPS0: 96 case KOMEDA_COMPONENT_IPS1: 97 temp = mdev->pipelines[id - KOMEDA_COMPONENT_IPS0]; 98 if (!temp) { 99 DRM_ERROR("ips-%d doesn't exist.\n", id); 100 return NULL; 101 } 102 pos = to_cpos(temp->improc); 103 break; 104 case KOMEDA_COMPONENT_TIMING_CTRLR: 105 pos = to_cpos(pipe->ctrlr); 106 break; 107 default: 108 pos = NULL; 109 DRM_ERROR("Unknown pipeline resource ID: %d.\n", id); 110 break; 111 } 112 113 return pos; 114 } 115 116 struct komeda_component * 117 komeda_pipeline_get_component(struct komeda_pipeline *pipe, int id) 118 { 119 struct komeda_component **pos = NULL; 120 struct komeda_component *c = NULL; 121 122 pos = komeda_pipeline_get_component_pos(pipe, id); 123 if (pos) 124 c = *pos; 125 126 return c; 127 } 128 129 /** komeda_component_add - Add a component to &komeda_pipeline */ 130 struct komeda_component * 131 komeda_component_add(struct komeda_pipeline *pipe, 132 size_t comp_sz, u32 id, u32 hw_id, 133 struct komeda_component_funcs *funcs, 134 u8 max_active_inputs, u32 supported_inputs, 135 u8 max_active_outputs, u32 __iomem *reg, 136 const char *name_fmt, ...) 137 { 138 struct komeda_component **pos; 139 struct komeda_component *c; 140 int idx, *num = NULL; 141 142 if (max_active_inputs > KOMEDA_COMPONENT_N_INPUTS) { 143 WARN(1, "please large KOMEDA_COMPONENT_N_INPUTS to %d.\n", 144 max_active_inputs); 145 return ERR_PTR(-ENOSPC); 146 } 147 148 pos = komeda_pipeline_get_component_pos(pipe, id); 149 if (!pos || (*pos)) 150 return ERR_PTR(-EINVAL); 151 152 if (has_bit(id, KOMEDA_PIPELINE_LAYERS)) { 153 idx = id - KOMEDA_COMPONENT_LAYER0; 154 num = &pipe->n_layers; 155 if (idx != pipe->n_layers) { 156 DRM_ERROR("please add Layer by id sequence.\n"); 157 return ERR_PTR(-EINVAL); 158 } 159 } else if (has_bit(id, KOMEDA_PIPELINE_SCALERS)) { 160 idx = id - KOMEDA_COMPONENT_SCALER0; 161 num = &pipe->n_scalers; 162 if (idx != pipe->n_scalers) { 163 DRM_ERROR("please add Scaler by id sequence.\n"); 164 return ERR_PTR(-EINVAL); 165 } 166 } 167 168 c = devm_kzalloc(pipe->mdev->dev, comp_sz, GFP_KERNEL); 169 if (!c) 170 return ERR_PTR(-ENOMEM); 171 172 c->id = id; 173 c->hw_id = hw_id; 174 c->reg = reg; 175 c->pipeline = pipe; 176 c->max_active_inputs = max_active_inputs; 177 c->max_active_outputs = max_active_outputs; 178 c->supported_inputs = supported_inputs; 179 c->funcs = funcs; 180 181 if (name_fmt) { 182 va_list args; 183 184 va_start(args, name_fmt); 185 vsnprintf(c->name, sizeof(c->name), name_fmt, args); 186 va_end(args); 187 } 188 189 if (num) 190 *num = *num + 1; 191 192 pipe->avail_comps |= BIT(c->id); 193 *pos = c; 194 195 return c; 196 } 197 198 void komeda_component_destroy(struct komeda_dev *mdev, 199 struct komeda_component *c) 200 { 201 devm_kfree(mdev->dev, c); 202 } 203 204 static void komeda_component_dump(struct komeda_component *c) 205 { 206 if (!c) 207 return; 208 209 DRM_DEBUG(" %s: ID %d-0x%08lx.\n", 210 c->name, c->id, BIT(c->id)); 211 DRM_DEBUG(" max_active_inputs:%d, supported_inputs: 0x%08x.\n", 212 c->max_active_inputs, c->supported_inputs); 213 DRM_DEBUG(" max_active_outputs:%d, supported_outputs: 0x%08x.\n", 214 c->max_active_outputs, c->supported_outputs); 215 } 216 217 static void komeda_pipeline_dump(struct komeda_pipeline *pipe) 218 { 219 struct komeda_component *c; 220 int id; 221 222 DRM_INFO("Pipeline-%d: n_layers: %d, n_scalers: %d, output: %s\n", 223 pipe->id, pipe->n_layers, pipe->n_scalers, 224 pipe->of_output_dev ? pipe->of_output_dev->full_name : "none"); 225 226 dp_for_each_set_bit(id, pipe->avail_comps) { 227 c = komeda_pipeline_get_component(pipe, id); 228 229 komeda_component_dump(c); 230 } 231 } 232 233 static void komeda_component_verify_inputs(struct komeda_component *c) 234 { 235 struct komeda_pipeline *pipe = c->pipeline; 236 struct komeda_component *input; 237 int id; 238 239 dp_for_each_set_bit(id, c->supported_inputs) { 240 input = komeda_pipeline_get_component(pipe, id); 241 if (!input) { 242 c->supported_inputs &= ~(BIT(id)); 243 DRM_WARN("Can not find input(ID-%d) for component: %s.\n", 244 id, c->name); 245 continue; 246 } 247 248 input->supported_outputs |= BIT(c->id); 249 } 250 } 251 252 static void komeda_pipeline_assemble(struct komeda_pipeline *pipe) 253 { 254 struct komeda_component *c; 255 int id; 256 257 dp_for_each_set_bit(id, pipe->avail_comps) { 258 c = komeda_pipeline_get_component(pipe, id); 259 260 komeda_component_verify_inputs(c); 261 } 262 } 263 264 int komeda_assemble_pipelines(struct komeda_dev *mdev) 265 { 266 struct komeda_pipeline *pipe; 267 int i; 268 269 for (i = 0; i < mdev->n_pipelines; i++) { 270 pipe = mdev->pipelines[i]; 271 272 komeda_pipeline_assemble(pipe); 273 komeda_pipeline_dump(pipe); 274 } 275 276 return 0; 277 } 278 279 void komeda_pipeline_dump_register(struct komeda_pipeline *pipe, 280 struct seq_file *sf) 281 { 282 struct komeda_component *c; 283 u32 id; 284 285 seq_printf(sf, "\n======== Pipeline-%d ==========\n", pipe->id); 286 287 if (pipe->funcs && pipe->funcs->dump_register) 288 pipe->funcs->dump_register(pipe, sf); 289 290 dp_for_each_set_bit(id, pipe->avail_comps) { 291 c = komeda_pipeline_get_component(pipe, id); 292 293 seq_printf(sf, "\n------%s------\n", c->name); 294 if (c->funcs->dump_register) 295 c->funcs->dump_register(c, sf); 296 } 297 } 298