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_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
  64static struct komeda_component **
  65komeda_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
 121struct komeda_component *
 122komeda_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
 134struct komeda_component *
 135komeda_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
 148static struct komeda_component *
 149komeda_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 */
 157struct komeda_component *
 158komeda_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
 225void komeda_component_destroy(struct komeda_dev *mdev,
 226                              struct komeda_component *c)
 227{
 228        devm_kfree(mdev->dev, c);
 229}
 230
 231static 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
 244static 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
 260static 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
 279static struct komeda_layer *
 280komeda_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
 292static 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 */
 313struct komeda_pipeline *
 314komeda_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
 324int 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
 339void 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