linux/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c
<<
>>
Prefs
   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 */
  13struct komeda_pipeline *
  14komeda_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
  44void 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
  65static struct komeda_component **
  66komeda_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
 122struct komeda_component *
 123komeda_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
 135struct komeda_component *
 136komeda_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
 149static struct komeda_component *
 150komeda_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 */
 158struct komeda_component *
 159komeda_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
 226void komeda_component_destroy(struct komeda_dev *mdev,
 227                              struct komeda_component *c)
 228{
 229        devm_kfree(mdev->dev, c);
 230}
 231
 232static 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
 245static 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
 267static 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
 286static struct komeda_layer *
 287komeda_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
 299static 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 */
 326struct komeda_pipeline *
 327komeda_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
 337int 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
 352void 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}
 371