linux/drivers/gpu/host1x/drm/dc.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2012 Avionic Design GmbH
   3 * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License version 2 as
   7 * published by the Free Software Foundation.
   8 */
   9
  10#include <linux/clk.h>
  11#include <linux/debugfs.h>
  12#include <linux/module.h>
  13#include <linux/of.h>
  14#include <linux/platform_device.h>
  15#include <linux/clk/tegra.h>
  16
  17#include "host1x_client.h"
  18#include "dc.h"
  19#include "drm.h"
  20#include "gem.h"
  21
  22struct tegra_plane {
  23        struct drm_plane base;
  24        unsigned int index;
  25};
  26
  27static inline struct tegra_plane *to_tegra_plane(struct drm_plane *plane)
  28{
  29        return container_of(plane, struct tegra_plane, base);
  30}
  31
  32static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
  33                              struct drm_framebuffer *fb, int crtc_x,
  34                              int crtc_y, unsigned int crtc_w,
  35                              unsigned int crtc_h, uint32_t src_x,
  36                              uint32_t src_y, uint32_t src_w, uint32_t src_h)
  37{
  38        struct tegra_plane *p = to_tegra_plane(plane);
  39        struct tegra_dc *dc = to_tegra_dc(crtc);
  40        struct tegra_dc_window window;
  41        unsigned int i;
  42
  43        memset(&window, 0, sizeof(window));
  44        window.src.x = src_x >> 16;
  45        window.src.y = src_y >> 16;
  46        window.src.w = src_w >> 16;
  47        window.src.h = src_h >> 16;
  48        window.dst.x = crtc_x;
  49        window.dst.y = crtc_y;
  50        window.dst.w = crtc_w;
  51        window.dst.h = crtc_h;
  52        window.format = tegra_dc_format(fb->pixel_format);
  53        window.bits_per_pixel = fb->bits_per_pixel;
  54
  55        for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
  56                struct tegra_bo *bo = tegra_fb_get_plane(fb, i);
  57
  58                window.base[i] = bo->paddr + fb->offsets[i];
  59
  60                /*
  61                 * Tegra doesn't support different strides for U and V planes
  62                 * so we display a warning if the user tries to display a
  63                 * framebuffer with such a configuration.
  64                 */
  65                if (i >= 2) {
  66                        if (fb->pitches[i] != window.stride[1])
  67                                DRM_ERROR("unsupported UV-plane configuration\n");
  68                } else {
  69                        window.stride[i] = fb->pitches[i];
  70                }
  71        }
  72
  73        return tegra_dc_setup_window(dc, p->index, &window);
  74}
  75
  76static int tegra_plane_disable(struct drm_plane *plane)
  77{
  78        struct tegra_dc *dc = to_tegra_dc(plane->crtc);
  79        struct tegra_plane *p = to_tegra_plane(plane);
  80        unsigned long value;
  81
  82        value = WINDOW_A_SELECT << p->index;
  83        tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
  84
  85        value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
  86        value &= ~WIN_ENABLE;
  87        tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
  88
  89        tegra_dc_writel(dc, WIN_A_UPDATE << p->index, DC_CMD_STATE_CONTROL);
  90        tegra_dc_writel(dc, WIN_A_ACT_REQ << p->index, DC_CMD_STATE_CONTROL);
  91
  92        return 0;
  93}
  94
  95static void tegra_plane_destroy(struct drm_plane *plane)
  96{
  97        tegra_plane_disable(plane);
  98        drm_plane_cleanup(plane);
  99}
 100
 101static const struct drm_plane_funcs tegra_plane_funcs = {
 102        .update_plane = tegra_plane_update,
 103        .disable_plane = tegra_plane_disable,
 104        .destroy = tegra_plane_destroy,
 105};
 106
 107static const uint32_t plane_formats[] = {
 108        DRM_FORMAT_XBGR8888,
 109        DRM_FORMAT_XRGB8888,
 110        DRM_FORMAT_RGB565,
 111        DRM_FORMAT_UYVY,
 112        DRM_FORMAT_YUV420,
 113        DRM_FORMAT_YUV422,
 114};
 115
 116static int tegra_dc_add_planes(struct drm_device *drm, struct tegra_dc *dc)
 117{
 118        unsigned int i;
 119        int err = 0;
 120
 121        for (i = 0; i < 2; i++) {
 122                struct tegra_plane *plane;
 123
 124                plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
 125                if (!plane)
 126                        return -ENOMEM;
 127
 128                plane->index = 1 + i;
 129
 130                err = drm_plane_init(drm, &plane->base, 1 << dc->pipe,
 131                                     &tegra_plane_funcs, plane_formats,
 132                                     ARRAY_SIZE(plane_formats), false);
 133                if (err < 0)
 134                        return err;
 135        }
 136
 137        return 0;
 138}
 139
 140static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
 141                             struct drm_framebuffer *fb)
 142{
 143        struct tegra_bo *bo = tegra_fb_get_plane(fb, 0);
 144        unsigned long value;
 145
 146        tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER);
 147
 148        value = fb->offsets[0] + y * fb->pitches[0] +
 149                x * fb->bits_per_pixel / 8;
 150
 151        tegra_dc_writel(dc, bo->paddr + value, DC_WINBUF_START_ADDR);
 152        tegra_dc_writel(dc, fb->pitches[0], DC_WIN_LINE_STRIDE);
 153
 154        value = GENERAL_UPDATE | WIN_A_UPDATE;
 155        tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
 156
 157        value = GENERAL_ACT_REQ | WIN_A_ACT_REQ;
 158        tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
 159
 160        return 0;
 161}
 162
 163void tegra_dc_enable_vblank(struct tegra_dc *dc)
 164{
 165        unsigned long value, flags;
 166
 167        spin_lock_irqsave(&dc->lock, flags);
 168
 169        value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
 170        value |= VBLANK_INT;
 171        tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
 172
 173        spin_unlock_irqrestore(&dc->lock, flags);
 174}
 175
 176void tegra_dc_disable_vblank(struct tegra_dc *dc)
 177{
 178        unsigned long value, flags;
 179
 180        spin_lock_irqsave(&dc->lock, flags);
 181
 182        value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
 183        value &= ~VBLANK_INT;
 184        tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
 185
 186        spin_unlock_irqrestore(&dc->lock, flags);
 187}
 188
 189static void tegra_dc_finish_page_flip(struct tegra_dc *dc)
 190{
 191        struct drm_device *drm = dc->base.dev;
 192        struct drm_crtc *crtc = &dc->base;
 193        unsigned long flags, base;
 194        struct tegra_bo *bo;
 195
 196        if (!dc->event)
 197                return;
 198
 199        bo = tegra_fb_get_plane(crtc->fb, 0);
 200
 201        /* check if new start address has been latched */
 202        tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS);
 203        base = tegra_dc_readl(dc, DC_WINBUF_START_ADDR);
 204        tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS);
 205
 206        if (base == bo->paddr + crtc->fb->offsets[0]) {
 207                spin_lock_irqsave(&drm->event_lock, flags);
 208                drm_send_vblank_event(drm, dc->pipe, dc->event);
 209                drm_vblank_put(drm, dc->pipe);
 210                dc->event = NULL;
 211                spin_unlock_irqrestore(&drm->event_lock, flags);
 212        }
 213}
 214
 215void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file)
 216{
 217        struct tegra_dc *dc = to_tegra_dc(crtc);
 218        struct drm_device *drm = crtc->dev;
 219        unsigned long flags;
 220
 221        spin_lock_irqsave(&drm->event_lock, flags);
 222
 223        if (dc->event && dc->event->base.file_priv == file) {
 224                dc->event->base.destroy(&dc->event->base);
 225                drm_vblank_put(drm, dc->pipe);
 226                dc->event = NULL;
 227        }
 228
 229        spin_unlock_irqrestore(&drm->event_lock, flags);
 230}
 231
 232static int tegra_dc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 233                              struct drm_pending_vblank_event *event)
 234{
 235        struct tegra_dc *dc = to_tegra_dc(crtc);
 236        struct drm_device *drm = crtc->dev;
 237
 238        if (dc->event)
 239                return -EBUSY;
 240
 241        if (event) {
 242                event->pipe = dc->pipe;
 243                dc->event = event;
 244                drm_vblank_get(drm, dc->pipe);
 245        }
 246
 247        tegra_dc_set_base(dc, 0, 0, fb);
 248        crtc->fb = fb;
 249
 250        return 0;
 251}
 252
 253static const struct drm_crtc_funcs tegra_crtc_funcs = {
 254        .page_flip = tegra_dc_page_flip,
 255        .set_config = drm_crtc_helper_set_config,
 256        .destroy = drm_crtc_cleanup,
 257};
 258
 259static void tegra_crtc_disable(struct drm_crtc *crtc)
 260{
 261        struct drm_device *drm = crtc->dev;
 262        struct drm_plane *plane;
 263
 264        list_for_each_entry(plane, &drm->mode_config.plane_list, head) {
 265                if (plane->crtc == crtc) {
 266                        tegra_plane_disable(plane);
 267                        plane->crtc = NULL;
 268
 269                        if (plane->fb) {
 270                                drm_framebuffer_unreference(plane->fb);
 271                                plane->fb = NULL;
 272                        }
 273                }
 274        }
 275}
 276
 277static bool tegra_crtc_mode_fixup(struct drm_crtc *crtc,
 278                                  const struct drm_display_mode *mode,
 279                                  struct drm_display_mode *adjusted)
 280{
 281        return true;
 282}
 283
 284static inline u32 compute_dda_inc(unsigned int in, unsigned int out, bool v,
 285                                  unsigned int bpp)
 286{
 287        fixed20_12 outf = dfixed_init(out);
 288        fixed20_12 inf = dfixed_init(in);
 289        u32 dda_inc;
 290        int max;
 291
 292        if (v)
 293                max = 15;
 294        else {
 295                switch (bpp) {
 296                case 2:
 297                        max = 8;
 298                        break;
 299
 300                default:
 301                        WARN_ON_ONCE(1);
 302                        /* fallthrough */
 303                case 4:
 304                        max = 4;
 305                        break;
 306                }
 307        }
 308
 309        outf.full = max_t(u32, outf.full - dfixed_const(1), dfixed_const(1));
 310        inf.full -= dfixed_const(1);
 311
 312        dda_inc = dfixed_div(inf, outf);
 313        dda_inc = min_t(u32, dda_inc, dfixed_const(max));
 314
 315        return dda_inc;
 316}
 317
 318static inline u32 compute_initial_dda(unsigned int in)
 319{
 320        fixed20_12 inf = dfixed_init(in);
 321        return dfixed_frac(inf);
 322}
 323
 324static int tegra_dc_set_timings(struct tegra_dc *dc,
 325                                struct drm_display_mode *mode)
 326{
 327        /* TODO: For HDMI compliance, h & v ref_to_sync should be set to 1 */
 328        unsigned int h_ref_to_sync = 0;
 329        unsigned int v_ref_to_sync = 0;
 330        unsigned long value;
 331
 332        tegra_dc_writel(dc, 0x0, DC_DISP_DISP_TIMING_OPTIONS);
 333
 334        value = (v_ref_to_sync << 16) | h_ref_to_sync;
 335        tegra_dc_writel(dc, value, DC_DISP_REF_TO_SYNC);
 336
 337        value = ((mode->vsync_end - mode->vsync_start) << 16) |
 338                ((mode->hsync_end - mode->hsync_start) <<  0);
 339        tegra_dc_writel(dc, value, DC_DISP_SYNC_WIDTH);
 340
 341        value = ((mode->vtotal - mode->vsync_end) << 16) |
 342                ((mode->htotal - mode->hsync_end) <<  0);
 343        tegra_dc_writel(dc, value, DC_DISP_BACK_PORCH);
 344
 345        value = ((mode->vsync_start - mode->vdisplay) << 16) |
 346                ((mode->hsync_start - mode->hdisplay) <<  0);
 347        tegra_dc_writel(dc, value, DC_DISP_FRONT_PORCH);
 348
 349        value = (mode->vdisplay << 16) | mode->hdisplay;
 350        tegra_dc_writel(dc, value, DC_DISP_ACTIVE);
 351
 352        return 0;
 353}
 354
 355static int tegra_crtc_setup_clk(struct drm_crtc *crtc,
 356                                struct drm_display_mode *mode,
 357                                unsigned long *div)
 358{
 359        unsigned long pclk = mode->clock * 1000, rate;
 360        struct tegra_dc *dc = to_tegra_dc(crtc);
 361        struct tegra_output *output = NULL;
 362        struct drm_encoder *encoder;
 363        long err;
 364
 365        list_for_each_entry(encoder, &crtc->dev->mode_config.encoder_list, head)
 366                if (encoder->crtc == crtc) {
 367                        output = encoder_to_output(encoder);
 368                        break;
 369                }
 370
 371        if (!output)
 372                return -ENODEV;
 373
 374        /*
 375         * This assumes that the display controller will divide its parent
 376         * clock by 2 to generate the pixel clock.
 377         */
 378        err = tegra_output_setup_clock(output, dc->clk, pclk * 2);
 379        if (err < 0) {
 380                dev_err(dc->dev, "failed to setup clock: %ld\n", err);
 381                return err;
 382        }
 383
 384        rate = clk_get_rate(dc->clk);
 385        *div = (rate * 2 / pclk) - 2;
 386
 387        DRM_DEBUG_KMS("rate: %lu, div: %lu\n", rate, *div);
 388
 389        return 0;
 390}
 391
 392static bool tegra_dc_format_is_yuv(unsigned int format, bool *planar)
 393{
 394        switch (format) {
 395        case WIN_COLOR_DEPTH_YCbCr422:
 396        case WIN_COLOR_DEPTH_YUV422:
 397                if (planar)
 398                        *planar = false;
 399
 400                return true;
 401
 402        case WIN_COLOR_DEPTH_YCbCr420P:
 403        case WIN_COLOR_DEPTH_YUV420P:
 404        case WIN_COLOR_DEPTH_YCbCr422P:
 405        case WIN_COLOR_DEPTH_YUV422P:
 406        case WIN_COLOR_DEPTH_YCbCr422R:
 407        case WIN_COLOR_DEPTH_YUV422R:
 408        case WIN_COLOR_DEPTH_YCbCr422RA:
 409        case WIN_COLOR_DEPTH_YUV422RA:
 410                if (planar)
 411                        *planar = true;
 412
 413                return true;
 414        }
 415
 416        return false;
 417}
 418
 419int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
 420                          const struct tegra_dc_window *window)
 421{
 422        unsigned h_offset, v_offset, h_size, v_size, h_dda, v_dda, bpp;
 423        unsigned long value;
 424        bool yuv, planar;
 425
 426        /*
 427         * For YUV planar modes, the number of bytes per pixel takes into
 428         * account only the luma component and therefore is 1.
 429         */
 430        yuv = tegra_dc_format_is_yuv(window->format, &planar);
 431        if (!yuv)
 432                bpp = window->bits_per_pixel / 8;
 433        else
 434                bpp = planar ? 1 : 2;
 435
 436        value = WINDOW_A_SELECT << index;
 437        tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
 438
 439        tegra_dc_writel(dc, window->format, DC_WIN_COLOR_DEPTH);
 440        tegra_dc_writel(dc, 0, DC_WIN_BYTE_SWAP);
 441
 442        value = V_POSITION(window->dst.y) | H_POSITION(window->dst.x);
 443        tegra_dc_writel(dc, value, DC_WIN_POSITION);
 444
 445        value = V_SIZE(window->dst.h) | H_SIZE(window->dst.w);
 446        tegra_dc_writel(dc, value, DC_WIN_SIZE);
 447
 448        h_offset = window->src.x * bpp;
 449        v_offset = window->src.y;
 450        h_size = window->src.w * bpp;
 451        v_size = window->src.h;
 452
 453        value = V_PRESCALED_SIZE(v_size) | H_PRESCALED_SIZE(h_size);
 454        tegra_dc_writel(dc, value, DC_WIN_PRESCALED_SIZE);
 455
 456        /*
 457         * For DDA computations the number of bytes per pixel for YUV planar
 458         * modes needs to take into account all Y, U and V components.
 459         */
 460        if (yuv && planar)
 461                bpp = 2;
 462
 463        h_dda = compute_dda_inc(window->src.w, window->dst.w, false, bpp);
 464        v_dda = compute_dda_inc(window->src.h, window->dst.h, true, bpp);
 465
 466        value = V_DDA_INC(v_dda) | H_DDA_INC(h_dda);
 467        tegra_dc_writel(dc, value, DC_WIN_DDA_INC);
 468
 469        h_dda = compute_initial_dda(window->src.x);
 470        v_dda = compute_initial_dda(window->src.y);
 471
 472        tegra_dc_writel(dc, h_dda, DC_WIN_H_INITIAL_DDA);
 473        tegra_dc_writel(dc, v_dda, DC_WIN_V_INITIAL_DDA);
 474
 475        tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE);
 476        tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE);
 477
 478        tegra_dc_writel(dc, window->base[0], DC_WINBUF_START_ADDR);
 479
 480        if (yuv && planar) {
 481                tegra_dc_writel(dc, window->base[1], DC_WINBUF_START_ADDR_U);
 482                tegra_dc_writel(dc, window->base[2], DC_WINBUF_START_ADDR_V);
 483                value = window->stride[1] << 16 | window->stride[0];
 484                tegra_dc_writel(dc, value, DC_WIN_LINE_STRIDE);
 485        } else {
 486                tegra_dc_writel(dc, window->stride[0], DC_WIN_LINE_STRIDE);
 487        }
 488
 489        tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET);
 490        tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET);
 491
 492        value = WIN_ENABLE;
 493
 494        if (yuv) {
 495                /* setup default colorspace conversion coefficients */
 496                tegra_dc_writel(dc, 0x00f0, DC_WIN_CSC_YOF);
 497                tegra_dc_writel(dc, 0x012a, DC_WIN_CSC_KYRGB);
 498                tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KUR);
 499                tegra_dc_writel(dc, 0x0198, DC_WIN_CSC_KVR);
 500                tegra_dc_writel(dc, 0x039b, DC_WIN_CSC_KUG);
 501                tegra_dc_writel(dc, 0x032f, DC_WIN_CSC_KVG);
 502                tegra_dc_writel(dc, 0x0204, DC_WIN_CSC_KUB);
 503                tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KVB);
 504
 505                value |= CSC_ENABLE;
 506        } else if (window->bits_per_pixel < 24) {
 507                value |= COLOR_EXPAND;
 508        }
 509
 510        tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
 511
 512        /*
 513         * Disable blending and assume Window A is the bottom-most window,
 514         * Window C is the top-most window and Window B is in the middle.
 515         */
 516        tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_NOKEY);
 517        tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_1WIN);
 518
 519        switch (index) {
 520        case 0:
 521                tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_X);
 522                tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y);
 523                tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY);
 524                break;
 525
 526        case 1:
 527                tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X);
 528                tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y);
 529                tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY);
 530                break;
 531
 532        case 2:
 533                tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X);
 534                tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_Y);
 535                tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_3WIN_XY);
 536                break;
 537        }
 538
 539        tegra_dc_writel(dc, WIN_A_UPDATE << index, DC_CMD_STATE_CONTROL);
 540        tegra_dc_writel(dc, WIN_A_ACT_REQ << index, DC_CMD_STATE_CONTROL);
 541
 542        return 0;
 543}
 544
 545unsigned int tegra_dc_format(uint32_t format)
 546{
 547        switch (format) {
 548        case DRM_FORMAT_XBGR8888:
 549                return WIN_COLOR_DEPTH_R8G8B8A8;
 550
 551        case DRM_FORMAT_XRGB8888:
 552                return WIN_COLOR_DEPTH_B8G8R8A8;
 553
 554        case DRM_FORMAT_RGB565:
 555                return WIN_COLOR_DEPTH_B5G6R5;
 556
 557        case DRM_FORMAT_UYVY:
 558                return WIN_COLOR_DEPTH_YCbCr422;
 559
 560        case DRM_FORMAT_YUV420:
 561                return WIN_COLOR_DEPTH_YCbCr420P;
 562
 563        case DRM_FORMAT_YUV422:
 564                return WIN_COLOR_DEPTH_YCbCr422P;
 565
 566        default:
 567                break;
 568        }
 569
 570        WARN(1, "unsupported pixel format %u, using default\n", format);
 571        return WIN_COLOR_DEPTH_B8G8R8A8;
 572}
 573
 574static int tegra_crtc_mode_set(struct drm_crtc *crtc,
 575                               struct drm_display_mode *mode,
 576                               struct drm_display_mode *adjusted,
 577                               int x, int y, struct drm_framebuffer *old_fb)
 578{
 579        struct tegra_bo *bo = tegra_fb_get_plane(crtc->fb, 0);
 580        struct tegra_dc *dc = to_tegra_dc(crtc);
 581        struct tegra_dc_window window;
 582        unsigned long div, value;
 583        int err;
 584
 585        drm_vblank_pre_modeset(crtc->dev, dc->pipe);
 586
 587        err = tegra_crtc_setup_clk(crtc, mode, &div);
 588        if (err) {
 589                dev_err(dc->dev, "failed to setup clock for CRTC: %d\n", err);
 590                return err;
 591        }
 592
 593        /* program display mode */
 594        tegra_dc_set_timings(dc, mode);
 595
 596        value = DE_SELECT_ACTIVE | DE_CONTROL_NORMAL;
 597        tegra_dc_writel(dc, value, DC_DISP_DATA_ENABLE_OPTIONS);
 598
 599        value = tegra_dc_readl(dc, DC_COM_PIN_OUTPUT_POLARITY(1));
 600        value &= ~LVS_OUTPUT_POLARITY_LOW;
 601        value &= ~LHS_OUTPUT_POLARITY_LOW;
 602        tegra_dc_writel(dc, value, DC_COM_PIN_OUTPUT_POLARITY(1));
 603
 604        value = DISP_DATA_FORMAT_DF1P1C | DISP_ALIGNMENT_MSB |
 605                DISP_ORDER_RED_BLUE;
 606        tegra_dc_writel(dc, value, DC_DISP_DISP_INTERFACE_CONTROL);
 607
 608        tegra_dc_writel(dc, 0x00010001, DC_DISP_SHIFT_CLOCK_OPTIONS);
 609
 610        value = SHIFT_CLK_DIVIDER(div) | PIXEL_CLK_DIVIDER_PCD1;
 611        tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);
 612
 613        /* setup window parameters */
 614        memset(&window, 0, sizeof(window));
 615        window.src.x = 0;
 616        window.src.y = 0;
 617        window.src.w = mode->hdisplay;
 618        window.src.h = mode->vdisplay;
 619        window.dst.x = 0;
 620        window.dst.y = 0;
 621        window.dst.w = mode->hdisplay;
 622        window.dst.h = mode->vdisplay;
 623        window.format = tegra_dc_format(crtc->fb->pixel_format);
 624        window.bits_per_pixel = crtc->fb->bits_per_pixel;
 625        window.stride[0] = crtc->fb->pitches[0];
 626        window.base[0] = bo->paddr;
 627
 628        err = tegra_dc_setup_window(dc, 0, &window);
 629        if (err < 0)
 630                dev_err(dc->dev, "failed to enable root plane\n");
 631
 632        return 0;
 633}
 634
 635static int tegra_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
 636                                    struct drm_framebuffer *old_fb)
 637{
 638        struct tegra_dc *dc = to_tegra_dc(crtc);
 639
 640        return tegra_dc_set_base(dc, x, y, crtc->fb);
 641}
 642
 643static void tegra_crtc_prepare(struct drm_crtc *crtc)
 644{
 645        struct tegra_dc *dc = to_tegra_dc(crtc);
 646        unsigned int syncpt;
 647        unsigned long value;
 648
 649        /* hardware initialization */
 650        tegra_periph_reset_deassert(dc->clk);
 651        usleep_range(10000, 20000);
 652
 653        if (dc->pipe)
 654                syncpt = SYNCPT_VBLANK1;
 655        else
 656                syncpt = SYNCPT_VBLANK0;
 657
 658        /* initialize display controller */
 659        tegra_dc_writel(dc, 0x00000100, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
 660        tegra_dc_writel(dc, 0x100 | syncpt, DC_CMD_CONT_SYNCPT_VSYNC);
 661
 662        value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | WIN_A_OF_INT;
 663        tegra_dc_writel(dc, value, DC_CMD_INT_TYPE);
 664
 665        value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
 666                WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
 667        tegra_dc_writel(dc, value, DC_CMD_INT_POLARITY);
 668
 669        value = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
 670                PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
 671        tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
 672
 673        value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
 674        value |= DISP_CTRL_MODE_C_DISPLAY;
 675        tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
 676
 677        /* initialize timer */
 678        value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(0x20) |
 679                WINDOW_B_THRESHOLD(0x20) | WINDOW_C_THRESHOLD(0x20);
 680        tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY);
 681
 682        value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(1) |
 683                WINDOW_B_THRESHOLD(1) | WINDOW_C_THRESHOLD(1);
 684        tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
 685
 686        value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT;
 687        tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);
 688
 689        value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT;
 690        tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
 691}
 692
 693static void tegra_crtc_commit(struct drm_crtc *crtc)
 694{
 695        struct tegra_dc *dc = to_tegra_dc(crtc);
 696        unsigned long value;
 697
 698        value = GENERAL_UPDATE | WIN_A_UPDATE;
 699        tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
 700
 701        value = GENERAL_ACT_REQ | WIN_A_ACT_REQ;
 702        tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
 703
 704        drm_vblank_post_modeset(crtc->dev, dc->pipe);
 705}
 706
 707static void tegra_crtc_load_lut(struct drm_crtc *crtc)
 708{
 709}
 710
 711static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = {
 712        .disable = tegra_crtc_disable,
 713        .mode_fixup = tegra_crtc_mode_fixup,
 714        .mode_set = tegra_crtc_mode_set,
 715        .mode_set_base = tegra_crtc_mode_set_base,
 716        .prepare = tegra_crtc_prepare,
 717        .commit = tegra_crtc_commit,
 718        .load_lut = tegra_crtc_load_lut,
 719};
 720
 721static irqreturn_t tegra_dc_irq(int irq, void *data)
 722{
 723        struct tegra_dc *dc = data;
 724        unsigned long status;
 725
 726        status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);
 727        tegra_dc_writel(dc, status, DC_CMD_INT_STATUS);
 728
 729        if (status & FRAME_END_INT) {
 730                /*
 731                dev_dbg(dc->dev, "%s(): frame end\n", __func__);
 732                */
 733        }
 734
 735        if (status & VBLANK_INT) {
 736                /*
 737                dev_dbg(dc->dev, "%s(): vertical blank\n", __func__);
 738                */
 739                drm_handle_vblank(dc->base.dev, dc->pipe);
 740                tegra_dc_finish_page_flip(dc);
 741        }
 742
 743        if (status & (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)) {
 744                /*
 745                dev_dbg(dc->dev, "%s(): underflow\n", __func__);
 746                */
 747        }
 748
 749        return IRQ_HANDLED;
 750}
 751
 752static int tegra_dc_show_regs(struct seq_file *s, void *data)
 753{
 754        struct drm_info_node *node = s->private;
 755        struct tegra_dc *dc = node->info_ent->data;
 756
 757#define DUMP_REG(name)                                          \
 758        seq_printf(s, "%-40s %#05x %08lx\n", #name, name,       \
 759                   tegra_dc_readl(dc, name))
 760
 761        DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT);
 762        DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
 763        DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT_ERROR);
 764        DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT);
 765        DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT_CNTRL);
 766        DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT_ERROR);
 767        DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT);
 768        DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT_CNTRL);
 769        DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT_ERROR);
 770        DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT);
 771        DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT_CNTRL);
 772        DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT_ERROR);
 773        DUMP_REG(DC_CMD_CONT_SYNCPT_VSYNC);
 774        DUMP_REG(DC_CMD_DISPLAY_COMMAND_OPTION0);
 775        DUMP_REG(DC_CMD_DISPLAY_COMMAND);
 776        DUMP_REG(DC_CMD_SIGNAL_RAISE);
 777        DUMP_REG(DC_CMD_DISPLAY_POWER_CONTROL);
 778        DUMP_REG(DC_CMD_INT_STATUS);
 779        DUMP_REG(DC_CMD_INT_MASK);
 780        DUMP_REG(DC_CMD_INT_ENABLE);
 781        DUMP_REG(DC_CMD_INT_TYPE);
 782        DUMP_REG(DC_CMD_INT_POLARITY);
 783        DUMP_REG(DC_CMD_SIGNAL_RAISE1);
 784        DUMP_REG(DC_CMD_SIGNAL_RAISE2);
 785        DUMP_REG(DC_CMD_SIGNAL_RAISE3);
 786        DUMP_REG(DC_CMD_STATE_ACCESS);
 787        DUMP_REG(DC_CMD_STATE_CONTROL);
 788        DUMP_REG(DC_CMD_DISPLAY_WINDOW_HEADER);
 789        DUMP_REG(DC_CMD_REG_ACT_CONTROL);
 790        DUMP_REG(DC_COM_CRC_CONTROL);
 791        DUMP_REG(DC_COM_CRC_CHECKSUM);
 792        DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(0));
 793        DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(1));
 794        DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(2));
 795        DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(3));
 796        DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(0));
 797        DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(1));
 798        DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(2));
 799        DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(3));
 800        DUMP_REG(DC_COM_PIN_OUTPUT_DATA(0));
 801        DUMP_REG(DC_COM_PIN_OUTPUT_DATA(1));
 802        DUMP_REG(DC_COM_PIN_OUTPUT_DATA(2));
 803        DUMP_REG(DC_COM_PIN_OUTPUT_DATA(3));
 804        DUMP_REG(DC_COM_PIN_INPUT_ENABLE(0));
 805        DUMP_REG(DC_COM_PIN_INPUT_ENABLE(1));
 806        DUMP_REG(DC_COM_PIN_INPUT_ENABLE(2));
 807        DUMP_REG(DC_COM_PIN_INPUT_ENABLE(3));
 808        DUMP_REG(DC_COM_PIN_INPUT_DATA(0));
 809        DUMP_REG(DC_COM_PIN_INPUT_DATA(1));
 810        DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(0));
 811        DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(1));
 812        DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(2));
 813        DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(3));
 814        DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(4));
 815        DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(5));
 816        DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(6));
 817        DUMP_REG(DC_COM_PIN_MISC_CONTROL);
 818        DUMP_REG(DC_COM_PIN_PM0_CONTROL);
 819        DUMP_REG(DC_COM_PIN_PM0_DUTY_CYCLE);
 820        DUMP_REG(DC_COM_PIN_PM1_CONTROL);
 821        DUMP_REG(DC_COM_PIN_PM1_DUTY_CYCLE);
 822        DUMP_REG(DC_COM_SPI_CONTROL);
 823        DUMP_REG(DC_COM_SPI_START_BYTE);
 824        DUMP_REG(DC_COM_HSPI_WRITE_DATA_AB);
 825        DUMP_REG(DC_COM_HSPI_WRITE_DATA_CD);
 826        DUMP_REG(DC_COM_HSPI_CS_DC);
 827        DUMP_REG(DC_COM_SCRATCH_REGISTER_A);
 828        DUMP_REG(DC_COM_SCRATCH_REGISTER_B);
 829        DUMP_REG(DC_COM_GPIO_CTRL);
 830        DUMP_REG(DC_COM_GPIO_DEBOUNCE_COUNTER);
 831        DUMP_REG(DC_COM_CRC_CHECKSUM_LATCHED);
 832        DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS0);
 833        DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS1);
 834        DUMP_REG(DC_DISP_DISP_WIN_OPTIONS);
 835        DUMP_REG(DC_DISP_DISP_MEM_HIGH_PRIORITY);
 836        DUMP_REG(DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
 837        DUMP_REG(DC_DISP_DISP_TIMING_OPTIONS);
 838        DUMP_REG(DC_DISP_REF_TO_SYNC);
 839        DUMP_REG(DC_DISP_SYNC_WIDTH);
 840        DUMP_REG(DC_DISP_BACK_PORCH);
 841        DUMP_REG(DC_DISP_ACTIVE);
 842        DUMP_REG(DC_DISP_FRONT_PORCH);
 843        DUMP_REG(DC_DISP_H_PULSE0_CONTROL);
 844        DUMP_REG(DC_DISP_H_PULSE0_POSITION_A);
 845        DUMP_REG(DC_DISP_H_PULSE0_POSITION_B);
 846        DUMP_REG(DC_DISP_H_PULSE0_POSITION_C);
 847        DUMP_REG(DC_DISP_H_PULSE0_POSITION_D);
 848        DUMP_REG(DC_DISP_H_PULSE1_CONTROL);
 849        DUMP_REG(DC_DISP_H_PULSE1_POSITION_A);
 850        DUMP_REG(DC_DISP_H_PULSE1_POSITION_B);
 851        DUMP_REG(DC_DISP_H_PULSE1_POSITION_C);
 852        DUMP_REG(DC_DISP_H_PULSE1_POSITION_D);
 853        DUMP_REG(DC_DISP_H_PULSE2_CONTROL);
 854        DUMP_REG(DC_DISP_H_PULSE2_POSITION_A);
 855        DUMP_REG(DC_DISP_H_PULSE2_POSITION_B);
 856        DUMP_REG(DC_DISP_H_PULSE2_POSITION_C);
 857        DUMP_REG(DC_DISP_H_PULSE2_POSITION_D);
 858        DUMP_REG(DC_DISP_V_PULSE0_CONTROL);
 859        DUMP_REG(DC_DISP_V_PULSE0_POSITION_A);
 860        DUMP_REG(DC_DISP_V_PULSE0_POSITION_B);
 861        DUMP_REG(DC_DISP_V_PULSE0_POSITION_C);
 862        DUMP_REG(DC_DISP_V_PULSE1_CONTROL);
 863        DUMP_REG(DC_DISP_V_PULSE1_POSITION_A);
 864        DUMP_REG(DC_DISP_V_PULSE1_POSITION_B);
 865        DUMP_REG(DC_DISP_V_PULSE1_POSITION_C);
 866        DUMP_REG(DC_DISP_V_PULSE2_CONTROL);
 867        DUMP_REG(DC_DISP_V_PULSE2_POSITION_A);
 868        DUMP_REG(DC_DISP_V_PULSE3_CONTROL);
 869        DUMP_REG(DC_DISP_V_PULSE3_POSITION_A);
 870        DUMP_REG(DC_DISP_M0_CONTROL);
 871        DUMP_REG(DC_DISP_M1_CONTROL);
 872        DUMP_REG(DC_DISP_DI_CONTROL);
 873        DUMP_REG(DC_DISP_PP_CONTROL);
 874        DUMP_REG(DC_DISP_PP_SELECT_A);
 875        DUMP_REG(DC_DISP_PP_SELECT_B);
 876        DUMP_REG(DC_DISP_PP_SELECT_C);
 877        DUMP_REG(DC_DISP_PP_SELECT_D);
 878        DUMP_REG(DC_DISP_DISP_CLOCK_CONTROL);
 879        DUMP_REG(DC_DISP_DISP_INTERFACE_CONTROL);
 880        DUMP_REG(DC_DISP_DISP_COLOR_CONTROL);
 881        DUMP_REG(DC_DISP_SHIFT_CLOCK_OPTIONS);
 882        DUMP_REG(DC_DISP_DATA_ENABLE_OPTIONS);
 883        DUMP_REG(DC_DISP_SERIAL_INTERFACE_OPTIONS);
 884        DUMP_REG(DC_DISP_LCD_SPI_OPTIONS);
 885        DUMP_REG(DC_DISP_BORDER_COLOR);
 886        DUMP_REG(DC_DISP_COLOR_KEY0_LOWER);
 887        DUMP_REG(DC_DISP_COLOR_KEY0_UPPER);
 888        DUMP_REG(DC_DISP_COLOR_KEY1_LOWER);
 889        DUMP_REG(DC_DISP_COLOR_KEY1_UPPER);
 890        DUMP_REG(DC_DISP_CURSOR_FOREGROUND);
 891        DUMP_REG(DC_DISP_CURSOR_BACKGROUND);
 892        DUMP_REG(DC_DISP_CURSOR_START_ADDR);
 893        DUMP_REG(DC_DISP_CURSOR_START_ADDR_NS);
 894        DUMP_REG(DC_DISP_CURSOR_POSITION);
 895        DUMP_REG(DC_DISP_CURSOR_POSITION_NS);
 896        DUMP_REG(DC_DISP_INIT_SEQ_CONTROL);
 897        DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_A);
 898        DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_B);
 899        DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_C);
 900        DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_D);
 901        DUMP_REG(DC_DISP_DC_MCCIF_FIFOCTRL);
 902        DUMP_REG(DC_DISP_MCCIF_DISPLAY0A_HYST);
 903        DUMP_REG(DC_DISP_MCCIF_DISPLAY0B_HYST);
 904        DUMP_REG(DC_DISP_MCCIF_DISPLAY1A_HYST);
 905        DUMP_REG(DC_DISP_MCCIF_DISPLAY1B_HYST);
 906        DUMP_REG(DC_DISP_DAC_CRT_CTRL);
 907        DUMP_REG(DC_DISP_DISP_MISC_CONTROL);
 908        DUMP_REG(DC_DISP_SD_CONTROL);
 909        DUMP_REG(DC_DISP_SD_CSC_COEFF);
 910        DUMP_REG(DC_DISP_SD_LUT(0));
 911        DUMP_REG(DC_DISP_SD_LUT(1));
 912        DUMP_REG(DC_DISP_SD_LUT(2));
 913        DUMP_REG(DC_DISP_SD_LUT(3));
 914        DUMP_REG(DC_DISP_SD_LUT(4));
 915        DUMP_REG(DC_DISP_SD_LUT(5));
 916        DUMP_REG(DC_DISP_SD_LUT(6));
 917        DUMP_REG(DC_DISP_SD_LUT(7));
 918        DUMP_REG(DC_DISP_SD_LUT(8));
 919        DUMP_REG(DC_DISP_SD_FLICKER_CONTROL);
 920        DUMP_REG(DC_DISP_DC_PIXEL_COUNT);
 921        DUMP_REG(DC_DISP_SD_HISTOGRAM(0));
 922        DUMP_REG(DC_DISP_SD_HISTOGRAM(1));
 923        DUMP_REG(DC_DISP_SD_HISTOGRAM(2));
 924        DUMP_REG(DC_DISP_SD_HISTOGRAM(3));
 925        DUMP_REG(DC_DISP_SD_HISTOGRAM(4));
 926        DUMP_REG(DC_DISP_SD_HISTOGRAM(5));
 927        DUMP_REG(DC_DISP_SD_HISTOGRAM(6));
 928        DUMP_REG(DC_DISP_SD_HISTOGRAM(7));
 929        DUMP_REG(DC_DISP_SD_BL_TF(0));
 930        DUMP_REG(DC_DISP_SD_BL_TF(1));
 931        DUMP_REG(DC_DISP_SD_BL_TF(2));
 932        DUMP_REG(DC_DISP_SD_BL_TF(3));
 933        DUMP_REG(DC_DISP_SD_BL_CONTROL);
 934        DUMP_REG(DC_DISP_SD_HW_K_VALUES);
 935        DUMP_REG(DC_DISP_SD_MAN_K_VALUES);
 936        DUMP_REG(DC_WIN_WIN_OPTIONS);
 937        DUMP_REG(DC_WIN_BYTE_SWAP);
 938        DUMP_REG(DC_WIN_BUFFER_CONTROL);
 939        DUMP_REG(DC_WIN_COLOR_DEPTH);
 940        DUMP_REG(DC_WIN_POSITION);
 941        DUMP_REG(DC_WIN_SIZE);
 942        DUMP_REG(DC_WIN_PRESCALED_SIZE);
 943        DUMP_REG(DC_WIN_H_INITIAL_DDA);
 944        DUMP_REG(DC_WIN_V_INITIAL_DDA);
 945        DUMP_REG(DC_WIN_DDA_INC);
 946        DUMP_REG(DC_WIN_LINE_STRIDE);
 947        DUMP_REG(DC_WIN_BUF_STRIDE);
 948        DUMP_REG(DC_WIN_UV_BUF_STRIDE);
 949        DUMP_REG(DC_WIN_BUFFER_ADDR_MODE);
 950        DUMP_REG(DC_WIN_DV_CONTROL);
 951        DUMP_REG(DC_WIN_BLEND_NOKEY);
 952        DUMP_REG(DC_WIN_BLEND_1WIN);
 953        DUMP_REG(DC_WIN_BLEND_2WIN_X);
 954        DUMP_REG(DC_WIN_BLEND_2WIN_Y);
 955        DUMP_REG(DC_WIN_BLEND_3WIN_XY);
 956        DUMP_REG(DC_WIN_HP_FETCH_CONTROL);
 957        DUMP_REG(DC_WINBUF_START_ADDR);
 958        DUMP_REG(DC_WINBUF_START_ADDR_NS);
 959        DUMP_REG(DC_WINBUF_START_ADDR_U);
 960        DUMP_REG(DC_WINBUF_START_ADDR_U_NS);
 961        DUMP_REG(DC_WINBUF_START_ADDR_V);
 962        DUMP_REG(DC_WINBUF_START_ADDR_V_NS);
 963        DUMP_REG(DC_WINBUF_ADDR_H_OFFSET);
 964        DUMP_REG(DC_WINBUF_ADDR_H_OFFSET_NS);
 965        DUMP_REG(DC_WINBUF_ADDR_V_OFFSET);
 966        DUMP_REG(DC_WINBUF_ADDR_V_OFFSET_NS);
 967        DUMP_REG(DC_WINBUF_UFLOW_STATUS);
 968        DUMP_REG(DC_WINBUF_AD_UFLOW_STATUS);
 969        DUMP_REG(DC_WINBUF_BD_UFLOW_STATUS);
 970        DUMP_REG(DC_WINBUF_CD_UFLOW_STATUS);
 971
 972#undef DUMP_REG
 973
 974        return 0;
 975}
 976
 977static struct drm_info_list debugfs_files[] = {
 978        { "regs", tegra_dc_show_regs, 0, NULL },
 979};
 980
 981static int tegra_dc_debugfs_init(struct tegra_dc *dc, struct drm_minor *minor)
 982{
 983        unsigned int i;
 984        char *name;
 985        int err;
 986
 987        name = kasprintf(GFP_KERNEL, "dc.%d", dc->pipe);
 988        dc->debugfs = debugfs_create_dir(name, minor->debugfs_root);
 989        kfree(name);
 990
 991        if (!dc->debugfs)
 992                return -ENOMEM;
 993
 994        dc->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
 995                                    GFP_KERNEL);
 996        if (!dc->debugfs_files) {
 997                err = -ENOMEM;
 998                goto remove;
 999        }
1000
1001        for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
1002                dc->debugfs_files[i].data = dc;
1003
1004        err = drm_debugfs_create_files(dc->debugfs_files,
1005                                       ARRAY_SIZE(debugfs_files),
1006                                       dc->debugfs, minor);
1007        if (err < 0)
1008                goto free;
1009
1010        dc->minor = minor;
1011
1012        return 0;
1013
1014free:
1015        kfree(dc->debugfs_files);
1016        dc->debugfs_files = NULL;
1017remove:
1018        debugfs_remove(dc->debugfs);
1019        dc->debugfs = NULL;
1020
1021        return err;
1022}
1023
1024static int tegra_dc_debugfs_exit(struct tegra_dc *dc)
1025{
1026        drm_debugfs_remove_files(dc->debugfs_files, ARRAY_SIZE(debugfs_files),
1027                                 dc->minor);
1028        dc->minor = NULL;
1029
1030        kfree(dc->debugfs_files);
1031        dc->debugfs_files = NULL;
1032
1033        debugfs_remove(dc->debugfs);
1034        dc->debugfs = NULL;
1035
1036        return 0;
1037}
1038
1039static int tegra_dc_drm_init(struct host1x_client *client,
1040                             struct drm_device *drm)
1041{
1042        struct tegra_dc *dc = host1x_client_to_dc(client);
1043        int err;
1044
1045        dc->pipe = drm->mode_config.num_crtc;
1046
1047        drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs);
1048        drm_mode_crtc_set_gamma_size(&dc->base, 256);
1049        drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
1050
1051        err = tegra_dc_rgb_init(drm, dc);
1052        if (err < 0 && err != -ENODEV) {
1053                dev_err(dc->dev, "failed to initialize RGB output: %d\n", err);
1054                return err;
1055        }
1056
1057        err = tegra_dc_add_planes(drm, dc);
1058        if (err < 0)
1059                return err;
1060
1061        if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1062                err = tegra_dc_debugfs_init(dc, drm->primary);
1063                if (err < 0)
1064                        dev_err(dc->dev, "debugfs setup failed: %d\n", err);
1065        }
1066
1067        err = devm_request_irq(dc->dev, dc->irq, tegra_dc_irq, 0,
1068                               dev_name(dc->dev), dc);
1069        if (err < 0) {
1070                dev_err(dc->dev, "failed to request IRQ#%u: %d\n", dc->irq,
1071                        err);
1072                return err;
1073        }
1074
1075        return 0;
1076}
1077
1078static int tegra_dc_drm_exit(struct host1x_client *client)
1079{
1080        struct tegra_dc *dc = host1x_client_to_dc(client);
1081        int err;
1082
1083        devm_free_irq(dc->dev, dc->irq, dc);
1084
1085        if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1086                err = tegra_dc_debugfs_exit(dc);
1087                if (err < 0)
1088                        dev_err(dc->dev, "debugfs cleanup failed: %d\n", err);
1089        }
1090
1091        err = tegra_dc_rgb_exit(dc);
1092        if (err) {
1093                dev_err(dc->dev, "failed to shutdown RGB output: %d\n", err);
1094                return err;
1095        }
1096
1097        return 0;
1098}
1099
1100static const struct host1x_client_ops dc_client_ops = {
1101        .drm_init = tegra_dc_drm_init,
1102        .drm_exit = tegra_dc_drm_exit,
1103};
1104
1105static int tegra_dc_probe(struct platform_device *pdev)
1106{
1107        struct host1x_drm *host1x = host1x_get_drm_data(pdev->dev.parent);
1108        struct resource *regs;
1109        struct tegra_dc *dc;
1110        int err;
1111
1112        dc = devm_kzalloc(&pdev->dev, sizeof(*dc), GFP_KERNEL);
1113        if (!dc)
1114                return -ENOMEM;
1115
1116        spin_lock_init(&dc->lock);
1117        INIT_LIST_HEAD(&dc->list);
1118        dc->dev = &pdev->dev;
1119
1120        dc->clk = devm_clk_get(&pdev->dev, NULL);
1121        if (IS_ERR(dc->clk)) {
1122                dev_err(&pdev->dev, "failed to get clock\n");
1123                return PTR_ERR(dc->clk);
1124        }
1125
1126        err = clk_prepare_enable(dc->clk);
1127        if (err < 0)
1128                return err;
1129
1130        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1131        dc->regs = devm_ioremap_resource(&pdev->dev, regs);
1132        if (IS_ERR(dc->regs))
1133                return PTR_ERR(dc->regs);
1134
1135        dc->irq = platform_get_irq(pdev, 0);
1136        if (dc->irq < 0) {
1137                dev_err(&pdev->dev, "failed to get IRQ\n");
1138                return -ENXIO;
1139        }
1140
1141        INIT_LIST_HEAD(&dc->client.list);
1142        dc->client.ops = &dc_client_ops;
1143        dc->client.dev = &pdev->dev;
1144
1145        err = tegra_dc_rgb_probe(dc);
1146        if (err < 0 && err != -ENODEV) {
1147                dev_err(&pdev->dev, "failed to probe RGB output: %d\n", err);
1148                return err;
1149        }
1150
1151        err = host1x_register_client(host1x, &dc->client);
1152        if (err < 0) {
1153                dev_err(&pdev->dev, "failed to register host1x client: %d\n",
1154                        err);
1155                return err;
1156        }
1157
1158        platform_set_drvdata(pdev, dc);
1159
1160        return 0;
1161}
1162
1163static int tegra_dc_remove(struct platform_device *pdev)
1164{
1165        struct host1x_drm *host1x = host1x_get_drm_data(pdev->dev.parent);
1166        struct tegra_dc *dc = platform_get_drvdata(pdev);
1167        int err;
1168
1169        err = host1x_unregister_client(host1x, &dc->client);
1170        if (err < 0) {
1171                dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
1172                        err);
1173                return err;
1174        }
1175
1176        clk_disable_unprepare(dc->clk);
1177
1178        return 0;
1179}
1180
1181static struct of_device_id tegra_dc_of_match[] = {
1182        { .compatible = "nvidia,tegra30-dc", },
1183        { .compatible = "nvidia,tegra20-dc", },
1184        { },
1185};
1186
1187struct platform_driver tegra_dc_driver = {
1188        .driver = {
1189                .name = "tegra-dc",
1190                .owner = THIS_MODULE,
1191                .of_match_table = tegra_dc_of_match,
1192        },
1193        .probe = tegra_dc_probe,
1194        .remove = tegra_dc_remove,
1195};
1196