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