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