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                /* vsync interrupt use different bit for read and clear */
 722                val |= MXR_INT_CLEAR_VSYNC;
 723                val &= ~MXR_INT_STATUS_VSYNC;
 724
 725                /* interlace scan need to check shadow register */
 726                if (ctx->interlace) {
 727                        base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
 728                        shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
 729                        if (base != shadow)
 730                                goto out;
 731
 732                        base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
 733                        shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
 734                        if (base != shadow)
 735                                goto out;
 736                }
 737
 738                drm_handle_vblank(ctx->drm_dev, ctx->pipe);
 739                exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
 740
 741                /* set wait vsync event to zero and wake up queue. */
 742                if (atomic_read(&ctx->wait_vsync_event)) {
 743                        atomic_set(&ctx->wait_vsync_event, 0);
 744                        wake_up(&ctx->wait_vsync_queue);
 745                }
 746        }
 747
 748out:
 749        /* clear interrupts */
 750        mixer_reg_write(res, MXR_INT_STATUS, val);
 751
 752        spin_unlock(&res->reg_slock);
 753
 754        return IRQ_HANDLED;
 755}
 756
 757static int mixer_resources_init(struct mixer_context *mixer_ctx)
 758{
 759        struct device *dev = &mixer_ctx->pdev->dev;
 760        struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
 761        struct resource *res;
 762        int ret;
 763
 764        spin_lock_init(&mixer_res->reg_slock);
 765
 766        mixer_res->mixer = devm_clk_get(dev, "mixer");
 767        if (IS_ERR(mixer_res->mixer)) {
 768                dev_err(dev, "failed to get clock 'mixer'\n");
 769                return -ENODEV;
 770        }
 771
 772        mixer_res->hdmi = devm_clk_get(dev, "hdmi");
 773        if (IS_ERR(mixer_res->hdmi)) {
 774                dev_err(dev, "failed to get clock 'hdmi'\n");
 775                return PTR_ERR(mixer_res->hdmi);
 776        }
 777
 778        mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
 779        if (IS_ERR(mixer_res->sclk_hdmi)) {
 780                dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
 781                return -ENODEV;
 782        }
 783        res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 0);
 784        if (res == NULL) {
 785                dev_err(dev, "get memory resource failed.\n");
 786                return -ENXIO;
 787        }
 788
 789        mixer_res->mixer_regs = devm_ioremap(dev, res->start,
 790                                                        resource_size(res));
 791        if (mixer_res->mixer_regs == NULL) {
 792                dev_err(dev, "register mapping failed.\n");
 793                return -ENXIO;
 794        }
 795
 796        res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_IRQ, 0);
 797        if (res == NULL) {
 798                dev_err(dev, "get interrupt resource failed.\n");
 799                return -ENXIO;
 800        }
 801
 802        ret = devm_request_irq(dev, res->start, mixer_irq_handler,
 803                                                0, "drm_mixer", mixer_ctx);
 804        if (ret) {
 805                dev_err(dev, "request interrupt failed.\n");
 806                return ret;
 807        }
 808        mixer_res->irq = res->start;
 809
 810        return 0;
 811}
 812
 813static int vp_resources_init(struct mixer_context *mixer_ctx)
 814{
 815        struct device *dev = &mixer_ctx->pdev->dev;
 816        struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
 817        struct resource *res;
 818
 819        mixer_res->vp = devm_clk_get(dev, "vp");
 820        if (IS_ERR(mixer_res->vp)) {
 821                dev_err(dev, "failed to get clock 'vp'\n");
 822                return -ENODEV;
 823        }
 824
 825        if (mixer_ctx->has_sclk) {
 826                mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
 827                if (IS_ERR(mixer_res->sclk_mixer)) {
 828                        dev_err(dev, "failed to get clock 'sclk_mixer'\n");
 829                        return -ENODEV;
 830                }
 831                mixer_res->mout_mixer = devm_clk_get(dev, "mout_mixer");
 832                if (IS_ERR(mixer_res->mout_mixer)) {
 833                        dev_err(dev, "failed to get clock 'mout_mixer'\n");
 834                        return -ENODEV;
 835                }
 836
 837                if (mixer_res->sclk_hdmi && mixer_res->mout_mixer)
 838                        clk_set_parent(mixer_res->mout_mixer,
 839                                       mixer_res->sclk_hdmi);
 840        }
 841
 842        res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1);
 843        if (res == NULL) {
 844                dev_err(dev, "get memory resource failed.\n");
 845                return -ENXIO;
 846        }
 847
 848        mixer_res->vp_regs = devm_ioremap(dev, res->start,
 849                                                        resource_size(res));
 850        if (mixer_res->vp_regs == NULL) {
 851                dev_err(dev, "register mapping failed.\n");
 852                return -ENXIO;
 853        }
 854
 855        return 0;
 856}
 857
 858static int mixer_initialize(struct mixer_context *mixer_ctx,
 859                        struct drm_device *drm_dev)
 860{
 861        int ret;
 862        struct exynos_drm_private *priv;
 863        priv = drm_dev->dev_private;
 864
 865        mixer_ctx->drm_dev = drm_dev;
 866        mixer_ctx->pipe = priv->pipe++;
 867
 868        /* acquire resources: regs, irqs, clocks */
 869        ret = mixer_resources_init(mixer_ctx);
 870        if (ret) {
 871                DRM_ERROR("mixer_resources_init failed ret=%d\n", ret);
 872                return ret;
 873        }
 874
 875        if (mixer_ctx->vp_enabled) {
 876                /* acquire vp resources: regs, irqs, clocks */
 877                ret = vp_resources_init(mixer_ctx);
 878                if (ret) {
 879                        DRM_ERROR("vp_resources_init failed ret=%d\n", ret);
 880                        return ret;
 881                }
 882        }
 883
 884        ret = drm_iommu_attach_device_if_possible(mixer_ctx->crtc, drm_dev,
 885                                                                mixer_ctx->dev);
 886        if (ret)
 887                priv->pipe--;
 888
 889        return ret;
 890}
 891
 892static void mixer_ctx_remove(struct mixer_context *mixer_ctx)
 893{
 894        if (is_drm_iommu_supported(mixer_ctx->drm_dev))
 895                drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
 896}
 897
 898static int mixer_enable_vblank(struct exynos_drm_crtc *crtc)
 899{
 900        struct mixer_context *mixer_ctx = crtc->ctx;
 901        struct mixer_resources *res = &mixer_ctx->mixer_res;
 902
 903        if (!mixer_ctx->powered) {
 904                mixer_ctx->int_en |= MXR_INT_EN_VSYNC;
 905                return 0;
 906        }
 907
 908        /* enable vsync interrupt */
 909        mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
 910        mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC);
 911
 912        return 0;
 913}
 914
 915static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
 916{
 917        struct mixer_context *mixer_ctx = crtc->ctx;
 918        struct mixer_resources *res = &mixer_ctx->mixer_res;
 919
 920        if (!mixer_ctx->powered) {
 921                mixer_ctx->int_en &= MXR_INT_EN_VSYNC;
 922                return;
 923        }
 924
 925        /* disable vsync interrupt */
 926        mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
 927        mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
 928}
 929
 930static void mixer_win_commit(struct exynos_drm_crtc *crtc, unsigned int win)
 931{
 932        struct mixer_context *mixer_ctx = crtc->ctx;
 933
 934        DRM_DEBUG_KMS("win: %d\n", win);
 935
 936        mutex_lock(&mixer_ctx->mixer_mutex);
 937        if (!mixer_ctx->powered) {
 938                mutex_unlock(&mixer_ctx->mixer_mutex);
 939                return;
 940        }
 941        mutex_unlock(&mixer_ctx->mixer_mutex);
 942
 943        if (win > 1 && mixer_ctx->vp_enabled)
 944                vp_video_buffer(mixer_ctx, win);
 945        else
 946                mixer_graph_buffer(mixer_ctx, win);
 947}
 948
 949static void mixer_win_disable(struct exynos_drm_crtc *crtc, unsigned int win)
 950{
 951        struct mixer_context *mixer_ctx = crtc->ctx;
 952        struct mixer_resources *res = &mixer_ctx->mixer_res;
 953        unsigned long flags;
 954
 955        DRM_DEBUG_KMS("win: %d\n", win);
 956
 957        mutex_lock(&mixer_ctx->mixer_mutex);
 958        if (!mixer_ctx->powered) {
 959                mutex_unlock(&mixer_ctx->mixer_mutex);
 960                return;
 961        }
 962        mutex_unlock(&mixer_ctx->mixer_mutex);
 963
 964        spin_lock_irqsave(&res->reg_slock, flags);
 965        mixer_vsync_set_update(mixer_ctx, false);
 966
 967        mixer_cfg_layer(mixer_ctx, win, false);
 968
 969        mixer_vsync_set_update(mixer_ctx, true);
 970        spin_unlock_irqrestore(&res->reg_slock, flags);
 971}
 972
 973static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
 974{
 975        struct mixer_context *mixer_ctx = crtc->ctx;
 976        int err;
 977
 978        mutex_lock(&mixer_ctx->mixer_mutex);
 979        if (!mixer_ctx->powered) {
 980                mutex_unlock(&mixer_ctx->mixer_mutex);
 981                return;
 982        }
 983        mutex_unlock(&mixer_ctx->mixer_mutex);
 984
 985        err = drm_vblank_get(mixer_ctx->drm_dev, mixer_ctx->pipe);
 986        if (err < 0) {
 987                DRM_DEBUG_KMS("failed to acquire vblank counter\n");
 988                return;
 989        }
 990
 991        atomic_set(&mixer_ctx->wait_vsync_event, 1);
 992
 993        /*
 994         * wait for MIXER to signal VSYNC interrupt or return after
 995         * timeout which is set to 50ms (refresh rate of 20).
 996         */
 997        if (!wait_event_timeout(mixer_ctx->wait_vsync_queue,
 998                                !atomic_read(&mixer_ctx->wait_vsync_event),
 999                                HZ/20))
1000                DRM_DEBUG_KMS("vblank wait timed out.\n");
1001
1002        drm_vblank_put(mixer_ctx->drm_dev, mixer_ctx->pipe);
1003}
1004
1005static void mixer_enable(struct exynos_drm_crtc *crtc)
1006{
1007        struct mixer_context *ctx = crtc->ctx;
1008        struct mixer_resources *res = &ctx->mixer_res;
1009        int ret;
1010
1011        mutex_lock(&ctx->mixer_mutex);
1012        if (ctx->powered) {
1013                mutex_unlock(&ctx->mixer_mutex);
1014                return;
1015        }
1016
1017        mutex_unlock(&ctx->mixer_mutex);
1018
1019        pm_runtime_get_sync(ctx->dev);
1020
1021        ret = clk_prepare_enable(res->mixer);
1022        if (ret < 0) {
1023                DRM_ERROR("Failed to prepare_enable the mixer clk [%d]\n", ret);
1024                return;
1025        }
1026        ret = clk_prepare_enable(res->hdmi);
1027        if (ret < 0) {
1028                DRM_ERROR("Failed to prepare_enable the hdmi clk [%d]\n", ret);
1029                return;
1030        }
1031        if (ctx->vp_enabled) {
1032                ret = clk_prepare_enable(res->vp);
1033                if (ret < 0) {
1034                        DRM_ERROR("Failed to prepare_enable the vp clk [%d]\n",
1035                                  ret);
1036                        return;
1037                }
1038                if (ctx->has_sclk) {
1039                        ret = clk_prepare_enable(res->sclk_mixer);
1040                        if (ret < 0) {
1041                                DRM_ERROR("Failed to prepare_enable the " \
1042                                           "sclk_mixer clk [%d]\n",
1043                                          ret);
1044                                return;
1045                        }
1046                }
1047        }
1048
1049        mutex_lock(&ctx->mixer_mutex);
1050        ctx->powered = true;
1051        mutex_unlock(&ctx->mixer_mutex);
1052
1053        mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
1054
1055        if (ctx->int_en & MXR_INT_EN_VSYNC)
1056                mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
1057        mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
1058        mixer_win_reset(ctx);
1059}
1060
1061static void mixer_disable(struct exynos_drm_crtc *crtc)
1062{
1063        struct mixer_context *ctx = crtc->ctx;
1064        struct mixer_resources *res = &ctx->mixer_res;
1065        int i;
1066
1067        mutex_lock(&ctx->mixer_mutex);
1068        if (!ctx->powered) {
1069                mutex_unlock(&ctx->mixer_mutex);
1070                return;
1071        }
1072        mutex_unlock(&ctx->mixer_mutex);
1073
1074        mixer_stop(ctx);
1075        mixer_regs_dump(ctx);
1076
1077        for (i = 0; i < MIXER_WIN_NR; i++)
1078                mixer_win_disable(crtc, i);
1079
1080        ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
1081
1082        mutex_lock(&ctx->mixer_mutex);
1083        ctx->powered = false;
1084        mutex_unlock(&ctx->mixer_mutex);
1085
1086        clk_disable_unprepare(res->hdmi);
1087        clk_disable_unprepare(res->mixer);
1088        if (ctx->vp_enabled) {
1089                clk_disable_unprepare(res->vp);
1090                if (ctx->has_sclk)
1091                        clk_disable_unprepare(res->sclk_mixer);
1092        }
1093
1094        pm_runtime_put_sync(ctx->dev);
1095}
1096
1097/* Only valid for Mixer version 16.0.33.0 */
1098int mixer_check_mode(struct drm_display_mode *mode)
1099{
1100        u32 w, h;
1101
1102        w = mode->hdisplay;
1103        h = mode->vdisplay;
1104
1105        DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
1106                mode->hdisplay, mode->vdisplay, mode->vrefresh,
1107                (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1108
1109        if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
1110                (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
1111                (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
1112                return 0;
1113
1114        return -EINVAL;
1115}
1116
1117static const struct exynos_drm_crtc_ops mixer_crtc_ops = {
1118        .enable                 = mixer_enable,
1119        .disable                = mixer_disable,
1120        .enable_vblank          = mixer_enable_vblank,
1121        .disable_vblank         = mixer_disable_vblank,
1122        .wait_for_vblank        = mixer_wait_for_vblank,
1123        .win_commit             = mixer_win_commit,
1124        .win_disable            = mixer_win_disable,
1125};
1126
1127static struct mixer_drv_data exynos5420_mxr_drv_data = {
1128        .version = MXR_VER_128_0_0_184,
1129        .is_vp_enabled = 0,
1130};
1131
1132static struct mixer_drv_data exynos5250_mxr_drv_data = {
1133        .version = MXR_VER_16_0_33_0,
1134        .is_vp_enabled = 0,
1135};
1136
1137static struct mixer_drv_data exynos4212_mxr_drv_data = {
1138        .version = MXR_VER_0_0_0_16,
1139        .is_vp_enabled = 1,
1140};
1141
1142static struct mixer_drv_data exynos4210_mxr_drv_data = {
1143        .version = MXR_VER_0_0_0_16,
1144        .is_vp_enabled = 1,
1145        .has_sclk = 1,
1146};
1147
1148static const struct platform_device_id mixer_driver_types[] = {
1149        {
1150                .name           = "s5p-mixer",
1151                .driver_data    = (unsigned long)&exynos4210_mxr_drv_data,
1152        }, {
1153                .name           = "exynos5-mixer",
1154                .driver_data    = (unsigned long)&exynos5250_mxr_drv_data,
1155        }, {
1156                /* end node */
1157        }
1158};
1159
1160static struct of_device_id mixer_match_types[] = {
1161        {
1162                .compatible = "samsung,exynos4210-mixer",
1163                .data   = &exynos4210_mxr_drv_data,
1164        }, {
1165                .compatible = "samsung,exynos4212-mixer",
1166                .data   = &exynos4212_mxr_drv_data,
1167        }, {
1168                .compatible = "samsung,exynos5-mixer",
1169                .data   = &exynos5250_mxr_drv_data,
1170        }, {
1171                .compatible = "samsung,exynos5250-mixer",
1172                .data   = &exynos5250_mxr_drv_data,
1173        }, {
1174                .compatible = "samsung,exynos5420-mixer",
1175                .data   = &exynos5420_mxr_drv_data,
1176        }, {
1177                /* end node */
1178        }
1179};
1180MODULE_DEVICE_TABLE(of, mixer_match_types);
1181
1182static int mixer_bind(struct device *dev, struct device *manager, void *data)
1183{
1184        struct mixer_context *ctx = dev_get_drvdata(dev);
1185        struct drm_device *drm_dev = data;
1186        struct exynos_drm_plane *exynos_plane;
1187        enum drm_plane_type type;
1188        unsigned int zpos;
1189        int ret;
1190
1191        ret = mixer_initialize(ctx, drm_dev);
1192        if (ret)
1193                return ret;
1194
1195        for (zpos = 0; zpos < MIXER_WIN_NR; zpos++) {
1196                type = (zpos == MIXER_DEFAULT_WIN) ? DRM_PLANE_TYPE_PRIMARY :
1197                                                DRM_PLANE_TYPE_OVERLAY;
1198                ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
1199                                        1 << ctx->pipe, type, zpos);
1200                if (ret)
1201                        return ret;
1202        }
1203
1204        exynos_plane = &ctx->planes[MIXER_DEFAULT_WIN];
1205        ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
1206                                           ctx->pipe, EXYNOS_DISPLAY_TYPE_HDMI,
1207                                           &mixer_crtc_ops, ctx);
1208        if (IS_ERR(ctx->crtc)) {
1209                mixer_ctx_remove(ctx);
1210                ret = PTR_ERR(ctx->crtc);
1211                goto free_ctx;
1212        }
1213
1214        return 0;
1215
1216free_ctx:
1217        devm_kfree(dev, ctx);
1218        return ret;
1219}
1220
1221static void mixer_unbind(struct device *dev, struct device *master, void *data)
1222{
1223        struct mixer_context *ctx = dev_get_drvdata(dev);
1224
1225        mixer_ctx_remove(ctx);
1226}
1227
1228static const struct component_ops mixer_component_ops = {
1229        .bind   = mixer_bind,
1230        .unbind = mixer_unbind,
1231};
1232
1233static int mixer_probe(struct platform_device *pdev)
1234{
1235        struct device *dev = &pdev->dev;
1236        struct mixer_drv_data *drv;
1237        struct mixer_context *ctx;
1238        int ret;
1239
1240        ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1241        if (!ctx) {
1242                DRM_ERROR("failed to alloc mixer context.\n");
1243                return -ENOMEM;
1244        }
1245
1246        mutex_init(&ctx->mixer_mutex);
1247
1248        if (dev->of_node) {
1249                const struct of_device_id *match;
1250
1251                match = of_match_node(mixer_match_types, dev->of_node);
1252                drv = (struct mixer_drv_data *)match->data;
1253        } else {
1254                drv = (struct mixer_drv_data *)
1255                        platform_get_device_id(pdev)->driver_data;
1256        }
1257
1258        ctx->pdev = pdev;
1259        ctx->dev = dev;
1260        ctx->vp_enabled = drv->is_vp_enabled;
1261        ctx->has_sclk = drv->has_sclk;
1262        ctx->mxr_ver = drv->version;
1263        init_waitqueue_head(&ctx->wait_vsync_queue);
1264        atomic_set(&ctx->wait_vsync_event, 0);
1265
1266        platform_set_drvdata(pdev, ctx);
1267
1268        ret = component_add(&pdev->dev, &mixer_component_ops);
1269        if (!ret)
1270                pm_runtime_enable(dev);
1271
1272        return ret;
1273}
1274
1275static int mixer_remove(struct platform_device *pdev)
1276{
1277        pm_runtime_disable(&pdev->dev);
1278
1279        component_del(&pdev->dev, &mixer_component_ops);
1280
1281        return 0;
1282}
1283
1284struct platform_driver mixer_driver = {
1285        .driver = {
1286                .name = "exynos-mixer",
1287                .owner = THIS_MODULE,
1288                .of_match_table = mixer_match_types,
1289        },
1290        .probe = mixer_probe,
1291        .remove = mixer_remove,
1292        .id_table       = mixer_driver_types,
1293};
1294