linux/drivers/gpu/drm/exynos/exynos_mixer.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2011 Samsung Electronics Co.Ltd
   3 * Authors:
   4 * Seung-Woo Kim <sw0312.kim@samsung.com>
   5 *      Inki Dae <inki.dae@samsung.com>
   6 *      Joonyoung Shim <jy0922.shim@samsung.com>
   7 *
   8 * Based on drivers/media/video/s5p-tv/mixer_reg.c
   9 *
  10 * This program is free software; you can redistribute  it and/or modify it
  11 * under  the terms of  the GNU General  Public License as published by the
  12 * Free Software Foundation;  either version 2 of the  License, or (at your
  13 * option) any later version.
  14 *
  15 */
  16
  17#include <drm/drmP.h>
  18
  19#include "regs-mixer.h"
  20#include "regs-vp.h"
  21
  22#include <linux/kernel.h>
  23#include <linux/spinlock.h>
  24#include <linux/wait.h>
  25#include <linux/i2c.h>
  26#include <linux/platform_device.h>
  27#include <linux/interrupt.h>
  28#include <linux/irq.h>
  29#include <linux/delay.h>
  30#include <linux/pm_runtime.h>
  31#include <linux/clk.h>
  32#include <linux/regulator/consumer.h>
  33#include <linux/of.h>
  34#include <linux/component.h>
  35
  36#include <drm/exynos_drm.h>
  37
  38#include "exynos_drm_drv.h"
  39#include "exynos_drm_crtc.h"
  40#include "exynos_drm_plane.h"
  41#include "exynos_drm_iommu.h"
  42#include "exynos_mixer.h"
  43
  44#define MIXER_WIN_NR            3
  45#define MIXER_DEFAULT_WIN       0
  46
  47/* The pixelformats that are natively supported by the mixer. */
  48#define MXR_FORMAT_RGB565       4
  49#define MXR_FORMAT_ARGB1555     5
  50#define MXR_FORMAT_ARGB4444     6
  51#define MXR_FORMAT_ARGB8888     7
  52
  53struct mixer_resources {
  54        int                     irq;
  55        void __iomem            *mixer_regs;
  56        void __iomem            *vp_regs;
  57        spinlock_t              reg_slock;
  58        struct clk              *mixer;
  59        struct clk              *vp;
  60        struct clk              *hdmi;
  61        struct clk              *sclk_mixer;
  62        struct clk              *sclk_hdmi;
  63        struct clk              *mout_mixer;
  64};
  65
  66enum mixer_version_id {
  67        MXR_VER_0_0_0_16,
  68        MXR_VER_16_0_33_0,
  69        MXR_VER_128_0_0_184,
  70};
  71
  72struct mixer_context {
  73        struct platform_device *pdev;
  74        struct device           *dev;
  75        struct drm_device       *drm_dev;
  76        struct exynos_drm_crtc  *crtc;
  77        struct exynos_drm_plane planes[MIXER_WIN_NR];
  78        int                     pipe;
  79        bool                    interlace;
  80        bool                    powered;
  81        bool                    vp_enabled;
  82        bool                    has_sclk;
  83        u32                     int_en;
  84
  85        struct mutex            mixer_mutex;
  86        struct mixer_resources  mixer_res;
  87        enum mixer_version_id   mxr_ver;
  88        wait_queue_head_t       wait_vsync_queue;
  89        atomic_t                wait_vsync_event;
  90};
  91
  92struct mixer_drv_data {
  93        enum mixer_version_id   version;
  94        bool                                    is_vp_enabled;
  95        bool                                    has_sclk;
  96};
  97
  98static const u8 filter_y_horiz_tap8[] = {
  99        0,      -1,     -1,     -1,     -1,     -1,     -1,     -1,
 100        -1,     -1,     -1,     -1,     -1,     0,      0,      0,
 101        0,      2,      4,      5,      6,      6,      6,      6,
 102        6,      5,      5,      4,      3,      2,      1,      1,
 103        0,      -6,     -12,    -16,    -18,    -20,    -21,    -20,
 104        -20,    -18,    -16,    -13,    -10,    -8,     -5,     -2,
 105        127,    126,    125,    121,    114,    107,    99,     89,
 106        79,     68,     57,     46,     35,     25,     16,     8,
 107};
 108
 109static const u8 filter_y_vert_tap4[] = {
 110        0,      -3,     -6,     -8,     -8,     -8,     -8,     -7,
 111        -6,     -5,     -4,     -3,     -2,     -1,     -1,     0,
 112        127,    126,    124,    118,    111,    102,    92,     81,
 113        70,     59,     48,     37,     27,     19,     11,     5,
 114        0,      5,      11,     19,     27,     37,     48,     59,
 115        70,     81,     92,     102,    111,    118,    124,    126,
 116        0,      0,      -1,     -1,     -2,     -3,     -4,     -5,
 117        -6,     -7,     -8,     -8,     -8,     -8,     -6,     -3,
 118};
 119
 120static const u8 filter_cr_horiz_tap4[] = {
 121        0,      -3,     -6,     -8,     -8,     -8,     -8,     -7,
 122        -6,     -5,     -4,     -3,     -2,     -1,     -1,     0,
 123        127,    126,    124,    118,    111,    102,    92,     81,
 124        70,     59,     48,     37,     27,     19,     11,     5,
 125};
 126
 127static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
 128{
 129        return readl(res->vp_regs + reg_id);
 130}
 131
 132static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id,
 133                                 u32 val)
 134{
 135        writel(val, res->vp_regs + reg_id);
 136}
 137
 138static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id,
 139                                 u32 val, u32 mask)
 140{
 141        u32 old = vp_reg_read(res, reg_id);
 142
 143        val = (val & mask) | (old & ~mask);
 144        writel(val, res->vp_regs + reg_id);
 145}
 146
 147static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
 148{
 149        return readl(res->mixer_regs + reg_id);
 150}
 151
 152static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id,
 153                                 u32 val)
 154{
 155        writel(val, res->mixer_regs + reg_id);
 156}
 157
 158static inline void mixer_reg_writemask(struct mixer_resources *res,
 159                                 u32 reg_id, u32 val, u32 mask)
 160{
 161        u32 old = mixer_reg_read(res, reg_id);
 162
 163        val = (val & mask) | (old & ~mask);
 164        writel(val, res->mixer_regs + reg_id);
 165}
 166
 167static void mixer_regs_dump(struct mixer_context *ctx)
 168{
 169#define DUMPREG(reg_id) \
 170do { \
 171        DRM_DEBUG_KMS(#reg_id " = %08x\n", \
 172                (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
 173} while (0)
 174
 175        DUMPREG(MXR_STATUS);
 176        DUMPREG(MXR_CFG);
 177        DUMPREG(MXR_INT_EN);
 178        DUMPREG(MXR_INT_STATUS);
 179
 180        DUMPREG(MXR_LAYER_CFG);
 181        DUMPREG(MXR_VIDEO_CFG);
 182
 183        DUMPREG(MXR_GRAPHIC0_CFG);
 184        DUMPREG(MXR_GRAPHIC0_BASE);
 185        DUMPREG(MXR_GRAPHIC0_SPAN);
 186        DUMPREG(MXR_GRAPHIC0_WH);
 187        DUMPREG(MXR_GRAPHIC0_SXY);
 188        DUMPREG(MXR_GRAPHIC0_DXY);
 189
 190        DUMPREG(MXR_GRAPHIC1_CFG);
 191        DUMPREG(MXR_GRAPHIC1_BASE);
 192        DUMPREG(MXR_GRAPHIC1_SPAN);
 193        DUMPREG(MXR_GRAPHIC1_WH);
 194        DUMPREG(MXR_GRAPHIC1_SXY);
 195        DUMPREG(MXR_GRAPHIC1_DXY);
 196#undef DUMPREG
 197}
 198
 199static void vp_regs_dump(struct mixer_context *ctx)
 200{
 201#define DUMPREG(reg_id) \
 202do { \
 203        DRM_DEBUG_KMS(#reg_id " = %08x\n", \
 204                (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
 205} while (0)
 206
 207        DUMPREG(VP_ENABLE);
 208        DUMPREG(VP_SRESET);
 209        DUMPREG(VP_SHADOW_UPDATE);
 210        DUMPREG(VP_FIELD_ID);
 211        DUMPREG(VP_MODE);
 212        DUMPREG(VP_IMG_SIZE_Y);
 213        DUMPREG(VP_IMG_SIZE_C);
 214        DUMPREG(VP_PER_RATE_CTRL);
 215        DUMPREG(VP_TOP_Y_PTR);
 216        DUMPREG(VP_BOT_Y_PTR);
 217        DUMPREG(VP_TOP_C_PTR);
 218        DUMPREG(VP_BOT_C_PTR);
 219        DUMPREG(VP_ENDIAN_MODE);
 220        DUMPREG(VP_SRC_H_POSITION);
 221        DUMPREG(VP_SRC_V_POSITION);
 222        DUMPREG(VP_SRC_WIDTH);
 223        DUMPREG(VP_SRC_HEIGHT);
 224        DUMPREG(VP_DST_H_POSITION);
 225        DUMPREG(VP_DST_V_POSITION);
 226        DUMPREG(VP_DST_WIDTH);
 227        DUMPREG(VP_DST_HEIGHT);
 228        DUMPREG(VP_H_RATIO);
 229        DUMPREG(VP_V_RATIO);
 230
 231#undef DUMPREG
 232}
 233
 234static inline void vp_filter_set(struct mixer_resources *res,
 235                int reg_id, const u8 *data, unsigned int size)
 236{
 237        /* assure 4-byte align */
 238        BUG_ON(size & 3);
 239        for (; size; size -= 4, reg_id += 4, data += 4) {
 240                u32 val = (data[0] << 24) |  (data[1] << 16) |
 241                        (data[2] << 8) | data[3];
 242                vp_reg_write(res, reg_id, val);
 243        }
 244}
 245
 246static void vp_default_filter(struct mixer_resources *res)
 247{
 248        vp_filter_set(res, VP_POLY8_Y0_LL,
 249                filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8));
 250        vp_filter_set(res, VP_POLY4_Y0_LL,
 251                filter_y_vert_tap4, sizeof(filter_y_vert_tap4));
 252        vp_filter_set(res, VP_POLY4_C0_LL,
 253                filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));
 254}
 255
 256static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
 257{
 258        struct mixer_resources *res = &ctx->mixer_res;
 259
 260        /* block update on vsync */
 261        mixer_reg_writemask(res, MXR_STATUS, enable ?
 262                        MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
 263
 264        if (ctx->vp_enabled)
 265                vp_reg_write(res, VP_SHADOW_UPDATE, enable ?
 266                        VP_SHADOW_UPDATE_ENABLE : 0);
 267}
 268
 269static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
 270{
 271        struct mixer_resources *res = &ctx->mixer_res;
 272        u32 val;
 273
 274        /* choosing between interlace and progressive mode */
 275        val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE :
 276                                MXR_CFG_SCAN_PROGRESSIVE);
 277
 278        if (ctx->mxr_ver != MXR_VER_128_0_0_184) {
 279                /* choosing between proper HD and SD mode */
 280                if (height <= 480)
 281                        val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
 282                else if (height <= 576)
 283                        val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
 284                else if (height <= 720)
 285                        val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
 286                else if (height <= 1080)
 287                        val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
 288                else
 289                        val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
 290        }
 291
 292        mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
 293}
 294
 295static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
 296{
 297        struct mixer_resources *res = &ctx->mixer_res;
 298        u32 val;
 299
 300        if (height == 480) {
 301                val = MXR_CFG_RGB601_0_255;
 302        } else if (height == 576) {
 303                val = MXR_CFG_RGB601_0_255;
 304        } else if (height == 720) {
 305                val = MXR_CFG_RGB709_16_235;
 306                mixer_reg_write(res, MXR_CM_COEFF_Y,
 307                                (1 << 30) | (94 << 20) | (314 << 10) |
 308                                (32 << 0));
 309                mixer_reg_write(res, MXR_CM_COEFF_CB,
 310                                (972 << 20) | (851 << 10) | (225 << 0));
 311                mixer_reg_write(res, MXR_CM_COEFF_CR,
 312                                (225 << 20) | (820 << 10) | (1004 << 0));
 313        } else if (height == 1080) {
 314                val = MXR_CFG_RGB709_16_235;
 315                mixer_reg_write(res, MXR_CM_COEFF_Y,
 316                                (1 << 30) | (94 << 20) | (314 << 10) |
 317                                (32 << 0));
 318                mixer_reg_write(res, MXR_CM_COEFF_CB,
 319                                (972 << 20) | (851 << 10) | (225 << 0));
 320                mixer_reg_write(res, MXR_CM_COEFF_CR,
 321                                (225 << 20) | (820 << 10) | (1004 << 0));
 322        } else {
 323                val = MXR_CFG_RGB709_16_235;
 324                mixer_reg_write(res, MXR_CM_COEFF_Y,
 325                                (1 << 30) | (94 << 20) | (314 << 10) |
 326                                (32 << 0));
 327                mixer_reg_write(res, MXR_CM_COEFF_CB,
 328                                (972 << 20) | (851 << 10) | (225 << 0));
 329                mixer_reg_write(res, MXR_CM_COEFF_CR,
 330                                (225 << 20) | (820 << 10) | (1004 << 0));
 331        }
 332
 333        mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
 334}
 335
 336static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win,
 337                                bool enable)
 338{
 339        struct mixer_resources *res = &ctx->mixer_res;
 340        u32 val = enable ? ~0 : 0;
 341
 342        switch (win) {
 343        case 0:
 344                mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
 345                break;
 346        case 1:
 347                mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
 348                break;
 349        case 2:
 350                if (ctx->vp_enabled) {
 351                        vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
 352                        mixer_reg_writemask(res, MXR_CFG, val,
 353                                MXR_CFG_VP_ENABLE);
 354
 355                        /* control blending of graphic layer 0 */
 356                        mixer_reg_writemask(res, MXR_GRAPHIC_CFG(0), val,
 357                                        MXR_GRP_CFG_BLEND_PRE_MUL |
 358                                        MXR_GRP_CFG_PIXEL_BLEND_EN);
 359                }
 360                break;
 361        }
 362}
 363
 364static void mixer_run(struct mixer_context *ctx)
 365{
 366        struct mixer_resources *res = &ctx->mixer_res;
 367
 368        mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
 369}
 370
 371static void mixer_stop(struct mixer_context *ctx)
 372{
 373        struct mixer_resources *res = &ctx->mixer_res;
 374        int timeout = 20;
 375
 376        mixer_reg_writemask(res, MXR_STATUS, 0, MXR_STATUS_REG_RUN);
 377
 378        while (!(mixer_reg_read(res, MXR_STATUS) & MXR_STATUS_REG_IDLE) &&
 379                        --timeout)
 380                usleep_range(10000, 12000);
 381}
 382
 383static void vp_video_buffer(struct mixer_context *ctx, unsigned int win)
 384{
 385        struct mixer_resources *res = &ctx->mixer_res;
 386        unsigned long flags;
 387        struct exynos_drm_plane *plane;
 388        dma_addr_t luma_addr[2], chroma_addr[2];
 389        bool tiled_mode = false;
 390        bool crcb_mode = false;
 391        u32 val;
 392
 393        plane = &ctx->planes[win];
 394
 395        switch (plane->pixel_format) {
 396        case DRM_FORMAT_NV12:
 397                crcb_mode = false;
 398                break;
 399        case DRM_FORMAT_NV21:
 400                crcb_mode = true;
 401                break;
 402        default:
 403                DRM_ERROR("pixel format for vp is wrong [%d].\n",
 404                                plane->pixel_format);
 405                return;
 406        }
 407
 408        luma_addr[0] = plane->dma_addr[0];
 409        chroma_addr[0] = plane->dma_addr[1];
 410
 411        if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE) {
 412                ctx->interlace = true;
 413                if (tiled_mode) {
 414                        luma_addr[1] = luma_addr[0] + 0x40;
 415                        chroma_addr[1] = chroma_addr[0] + 0x40;
 416                } else {
 417                        luma_addr[1] = luma_addr[0] + plane->pitch;
 418                        chroma_addr[1] = chroma_addr[0] + plane->pitch;
 419                }
 420        } else {
 421                ctx->interlace = false;
 422                luma_addr[1] = 0;
 423                chroma_addr[1] = 0;
 424        }
 425
 426        spin_lock_irqsave(&res->reg_slock, flags);
 427        mixer_vsync_set_update(ctx, false);
 428
 429        /* interlace or progressive scan mode */
 430        val = (ctx->interlace ? ~0 : 0);
 431        vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
 432
 433        /* setup format */
 434        val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12);
 435        val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
 436        vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
 437
 438        /* setting size of input image */
 439        vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(plane->pitch) |
 440                VP_IMG_VSIZE(plane->fb_height));
 441        /* chroma height has to reduced by 2 to avoid chroma distorions */
 442        vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(plane->pitch) |
 443                VP_IMG_VSIZE(plane->fb_height / 2));
 444
 445        vp_reg_write(res, VP_SRC_WIDTH, plane->src_width);
 446        vp_reg_write(res, VP_SRC_HEIGHT, plane->src_height);
 447        vp_reg_write(res, VP_SRC_H_POSITION,
 448                        VP_SRC_H_POSITION_VAL(plane->src_x));
 449        vp_reg_write(res, VP_SRC_V_POSITION, plane->src_y);
 450
 451        vp_reg_write(res, VP_DST_WIDTH, plane->crtc_width);
 452        vp_reg_write(res, VP_DST_H_POSITION, plane->crtc_x);
 453        if (ctx->interlace) {
 454                vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height / 2);
 455                vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y / 2);
 456        } else {
 457                vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height);
 458                vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y);
 459        }
 460
 461        vp_reg_write(res, VP_H_RATIO, plane->h_ratio);
 462        vp_reg_write(res, VP_V_RATIO, plane->v_ratio);
 463
 464        vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
 465
 466        /* set buffer address to vp */
 467        vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
 468        vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
 469        vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
 470        vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
 471
 472        mixer_cfg_scan(ctx, plane->mode_height);
 473        mixer_cfg_rgb_fmt(ctx, plane->mode_height);
 474        mixer_cfg_layer(ctx, win, true);
 475        mixer_run(ctx);
 476
 477        mixer_vsync_set_update(ctx, true);
 478        spin_unlock_irqrestore(&res->reg_slock, flags);
 479
 480        mixer_regs_dump(ctx);
 481        vp_regs_dump(ctx);
 482}
 483
 484static void mixer_layer_update(struct mixer_context *ctx)
 485{
 486        struct mixer_resources *res = &ctx->mixer_res;
 487
 488        mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
 489}
 490
 491static int mixer_setup_scale(const struct exynos_drm_plane *plane,
 492                unsigned int *x_ratio, unsigned int *y_ratio)
 493{
 494        if (plane->crtc_width != plane->src_width) {
 495                if (plane->crtc_width == 2 * plane->src_width)
 496                        *x_ratio = 1;
 497                else
 498                        goto fail;
 499        }
 500
 501        if (plane->crtc_height != plane->src_height) {
 502                if (plane->crtc_height == 2 * plane->src_height)
 503                        *y_ratio = 1;
 504                else
 505                        goto fail;
 506        }
 507
 508        return 0;
 509
 510fail:
 511        DRM_DEBUG_KMS("only 2x width/height scaling of plane supported\n");
 512        return -ENOTSUPP;
 513}
 514
 515static void mixer_graph_buffer(struct mixer_context *ctx, unsigned int win)
 516{
 517        struct mixer_resources *res = &ctx->mixer_res;
 518        unsigned long flags;
 519        struct exynos_drm_plane *plane;
 520        unsigned int x_ratio = 0, y_ratio = 0;
 521        unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
 522        dma_addr_t dma_addr;
 523        unsigned int fmt;
 524        u32 val;
 525
 526        plane = &ctx->planes[win];
 527
 528        switch (plane->pixel_format) {
 529        case DRM_FORMAT_XRGB4444:
 530                fmt = MXR_FORMAT_ARGB4444;
 531                break;
 532
 533        case DRM_FORMAT_XRGB1555:
 534                fmt = MXR_FORMAT_ARGB1555;
 535                break;
 536
 537        case DRM_FORMAT_RGB565:
 538                fmt = MXR_FORMAT_RGB565;
 539                break;
 540
 541        case DRM_FORMAT_XRGB8888:
 542        case DRM_FORMAT_ARGB8888:
 543                fmt = MXR_FORMAT_ARGB8888;
 544                break;
 545
 546        default:
 547                DRM_DEBUG_KMS("pixelformat unsupported by mixer\n");
 548                return;
 549        }
 550
 551        /* check if mixer supports requested scaling setup */
 552        if (mixer_setup_scale(plane, &x_ratio, &y_ratio))
 553                return;
 554
 555        dst_x_offset = plane->crtc_x;
 556        dst_y_offset = plane->crtc_y;
 557
 558        /* converting dma address base and source offset */
 559        dma_addr = plane->dma_addr[0]
 560                + (plane->src_x * plane->bpp >> 3)
 561                + (plane->src_y * plane->pitch);
 562        src_x_offset = 0;
 563        src_y_offset = 0;
 564
 565        if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE)
 566                ctx->interlace = true;
 567        else
 568                ctx->interlace = false;
 569
 570        spin_lock_irqsave(&res->reg_slock, flags);
 571        mixer_vsync_set_update(ctx, false);
 572
 573        /* setup format */
 574        mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
 575                MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
 576
 577        /* setup geometry */
 578        mixer_reg_write(res, MXR_GRAPHIC_SPAN(win),
 579                        plane->pitch / (plane->bpp >> 3));
 580
 581        /* setup display size */
 582        if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
 583                win == MIXER_DEFAULT_WIN) {
 584                val  = MXR_MXR_RES_HEIGHT(plane->mode_height);
 585                val |= MXR_MXR_RES_WIDTH(plane->mode_width);
 586                mixer_reg_write(res, MXR_RESOLUTION, val);
 587        }
 588
 589        val  = MXR_GRP_WH_WIDTH(plane->src_width);
 590        val |= MXR_GRP_WH_HEIGHT(plane->src_height);
 591        val |= MXR_GRP_WH_H_SCALE(x_ratio);
 592        val |= MXR_GRP_WH_V_SCALE(y_ratio);
 593        mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
 594
 595        /* setup offsets in source image */
 596        val  = MXR_GRP_SXY_SX(src_x_offset);
 597        val |= MXR_GRP_SXY_SY(src_y_offset);
 598        mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
 599
 600        /* setup offsets in display image */
 601        val  = MXR_GRP_DXY_DX(dst_x_offset);
 602        val |= MXR_GRP_DXY_DY(dst_y_offset);
 603        mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
 604
 605        /* set buffer address to mixer */
 606        mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
 607
 608        mixer_cfg_scan(ctx, plane->mode_height);
 609        mixer_cfg_rgb_fmt(ctx, plane->mode_height);
 610        mixer_cfg_layer(ctx, win, true);
 611
 612        /* layer update mandatory for mixer 16.0.33.0 */
 613        if (ctx->mxr_ver == MXR_VER_16_0_33_0 ||
 614                ctx->mxr_ver == MXR_VER_128_0_0_184)
 615                mixer_layer_update(ctx);
 616
 617        mixer_run(ctx);
 618
 619        mixer_vsync_set_update(ctx, true);
 620        spin_unlock_irqrestore(&res->reg_slock, flags);
 621
 622        mixer_regs_dump(ctx);
 623}
 624
 625static void vp_win_reset(struct mixer_context *ctx)
 626{
 627        struct mixer_resources *res = &ctx->mixer_res;
 628        int tries = 100;
 629
 630        vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
 631        for (tries = 100; tries; --tries) {
 632                /* waiting until VP_SRESET_PROCESSING is 0 */
 633                if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
 634                        break;
 635                usleep_range(10000, 12000);
 636        }
 637        WARN(tries == 0, "failed to reset Video Processor\n");
 638}
 639
 640static void mixer_win_reset(struct mixer_context *ctx)
 641{
 642        struct mixer_resources *res = &ctx->mixer_res;
 643        unsigned long flags;
 644        u32 val; /* value stored to register */
 645
 646        spin_lock_irqsave(&res->reg_slock, flags);
 647        mixer_vsync_set_update(ctx, false);
 648
 649        mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
 650
 651        /* set output in RGB888 mode */
 652        mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
 653
 654        /* 16 beat burst in DMA */
 655        mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
 656                MXR_STATUS_BURST_MASK);
 657
 658        /* setting default layer priority: layer1 > layer0 > video
 659         * because typical usage scenario would be
 660         * layer1 - OSD
 661         * layer0 - framebuffer
 662         * video - video overlay
 663         */
 664        val = MXR_LAYER_CFG_GRP1_VAL(3);
 665        val |= MXR_LAYER_CFG_GRP0_VAL(2);
 666        if (ctx->vp_enabled)
 667                val |= MXR_LAYER_CFG_VP_VAL(1);
 668        mixer_reg_write(res, MXR_LAYER_CFG, val);
 669
 670        /* setting background color */
 671        mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
 672        mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
 673        mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
 674
 675        /* setting graphical layers */
 676        val  = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
 677        val |= MXR_GRP_CFG_WIN_BLEND_EN;
 678        val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
 679
 680        /* Don't blend layer 0 onto the mixer background */
 681        mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
 682
 683        /* Blend layer 1 into layer 0 */
 684        val |= MXR_GRP_CFG_BLEND_PRE_MUL;
 685        val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
 686        mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
 687
 688        /* setting video layers */
 689        val = MXR_GRP_CFG_ALPHA_VAL(0);
 690        mixer_reg_write(res, MXR_VIDEO_CFG, val);
 691
 692        if (ctx->vp_enabled) {
 693                /* configuration of Video Processor Registers */
 694                vp_win_reset(ctx);
 695                vp_default_filter(res);
 696        }
 697
 698        /* disable all layers */
 699        mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
 700        mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
 701        if (ctx->vp_enabled)
 702                mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
 703
 704        mixer_vsync_set_update(ctx, true);
 705        spin_unlock_irqrestore(&res->reg_slock, flags);
 706}
 707
 708static irqreturn_t mixer_irq_handler(int irq, void *arg)
 709{
 710        struct mixer_context *ctx = arg;
 711        struct mixer_resources *res = &ctx->mixer_res;
 712        u32 val, base, shadow;
 713
 714        spin_lock(&res->reg_slock);
 715
 716        /* read interrupt status for handling and clearing flags for VSYNC */
 717        val = mixer_reg_read(res, MXR_INT_STATUS);
 718
 719        /* handling VSYNC */
 720        if (val & MXR_INT_STATUS_VSYNC) {
 721                /* interlace scan need to check shadow register */
 722                if (ctx->interlace) {
 723                        base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
 724                        shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
 725                        if (base != shadow)
 726                                goto out;
 727
 728                        base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
 729                        shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
 730                        if (base != shadow)
 731                                goto out;
 732                }
 733
 734                drm_handle_vblank(ctx->drm_dev, ctx->pipe);
 735                exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
 736
 737                /* set wait vsync event to zero and wake up queue. */
 738                if (atomic_read(&ctx->wait_vsync_event)) {
 739                        atomic_set(&ctx->wait_vsync_event, 0);
 740                        wake_up(&ctx->wait_vsync_queue);
 741                }
 742        }
 743
 744out:
 745        /* clear interrupts */
 746        if (~val & MXR_INT_EN_VSYNC) {
 747                /* vsync interrupt use different bit for read and clear */
 748                val &= ~MXR_INT_EN_VSYNC;
 749                val |= MXR_INT_CLEAR_VSYNC;
 750        }
 751        mixer_reg_write(res, MXR_INT_STATUS, val);
 752
 753        spin_unlock(&res->reg_slock);
 754
 755        return IRQ_HANDLED;
 756}
 757
 758static int mixer_resources_init(struct mixer_context *mixer_ctx)
 759{
 760        struct device *dev = &mixer_ctx->pdev->dev;
 761        struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
 762        struct resource *res;
 763        int ret;
 764
 765        spin_lock_init(&mixer_res->reg_slock);
 766
 767        mixer_res->mixer = devm_clk_get(dev, "mixer");
 768        if (IS_ERR(mixer_res->mixer)) {
 769                dev_err(dev, "failed to get clock 'mixer'\n");
 770                return -ENODEV;
 771        }
 772
 773        mixer_res->hdmi = devm_clk_get(dev, "hdmi");
 774        if (IS_ERR(mixer_res->hdmi)) {
 775                dev_err(dev, "failed to get clock 'hdmi'\n");
 776                return PTR_ERR(mixer_res->hdmi);
 777        }
 778
 779        mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
 780        if (IS_ERR(mixer_res->sclk_hdmi)) {
 781                dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
 782                return -ENODEV;
 783        }
 784        res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 0);
 785        if (res == NULL) {
 786                dev_err(dev, "get memory resource failed.\n");
 787                return -ENXIO;
 788        }
 789
 790        mixer_res->mixer_regs = devm_ioremap(dev, res->start,
 791                                                        resource_size(res));
 792        if (mixer_res->mixer_regs == NULL) {
 793                dev_err(dev, "register mapping failed.\n");
 794                return -ENXIO;
 795        }
 796
 797        res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_IRQ, 0);
 798        if (res == NULL) {
 799                dev_err(dev, "get interrupt resource failed.\n");
 800                return -ENXIO;
 801        }
 802
 803        ret = devm_request_irq(dev, res->start, mixer_irq_handler,
 804                                                0, "drm_mixer", mixer_ctx);
 805        if (ret) {
 806                dev_err(dev, "request interrupt failed.\n");
 807                return ret;
 808        }
 809        mixer_res->irq = res->start;
 810
 811        return 0;
 812}
 813
 814static int vp_resources_init(struct mixer_context *mixer_ctx)
 815{
 816        struct device *dev = &mixer_ctx->pdev->dev;
 817        struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
 818        struct resource *res;
 819
 820        mixer_res->vp = devm_clk_get(dev, "vp");
 821        if (IS_ERR(mixer_res->vp)) {
 822                dev_err(dev, "failed to get clock 'vp'\n");
 823                return -ENODEV;
 824        }
 825
 826        if (mixer_ctx->has_sclk) {
 827                mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
 828                if (IS_ERR(mixer_res->sclk_mixer)) {
 829                        dev_err(dev, "failed to get clock 'sclk_mixer'\n");
 830                        return -ENODEV;
 831                }
 832                mixer_res->mout_mixer = devm_clk_get(dev, "mout_mixer");
 833                if (IS_ERR(mixer_res->mout_mixer)) {
 834                        dev_err(dev, "failed to get clock 'mout_mixer'\n");
 835                        return -ENODEV;
 836                }
 837
 838                if (mixer_res->sclk_hdmi && mixer_res->mout_mixer)
 839                        clk_set_parent(mixer_res->mout_mixer,
 840                                       mixer_res->sclk_hdmi);
 841        }
 842
 843        res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1);
 844        if (res == NULL) {
 845                dev_err(dev, "get memory resource failed.\n");
 846                return -ENXIO;
 847        }
 848
 849        mixer_res->vp_regs = devm_ioremap(dev, res->start,
 850                                                        resource_size(res));
 851        if (mixer_res->vp_regs == NULL) {
 852                dev_err(dev, "register mapping failed.\n");
 853                return -ENXIO;
 854        }
 855
 856        return 0;
 857}
 858
 859static int mixer_initialize(struct mixer_context *mixer_ctx,
 860                        struct drm_device *drm_dev)
 861{
 862        int ret;
 863        struct exynos_drm_private *priv;
 864        priv = drm_dev->dev_private;
 865
 866        mixer_ctx->drm_dev = drm_dev;
 867        mixer_ctx->pipe = priv->pipe++;
 868
 869        /* acquire resources: regs, irqs, clocks */
 870        ret = mixer_resources_init(mixer_ctx);
 871        if (ret) {
 872                DRM_ERROR("mixer_resources_init failed ret=%d\n", ret);
 873                return ret;
 874        }
 875
 876        if (mixer_ctx->vp_enabled) {
 877                /* acquire vp resources: regs, irqs, clocks */
 878                ret = vp_resources_init(mixer_ctx);
 879                if (ret) {
 880                        DRM_ERROR("vp_resources_init failed ret=%d\n", ret);
 881                        return ret;
 882                }
 883        }
 884
 885        if (!is_drm_iommu_supported(mixer_ctx->drm_dev))
 886                return 0;
 887
 888        return drm_iommu_attach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
 889}
 890
 891static void mixer_ctx_remove(struct mixer_context *mixer_ctx)
 892{
 893        if (is_drm_iommu_supported(mixer_ctx->drm_dev))
 894                drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
 895}
 896
 897static int mixer_enable_vblank(struct exynos_drm_crtc *crtc)
 898{
 899        struct mixer_context *mixer_ctx = crtc->ctx;
 900        struct mixer_resources *res = &mixer_ctx->mixer_res;
 901
 902        if (!mixer_ctx->powered) {
 903                mixer_ctx->int_en |= MXR_INT_EN_VSYNC;
 904                return 0;
 905        }
 906
 907        /* enable vsync interrupt */
 908        mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
 909                        MXR_INT_EN_VSYNC);
 910
 911        return 0;
 912}
 913
 914static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
 915{
 916        struct mixer_context *mixer_ctx = crtc->ctx;
 917        struct mixer_resources *res = &mixer_ctx->mixer_res;
 918
 919        /* disable vsync interrupt */
 920        mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
 921}
 922
 923static void mixer_win_commit(struct exynos_drm_crtc *crtc, unsigned int win)
 924{
 925        struct mixer_context *mixer_ctx = crtc->ctx;
 926
 927        DRM_DEBUG_KMS("win: %d\n", win);
 928
 929        mutex_lock(&mixer_ctx->mixer_mutex);
 930        if (!mixer_ctx->powered) {
 931                mutex_unlock(&mixer_ctx->mixer_mutex);
 932                return;
 933        }
 934        mutex_unlock(&mixer_ctx->mixer_mutex);
 935
 936        if (win > 1 && mixer_ctx->vp_enabled)
 937                vp_video_buffer(mixer_ctx, win);
 938        else
 939                mixer_graph_buffer(mixer_ctx, win);
 940
 941        mixer_ctx->planes[win].enabled = true;
 942}
 943
 944static void mixer_win_disable(struct exynos_drm_crtc *crtc, unsigned int win)
 945{
 946        struct mixer_context *mixer_ctx = crtc->ctx;
 947        struct mixer_resources *res = &mixer_ctx->mixer_res;
 948        unsigned long flags;
 949
 950        DRM_DEBUG_KMS("win: %d\n", win);
 951
 952        mutex_lock(&mixer_ctx->mixer_mutex);
 953        if (!mixer_ctx->powered) {
 954                mutex_unlock(&mixer_ctx->mixer_mutex);
 955                mixer_ctx->planes[win].resume = false;
 956                return;
 957        }
 958        mutex_unlock(&mixer_ctx->mixer_mutex);
 959
 960        spin_lock_irqsave(&res->reg_slock, flags);
 961        mixer_vsync_set_update(mixer_ctx, false);
 962
 963        mixer_cfg_layer(mixer_ctx, win, false);
 964
 965        mixer_vsync_set_update(mixer_ctx, true);
 966        spin_unlock_irqrestore(&res->reg_slock, flags);
 967
 968        mixer_ctx->planes[win].enabled = false;
 969}
 970
 971static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
 972{
 973        struct mixer_context *mixer_ctx = crtc->ctx;
 974        int err;
 975
 976        mutex_lock(&mixer_ctx->mixer_mutex);
 977        if (!mixer_ctx->powered) {
 978                mutex_unlock(&mixer_ctx->mixer_mutex);
 979                return;
 980        }
 981        mutex_unlock(&mixer_ctx->mixer_mutex);
 982
 983        err = drm_vblank_get(mixer_ctx->drm_dev, mixer_ctx->pipe);
 984        if (err < 0) {
 985                DRM_DEBUG_KMS("failed to acquire vblank counter\n");
 986                return;
 987        }
 988
 989        atomic_set(&mixer_ctx->wait_vsync_event, 1);
 990
 991        /*
 992         * wait for MIXER to signal VSYNC interrupt or return after
 993         * timeout which is set to 50ms (refresh rate of 20).
 994         */
 995        if (!wait_event_timeout(mixer_ctx->wait_vsync_queue,
 996                                !atomic_read(&mixer_ctx->wait_vsync_event),
 997                                HZ/20))
 998                DRM_DEBUG_KMS("vblank wait timed out.\n");
 999
1000        drm_vblank_put(mixer_ctx->drm_dev, mixer_ctx->pipe);
1001}
1002
1003static void mixer_window_suspend(struct mixer_context *ctx)
1004{
1005        struct exynos_drm_plane *plane;
1006        int i;
1007
1008        for (i = 0; i < MIXER_WIN_NR; i++) {
1009                plane = &ctx->planes[i];
1010                plane->resume = plane->enabled;
1011                mixer_win_disable(ctx->crtc, i);
1012        }
1013        mixer_wait_for_vblank(ctx->crtc);
1014}
1015
1016static void mixer_window_resume(struct mixer_context *ctx)
1017{
1018        struct exynos_drm_plane *plane;
1019        int i;
1020
1021        for (i = 0; i < MIXER_WIN_NR; i++) {
1022                plane = &ctx->planes[i];
1023                plane->enabled = plane->resume;
1024                plane->resume = false;
1025                if (plane->enabled)
1026                        mixer_win_commit(ctx->crtc, i);
1027        }
1028}
1029
1030static void mixer_poweron(struct mixer_context *ctx)
1031{
1032        struct mixer_resources *res = &ctx->mixer_res;
1033
1034        mutex_lock(&ctx->mixer_mutex);
1035        if (ctx->powered) {
1036                mutex_unlock(&ctx->mixer_mutex);
1037                return;
1038        }
1039
1040        mutex_unlock(&ctx->mixer_mutex);
1041
1042        pm_runtime_get_sync(ctx->dev);
1043
1044        clk_prepare_enable(res->mixer);
1045        clk_prepare_enable(res->hdmi);
1046        if (ctx->vp_enabled) {
1047                clk_prepare_enable(res->vp);
1048                if (ctx->has_sclk)
1049                        clk_prepare_enable(res->sclk_mixer);
1050        }
1051
1052        mutex_lock(&ctx->mixer_mutex);
1053        ctx->powered = true;
1054        mutex_unlock(&ctx->mixer_mutex);
1055
1056        mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
1057
1058        mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
1059        mixer_win_reset(ctx);
1060
1061        mixer_window_resume(ctx);
1062}
1063
1064static void mixer_poweroff(struct mixer_context *ctx)
1065{
1066        struct mixer_resources *res = &ctx->mixer_res;
1067
1068        mutex_lock(&ctx->mixer_mutex);
1069        if (!ctx->powered) {
1070                mutex_unlock(&ctx->mixer_mutex);
1071                return;
1072        }
1073        mutex_unlock(&ctx->mixer_mutex);
1074
1075        mixer_stop(ctx);
1076        mixer_regs_dump(ctx);
1077        mixer_window_suspend(ctx);
1078
1079        ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
1080
1081        mutex_lock(&ctx->mixer_mutex);
1082        ctx->powered = false;
1083        mutex_unlock(&ctx->mixer_mutex);
1084
1085        clk_disable_unprepare(res->hdmi);
1086        clk_disable_unprepare(res->mixer);
1087        if (ctx->vp_enabled) {
1088                clk_disable_unprepare(res->vp);
1089                if (ctx->has_sclk)
1090                        clk_disable_unprepare(res->sclk_mixer);
1091        }
1092
1093        pm_runtime_put_sync(ctx->dev);
1094}
1095
1096static void mixer_dpms(struct exynos_drm_crtc *crtc, int mode)
1097{
1098        switch (mode) {
1099        case DRM_MODE_DPMS_ON:
1100                mixer_poweron(crtc->ctx);
1101                break;
1102        case DRM_MODE_DPMS_STANDBY:
1103        case DRM_MODE_DPMS_SUSPEND:
1104        case DRM_MODE_DPMS_OFF:
1105                mixer_poweroff(crtc->ctx);
1106                break;
1107        default:
1108                DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
1109                break;
1110        }
1111}
1112
1113/* Only valid for Mixer version 16.0.33.0 */
1114int mixer_check_mode(struct drm_display_mode *mode)
1115{
1116        u32 w, h;
1117
1118        w = mode->hdisplay;
1119        h = mode->vdisplay;
1120
1121        DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
1122                mode->hdisplay, mode->vdisplay, mode->vrefresh,
1123                (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1124
1125        if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
1126                (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
1127                (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
1128                return 0;
1129
1130        return -EINVAL;
1131}
1132
1133static const struct exynos_drm_crtc_ops mixer_crtc_ops = {
1134        .dpms                   = mixer_dpms,
1135        .enable_vblank          = mixer_enable_vblank,
1136        .disable_vblank         = mixer_disable_vblank,
1137        .wait_for_vblank        = mixer_wait_for_vblank,
1138        .win_commit             = mixer_win_commit,
1139        .win_disable            = mixer_win_disable,
1140};
1141
1142static struct mixer_drv_data exynos5420_mxr_drv_data = {
1143        .version = MXR_VER_128_0_0_184,
1144        .is_vp_enabled = 0,
1145};
1146
1147static struct mixer_drv_data exynos5250_mxr_drv_data = {
1148        .version = MXR_VER_16_0_33_0,
1149        .is_vp_enabled = 0,
1150};
1151
1152static struct mixer_drv_data exynos4212_mxr_drv_data = {
1153        .version = MXR_VER_0_0_0_16,
1154        .is_vp_enabled = 1,
1155};
1156
1157static struct mixer_drv_data exynos4210_mxr_drv_data = {
1158        .version = MXR_VER_0_0_0_16,
1159        .is_vp_enabled = 1,
1160        .has_sclk = 1,
1161};
1162
1163static const struct platform_device_id mixer_driver_types[] = {
1164        {
1165                .name           = "s5p-mixer",
1166                .driver_data    = (unsigned long)&exynos4210_mxr_drv_data,
1167        }, {
1168                .name           = "exynos5-mixer",
1169                .driver_data    = (unsigned long)&exynos5250_mxr_drv_data,
1170        }, {
1171                /* end node */
1172        }
1173};
1174
1175static struct of_device_id mixer_match_types[] = {
1176        {
1177                .compatible = "samsung,exynos4210-mixer",
1178                .data   = &exynos4210_mxr_drv_data,
1179        }, {
1180                .compatible = "samsung,exynos4212-mixer",
1181                .data   = &exynos4212_mxr_drv_data,
1182        }, {
1183                .compatible = "samsung,exynos5-mixer",
1184                .data   = &exynos5250_mxr_drv_data,
1185        }, {
1186                .compatible = "samsung,exynos5250-mixer",
1187                .data   = &exynos5250_mxr_drv_data,
1188        }, {
1189                .compatible = "samsung,exynos5420-mixer",
1190                .data   = &exynos5420_mxr_drv_data,
1191        }, {
1192                /* end node */
1193        }
1194};
1195MODULE_DEVICE_TABLE(of, mixer_match_types);
1196
1197static int mixer_bind(struct device *dev, struct device *manager, void *data)
1198{
1199        struct mixer_context *ctx = dev_get_drvdata(dev);
1200        struct drm_device *drm_dev = data;
1201        struct exynos_drm_plane *exynos_plane;
1202        enum drm_plane_type type;
1203        unsigned int zpos;
1204        int ret;
1205
1206        ret = mixer_initialize(ctx, drm_dev);
1207        if (ret)
1208                return ret;
1209
1210        for (zpos = 0; zpos < MIXER_WIN_NR; zpos++) {
1211                type = (zpos == MIXER_DEFAULT_WIN) ? DRM_PLANE_TYPE_PRIMARY :
1212                                                DRM_PLANE_TYPE_OVERLAY;
1213                ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
1214                                        1 << ctx->pipe, type, zpos);
1215                if (ret)
1216                        return ret;
1217        }
1218
1219        exynos_plane = &ctx->planes[MIXER_DEFAULT_WIN];
1220        ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
1221                                           ctx->pipe, EXYNOS_DISPLAY_TYPE_HDMI,
1222                                           &mixer_crtc_ops, ctx);
1223        if (IS_ERR(ctx->crtc)) {
1224                mixer_ctx_remove(ctx);
1225                ret = PTR_ERR(ctx->crtc);
1226                goto free_ctx;
1227        }
1228
1229        return 0;
1230
1231free_ctx:
1232        devm_kfree(dev, ctx);
1233        return ret;
1234}
1235
1236static void mixer_unbind(struct device *dev, struct device *master, void *data)
1237{
1238        struct mixer_context *ctx = dev_get_drvdata(dev);
1239
1240        mixer_ctx_remove(ctx);
1241}
1242
1243static const struct component_ops mixer_component_ops = {
1244        .bind   = mixer_bind,
1245        .unbind = mixer_unbind,
1246};
1247
1248static int mixer_probe(struct platform_device *pdev)
1249{
1250        struct device *dev = &pdev->dev;
1251        struct mixer_drv_data *drv;
1252        struct mixer_context *ctx;
1253        int ret;
1254
1255        ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1256        if (!ctx) {
1257                DRM_ERROR("failed to alloc mixer context.\n");
1258                return -ENOMEM;
1259        }
1260
1261        mutex_init(&ctx->mixer_mutex);
1262
1263        if (dev->of_node) {
1264                const struct of_device_id *match;
1265
1266                match = of_match_node(mixer_match_types, dev->of_node);
1267                drv = (struct mixer_drv_data *)match->data;
1268        } else {
1269                drv = (struct mixer_drv_data *)
1270                        platform_get_device_id(pdev)->driver_data;
1271        }
1272
1273        ctx->pdev = pdev;
1274        ctx->dev = dev;
1275        ctx->vp_enabled = drv->is_vp_enabled;
1276        ctx->has_sclk = drv->has_sclk;
1277        ctx->mxr_ver = drv->version;
1278        init_waitqueue_head(&ctx->wait_vsync_queue);
1279        atomic_set(&ctx->wait_vsync_event, 0);
1280
1281        platform_set_drvdata(pdev, ctx);
1282
1283        ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC,
1284                                        EXYNOS_DISPLAY_TYPE_HDMI);
1285        if (ret)
1286                return ret;
1287
1288        ret = component_add(&pdev->dev, &mixer_component_ops);
1289        if (ret) {
1290                exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
1291                return ret;
1292        }
1293
1294        pm_runtime_enable(dev);
1295
1296        return ret;
1297}
1298
1299static int mixer_remove(struct platform_device *pdev)
1300{
1301        pm_runtime_disable(&pdev->dev);
1302
1303        component_del(&pdev->dev, &mixer_component_ops);
1304        exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
1305
1306        return 0;
1307}
1308
1309struct platform_driver mixer_driver = {
1310        .driver = {
1311                .name = "exynos-mixer",
1312                .owner = THIS_MODULE,
1313                .of_match_table = mixer_match_types,
1314        },
1315        .probe = mixer_probe,
1316        .remove = mixer_remove,
1317        .id_table       = mixer_driver_types,
1318};
1319