linux/drivers/gpu/drm/rcar-du/rcar_du_kms.c
<<
>>
Prefs
   1/*
   2 * rcar_du_kms.c  --  R-Car Display Unit Mode Setting
   3 *
   4 * Copyright (C) 2013-2015 Renesas Electronics Corporation
   5 *
   6 * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; either version 2 of the License, or
  11 * (at your option) any later version.
  12 */
  13
  14#include <drm/drmP.h>
  15#include <drm/drm_atomic.h>
  16#include <drm/drm_atomic_helper.h>
  17#include <drm/drm_crtc.h>
  18#include <drm/drm_crtc_helper.h>
  19#include <drm/drm_fb_cma_helper.h>
  20#include <drm/drm_gem_cma_helper.h>
  21
  22#include <linux/of_graph.h>
  23#include <linux/wait.h>
  24
  25#include "rcar_du_crtc.h"
  26#include "rcar_du_drv.h"
  27#include "rcar_du_encoder.h"
  28#include "rcar_du_kms.h"
  29#include "rcar_du_lvdsenc.h"
  30#include "rcar_du_regs.h"
  31#include "rcar_du_vsp.h"
  32
  33/* -----------------------------------------------------------------------------
  34 * Format helpers
  35 */
  36
  37static const struct rcar_du_format_info rcar_du_format_infos[] = {
  38        {
  39                .fourcc = DRM_FORMAT_RGB565,
  40                .bpp = 16,
  41                .planes = 1,
  42                .pnmr = PnMR_SPIM_TP | PnMR_DDDF_16BPP,
  43                .edf = PnDDCR4_EDF_NONE,
  44        }, {
  45                .fourcc = DRM_FORMAT_ARGB1555,
  46                .bpp = 16,
  47                .planes = 1,
  48                .pnmr = PnMR_SPIM_ALP | PnMR_DDDF_ARGB,
  49                .edf = PnDDCR4_EDF_NONE,
  50        }, {
  51                .fourcc = DRM_FORMAT_XRGB1555,
  52                .bpp = 16,
  53                .planes = 1,
  54                .pnmr = PnMR_SPIM_ALP | PnMR_DDDF_ARGB,
  55                .edf = PnDDCR4_EDF_NONE,
  56        }, {
  57                .fourcc = DRM_FORMAT_XRGB8888,
  58                .bpp = 32,
  59                .planes = 1,
  60                .pnmr = PnMR_SPIM_TP | PnMR_DDDF_16BPP,
  61                .edf = PnDDCR4_EDF_RGB888,
  62        }, {
  63                .fourcc = DRM_FORMAT_ARGB8888,
  64                .bpp = 32,
  65                .planes = 1,
  66                .pnmr = PnMR_SPIM_ALP | PnMR_DDDF_16BPP,
  67                .edf = PnDDCR4_EDF_ARGB8888,
  68        }, {
  69                .fourcc = DRM_FORMAT_UYVY,
  70                .bpp = 16,
  71                .planes = 1,
  72                .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC,
  73                .edf = PnDDCR4_EDF_NONE,
  74        }, {
  75                .fourcc = DRM_FORMAT_YUYV,
  76                .bpp = 16,
  77                .planes = 1,
  78                .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC,
  79                .edf = PnDDCR4_EDF_NONE,
  80        }, {
  81                .fourcc = DRM_FORMAT_NV12,
  82                .bpp = 12,
  83                .planes = 2,
  84                .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC,
  85                .edf = PnDDCR4_EDF_NONE,
  86        }, {
  87                .fourcc = DRM_FORMAT_NV21,
  88                .bpp = 12,
  89                .planes = 2,
  90                .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC,
  91                .edf = PnDDCR4_EDF_NONE,
  92        }, {
  93                .fourcc = DRM_FORMAT_NV16,
  94                .bpp = 16,
  95                .planes = 2,
  96                .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC,
  97                .edf = PnDDCR4_EDF_NONE,
  98        },
  99        /* The following formats are not supported on Gen2 and thus have no
 100         * associated .pnmr or .edf settings.
 101         */
 102        {
 103                .fourcc = DRM_FORMAT_NV61,
 104                .bpp = 16,
 105                .planes = 2,
 106        }, {
 107                .fourcc = DRM_FORMAT_YUV420,
 108                .bpp = 12,
 109                .planes = 3,
 110        }, {
 111                .fourcc = DRM_FORMAT_YVU420,
 112                .bpp = 12,
 113                .planes = 3,
 114        }, {
 115                .fourcc = DRM_FORMAT_YUV422,
 116                .bpp = 16,
 117                .planes = 3,
 118        }, {
 119                .fourcc = DRM_FORMAT_YVU422,
 120                .bpp = 16,
 121                .planes = 3,
 122        }, {
 123                .fourcc = DRM_FORMAT_YUV444,
 124                .bpp = 24,
 125                .planes = 3,
 126        }, {
 127                .fourcc = DRM_FORMAT_YVU444,
 128                .bpp = 24,
 129                .planes = 3,
 130        },
 131};
 132
 133const struct rcar_du_format_info *rcar_du_format_info(u32 fourcc)
 134{
 135        unsigned int i;
 136
 137        for (i = 0; i < ARRAY_SIZE(rcar_du_format_infos); ++i) {
 138                if (rcar_du_format_infos[i].fourcc == fourcc)
 139                        return &rcar_du_format_infos[i];
 140        }
 141
 142        return NULL;
 143}
 144
 145/* -----------------------------------------------------------------------------
 146 * Frame buffer
 147 */
 148
 149int rcar_du_dumb_create(struct drm_file *file, struct drm_device *dev,
 150                        struct drm_mode_create_dumb *args)
 151{
 152        struct rcar_du_device *rcdu = dev->dev_private;
 153        unsigned int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
 154        unsigned int align;
 155
 156        /* The R8A7779 DU requires a 16 pixels pitch alignment as documented,
 157         * but the R8A7790 DU seems to require a 128 bytes pitch alignment.
 158         */
 159        if (rcar_du_needs(rcdu, RCAR_DU_QUIRK_ALIGN_128B))
 160                align = 128;
 161        else
 162                align = 16 * args->bpp / 8;
 163
 164        args->pitch = roundup(min_pitch, align);
 165
 166        return drm_gem_cma_dumb_create_internal(file, dev, args);
 167}
 168
 169static struct drm_framebuffer *
 170rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv,
 171                  const struct drm_mode_fb_cmd2 *mode_cmd)
 172{
 173        struct rcar_du_device *rcdu = dev->dev_private;
 174        const struct rcar_du_format_info *format;
 175        unsigned int max_pitch;
 176        unsigned int align;
 177        unsigned int bpp;
 178        unsigned int i;
 179
 180        format = rcar_du_format_info(mode_cmd->pixel_format);
 181        if (format == NULL) {
 182                dev_dbg(dev->dev, "unsupported pixel format %08x\n",
 183                        mode_cmd->pixel_format);
 184                return ERR_PTR(-EINVAL);
 185        }
 186
 187        /*
 188         * The pitch and alignment constraints are expressed in pixels on the
 189         * hardware side and in bytes in the DRM API.
 190         */
 191        bpp = format->planes == 1 ? format->bpp / 8 : 1;
 192        max_pitch =  4096 * bpp;
 193
 194        if (rcar_du_needs(rcdu, RCAR_DU_QUIRK_ALIGN_128B))
 195                align = 128;
 196        else
 197                align = 16 * bpp;
 198
 199        if (mode_cmd->pitches[0] & (align - 1) ||
 200            mode_cmd->pitches[0] >= max_pitch) {
 201                dev_dbg(dev->dev, "invalid pitch value %u\n",
 202                        mode_cmd->pitches[0]);
 203                return ERR_PTR(-EINVAL);
 204        }
 205
 206        for (i = 1; i < format->planes; ++i) {
 207                if (mode_cmd->pitches[i] != mode_cmd->pitches[0]) {
 208                        dev_dbg(dev->dev,
 209                                "luma and chroma pitches do not match\n");
 210                        return ERR_PTR(-EINVAL);
 211                }
 212        }
 213
 214        return drm_fb_cma_create(dev, file_priv, mode_cmd);
 215}
 216
 217static void rcar_du_output_poll_changed(struct drm_device *dev)
 218{
 219        struct rcar_du_device *rcdu = dev->dev_private;
 220
 221        drm_fbdev_cma_hotplug_event(rcdu->fbdev);
 222}
 223
 224/* -----------------------------------------------------------------------------
 225 * Atomic Check and Update
 226 */
 227
 228static int rcar_du_atomic_check(struct drm_device *dev,
 229                                struct drm_atomic_state *state)
 230{
 231        struct rcar_du_device *rcdu = dev->dev_private;
 232        int ret;
 233
 234        ret = drm_atomic_helper_check_modeset(dev, state);
 235        if (ret)
 236                return ret;
 237
 238        ret = drm_atomic_normalize_zpos(dev, state);
 239        if (ret)
 240                return ret;
 241
 242        ret = drm_atomic_helper_check_planes(dev, state);
 243        if (ret)
 244                return ret;
 245
 246        if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE))
 247                return 0;
 248
 249        return rcar_du_atomic_check_planes(dev, state);
 250}
 251
 252struct rcar_du_commit {
 253        struct work_struct work;
 254        struct drm_device *dev;
 255        struct drm_atomic_state *state;
 256        u32 crtcs;
 257};
 258
 259static void rcar_du_atomic_complete(struct rcar_du_commit *commit)
 260{
 261        struct drm_device *dev = commit->dev;
 262        struct rcar_du_device *rcdu = dev->dev_private;
 263        struct drm_atomic_state *old_state = commit->state;
 264
 265        /* Apply the atomic update. */
 266        drm_atomic_helper_commit_modeset_disables(dev, old_state);
 267        drm_atomic_helper_commit_modeset_enables(dev, old_state);
 268        drm_atomic_helper_commit_planes(dev, old_state,
 269                                        DRM_PLANE_COMMIT_ACTIVE_ONLY);
 270
 271        drm_atomic_helper_wait_for_vblanks(dev, old_state);
 272
 273        drm_atomic_helper_cleanup_planes(dev, old_state);
 274
 275        drm_atomic_state_free(old_state);
 276
 277        /* Complete the commit, wake up any waiter. */
 278        spin_lock(&rcdu->commit.wait.lock);
 279        rcdu->commit.pending &= ~commit->crtcs;
 280        wake_up_all_locked(&rcdu->commit.wait);
 281        spin_unlock(&rcdu->commit.wait.lock);
 282
 283        kfree(commit);
 284}
 285
 286static void rcar_du_atomic_work(struct work_struct *work)
 287{
 288        struct rcar_du_commit *commit =
 289                container_of(work, struct rcar_du_commit, work);
 290
 291        rcar_du_atomic_complete(commit);
 292}
 293
 294static int rcar_du_atomic_commit(struct drm_device *dev,
 295                                 struct drm_atomic_state *state,
 296                                 bool nonblock)
 297{
 298        struct rcar_du_device *rcdu = dev->dev_private;
 299        struct rcar_du_commit *commit;
 300        struct drm_crtc *crtc;
 301        struct drm_crtc_state *crtc_state;
 302        unsigned int i;
 303        int ret;
 304
 305        ret = drm_atomic_helper_prepare_planes(dev, state);
 306        if (ret)
 307                return ret;
 308
 309        /* Allocate the commit object. */
 310        commit = kzalloc(sizeof(*commit), GFP_KERNEL);
 311        if (commit == NULL) {
 312                ret = -ENOMEM;
 313                goto error;
 314        }
 315
 316        INIT_WORK(&commit->work, rcar_du_atomic_work);
 317        commit->dev = dev;
 318        commit->state = state;
 319
 320        /* Wait until all affected CRTCs have completed previous commits and
 321         * mark them as pending.
 322         */
 323        for_each_crtc_in_state(state, crtc, crtc_state, i)
 324                commit->crtcs |= drm_crtc_mask(crtc);
 325
 326        spin_lock(&rcdu->commit.wait.lock);
 327        ret = wait_event_interruptible_locked(rcdu->commit.wait,
 328                        !(rcdu->commit.pending & commit->crtcs));
 329        if (ret == 0)
 330                rcdu->commit.pending |= commit->crtcs;
 331        spin_unlock(&rcdu->commit.wait.lock);
 332
 333        if (ret) {
 334                kfree(commit);
 335                goto error;
 336        }
 337
 338        /* Swap the state, this is the point of no return. */
 339        drm_atomic_helper_swap_state(state, true);
 340
 341        if (nonblock)
 342                schedule_work(&commit->work);
 343        else
 344                rcar_du_atomic_complete(commit);
 345
 346        return 0;
 347
 348error:
 349        drm_atomic_helper_cleanup_planes(dev, state);
 350        return ret;
 351}
 352
 353/* -----------------------------------------------------------------------------
 354 * Initialization
 355 */
 356
 357static const struct drm_mode_config_funcs rcar_du_mode_config_funcs = {
 358        .fb_create = rcar_du_fb_create,
 359        .output_poll_changed = rcar_du_output_poll_changed,
 360        .atomic_check = rcar_du_atomic_check,
 361        .atomic_commit = rcar_du_atomic_commit,
 362};
 363
 364static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
 365                                     enum rcar_du_output output,
 366                                     struct of_endpoint *ep)
 367{
 368        static const struct {
 369                const char *compatible;
 370                enum rcar_du_encoder_type type;
 371        } encoders[] = {
 372                { "adi,adv7123", RCAR_DU_ENCODER_VGA },
 373                { "adi,adv7511w", RCAR_DU_ENCODER_HDMI },
 374                { "thine,thc63lvdm83d", RCAR_DU_ENCODER_LVDS },
 375        };
 376
 377        enum rcar_du_encoder_type enc_type = RCAR_DU_ENCODER_NONE;
 378        struct device_node *connector = NULL;
 379        struct device_node *encoder = NULL;
 380        struct device_node *ep_node = NULL;
 381        struct device_node *entity_ep_node;
 382        struct device_node *entity;
 383        int ret;
 384
 385        /*
 386         * Locate the connected entity and infer its type from the number of
 387         * endpoints.
 388         */
 389        entity = of_graph_get_remote_port_parent(ep->local_node);
 390        if (!entity) {
 391                dev_dbg(rcdu->dev, "unconnected endpoint %s, skipping\n",
 392                        ep->local_node->full_name);
 393                return -ENODEV;
 394        }
 395
 396        entity_ep_node = of_parse_phandle(ep->local_node, "remote-endpoint", 0);
 397
 398        for_each_endpoint_of_node(entity, ep_node) {
 399                if (ep_node == entity_ep_node)
 400                        continue;
 401
 402                /*
 403                 * We've found one endpoint other than the input, this must
 404                 * be an encoder. Locate the connector.
 405                 */
 406                encoder = entity;
 407                connector = of_graph_get_remote_port_parent(ep_node);
 408                of_node_put(ep_node);
 409
 410                if (!connector) {
 411                        dev_warn(rcdu->dev,
 412                                 "no connector for encoder %s, skipping\n",
 413                                 encoder->full_name);
 414                        of_node_put(entity_ep_node);
 415                        of_node_put(encoder);
 416                        return -ENODEV;
 417                }
 418
 419                break;
 420        }
 421
 422        of_node_put(entity_ep_node);
 423
 424        if (encoder) {
 425                /*
 426                 * If an encoder has been found, get its type based on its
 427                 * compatible string.
 428                 */
 429                unsigned int i;
 430
 431                for (i = 0; i < ARRAY_SIZE(encoders); ++i) {
 432                        if (of_device_is_compatible(encoder,
 433                                                    encoders[i].compatible)) {
 434                                enc_type = encoders[i].type;
 435                                break;
 436                        }
 437                }
 438
 439                if (i == ARRAY_SIZE(encoders)) {
 440                        dev_warn(rcdu->dev,
 441                                 "unknown encoder type for %s, skipping\n",
 442                                 encoder->full_name);
 443                        of_node_put(encoder);
 444                        of_node_put(connector);
 445                        return -EINVAL;
 446                }
 447        } else {
 448                /*
 449                 * If no encoder has been found the entity must be the
 450                 * connector.
 451                 */
 452                connector = entity;
 453        }
 454
 455        ret = rcar_du_encoder_init(rcdu, enc_type, output, encoder, connector);
 456        of_node_put(encoder);
 457        of_node_put(connector);
 458
 459        if (ret && ret != -EPROBE_DEFER)
 460                dev_warn(rcdu->dev,
 461                         "failed to initialize encoder %s (%d), skipping\n",
 462                         encoder->full_name, ret);
 463
 464        return ret;
 465}
 466
 467static int rcar_du_encoders_init(struct rcar_du_device *rcdu)
 468{
 469        struct device_node *np = rcdu->dev->of_node;
 470        struct device_node *ep_node;
 471        unsigned int num_encoders = 0;
 472
 473        /*
 474         * Iterate over the endpoints and create one encoder for each output
 475         * pipeline.
 476         */
 477        for_each_endpoint_of_node(np, ep_node) {
 478                enum rcar_du_output output;
 479                struct of_endpoint ep;
 480                unsigned int i;
 481                int ret;
 482
 483                ret = of_graph_parse_endpoint(ep_node, &ep);
 484                if (ret < 0) {
 485                        of_node_put(ep_node);
 486                        return ret;
 487                }
 488
 489                /* Find the output route corresponding to the port number. */
 490                for (i = 0; i < RCAR_DU_OUTPUT_MAX; ++i) {
 491                        if (rcdu->info->routes[i].possible_crtcs &&
 492                            rcdu->info->routes[i].port == ep.port) {
 493                                output = i;
 494                                break;
 495                        }
 496                }
 497
 498                if (i == RCAR_DU_OUTPUT_MAX) {
 499                        dev_warn(rcdu->dev,
 500                                 "port %u references unexisting output, skipping\n",
 501                                 ep.port);
 502                        continue;
 503                }
 504
 505                /* Process the output pipeline. */
 506                ret = rcar_du_encoders_init_one(rcdu, output, &ep);
 507                if (ret < 0) {
 508                        if (ret == -EPROBE_DEFER) {
 509                                of_node_put(ep_node);
 510                                return ret;
 511                        }
 512
 513                        continue;
 514                }
 515
 516                num_encoders++;
 517        }
 518
 519        return num_encoders;
 520}
 521
 522static int rcar_du_properties_init(struct rcar_du_device *rcdu)
 523{
 524        rcdu->props.alpha =
 525                drm_property_create_range(rcdu->ddev, 0, "alpha", 0, 255);
 526        if (rcdu->props.alpha == NULL)
 527                return -ENOMEM;
 528
 529        /* The color key is expressed as an RGB888 triplet stored in a 32-bit
 530         * integer in XRGB8888 format. Bit 24 is used as a flag to disable (0)
 531         * or enable source color keying (1).
 532         */
 533        rcdu->props.colorkey =
 534                drm_property_create_range(rcdu->ddev, 0, "colorkey",
 535                                          0, 0x01ffffff);
 536        if (rcdu->props.colorkey == NULL)
 537                return -ENOMEM;
 538
 539        return 0;
 540}
 541
 542int rcar_du_modeset_init(struct rcar_du_device *rcdu)
 543{
 544        static const unsigned int mmio_offsets[] = {
 545                DU0_REG_OFFSET, DU2_REG_OFFSET
 546        };
 547
 548        struct drm_device *dev = rcdu->ddev;
 549        struct drm_encoder *encoder;
 550        struct drm_fbdev_cma *fbdev;
 551        unsigned int num_encoders;
 552        unsigned int num_groups;
 553        unsigned int i;
 554        int ret;
 555
 556        drm_mode_config_init(dev);
 557
 558        dev->mode_config.min_width = 0;
 559        dev->mode_config.min_height = 0;
 560        dev->mode_config.max_width = 4095;
 561        dev->mode_config.max_height = 2047;
 562        dev->mode_config.funcs = &rcar_du_mode_config_funcs;
 563
 564        rcdu->num_crtcs = rcdu->info->num_crtcs;
 565
 566        ret = rcar_du_properties_init(rcdu);
 567        if (ret < 0)
 568                return ret;
 569
 570        /* Initialize the groups. */
 571        num_groups = DIV_ROUND_UP(rcdu->num_crtcs, 2);
 572
 573        for (i = 0; i < num_groups; ++i) {
 574                struct rcar_du_group *rgrp = &rcdu->groups[i];
 575
 576                mutex_init(&rgrp->lock);
 577
 578                rgrp->dev = rcdu;
 579                rgrp->mmio_offset = mmio_offsets[i];
 580                rgrp->index = i;
 581                rgrp->num_crtcs = min(rcdu->num_crtcs - 2 * i, 2U);
 582
 583                /* If we have more than one CRTCs in this group pre-associate
 584                 * the low-order planes with CRTC 0 and the high-order planes
 585                 * with CRTC 1 to minimize flicker occurring when the
 586                 * association is changed.
 587                 */
 588                rgrp->dptsr_planes = rgrp->num_crtcs > 1
 589                                   ? (rcdu->info->gen >= 3 ? 0x04 : 0xf0)
 590                                   : 0;
 591
 592                if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {
 593                        ret = rcar_du_planes_init(rgrp);
 594                        if (ret < 0)
 595                                return ret;
 596                }
 597        }
 598
 599        /* Initialize the compositors. */
 600        if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {
 601                for (i = 0; i < rcdu->num_crtcs; ++i) {
 602                        struct rcar_du_vsp *vsp = &rcdu->vsps[i];
 603
 604                        vsp->index = i;
 605                        vsp->dev = rcdu;
 606                        rcdu->crtcs[i].vsp = vsp;
 607
 608                        ret = rcar_du_vsp_init(vsp);
 609                        if (ret < 0)
 610                                return ret;
 611                }
 612        }
 613
 614        /* Create the CRTCs. */
 615        for (i = 0; i < rcdu->num_crtcs; ++i) {
 616                struct rcar_du_group *rgrp = &rcdu->groups[i / 2];
 617
 618                ret = rcar_du_crtc_create(rgrp, i);
 619                if (ret < 0)
 620                        return ret;
 621        }
 622
 623        /* Initialize the encoders. */
 624        ret = rcar_du_lvdsenc_init(rcdu);
 625        if (ret < 0)
 626                return ret;
 627
 628        ret = rcar_du_encoders_init(rcdu);
 629        if (ret < 0)
 630                return ret;
 631
 632        if (ret == 0) {
 633                dev_err(rcdu->dev, "error: no encoder could be initialized\n");
 634                return -EINVAL;
 635        }
 636
 637        num_encoders = ret;
 638
 639        /* Set the possible CRTCs and possible clones. There's always at least
 640         * one way for all encoders to clone each other, set all bits in the
 641         * possible clones field.
 642         */
 643        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 644                struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
 645                const struct rcar_du_output_routing *route =
 646                        &rcdu->info->routes[renc->output];
 647
 648                encoder->possible_crtcs = route->possible_crtcs;
 649                encoder->possible_clones = (1 << num_encoders) - 1;
 650        }
 651
 652        drm_mode_config_reset(dev);
 653
 654        drm_kms_helper_poll_init(dev);
 655
 656        if (dev->mode_config.num_connector) {
 657                fbdev = drm_fbdev_cma_init(dev, 32, dev->mode_config.num_crtc,
 658                                           dev->mode_config.num_connector);
 659                if (IS_ERR(fbdev))
 660                        return PTR_ERR(fbdev);
 661
 662                rcdu->fbdev = fbdev;
 663        } else {
 664                dev_info(rcdu->dev,
 665                         "no connector found, disabling fbdev emulation\n");
 666        }
 667
 668        return 0;
 669}
 670