linux/drivers/gpu/drm/vc4/vc4_hvs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2015 Broadcom
   4 */
   5
   6/**
   7 * DOC: VC4 HVS module.
   8 *
   9 * The Hardware Video Scaler (HVS) is the piece of hardware that does
  10 * translation, scaling, colorspace conversion, and compositing of
  11 * pixels stored in framebuffers into a FIFO of pixels going out to
  12 * the Pixel Valve (CRTC).  It operates at the system clock rate (the
  13 * system audio clock gate, specifically), which is much higher than
  14 * the pixel clock rate.
  15 *
  16 * There is a single global HVS, with multiple output FIFOs that can
  17 * be consumed by the PVs.  This file just manages the resources for
  18 * the HVS, while the vc4_crtc.c code actually drives HVS setup for
  19 * each CRTC.
  20 */
  21
  22#include <linux/bitfield.h>
  23#include <linux/clk.h>
  24#include <linux/component.h>
  25#include <linux/platform_device.h>
  26
  27#include <drm/drm_atomic_helper.h>
  28#include <drm/drm_vblank.h>
  29
  30#include "vc4_drv.h"
  31#include "vc4_regs.h"
  32
  33static const struct debugfs_reg32 hvs_regs[] = {
  34        VC4_REG32(SCALER_DISPCTRL),
  35        VC4_REG32(SCALER_DISPSTAT),
  36        VC4_REG32(SCALER_DISPID),
  37        VC4_REG32(SCALER_DISPECTRL),
  38        VC4_REG32(SCALER_DISPPROF),
  39        VC4_REG32(SCALER_DISPDITHER),
  40        VC4_REG32(SCALER_DISPEOLN),
  41        VC4_REG32(SCALER_DISPLIST0),
  42        VC4_REG32(SCALER_DISPLIST1),
  43        VC4_REG32(SCALER_DISPLIST2),
  44        VC4_REG32(SCALER_DISPLSTAT),
  45        VC4_REG32(SCALER_DISPLACT0),
  46        VC4_REG32(SCALER_DISPLACT1),
  47        VC4_REG32(SCALER_DISPLACT2),
  48        VC4_REG32(SCALER_DISPCTRL0),
  49        VC4_REG32(SCALER_DISPBKGND0),
  50        VC4_REG32(SCALER_DISPSTAT0),
  51        VC4_REG32(SCALER_DISPBASE0),
  52        VC4_REG32(SCALER_DISPCTRL1),
  53        VC4_REG32(SCALER_DISPBKGND1),
  54        VC4_REG32(SCALER_DISPSTAT1),
  55        VC4_REG32(SCALER_DISPBASE1),
  56        VC4_REG32(SCALER_DISPCTRL2),
  57        VC4_REG32(SCALER_DISPBKGND2),
  58        VC4_REG32(SCALER_DISPSTAT2),
  59        VC4_REG32(SCALER_DISPBASE2),
  60        VC4_REG32(SCALER_DISPALPHA2),
  61        VC4_REG32(SCALER_OLEDOFFS),
  62        VC4_REG32(SCALER_OLEDCOEF0),
  63        VC4_REG32(SCALER_OLEDCOEF1),
  64        VC4_REG32(SCALER_OLEDCOEF2),
  65};
  66
  67void vc4_hvs_dump_state(struct drm_device *dev)
  68{
  69        struct vc4_dev *vc4 = to_vc4_dev(dev);
  70        struct drm_printer p = drm_info_printer(&vc4->hvs->pdev->dev);
  71        int i;
  72
  73        drm_print_regset32(&p, &vc4->hvs->regset);
  74
  75        DRM_INFO("HVS ctx:\n");
  76        for (i = 0; i < 64; i += 4) {
  77                DRM_INFO("0x%08x (%s): 0x%08x 0x%08x 0x%08x 0x%08x\n",
  78                         i * 4, i < HVS_BOOTLOADER_DLIST_END ? "B" : "D",
  79                         readl((u32 __iomem *)vc4->hvs->dlist + i + 0),
  80                         readl((u32 __iomem *)vc4->hvs->dlist + i + 1),
  81                         readl((u32 __iomem *)vc4->hvs->dlist + i + 2),
  82                         readl((u32 __iomem *)vc4->hvs->dlist + i + 3));
  83        }
  84}
  85
  86static int vc4_hvs_debugfs_underrun(struct seq_file *m, void *data)
  87{
  88        struct drm_info_node *node = m->private;
  89        struct drm_device *dev = node->minor->dev;
  90        struct vc4_dev *vc4 = to_vc4_dev(dev);
  91        struct drm_printer p = drm_seq_file_printer(m);
  92
  93        drm_printf(&p, "%d\n", atomic_read(&vc4->underrun));
  94
  95        return 0;
  96}
  97
  98/* The filter kernel is composed of dwords each containing 3 9-bit
  99 * signed integers packed next to each other.
 100 */
 101#define VC4_INT_TO_COEFF(coeff) (coeff & 0x1ff)
 102#define VC4_PPF_FILTER_WORD(c0, c1, c2)                         \
 103        ((((c0) & 0x1ff) << 0) |                                \
 104         (((c1) & 0x1ff) << 9) |                                \
 105         (((c2) & 0x1ff) << 18))
 106
 107/* The whole filter kernel is arranged as the coefficients 0-16 going
 108 * up, then a pad, then 17-31 going down and reversed within the
 109 * dwords.  This means that a linear phase kernel (where it's
 110 * symmetrical at the boundary between 15 and 16) has the last 5
 111 * dwords matching the first 5, but reversed.
 112 */
 113#define VC4_LINEAR_PHASE_KERNEL(c0, c1, c2, c3, c4, c5, c6, c7, c8,     \
 114                                c9, c10, c11, c12, c13, c14, c15)       \
 115        {VC4_PPF_FILTER_WORD(c0, c1, c2),                               \
 116         VC4_PPF_FILTER_WORD(c3, c4, c5),                               \
 117         VC4_PPF_FILTER_WORD(c6, c7, c8),                               \
 118         VC4_PPF_FILTER_WORD(c9, c10, c11),                             \
 119         VC4_PPF_FILTER_WORD(c12, c13, c14),                            \
 120         VC4_PPF_FILTER_WORD(c15, c15, 0)}
 121
 122#define VC4_LINEAR_PHASE_KERNEL_DWORDS 6
 123#define VC4_KERNEL_DWORDS (VC4_LINEAR_PHASE_KERNEL_DWORDS * 2 - 1)
 124
 125/* Recommended B=1/3, C=1/3 filter choice from Mitchell/Netravali.
 126 * http://www.cs.utexas.edu/~fussell/courses/cs384g/lectures/mitchell/Mitchell.pdf
 127 */
 128static const u32 mitchell_netravali_1_3_1_3_kernel[] =
 129        VC4_LINEAR_PHASE_KERNEL(0, -2, -6, -8, -10, -8, -3, 2, 18,
 130                                50, 82, 119, 155, 187, 213, 227);
 131
 132static int vc4_hvs_upload_linear_kernel(struct vc4_hvs *hvs,
 133                                        struct drm_mm_node *space,
 134                                        const u32 *kernel)
 135{
 136        int ret, i;
 137        u32 __iomem *dst_kernel;
 138
 139        ret = drm_mm_insert_node(&hvs->dlist_mm, space, VC4_KERNEL_DWORDS);
 140        if (ret) {
 141                DRM_ERROR("Failed to allocate space for filter kernel: %d\n",
 142                          ret);
 143                return ret;
 144        }
 145
 146        dst_kernel = hvs->dlist + space->start;
 147
 148        for (i = 0; i < VC4_KERNEL_DWORDS; i++) {
 149                if (i < VC4_LINEAR_PHASE_KERNEL_DWORDS)
 150                        writel(kernel[i], &dst_kernel[i]);
 151                else {
 152                        writel(kernel[VC4_KERNEL_DWORDS - i - 1],
 153                               &dst_kernel[i]);
 154                }
 155        }
 156
 157        return 0;
 158}
 159
 160static void vc4_hvs_lut_load(struct drm_crtc *crtc)
 161{
 162        struct drm_device *dev = crtc->dev;
 163        struct vc4_dev *vc4 = to_vc4_dev(dev);
 164        struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 165        struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 166        u32 i;
 167
 168        /* The LUT memory is laid out with each HVS channel in order,
 169         * each of which takes 256 writes for R, 256 for G, then 256
 170         * for B.
 171         */
 172        HVS_WRITE(SCALER_GAMADDR,
 173                  SCALER_GAMADDR_AUTOINC |
 174                  (vc4_state->assigned_channel * 3 * crtc->gamma_size));
 175
 176        for (i = 0; i < crtc->gamma_size; i++)
 177                HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_r[i]);
 178        for (i = 0; i < crtc->gamma_size; i++)
 179                HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_g[i]);
 180        for (i = 0; i < crtc->gamma_size; i++)
 181                HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_b[i]);
 182}
 183
 184static void vc4_hvs_update_gamma_lut(struct drm_crtc *crtc)
 185{
 186        struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 187        struct drm_color_lut *lut = crtc->state->gamma_lut->data;
 188        u32 length = drm_color_lut_size(crtc->state->gamma_lut);
 189        u32 i;
 190
 191        for (i = 0; i < length; i++) {
 192                vc4_crtc->lut_r[i] = drm_color_lut_extract(lut[i].red, 8);
 193                vc4_crtc->lut_g[i] = drm_color_lut_extract(lut[i].green, 8);
 194                vc4_crtc->lut_b[i] = drm_color_lut_extract(lut[i].blue, 8);
 195        }
 196
 197        vc4_hvs_lut_load(crtc);
 198}
 199
 200int vc4_hvs_get_fifo_from_output(struct drm_device *dev, unsigned int output)
 201{
 202        struct vc4_dev *vc4 = to_vc4_dev(dev);
 203        u32 reg;
 204        int ret;
 205
 206        if (!vc4->hvs->hvs5)
 207                return output;
 208
 209        switch (output) {
 210        case 0:
 211                return 0;
 212
 213        case 1:
 214                return 1;
 215
 216        case 2:
 217                reg = HVS_READ(SCALER_DISPECTRL);
 218                ret = FIELD_GET(SCALER_DISPECTRL_DSP2_MUX_MASK, reg);
 219                if (ret == 0)
 220                        return 2;
 221
 222                return 0;
 223
 224        case 3:
 225                reg = HVS_READ(SCALER_DISPCTRL);
 226                ret = FIELD_GET(SCALER_DISPCTRL_DSP3_MUX_MASK, reg);
 227                if (ret == 3)
 228                        return -EPIPE;
 229
 230                return ret;
 231
 232        case 4:
 233                reg = HVS_READ(SCALER_DISPEOLN);
 234                ret = FIELD_GET(SCALER_DISPEOLN_DSP4_MUX_MASK, reg);
 235                if (ret == 3)
 236                        return -EPIPE;
 237
 238                return ret;
 239
 240        case 5:
 241                reg = HVS_READ(SCALER_DISPDITHER);
 242                ret = FIELD_GET(SCALER_DISPDITHER_DSP5_MUX_MASK, reg);
 243                if (ret == 3)
 244                        return -EPIPE;
 245
 246                return ret;
 247
 248        default:
 249                return -EPIPE;
 250        }
 251}
 252
 253static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
 254                                struct drm_display_mode *mode, bool oneshot)
 255{
 256        struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
 257        unsigned int chan = vc4_crtc_state->assigned_channel;
 258        bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
 259        u32 dispbkgndx;
 260        u32 dispctrl;
 261
 262        HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
 263        HVS_WRITE(SCALER_DISPCTRLX(chan), SCALER_DISPCTRLX_RESET);
 264        HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
 265
 266        /* Turn on the scaler, which will wait for vstart to start
 267         * compositing.
 268         * When feeding the transposer, we should operate in oneshot
 269         * mode.
 270         */
 271        dispctrl = SCALER_DISPCTRLX_ENABLE;
 272
 273        if (!vc4->hvs->hvs5)
 274                dispctrl |= VC4_SET_FIELD(mode->hdisplay,
 275                                          SCALER_DISPCTRLX_WIDTH) |
 276                            VC4_SET_FIELD(mode->vdisplay,
 277                                          SCALER_DISPCTRLX_HEIGHT) |
 278                            (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0);
 279        else
 280                dispctrl |= VC4_SET_FIELD(mode->hdisplay,
 281                                          SCALER5_DISPCTRLX_WIDTH) |
 282                            VC4_SET_FIELD(mode->vdisplay,
 283                                          SCALER5_DISPCTRLX_HEIGHT) |
 284                            (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
 285
 286        HVS_WRITE(SCALER_DISPCTRLX(chan), dispctrl);
 287
 288        dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(chan));
 289        dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
 290        dispbkgndx &= ~SCALER_DISPBKGND_INTERLACE;
 291
 292        HVS_WRITE(SCALER_DISPBKGNDX(chan), dispbkgndx |
 293                  SCALER_DISPBKGND_AUTOHS |
 294                  ((!vc4->hvs->hvs5) ? SCALER_DISPBKGND_GAMMA : 0) |
 295                  (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
 296
 297        /* Reload the LUT, since the SRAMs would have been disabled if
 298         * all CRTCs had SCALER_DISPBKGND_GAMMA unset at once.
 299         */
 300        vc4_hvs_lut_load(crtc);
 301
 302        return 0;
 303}
 304
 305void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int chan)
 306{
 307        struct vc4_dev *vc4 = to_vc4_dev(dev);
 308
 309        if (HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_ENABLE)
 310                return;
 311
 312        HVS_WRITE(SCALER_DISPCTRLX(chan),
 313                  HVS_READ(SCALER_DISPCTRLX(chan)) | SCALER_DISPCTRLX_RESET);
 314        HVS_WRITE(SCALER_DISPCTRLX(chan),
 315                  HVS_READ(SCALER_DISPCTRLX(chan)) & ~SCALER_DISPCTRLX_ENABLE);
 316
 317        /* Once we leave, the scaler should be disabled and its fifo empty. */
 318        WARN_ON_ONCE(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_RESET);
 319
 320        WARN_ON_ONCE(VC4_GET_FIELD(HVS_READ(SCALER_DISPSTATX(chan)),
 321                                   SCALER_DISPSTATX_MODE) !=
 322                     SCALER_DISPSTATX_MODE_DISABLED);
 323
 324        WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) &
 325                      (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) !=
 326                     SCALER_DISPSTATX_EMPTY);
 327}
 328
 329int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state)
 330{
 331        struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
 332        struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
 333        struct drm_device *dev = crtc->dev;
 334        struct vc4_dev *vc4 = to_vc4_dev(dev);
 335        struct drm_plane *plane;
 336        unsigned long flags;
 337        const struct drm_plane_state *plane_state;
 338        u32 dlist_count = 0;
 339        int ret;
 340
 341        /* The pixelvalve can only feed one encoder (and encoders are
 342         * 1:1 with connectors.)
 343         */
 344        if (hweight32(crtc_state->connector_mask) > 1)
 345                return -EINVAL;
 346
 347        drm_atomic_crtc_state_for_each_plane_state(plane, plane_state, crtc_state)
 348                dlist_count += vc4_plane_dlist_size(plane_state);
 349
 350        dlist_count++; /* Account for SCALER_CTL0_END. */
 351
 352        spin_lock_irqsave(&vc4->hvs->mm_lock, flags);
 353        ret = drm_mm_insert_node(&vc4->hvs->dlist_mm, &vc4_state->mm,
 354                                 dlist_count);
 355        spin_unlock_irqrestore(&vc4->hvs->mm_lock, flags);
 356        if (ret)
 357                return ret;
 358
 359        return 0;
 360}
 361
 362static void vc4_hvs_update_dlist(struct drm_crtc *crtc)
 363{
 364        struct drm_device *dev = crtc->dev;
 365        struct vc4_dev *vc4 = to_vc4_dev(dev);
 366        struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 367        struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 368
 369        if (crtc->state->event) {
 370                unsigned long flags;
 371
 372                crtc->state->event->pipe = drm_crtc_index(crtc);
 373
 374                WARN_ON(drm_crtc_vblank_get(crtc) != 0);
 375
 376                spin_lock_irqsave(&dev->event_lock, flags);
 377
 378                if (!vc4_state->feed_txp || vc4_state->txp_armed) {
 379                        vc4_crtc->event = crtc->state->event;
 380                        crtc->state->event = NULL;
 381                }
 382
 383                HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
 384                          vc4_state->mm.start);
 385
 386                spin_unlock_irqrestore(&dev->event_lock, flags);
 387        } else {
 388                HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
 389                          vc4_state->mm.start);
 390        }
 391}
 392
 393void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
 394                           struct drm_atomic_state *state)
 395{
 396        struct drm_device *dev = crtc->dev;
 397        struct vc4_dev *vc4 = to_vc4_dev(dev);
 398        struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
 399        struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(new_crtc_state);
 400        struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 401        bool oneshot = vc4_state->feed_txp;
 402
 403        vc4_hvs_update_dlist(crtc);
 404        vc4_hvs_init_channel(vc4, crtc, mode, oneshot);
 405}
 406
 407void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
 408                            struct drm_atomic_state *state)
 409{
 410        struct drm_device *dev = crtc->dev;
 411        struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state, crtc);
 412        struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(old_state);
 413        unsigned int chan = vc4_state->assigned_channel;
 414
 415        vc4_hvs_stop_channel(dev, chan);
 416}
 417
 418void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 419                          struct drm_atomic_state *state)
 420{
 421        struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state,
 422                                                                         crtc);
 423        struct drm_device *dev = crtc->dev;
 424        struct vc4_dev *vc4 = to_vc4_dev(dev);
 425        struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 426        struct drm_plane *plane;
 427        struct vc4_plane_state *vc4_plane_state;
 428        bool debug_dump_regs = false;
 429        bool enable_bg_fill = false;
 430        u32 __iomem *dlist_start = vc4->hvs->dlist + vc4_state->mm.start;
 431        u32 __iomem *dlist_next = dlist_start;
 432
 433        if (debug_dump_regs) {
 434                DRM_INFO("CRTC %d HVS before:\n", drm_crtc_index(crtc));
 435                vc4_hvs_dump_state(dev);
 436        }
 437
 438        /* Copy all the active planes' dlist contents to the hardware dlist. */
 439        drm_atomic_crtc_for_each_plane(plane, crtc) {
 440                /* Is this the first active plane? */
 441                if (dlist_next == dlist_start) {
 442                        /* We need to enable background fill when a plane
 443                         * could be alpha blending from the background, i.e.
 444                         * where no other plane is underneath. It suffices to
 445                         * consider the first active plane here since we set
 446                         * needs_bg_fill such that either the first plane
 447                         * already needs it or all planes on top blend from
 448                         * the first or a lower plane.
 449                         */
 450                        vc4_plane_state = to_vc4_plane_state(plane->state);
 451                        enable_bg_fill = vc4_plane_state->needs_bg_fill;
 452                }
 453
 454                dlist_next += vc4_plane_write_dlist(plane, dlist_next);
 455        }
 456
 457        writel(SCALER_CTL0_END, dlist_next);
 458        dlist_next++;
 459
 460        WARN_ON_ONCE(dlist_next - dlist_start != vc4_state->mm.size);
 461
 462        if (enable_bg_fill)
 463                /* This sets a black background color fill, as is the case
 464                 * with other DRM drivers.
 465                 */
 466                HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
 467                          HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel)) |
 468                          SCALER_DISPBKGND_FILL);
 469
 470        /* Only update DISPLIST if the CRTC was already running and is not
 471         * being disabled.
 472         * vc4_crtc_enable() takes care of updating the dlist just after
 473         * re-enabling VBLANK interrupts and before enabling the engine.
 474         * If the CRTC is being disabled, there's no point in updating this
 475         * information.
 476         */
 477        if (crtc->state->active && old_state->active)
 478                vc4_hvs_update_dlist(crtc);
 479
 480        if (crtc->state->color_mgmt_changed) {
 481                u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel));
 482
 483                if (crtc->state->gamma_lut) {
 484                        vc4_hvs_update_gamma_lut(crtc);
 485                        dispbkgndx |= SCALER_DISPBKGND_GAMMA;
 486                } else {
 487                        /* Unsetting DISPBKGND_GAMMA skips the gamma lut step
 488                         * in hardware, which is the same as a linear lut that
 489                         * DRM expects us to use in absence of a user lut.
 490                         */
 491                        dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
 492                }
 493                HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel), dispbkgndx);
 494        }
 495
 496        if (debug_dump_regs) {
 497                DRM_INFO("CRTC %d HVS after:\n", drm_crtc_index(crtc));
 498                vc4_hvs_dump_state(dev);
 499        }
 500}
 501
 502void vc4_hvs_mask_underrun(struct drm_device *dev, int channel)
 503{
 504        struct vc4_dev *vc4 = to_vc4_dev(dev);
 505        u32 dispctrl = HVS_READ(SCALER_DISPCTRL);
 506
 507        dispctrl &= ~SCALER_DISPCTRL_DSPEISLUR(channel);
 508
 509        HVS_WRITE(SCALER_DISPCTRL, dispctrl);
 510}
 511
 512void vc4_hvs_unmask_underrun(struct drm_device *dev, int channel)
 513{
 514        struct vc4_dev *vc4 = to_vc4_dev(dev);
 515        u32 dispctrl = HVS_READ(SCALER_DISPCTRL);
 516
 517        dispctrl |= SCALER_DISPCTRL_DSPEISLUR(channel);
 518
 519        HVS_WRITE(SCALER_DISPSTAT,
 520                  SCALER_DISPSTAT_EUFLOW(channel));
 521        HVS_WRITE(SCALER_DISPCTRL, dispctrl);
 522}
 523
 524static void vc4_hvs_report_underrun(struct drm_device *dev)
 525{
 526        struct vc4_dev *vc4 = to_vc4_dev(dev);
 527
 528        atomic_inc(&vc4->underrun);
 529        DRM_DEV_ERROR(dev->dev, "HVS underrun\n");
 530}
 531
 532static irqreturn_t vc4_hvs_irq_handler(int irq, void *data)
 533{
 534        struct drm_device *dev = data;
 535        struct vc4_dev *vc4 = to_vc4_dev(dev);
 536        irqreturn_t irqret = IRQ_NONE;
 537        int channel;
 538        u32 control;
 539        u32 status;
 540
 541        status = HVS_READ(SCALER_DISPSTAT);
 542        control = HVS_READ(SCALER_DISPCTRL);
 543
 544        for (channel = 0; channel < SCALER_CHANNELS_COUNT; channel++) {
 545                /* Interrupt masking is not always honored, so check it here. */
 546                if (status & SCALER_DISPSTAT_EUFLOW(channel) &&
 547                    control & SCALER_DISPCTRL_DSPEISLUR(channel)) {
 548                        vc4_hvs_mask_underrun(dev, channel);
 549                        vc4_hvs_report_underrun(dev);
 550
 551                        irqret = IRQ_HANDLED;
 552                }
 553        }
 554
 555        /* Clear every per-channel interrupt flag. */
 556        HVS_WRITE(SCALER_DISPSTAT, SCALER_DISPSTAT_IRQMASK(0) |
 557                                   SCALER_DISPSTAT_IRQMASK(1) |
 558                                   SCALER_DISPSTAT_IRQMASK(2));
 559
 560        return irqret;
 561}
 562
 563static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
 564{
 565        struct platform_device *pdev = to_platform_device(dev);
 566        struct drm_device *drm = dev_get_drvdata(master);
 567        struct vc4_dev *vc4 = to_vc4_dev(drm);
 568        struct vc4_hvs *hvs = NULL;
 569        int ret;
 570        u32 dispctrl;
 571
 572        hvs = devm_kzalloc(&pdev->dev, sizeof(*hvs), GFP_KERNEL);
 573        if (!hvs)
 574                return -ENOMEM;
 575
 576        hvs->pdev = pdev;
 577
 578        if (of_device_is_compatible(pdev->dev.of_node, "brcm,bcm2711-hvs"))
 579                hvs->hvs5 = true;
 580
 581        hvs->regs = vc4_ioremap_regs(pdev, 0);
 582        if (IS_ERR(hvs->regs))
 583                return PTR_ERR(hvs->regs);
 584
 585        hvs->regset.base = hvs->regs;
 586        hvs->regset.regs = hvs_regs;
 587        hvs->regset.nregs = ARRAY_SIZE(hvs_regs);
 588
 589        if (hvs->hvs5) {
 590                hvs->core_clk = devm_clk_get(&pdev->dev, NULL);
 591                if (IS_ERR(hvs->core_clk)) {
 592                        dev_err(&pdev->dev, "Couldn't get core clock\n");
 593                        return PTR_ERR(hvs->core_clk);
 594                }
 595
 596                ret = clk_prepare_enable(hvs->core_clk);
 597                if (ret) {
 598                        dev_err(&pdev->dev, "Couldn't enable the core clock\n");
 599                        return ret;
 600                }
 601        }
 602
 603        if (!hvs->hvs5)
 604                hvs->dlist = hvs->regs + SCALER_DLIST_START;
 605        else
 606                hvs->dlist = hvs->regs + SCALER5_DLIST_START;
 607
 608        spin_lock_init(&hvs->mm_lock);
 609
 610        /* Set up the HVS display list memory manager.  We never
 611         * overwrite the setup from the bootloader (just 128b out of
 612         * our 16K), since we don't want to scramble the screen when
 613         * transitioning from the firmware's boot setup to runtime.
 614         */
 615        drm_mm_init(&hvs->dlist_mm,
 616                    HVS_BOOTLOADER_DLIST_END,
 617                    (SCALER_DLIST_SIZE >> 2) - HVS_BOOTLOADER_DLIST_END);
 618
 619        /* Set up the HVS LBM memory manager.  We could have some more
 620         * complicated data structure that allowed reuse of LBM areas
 621         * between planes when they don't overlap on the screen, but
 622         * for now we just allocate globally.
 623         */
 624        if (!hvs->hvs5)
 625                /* 48k words of 2x12-bit pixels */
 626                drm_mm_init(&hvs->lbm_mm, 0, 48 * 1024);
 627        else
 628                /* 60k words of 4x12-bit pixels */
 629                drm_mm_init(&hvs->lbm_mm, 0, 60 * 1024);
 630
 631        /* Upload filter kernels.  We only have the one for now, so we
 632         * keep it around for the lifetime of the driver.
 633         */
 634        ret = vc4_hvs_upload_linear_kernel(hvs,
 635                                           &hvs->mitchell_netravali_filter,
 636                                           mitchell_netravali_1_3_1_3_kernel);
 637        if (ret)
 638                return ret;
 639
 640        vc4->hvs = hvs;
 641
 642        dispctrl = HVS_READ(SCALER_DISPCTRL);
 643
 644        dispctrl |= SCALER_DISPCTRL_ENABLE;
 645        dispctrl |= SCALER_DISPCTRL_DISPEIRQ(0) |
 646                    SCALER_DISPCTRL_DISPEIRQ(1) |
 647                    SCALER_DISPCTRL_DISPEIRQ(2);
 648
 649        /* Set DSP3 (PV1) to use HVS channel 2, which would otherwise
 650         * be unused.
 651         */
 652        dispctrl &= ~SCALER_DISPCTRL_DSP3_MUX_MASK;
 653        dispctrl &= ~(SCALER_DISPCTRL_DMAEIRQ |
 654                      SCALER_DISPCTRL_SLVWREIRQ |
 655                      SCALER_DISPCTRL_SLVRDEIRQ |
 656                      SCALER_DISPCTRL_DSPEIEOF(0) |
 657                      SCALER_DISPCTRL_DSPEIEOF(1) |
 658                      SCALER_DISPCTRL_DSPEIEOF(2) |
 659                      SCALER_DISPCTRL_DSPEIEOLN(0) |
 660                      SCALER_DISPCTRL_DSPEIEOLN(1) |
 661                      SCALER_DISPCTRL_DSPEIEOLN(2) |
 662                      SCALER_DISPCTRL_DSPEISLUR(0) |
 663                      SCALER_DISPCTRL_DSPEISLUR(1) |
 664                      SCALER_DISPCTRL_DSPEISLUR(2) |
 665                      SCALER_DISPCTRL_SCLEIRQ);
 666        dispctrl |= VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX);
 667
 668        HVS_WRITE(SCALER_DISPCTRL, dispctrl);
 669
 670        ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
 671                               vc4_hvs_irq_handler, 0, "vc4 hvs", drm);
 672        if (ret)
 673                return ret;
 674
 675        vc4_debugfs_add_regset32(drm, "hvs_regs", &hvs->regset);
 676        vc4_debugfs_add_file(drm, "hvs_underrun", vc4_hvs_debugfs_underrun,
 677                             NULL);
 678
 679        return 0;
 680}
 681
 682static void vc4_hvs_unbind(struct device *dev, struct device *master,
 683                           void *data)
 684{
 685        struct drm_device *drm = dev_get_drvdata(master);
 686        struct vc4_dev *vc4 = to_vc4_dev(drm);
 687        struct vc4_hvs *hvs = vc4->hvs;
 688
 689        if (drm_mm_node_allocated(&vc4->hvs->mitchell_netravali_filter))
 690                drm_mm_remove_node(&vc4->hvs->mitchell_netravali_filter);
 691
 692        drm_mm_takedown(&vc4->hvs->dlist_mm);
 693        drm_mm_takedown(&vc4->hvs->lbm_mm);
 694
 695        clk_disable_unprepare(hvs->core_clk);
 696
 697        vc4->hvs = NULL;
 698}
 699
 700static const struct component_ops vc4_hvs_ops = {
 701        .bind   = vc4_hvs_bind,
 702        .unbind = vc4_hvs_unbind,
 703};
 704
 705static int vc4_hvs_dev_probe(struct platform_device *pdev)
 706{
 707        return component_add(&pdev->dev, &vc4_hvs_ops);
 708}
 709
 710static int vc4_hvs_dev_remove(struct platform_device *pdev)
 711{
 712        component_del(&pdev->dev, &vc4_hvs_ops);
 713        return 0;
 714}
 715
 716static const struct of_device_id vc4_hvs_dt_match[] = {
 717        { .compatible = "brcm,bcm2711-hvs" },
 718        { .compatible = "brcm,bcm2835-hvs" },
 719        {}
 720};
 721
 722struct platform_driver vc4_hvs_driver = {
 723        .probe = vc4_hvs_dev_probe,
 724        .remove = vc4_hvs_dev_remove,
 725        .driver = {
 726                .name = "vc4_hvs",
 727                .of_match_table = vc4_hvs_dt_match,
 728        },
 729};
 730