root/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. komeda_pipeline_add
  2. komeda_pipeline_destroy
  3. komeda_pipeline_get_component_pos
  4. komeda_pipeline_get_component
  5. komeda_pipeline_get_first_component
  6. komeda_component_pickup_input
  7. komeda_component_add
  8. komeda_component_destroy
  9. komeda_component_dump
  10. komeda_pipeline_dump
  11. komeda_component_verify_inputs
  12. komeda_get_layer_split_right_layer
  13. komeda_pipeline_assemble
  14. komeda_pipeline_get_slave
  15. komeda_assemble_pipelines
  16. komeda_pipeline_dump_register

   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         int id;
 141 
 142         id = find_first_bit((unsigned long *)&comp_mask, 32);
 143         if (id < 32)
 144                 c = komeda_pipeline_get_component(pipe, id);
 145 
 146         return c;
 147 }
 148 
 149 static struct komeda_component *
 150 komeda_component_pickup_input(struct komeda_component *c, u32 avail_comps)
 151 {
 152         u32 avail_inputs = c->supported_inputs & (avail_comps);
 153 
 154         return komeda_pipeline_get_first_component(c->pipeline, avail_inputs);
 155 }
 156 
 157 /** komeda_component_add - Add a component to &komeda_pipeline */
 158 struct komeda_component *
 159 komeda_component_add(struct komeda_pipeline *pipe,
 160                      size_t comp_sz, u32 id, u32 hw_id,
 161                      const struct komeda_component_funcs *funcs,
 162                      u8 max_active_inputs, u32 supported_inputs,
 163                      u8 max_active_outputs, u32 __iomem *reg,
 164                      const char *name_fmt, ...)
 165 {
 166         struct komeda_component **pos;
 167         struct komeda_component *c;
 168         int idx, *num = NULL;
 169 
 170         if (max_active_inputs > KOMEDA_COMPONENT_N_INPUTS) {
 171                 WARN(1, "please large KOMEDA_COMPONENT_N_INPUTS to %d.\n",
 172                      max_active_inputs);
 173                 return ERR_PTR(-ENOSPC);
 174         }
 175 
 176         pos = komeda_pipeline_get_component_pos(pipe, id);
 177         if (!pos || (*pos))
 178                 return ERR_PTR(-EINVAL);
 179 
 180         if (has_bit(id, KOMEDA_PIPELINE_LAYERS)) {
 181                 idx = id - KOMEDA_COMPONENT_LAYER0;
 182                 num = &pipe->n_layers;
 183                 if (idx != pipe->n_layers) {
 184                         DRM_ERROR("please add Layer by id sequence.\n");
 185                         return ERR_PTR(-EINVAL);
 186                 }
 187         } else if (has_bit(id,  KOMEDA_PIPELINE_SCALERS)) {
 188                 idx = id - KOMEDA_COMPONENT_SCALER0;
 189                 num = &pipe->n_scalers;
 190                 if (idx != pipe->n_scalers) {
 191                         DRM_ERROR("please add Scaler by id sequence.\n");
 192                         return ERR_PTR(-EINVAL);
 193                 }
 194         }
 195 
 196         c = devm_kzalloc(pipe->mdev->dev, comp_sz, GFP_KERNEL);
 197         if (!c)
 198                 return ERR_PTR(-ENOMEM);
 199 
 200         c->id = id;
 201         c->hw_id = hw_id;
 202         c->reg = reg;
 203         c->pipeline = pipe;
 204         c->max_active_inputs = max_active_inputs;
 205         c->max_active_outputs = max_active_outputs;
 206         c->supported_inputs = supported_inputs;
 207         c->funcs = funcs;
 208 
 209         if (name_fmt) {
 210                 va_list args;
 211 
 212                 va_start(args, name_fmt);
 213                 vsnprintf(c->name, sizeof(c->name), name_fmt, args);
 214                 va_end(args);
 215         }
 216 
 217         if (num)
 218                 *num = *num + 1;
 219 
 220         pipe->avail_comps |= BIT(c->id);
 221         *pos = c;
 222 
 223         return c;
 224 }
 225 
 226 void komeda_component_destroy(struct komeda_dev *mdev,
 227                               struct komeda_component *c)
 228 {
 229         devm_kfree(mdev->dev, c);
 230 }
 231 
 232 static void komeda_component_dump(struct komeda_component *c)
 233 {
 234         if (!c)
 235                 return;
 236 
 237         DRM_DEBUG("     %s: ID %d-0x%08lx.\n",
 238                   c->name, c->id, BIT(c->id));
 239         DRM_DEBUG("             max_active_inputs:%d, supported_inputs: 0x%08x.\n",
 240                   c->max_active_inputs, c->supported_inputs);
 241         DRM_DEBUG("             max_active_outputs:%d, supported_outputs: 0x%08x.\n",
 242                   c->max_active_outputs, c->supported_outputs);
 243 }
 244 
 245 static void komeda_pipeline_dump(struct komeda_pipeline *pipe)
 246 {
 247         struct komeda_component *c;
 248         int id;
 249 
 250         DRM_INFO("Pipeline-%d: n_layers: %d, n_scalers: %d, output: %s.\n",
 251                  pipe->id, pipe->n_layers, pipe->n_scalers,
 252                  pipe->dual_link ? "dual-link" : "single-link");
 253         DRM_INFO("      output_link[0]: %s.\n",
 254                  pipe->of_output_links[0] ?
 255                  pipe->of_output_links[0]->full_name : "none");
 256         DRM_INFO("      output_link[1]: %s.\n",
 257                  pipe->of_output_links[1] ?
 258                  pipe->of_output_links[1]->full_name : "none");
 259 
 260         dp_for_each_set_bit(id, pipe->avail_comps) {
 261                 c = komeda_pipeline_get_component(pipe, id);
 262 
 263                 komeda_component_dump(c);
 264         }
 265 }
 266 
 267 static void komeda_component_verify_inputs(struct komeda_component *c)
 268 {
 269         struct komeda_pipeline *pipe = c->pipeline;
 270         struct komeda_component *input;
 271         int id;
 272 
 273         dp_for_each_set_bit(id, c->supported_inputs) {
 274                 input = komeda_pipeline_get_component(pipe, id);
 275                 if (!input) {
 276                         c->supported_inputs &= ~(BIT(id));
 277                         DRM_WARN("Can not find input(ID-%d) for component: %s.\n",
 278                                  id, c->name);
 279                         continue;
 280                 }
 281 
 282                 input->supported_outputs |= BIT(c->id);
 283         }
 284 }
 285 
 286 static struct komeda_layer *
 287 komeda_get_layer_split_right_layer(struct komeda_pipeline *pipe,
 288                                    struct komeda_layer *left)
 289 {
 290         int index = left->base.id - KOMEDA_COMPONENT_LAYER0;
 291         int i;
 292 
 293         for (i = index + 1; i < pipe->n_layers; i++)
 294                 if (left->layer_type == pipe->layers[i]->layer_type)
 295                         return pipe->layers[i];
 296         return NULL;
 297 }
 298 
 299 static void komeda_pipeline_assemble(struct komeda_pipeline *pipe)
 300 {
 301         struct komeda_component *c;
 302         struct komeda_layer *layer;
 303         int i, id;
 304 
 305         dp_for_each_set_bit(id, pipe->avail_comps) {
 306                 c = komeda_pipeline_get_component(pipe, id);
 307                 komeda_component_verify_inputs(c);
 308         }
 309         /* calculate right layer for the layer split */
 310         for (i = 0; i < pipe->n_layers; i++) {
 311                 layer = pipe->layers[i];
 312 
 313                 layer->right = komeda_get_layer_split_right_layer(pipe, layer);
 314         }
 315 
 316         if (pipe->dual_link && !pipe->ctrlr->supports_dual_link) {
 317                 pipe->dual_link = false;
 318                 DRM_WARN("PIPE-%d doesn't support dual-link, ignore DT dual-link configuration.\n",
 319                          pipe->id);
 320         }
 321 }
 322 
 323 /* if pipeline_A accept another pipeline_B's component as input, treat
 324  * pipeline_B as slave of pipeline_A.
 325  */
 326 struct komeda_pipeline *
 327 komeda_pipeline_get_slave(struct komeda_pipeline *master)
 328 {
 329         struct komeda_component *slave;
 330 
 331         slave = komeda_component_pickup_input(&master->compiz->base,
 332                                               KOMEDA_PIPELINE_COMPIZS);
 333 
 334         return slave ? slave->pipeline : NULL;
 335 }
 336 
 337 int komeda_assemble_pipelines(struct komeda_dev *mdev)
 338 {
 339         struct komeda_pipeline *pipe;
 340         int i;
 341 
 342         for (i = 0; i < mdev->n_pipelines; i++) {
 343                 pipe = mdev->pipelines[i];
 344 
 345                 komeda_pipeline_assemble(pipe);
 346                 komeda_pipeline_dump(pipe);
 347         }
 348 
 349         return 0;
 350 }
 351 
 352 void komeda_pipeline_dump_register(struct komeda_pipeline *pipe,
 353                                    struct seq_file *sf)
 354 {
 355         struct komeda_component *c;
 356         u32 id;
 357 
 358         seq_printf(sf, "\n======== Pipeline-%d ==========\n", pipe->id);
 359 
 360         if (pipe->funcs && pipe->funcs->dump_register)
 361                 pipe->funcs->dump_register(pipe, sf);
 362 
 363         dp_for_each_set_bit(id, pipe->avail_comps) {
 364                 c = komeda_pipeline_get_component(pipe, id);
 365 
 366                 seq_printf(sf, "\n------%s------\n", c->name);
 367                 if (c->funcs->dump_register)
 368                         c->funcs->dump_register(c, sf);
 369         }
 370 }

/* [<][>][^][v][top][bottom][index][help] */