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_iommu.h"
  41#include "exynos_mixer.h"
  42
  43#define get_mixer_manager(dev)  platform_get_drvdata(to_platform_device(dev))
  44
  45#define MIXER_WIN_NR            3
  46#define MIXER_DEFAULT_WIN       0
  47
  48struct hdmi_win_data {
  49        dma_addr_t              dma_addr;
  50        dma_addr_t              chroma_dma_addr;
  51        uint32_t                pixel_format;
  52        unsigned int            bpp;
  53        unsigned int            crtc_x;
  54        unsigned int            crtc_y;
  55        unsigned int            crtc_width;
  56        unsigned int            crtc_height;
  57        unsigned int            fb_x;
  58        unsigned int            fb_y;
  59        unsigned int            fb_width;
  60        unsigned int            fb_height;
  61        unsigned int            src_width;
  62        unsigned int            src_height;
  63        unsigned int            mode_width;
  64        unsigned int            mode_height;
  65        unsigned int            scan_flags;
  66        bool                    enabled;
  67        bool                    resume;
  68};
  69
  70struct mixer_resources {
  71        int                     irq;
  72        void __iomem            *mixer_regs;
  73        void __iomem            *vp_regs;
  74        spinlock_t              reg_slock;
  75        struct clk              *mixer;
  76        struct clk              *vp;
  77        struct clk              *sclk_mixer;
  78        struct clk              *sclk_hdmi;
  79        struct clk              *mout_mixer;
  80};
  81
  82enum mixer_version_id {
  83        MXR_VER_0_0_0_16,
  84        MXR_VER_16_0_33_0,
  85        MXR_VER_128_0_0_184,
  86};
  87
  88struct mixer_context {
  89        struct platform_device *pdev;
  90        struct device           *dev;
  91        struct drm_device       *drm_dev;
  92        int                     pipe;
  93        bool                    interlace;
  94        bool                    powered;
  95        bool                    vp_enabled;
  96        bool                    has_sclk;
  97        u32                     int_en;
  98
  99        struct mutex            mixer_mutex;
 100        struct mixer_resources  mixer_res;
 101        struct hdmi_win_data    win_data[MIXER_WIN_NR];
 102        enum mixer_version_id   mxr_ver;
 103        wait_queue_head_t       wait_vsync_queue;
 104        atomic_t                wait_vsync_event;
 105};
 106
 107struct mixer_drv_data {
 108        enum mixer_version_id   version;
 109        bool                                    is_vp_enabled;
 110        bool                                    has_sclk;
 111};
 112
 113static const u8 filter_y_horiz_tap8[] = {
 114        0,      -1,     -1,     -1,     -1,     -1,     -1,     -1,
 115        -1,     -1,     -1,     -1,     -1,     0,      0,      0,
 116        0,      2,      4,      5,      6,      6,      6,      6,
 117        6,      5,      5,      4,      3,      2,      1,      1,
 118        0,      -6,     -12,    -16,    -18,    -20,    -21,    -20,
 119        -20,    -18,    -16,    -13,    -10,    -8,     -5,     -2,
 120        127,    126,    125,    121,    114,    107,    99,     89,
 121        79,     68,     57,     46,     35,     25,     16,     8,
 122};
 123
 124static const u8 filter_y_vert_tap4[] = {
 125        0,      -3,     -6,     -8,     -8,     -8,     -8,     -7,
 126        -6,     -5,     -4,     -3,     -2,     -1,     -1,     0,
 127        127,    126,    124,    118,    111,    102,    92,     81,
 128        70,     59,     48,     37,     27,     19,     11,     5,
 129        0,      5,      11,     19,     27,     37,     48,     59,
 130        70,     81,     92,     102,    111,    118,    124,    126,
 131        0,      0,      -1,     -1,     -2,     -3,     -4,     -5,
 132        -6,     -7,     -8,     -8,     -8,     -8,     -6,     -3,
 133};
 134
 135static const u8 filter_cr_horiz_tap4[] = {
 136        0,      -3,     -6,     -8,     -8,     -8,     -8,     -7,
 137        -6,     -5,     -4,     -3,     -2,     -1,     -1,     0,
 138        127,    126,    124,    118,    111,    102,    92,     81,
 139        70,     59,     48,     37,     27,     19,     11,     5,
 140};
 141
 142static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
 143{
 144        return readl(res->vp_regs + reg_id);
 145}
 146
 147static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id,
 148                                 u32 val)
 149{
 150        writel(val, res->vp_regs + reg_id);
 151}
 152
 153static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id,
 154                                 u32 val, u32 mask)
 155{
 156        u32 old = vp_reg_read(res, reg_id);
 157
 158        val = (val & mask) | (old & ~mask);
 159        writel(val, res->vp_regs + reg_id);
 160}
 161
 162static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
 163{
 164        return readl(res->mixer_regs + reg_id);
 165}
 166
 167static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id,
 168                                 u32 val)
 169{
 170        writel(val, res->mixer_regs + reg_id);
 171}
 172
 173static inline void mixer_reg_writemask(struct mixer_resources *res,
 174                                 u32 reg_id, u32 val, u32 mask)
 175{
 176        u32 old = mixer_reg_read(res, reg_id);
 177
 178        val = (val & mask) | (old & ~mask);
 179        writel(val, res->mixer_regs + reg_id);
 180}
 181
 182static void mixer_regs_dump(struct mixer_context *ctx)
 183{
 184#define DUMPREG(reg_id) \
 185do { \
 186        DRM_DEBUG_KMS(#reg_id " = %08x\n", \
 187                (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
 188} while (0)
 189
 190        DUMPREG(MXR_STATUS);
 191        DUMPREG(MXR_CFG);
 192        DUMPREG(MXR_INT_EN);
 193        DUMPREG(MXR_INT_STATUS);
 194
 195        DUMPREG(MXR_LAYER_CFG);
 196        DUMPREG(MXR_VIDEO_CFG);
 197
 198        DUMPREG(MXR_GRAPHIC0_CFG);
 199        DUMPREG(MXR_GRAPHIC0_BASE);
 200        DUMPREG(MXR_GRAPHIC0_SPAN);
 201        DUMPREG(MXR_GRAPHIC0_WH);
 202        DUMPREG(MXR_GRAPHIC0_SXY);
 203        DUMPREG(MXR_GRAPHIC0_DXY);
 204
 205        DUMPREG(MXR_GRAPHIC1_CFG);
 206        DUMPREG(MXR_GRAPHIC1_BASE);
 207        DUMPREG(MXR_GRAPHIC1_SPAN);
 208        DUMPREG(MXR_GRAPHIC1_WH);
 209        DUMPREG(MXR_GRAPHIC1_SXY);
 210        DUMPREG(MXR_GRAPHIC1_DXY);
 211#undef DUMPREG
 212}
 213
 214static void vp_regs_dump(struct mixer_context *ctx)
 215{
 216#define DUMPREG(reg_id) \
 217do { \
 218        DRM_DEBUG_KMS(#reg_id " = %08x\n", \
 219                (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
 220} while (0)
 221
 222        DUMPREG(VP_ENABLE);
 223        DUMPREG(VP_SRESET);
 224        DUMPREG(VP_SHADOW_UPDATE);
 225        DUMPREG(VP_FIELD_ID);
 226        DUMPREG(VP_MODE);
 227        DUMPREG(VP_IMG_SIZE_Y);
 228        DUMPREG(VP_IMG_SIZE_C);
 229        DUMPREG(VP_PER_RATE_CTRL);
 230        DUMPREG(VP_TOP_Y_PTR);
 231        DUMPREG(VP_BOT_Y_PTR);
 232        DUMPREG(VP_TOP_C_PTR);
 233        DUMPREG(VP_BOT_C_PTR);
 234        DUMPREG(VP_ENDIAN_MODE);
 235        DUMPREG(VP_SRC_H_POSITION);
 236        DUMPREG(VP_SRC_V_POSITION);
 237        DUMPREG(VP_SRC_WIDTH);
 238        DUMPREG(VP_SRC_HEIGHT);
 239        DUMPREG(VP_DST_H_POSITION);
 240        DUMPREG(VP_DST_V_POSITION);
 241        DUMPREG(VP_DST_WIDTH);
 242        DUMPREG(VP_DST_HEIGHT);
 243        DUMPREG(VP_H_RATIO);
 244        DUMPREG(VP_V_RATIO);
 245
 246#undef DUMPREG
 247}
 248
 249static inline void vp_filter_set(struct mixer_resources *res,
 250                int reg_id, const u8 *data, unsigned int size)
 251{
 252        /* assure 4-byte align */
 253        BUG_ON(size & 3);
 254        for (; size; size -= 4, reg_id += 4, data += 4) {
 255                u32 val = (data[0] << 24) |  (data[1] << 16) |
 256                        (data[2] << 8) | data[3];
 257                vp_reg_write(res, reg_id, val);
 258        }
 259}
 260
 261static void vp_default_filter(struct mixer_resources *res)
 262{
 263        vp_filter_set(res, VP_POLY8_Y0_LL,
 264                filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8));
 265        vp_filter_set(res, VP_POLY4_Y0_LL,
 266                filter_y_vert_tap4, sizeof(filter_y_vert_tap4));
 267        vp_filter_set(res, VP_POLY4_C0_LL,
 268                filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));
 269}
 270
 271static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
 272{
 273        struct mixer_resources *res = &ctx->mixer_res;
 274
 275        /* block update on vsync */
 276        mixer_reg_writemask(res, MXR_STATUS, enable ?
 277                        MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
 278
 279        if (ctx->vp_enabled)
 280                vp_reg_write(res, VP_SHADOW_UPDATE, enable ?
 281                        VP_SHADOW_UPDATE_ENABLE : 0);
 282}
 283
 284static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
 285{
 286        struct mixer_resources *res = &ctx->mixer_res;
 287        u32 val;
 288
 289        /* choosing between interlace and progressive mode */
 290        val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE :
 291                                MXR_CFG_SCAN_PROGRASSIVE);
 292
 293        if (ctx->mxr_ver != MXR_VER_128_0_0_184) {
 294                /* choosing between proper HD and SD mode */
 295                if (height <= 480)
 296                        val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
 297                else if (height <= 576)
 298                        val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
 299                else if (height <= 720)
 300                        val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
 301                else if (height <= 1080)
 302                        val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
 303                else
 304                        val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
 305        }
 306
 307        mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
 308}
 309
 310static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
 311{
 312        struct mixer_resources *res = &ctx->mixer_res;
 313        u32 val;
 314
 315        if (height == 480) {
 316                val = MXR_CFG_RGB601_0_255;
 317        } else if (height == 576) {
 318                val = MXR_CFG_RGB601_0_255;
 319        } else if (height == 720) {
 320                val = MXR_CFG_RGB709_16_235;
 321                mixer_reg_write(res, MXR_CM_COEFF_Y,
 322                                (1 << 30) | (94 << 20) | (314 << 10) |
 323                                (32 << 0));
 324                mixer_reg_write(res, MXR_CM_COEFF_CB,
 325                                (972 << 20) | (851 << 10) | (225 << 0));
 326                mixer_reg_write(res, MXR_CM_COEFF_CR,
 327                                (225 << 20) | (820 << 10) | (1004 << 0));
 328        } else if (height == 1080) {
 329                val = MXR_CFG_RGB709_16_235;
 330                mixer_reg_write(res, MXR_CM_COEFF_Y,
 331                                (1 << 30) | (94 << 20) | (314 << 10) |
 332                                (32 << 0));
 333                mixer_reg_write(res, MXR_CM_COEFF_CB,
 334                                (972 << 20) | (851 << 10) | (225 << 0));
 335                mixer_reg_write(res, MXR_CM_COEFF_CR,
 336                                (225 << 20) | (820 << 10) | (1004 << 0));
 337        } else {
 338                val = MXR_CFG_RGB709_16_235;
 339                mixer_reg_write(res, MXR_CM_COEFF_Y,
 340                                (1 << 30) | (94 << 20) | (314 << 10) |
 341                                (32 << 0));
 342                mixer_reg_write(res, MXR_CM_COEFF_CB,
 343                                (972 << 20) | (851 << 10) | (225 << 0));
 344                mixer_reg_write(res, MXR_CM_COEFF_CR,
 345                                (225 << 20) | (820 << 10) | (1004 << 0));
 346        }
 347
 348        mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
 349}
 350
 351static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable)
 352{
 353        struct mixer_resources *res = &ctx->mixer_res;
 354        u32 val = enable ? ~0 : 0;
 355
 356        switch (win) {
 357        case 0:
 358                mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
 359                break;
 360        case 1:
 361                mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
 362                break;
 363        case 2:
 364                if (ctx->vp_enabled) {
 365                        vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
 366                        mixer_reg_writemask(res, MXR_CFG, val,
 367                                MXR_CFG_VP_ENABLE);
 368
 369                        /* control blending of graphic layer 0 */
 370                        mixer_reg_writemask(res, MXR_GRAPHIC_CFG(0), val,
 371                                        MXR_GRP_CFG_BLEND_PRE_MUL |
 372                                        MXR_GRP_CFG_PIXEL_BLEND_EN);
 373                }
 374                break;
 375        }
 376}
 377
 378static void mixer_run(struct mixer_context *ctx)
 379{
 380        struct mixer_resources *res = &ctx->mixer_res;
 381
 382        mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
 383
 384        mixer_regs_dump(ctx);
 385}
 386
 387static void mixer_stop(struct mixer_context *ctx)
 388{
 389        struct mixer_resources *res = &ctx->mixer_res;
 390        int timeout = 20;
 391
 392        mixer_reg_writemask(res, MXR_STATUS, 0, MXR_STATUS_REG_RUN);
 393
 394        while (!(mixer_reg_read(res, MXR_STATUS) & MXR_STATUS_REG_IDLE) &&
 395                        --timeout)
 396                usleep_range(10000, 12000);
 397
 398        mixer_regs_dump(ctx);
 399}
 400
 401static void vp_video_buffer(struct mixer_context *ctx, int win)
 402{
 403        struct mixer_resources *res = &ctx->mixer_res;
 404        unsigned long flags;
 405        struct hdmi_win_data *win_data;
 406        unsigned int x_ratio, y_ratio;
 407        unsigned int buf_num = 1;
 408        dma_addr_t luma_addr[2], chroma_addr[2];
 409        bool tiled_mode = false;
 410        bool crcb_mode = false;
 411        u32 val;
 412
 413        win_data = &ctx->win_data[win];
 414
 415        switch (win_data->pixel_format) {
 416        case DRM_FORMAT_NV12MT:
 417                tiled_mode = true;
 418        case DRM_FORMAT_NV12:
 419                crcb_mode = false;
 420                buf_num = 2;
 421                break;
 422        /* TODO: single buffer format NV12, NV21 */
 423        default:
 424                /* ignore pixel format at disable time */
 425                if (!win_data->dma_addr)
 426                        break;
 427
 428                DRM_ERROR("pixel format for vp is wrong [%d].\n",
 429                                win_data->pixel_format);
 430                return;
 431        }
 432
 433        /* scaling feature: (src << 16) / dst */
 434        x_ratio = (win_data->src_width << 16) / win_data->crtc_width;
 435        y_ratio = (win_data->src_height << 16) / win_data->crtc_height;
 436
 437        if (buf_num == 2) {
 438                luma_addr[0] = win_data->dma_addr;
 439                chroma_addr[0] = win_data->chroma_dma_addr;
 440        } else {
 441                luma_addr[0] = win_data->dma_addr;
 442                chroma_addr[0] = win_data->dma_addr
 443                        + (win_data->fb_width * win_data->fb_height);
 444        }
 445
 446        if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
 447                ctx->interlace = true;
 448                if (tiled_mode) {
 449                        luma_addr[1] = luma_addr[0] + 0x40;
 450                        chroma_addr[1] = chroma_addr[0] + 0x40;
 451                } else {
 452                        luma_addr[1] = luma_addr[0] + win_data->fb_width;
 453                        chroma_addr[1] = chroma_addr[0] + win_data->fb_width;
 454                }
 455        } else {
 456                ctx->interlace = false;
 457                luma_addr[1] = 0;
 458                chroma_addr[1] = 0;
 459        }
 460
 461        spin_lock_irqsave(&res->reg_slock, flags);
 462        mixer_vsync_set_update(ctx, false);
 463
 464        /* interlace or progressive scan mode */
 465        val = (ctx->interlace ? ~0 : 0);
 466        vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
 467
 468        /* setup format */
 469        val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12);
 470        val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
 471        vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
 472
 473        /* setting size of input image */
 474        vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_width) |
 475                VP_IMG_VSIZE(win_data->fb_height));
 476        /* chroma height has to reduced by 2 to avoid chroma distorions */
 477        vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_width) |
 478                VP_IMG_VSIZE(win_data->fb_height / 2));
 479
 480        vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width);
 481        vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height);
 482        vp_reg_write(res, VP_SRC_H_POSITION,
 483                        VP_SRC_H_POSITION_VAL(win_data->fb_x));
 484        vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y);
 485
 486        vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width);
 487        vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x);
 488        if (ctx->interlace) {
 489                vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height / 2);
 490                vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y / 2);
 491        } else {
 492                vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height);
 493                vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y);
 494        }
 495
 496        vp_reg_write(res, VP_H_RATIO, x_ratio);
 497        vp_reg_write(res, VP_V_RATIO, y_ratio);
 498
 499        vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
 500
 501        /* set buffer address to vp */
 502        vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
 503        vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
 504        vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
 505        vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
 506
 507        mixer_cfg_scan(ctx, win_data->mode_height);
 508        mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
 509        mixer_cfg_layer(ctx, win, true);
 510        mixer_run(ctx);
 511
 512        mixer_vsync_set_update(ctx, true);
 513        spin_unlock_irqrestore(&res->reg_slock, flags);
 514
 515        vp_regs_dump(ctx);
 516}
 517
 518static void mixer_layer_update(struct mixer_context *ctx)
 519{
 520        struct mixer_resources *res = &ctx->mixer_res;
 521
 522        mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
 523}
 524
 525static void mixer_graph_buffer(struct mixer_context *ctx, int win)
 526{
 527        struct mixer_resources *res = &ctx->mixer_res;
 528        unsigned long flags;
 529        struct hdmi_win_data *win_data;
 530        unsigned int x_ratio, y_ratio;
 531        unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
 532        dma_addr_t dma_addr;
 533        unsigned int fmt;
 534        u32 val;
 535
 536        win_data = &ctx->win_data[win];
 537
 538        #define RGB565 4
 539        #define ARGB1555 5
 540        #define ARGB4444 6
 541        #define ARGB8888 7
 542
 543        switch (win_data->bpp) {
 544        case 16:
 545                fmt = ARGB4444;
 546                break;
 547        case 32:
 548                fmt = ARGB8888;
 549                break;
 550        default:
 551                fmt = ARGB8888;
 552        }
 553
 554        /* 2x scaling feature */
 555        x_ratio = 0;
 556        y_ratio = 0;
 557
 558        dst_x_offset = win_data->crtc_x;
 559        dst_y_offset = win_data->crtc_y;
 560
 561        /* converting dma address base and source offset */
 562        dma_addr = win_data->dma_addr
 563                + (win_data->fb_x * win_data->bpp >> 3)
 564                + (win_data->fb_y * win_data->fb_width * win_data->bpp >> 3);
 565        src_x_offset = 0;
 566        src_y_offset = 0;
 567
 568        if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
 569                ctx->interlace = true;
 570        else
 571                ctx->interlace = false;
 572
 573        spin_lock_irqsave(&res->reg_slock, flags);
 574        mixer_vsync_set_update(ctx, false);
 575
 576        /* setup format */
 577        mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
 578                MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
 579
 580        /* setup geometry */
 581        mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), win_data->fb_width);
 582
 583        /* setup display size */
 584        if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
 585                win == MIXER_DEFAULT_WIN) {
 586                val  = MXR_MXR_RES_HEIGHT(win_data->fb_height);
 587                val |= MXR_MXR_RES_WIDTH(win_data->fb_width);
 588                mixer_reg_write(res, MXR_RESOLUTION, val);
 589        }
 590
 591        val  = MXR_GRP_WH_WIDTH(win_data->crtc_width);
 592        val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height);
 593        val |= MXR_GRP_WH_H_SCALE(x_ratio);
 594        val |= MXR_GRP_WH_V_SCALE(y_ratio);
 595        mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
 596
 597        /* setup offsets in source image */
 598        val  = MXR_GRP_SXY_SX(src_x_offset);
 599        val |= MXR_GRP_SXY_SY(src_y_offset);
 600        mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
 601
 602        /* setup offsets in display image */
 603        val  = MXR_GRP_DXY_DX(dst_x_offset);
 604        val |= MXR_GRP_DXY_DY(dst_y_offset);
 605        mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
 606
 607        /* set buffer address to mixer */
 608        mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
 609
 610        mixer_cfg_scan(ctx, win_data->mode_height);
 611        mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
 612        mixer_cfg_layer(ctx, win, true);
 613
 614        /* layer update mandatory for mixer 16.0.33.0 */
 615        if (ctx->mxr_ver == MXR_VER_16_0_33_0 ||
 616                ctx->mxr_ver == MXR_VER_128_0_0_184)
 617                mixer_layer_update(ctx);
 618
 619        mixer_run(ctx);
 620
 621        mixer_vsync_set_update(ctx, true);
 622        spin_unlock_irqrestore(&res->reg_slock, flags);
 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->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
 774        if (IS_ERR(mixer_res->sclk_hdmi)) {
 775                dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
 776                return -ENODEV;
 777        }
 778        res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 0);
 779        if (res == NULL) {
 780                dev_err(dev, "get memory resource failed.\n");
 781                return -ENXIO;
 782        }
 783
 784        mixer_res->mixer_regs = devm_ioremap(dev, res->start,
 785                                                        resource_size(res));
 786        if (mixer_res->mixer_regs == NULL) {
 787                dev_err(dev, "register mapping failed.\n");
 788                return -ENXIO;
 789        }
 790
 791        res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_IRQ, 0);
 792        if (res == NULL) {
 793                dev_err(dev, "get interrupt resource failed.\n");
 794                return -ENXIO;
 795        }
 796
 797        ret = devm_request_irq(dev, res->start, mixer_irq_handler,
 798                                                0, "drm_mixer", mixer_ctx);
 799        if (ret) {
 800                dev_err(dev, "request interrupt failed.\n");
 801                return ret;
 802        }
 803        mixer_res->irq = res->start;
 804
 805        return 0;
 806}
 807
 808static int vp_resources_init(struct mixer_context *mixer_ctx)
 809{
 810        struct device *dev = &mixer_ctx->pdev->dev;
 811        struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
 812        struct resource *res;
 813
 814        mixer_res->vp = devm_clk_get(dev, "vp");
 815        if (IS_ERR(mixer_res->vp)) {
 816                dev_err(dev, "failed to get clock 'vp'\n");
 817                return -ENODEV;
 818        }
 819
 820        if (mixer_ctx->has_sclk) {
 821                mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
 822                if (IS_ERR(mixer_res->sclk_mixer)) {
 823                        dev_err(dev, "failed to get clock 'sclk_mixer'\n");
 824                        return -ENODEV;
 825                }
 826                mixer_res->mout_mixer = devm_clk_get(dev, "mout_mixer");
 827                if (IS_ERR(mixer_res->mout_mixer)) {
 828                        dev_err(dev, "failed to get clock 'mout_mixer'\n");
 829                        return -ENODEV;
 830                }
 831
 832                if (mixer_res->sclk_hdmi && mixer_res->mout_mixer)
 833                        clk_set_parent(mixer_res->mout_mixer,
 834                                       mixer_res->sclk_hdmi);
 835        }
 836
 837        res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1);
 838        if (res == NULL) {
 839                dev_err(dev, "get memory resource failed.\n");
 840                return -ENXIO;
 841        }
 842
 843        mixer_res->vp_regs = devm_ioremap(dev, res->start,
 844                                                        resource_size(res));
 845        if (mixer_res->vp_regs == NULL) {
 846                dev_err(dev, "register mapping failed.\n");
 847                return -ENXIO;
 848        }
 849
 850        return 0;
 851}
 852
 853static int mixer_initialize(struct exynos_drm_manager *mgr,
 854                        struct drm_device *drm_dev)
 855{
 856        int ret;
 857        struct mixer_context *mixer_ctx = mgr->ctx;
 858        struct exynos_drm_private *priv;
 859        priv = drm_dev->dev_private;
 860
 861        mgr->drm_dev = mixer_ctx->drm_dev = drm_dev;
 862        mgr->pipe = mixer_ctx->pipe = priv->pipe++;
 863
 864        /* acquire resources: regs, irqs, clocks */
 865        ret = mixer_resources_init(mixer_ctx);
 866        if (ret) {
 867                DRM_ERROR("mixer_resources_init failed ret=%d\n", ret);
 868                return ret;
 869        }
 870
 871        if (mixer_ctx->vp_enabled) {
 872                /* acquire vp resources: regs, irqs, clocks */
 873                ret = vp_resources_init(mixer_ctx);
 874                if (ret) {
 875                        DRM_ERROR("vp_resources_init failed ret=%d\n", ret);
 876                        return ret;
 877                }
 878        }
 879
 880        if (!is_drm_iommu_supported(mixer_ctx->drm_dev))
 881                return 0;
 882
 883        return drm_iommu_attach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
 884}
 885
 886static void mixer_mgr_remove(struct exynos_drm_manager *mgr)
 887{
 888        struct mixer_context *mixer_ctx = mgr->ctx;
 889
 890        if (is_drm_iommu_supported(mixer_ctx->drm_dev))
 891                drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
 892}
 893
 894static int mixer_enable_vblank(struct exynos_drm_manager *mgr)
 895{
 896        struct mixer_context *mixer_ctx = mgr->ctx;
 897        struct mixer_resources *res = &mixer_ctx->mixer_res;
 898
 899        if (!mixer_ctx->powered) {
 900                mixer_ctx->int_en |= MXR_INT_EN_VSYNC;
 901                return 0;
 902        }
 903
 904        /* enable vsync interrupt */
 905        mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
 906                        MXR_INT_EN_VSYNC);
 907
 908        return 0;
 909}
 910
 911static void mixer_disable_vblank(struct exynos_drm_manager *mgr)
 912{
 913        struct mixer_context *mixer_ctx = mgr->ctx;
 914        struct mixer_resources *res = &mixer_ctx->mixer_res;
 915
 916        /* disable vsync interrupt */
 917        mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
 918}
 919
 920static void mixer_win_mode_set(struct exynos_drm_manager *mgr,
 921                        struct exynos_drm_overlay *overlay)
 922{
 923        struct mixer_context *mixer_ctx = mgr->ctx;
 924        struct hdmi_win_data *win_data;
 925        int win;
 926
 927        if (!overlay) {
 928                DRM_ERROR("overlay is NULL\n");
 929                return;
 930        }
 931
 932        DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
 933                                 overlay->fb_width, overlay->fb_height,
 934                                 overlay->fb_x, overlay->fb_y,
 935                                 overlay->crtc_width, overlay->crtc_height,
 936                                 overlay->crtc_x, overlay->crtc_y);
 937
 938        win = overlay->zpos;
 939        if (win == DEFAULT_ZPOS)
 940                win = MIXER_DEFAULT_WIN;
 941
 942        if (win < 0 || win >= MIXER_WIN_NR) {
 943                DRM_ERROR("mixer window[%d] is wrong\n", win);
 944                return;
 945        }
 946
 947        win_data = &mixer_ctx->win_data[win];
 948
 949        win_data->dma_addr = overlay->dma_addr[0];
 950        win_data->chroma_dma_addr = overlay->dma_addr[1];
 951        win_data->pixel_format = overlay->pixel_format;
 952        win_data->bpp = overlay->bpp;
 953
 954        win_data->crtc_x = overlay->crtc_x;
 955        win_data->crtc_y = overlay->crtc_y;
 956        win_data->crtc_width = overlay->crtc_width;
 957        win_data->crtc_height = overlay->crtc_height;
 958
 959        win_data->fb_x = overlay->fb_x;
 960        win_data->fb_y = overlay->fb_y;
 961        win_data->fb_width = overlay->fb_width;
 962        win_data->fb_height = overlay->fb_height;
 963        win_data->src_width = overlay->src_width;
 964        win_data->src_height = overlay->src_height;
 965
 966        win_data->mode_width = overlay->mode_width;
 967        win_data->mode_height = overlay->mode_height;
 968
 969        win_data->scan_flags = overlay->scan_flag;
 970}
 971
 972static void mixer_win_commit(struct exynos_drm_manager *mgr, int zpos)
 973{
 974        struct mixer_context *mixer_ctx = mgr->ctx;
 975        int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos;
 976
 977        DRM_DEBUG_KMS("win: %d\n", win);
 978
 979        mutex_lock(&mixer_ctx->mixer_mutex);
 980        if (!mixer_ctx->powered) {
 981                mutex_unlock(&mixer_ctx->mixer_mutex);
 982                return;
 983        }
 984        mutex_unlock(&mixer_ctx->mixer_mutex);
 985
 986        if (win > 1 && mixer_ctx->vp_enabled)
 987                vp_video_buffer(mixer_ctx, win);
 988        else
 989                mixer_graph_buffer(mixer_ctx, win);
 990
 991        mixer_ctx->win_data[win].enabled = true;
 992}
 993
 994static void mixer_win_disable(struct exynos_drm_manager *mgr, int zpos)
 995{
 996        struct mixer_context *mixer_ctx = mgr->ctx;
 997        struct mixer_resources *res = &mixer_ctx->mixer_res;
 998        int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos;
 999        unsigned long flags;
1000
1001        DRM_DEBUG_KMS("win: %d\n", win);
1002
1003        mutex_lock(&mixer_ctx->mixer_mutex);
1004        if (!mixer_ctx->powered) {
1005                mutex_unlock(&mixer_ctx->mixer_mutex);
1006                mixer_ctx->win_data[win].resume = false;
1007                return;
1008        }
1009        mutex_unlock(&mixer_ctx->mixer_mutex);
1010
1011        spin_lock_irqsave(&res->reg_slock, flags);
1012        mixer_vsync_set_update(mixer_ctx, false);
1013
1014        mixer_cfg_layer(mixer_ctx, win, false);
1015
1016        mixer_vsync_set_update(mixer_ctx, true);
1017        spin_unlock_irqrestore(&res->reg_slock, flags);
1018
1019        mixer_ctx->win_data[win].enabled = false;
1020}
1021
1022static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr)
1023{
1024        struct mixer_context *mixer_ctx = mgr->ctx;
1025
1026        mutex_lock(&mixer_ctx->mixer_mutex);
1027        if (!mixer_ctx->powered) {
1028                mutex_unlock(&mixer_ctx->mixer_mutex);
1029                return;
1030        }
1031        mutex_unlock(&mixer_ctx->mixer_mutex);
1032
1033        drm_vblank_get(mgr->crtc->dev, mixer_ctx->pipe);
1034
1035        atomic_set(&mixer_ctx->wait_vsync_event, 1);
1036
1037        /*
1038         * wait for MIXER to signal VSYNC interrupt or return after
1039         * timeout which is set to 50ms (refresh rate of 20).
1040         */
1041        if (!wait_event_timeout(mixer_ctx->wait_vsync_queue,
1042                                !atomic_read(&mixer_ctx->wait_vsync_event),
1043                                HZ/20))
1044                DRM_DEBUG_KMS("vblank wait timed out.\n");
1045
1046        drm_vblank_put(mgr->crtc->dev, mixer_ctx->pipe);
1047}
1048
1049static void mixer_window_suspend(struct exynos_drm_manager *mgr)
1050{
1051        struct mixer_context *ctx = mgr->ctx;
1052        struct hdmi_win_data *win_data;
1053        int i;
1054
1055        for (i = 0; i < MIXER_WIN_NR; i++) {
1056                win_data = &ctx->win_data[i];
1057                win_data->resume = win_data->enabled;
1058                mixer_win_disable(mgr, i);
1059        }
1060        mixer_wait_for_vblank(mgr);
1061}
1062
1063static void mixer_window_resume(struct exynos_drm_manager *mgr)
1064{
1065        struct mixer_context *ctx = mgr->ctx;
1066        struct hdmi_win_data *win_data;
1067        int i;
1068
1069        for (i = 0; i < MIXER_WIN_NR; i++) {
1070                win_data = &ctx->win_data[i];
1071                win_data->enabled = win_data->resume;
1072                win_data->resume = false;
1073                if (win_data->enabled)
1074                        mixer_win_commit(mgr, i);
1075        }
1076}
1077
1078static void mixer_poweron(struct exynos_drm_manager *mgr)
1079{
1080        struct mixer_context *ctx = mgr->ctx;
1081        struct mixer_resources *res = &ctx->mixer_res;
1082
1083        mutex_lock(&ctx->mixer_mutex);
1084        if (ctx->powered) {
1085                mutex_unlock(&ctx->mixer_mutex);
1086                return;
1087        }
1088
1089        mutex_unlock(&ctx->mixer_mutex);
1090
1091        pm_runtime_get_sync(ctx->dev);
1092
1093        clk_prepare_enable(res->mixer);
1094        if (ctx->vp_enabled) {
1095                clk_prepare_enable(res->vp);
1096                if (ctx->has_sclk)
1097                        clk_prepare_enable(res->sclk_mixer);
1098        }
1099
1100        mutex_lock(&ctx->mixer_mutex);
1101        ctx->powered = true;
1102        mutex_unlock(&ctx->mixer_mutex);
1103
1104        mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
1105
1106        mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
1107        mixer_win_reset(ctx);
1108
1109        mixer_window_resume(mgr);
1110}
1111
1112static void mixer_poweroff(struct exynos_drm_manager *mgr)
1113{
1114        struct mixer_context *ctx = mgr->ctx;
1115        struct mixer_resources *res = &ctx->mixer_res;
1116
1117        mutex_lock(&ctx->mixer_mutex);
1118        if (!ctx->powered) {
1119                mutex_unlock(&ctx->mixer_mutex);
1120                return;
1121        }
1122        mutex_unlock(&ctx->mixer_mutex);
1123
1124        mixer_stop(ctx);
1125        mixer_window_suspend(mgr);
1126
1127        ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
1128
1129        mutex_lock(&ctx->mixer_mutex);
1130        ctx->powered = false;
1131        mutex_unlock(&ctx->mixer_mutex);
1132
1133        clk_disable_unprepare(res->mixer);
1134        if (ctx->vp_enabled) {
1135                clk_disable_unprepare(res->vp);
1136                if (ctx->has_sclk)
1137                        clk_disable_unprepare(res->sclk_mixer);
1138        }
1139
1140        pm_runtime_put_sync(ctx->dev);
1141}
1142
1143static void mixer_dpms(struct exynos_drm_manager *mgr, int mode)
1144{
1145        switch (mode) {
1146        case DRM_MODE_DPMS_ON:
1147                mixer_poweron(mgr);
1148                break;
1149        case DRM_MODE_DPMS_STANDBY:
1150        case DRM_MODE_DPMS_SUSPEND:
1151        case DRM_MODE_DPMS_OFF:
1152                mixer_poweroff(mgr);
1153                break;
1154        default:
1155                DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
1156                break;
1157        }
1158}
1159
1160/* Only valid for Mixer version 16.0.33.0 */
1161int mixer_check_mode(struct drm_display_mode *mode)
1162{
1163        u32 w, h;
1164
1165        w = mode->hdisplay;
1166        h = mode->vdisplay;
1167
1168        DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
1169                mode->hdisplay, mode->vdisplay, mode->vrefresh,
1170                (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1171
1172        if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
1173                (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
1174                (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
1175                return 0;
1176
1177        return -EINVAL;
1178}
1179
1180static struct exynos_drm_manager_ops mixer_manager_ops = {
1181        .dpms                   = mixer_dpms,
1182        .enable_vblank          = mixer_enable_vblank,
1183        .disable_vblank         = mixer_disable_vblank,
1184        .wait_for_vblank        = mixer_wait_for_vblank,
1185        .win_mode_set           = mixer_win_mode_set,
1186        .win_commit             = mixer_win_commit,
1187        .win_disable            = mixer_win_disable,
1188};
1189
1190static struct exynos_drm_manager mixer_manager = {
1191        .type                   = EXYNOS_DISPLAY_TYPE_HDMI,
1192        .ops                    = &mixer_manager_ops,
1193};
1194
1195static struct mixer_drv_data exynos5420_mxr_drv_data = {
1196        .version = MXR_VER_128_0_0_184,
1197        .is_vp_enabled = 0,
1198};
1199
1200static struct mixer_drv_data exynos5250_mxr_drv_data = {
1201        .version = MXR_VER_16_0_33_0,
1202        .is_vp_enabled = 0,
1203};
1204
1205static struct mixer_drv_data exynos4212_mxr_drv_data = {
1206        .version = MXR_VER_0_0_0_16,
1207        .is_vp_enabled = 1,
1208};
1209
1210static struct mixer_drv_data exynos4210_mxr_drv_data = {
1211        .version = MXR_VER_0_0_0_16,
1212        .is_vp_enabled = 1,
1213        .has_sclk = 1,
1214};
1215
1216static struct platform_device_id mixer_driver_types[] = {
1217        {
1218                .name           = "s5p-mixer",
1219                .driver_data    = (unsigned long)&exynos4210_mxr_drv_data,
1220        }, {
1221                .name           = "exynos5-mixer",
1222                .driver_data    = (unsigned long)&exynos5250_mxr_drv_data,
1223        }, {
1224                /* end node */
1225        }
1226};
1227
1228static struct of_device_id mixer_match_types[] = {
1229        {
1230                .compatible = "samsung,exynos4210-mixer",
1231                .data   = &exynos4210_mxr_drv_data,
1232        }, {
1233                .compatible = "samsung,exynos4212-mixer",
1234                .data   = &exynos4212_mxr_drv_data,
1235        }, {
1236                .compatible = "samsung,exynos5-mixer",
1237                .data   = &exynos5250_mxr_drv_data,
1238        }, {
1239                .compatible = "samsung,exynos5250-mixer",
1240                .data   = &exynos5250_mxr_drv_data,
1241        }, {
1242                .compatible = "samsung,exynos5420-mixer",
1243                .data   = &exynos5420_mxr_drv_data,
1244        }, {
1245                /* end node */
1246        }
1247};
1248MODULE_DEVICE_TABLE(of, mixer_match_types);
1249
1250static int mixer_bind(struct device *dev, struct device *manager, void *data)
1251{
1252        struct platform_device *pdev = to_platform_device(dev);
1253        struct drm_device *drm_dev = data;
1254        struct mixer_context *ctx;
1255        struct mixer_drv_data *drv;
1256        int ret;
1257
1258        dev_info(dev, "probe start\n");
1259
1260        ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1261        if (!ctx) {
1262                DRM_ERROR("failed to alloc mixer context.\n");
1263                return -ENOMEM;
1264        }
1265
1266        mutex_init(&ctx->mixer_mutex);
1267
1268        if (dev->of_node) {
1269                const struct of_device_id *match;
1270                match = of_match_node(mixer_match_types, dev->of_node);
1271                drv = (struct mixer_drv_data *)match->data;
1272        } else {
1273                drv = (struct mixer_drv_data *)
1274                        platform_get_device_id(pdev)->driver_data;
1275        }
1276
1277        ctx->pdev = pdev;
1278        ctx->dev = dev;
1279        ctx->vp_enabled = drv->is_vp_enabled;
1280        ctx->has_sclk = drv->has_sclk;
1281        ctx->mxr_ver = drv->version;
1282        init_waitqueue_head(&ctx->wait_vsync_queue);
1283        atomic_set(&ctx->wait_vsync_event, 0);
1284
1285        mixer_manager.ctx = ctx;
1286        ret = mixer_initialize(&mixer_manager, drm_dev);
1287        if (ret)
1288                return ret;
1289
1290        platform_set_drvdata(pdev, &mixer_manager);
1291        ret = exynos_drm_crtc_create(&mixer_manager);
1292        if (ret) {
1293                mixer_mgr_remove(&mixer_manager);
1294                return ret;
1295        }
1296
1297        pm_runtime_enable(dev);
1298
1299        return 0;
1300}
1301
1302static void mixer_unbind(struct device *dev, struct device *master, void *data)
1303{
1304        struct exynos_drm_manager *mgr = dev_get_drvdata(dev);
1305        struct drm_crtc *crtc = mgr->crtc;
1306
1307        dev_info(dev, "remove successful\n");
1308
1309        mixer_mgr_remove(mgr);
1310
1311        pm_runtime_disable(dev);
1312
1313        crtc->funcs->destroy(crtc);
1314}
1315
1316static const struct component_ops mixer_component_ops = {
1317        .bind   = mixer_bind,
1318        .unbind = mixer_unbind,
1319};
1320
1321static int mixer_probe(struct platform_device *pdev)
1322{
1323        int ret;
1324
1325        ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC,
1326                                        mixer_manager.type);
1327        if (ret)
1328                return ret;
1329
1330        ret = component_add(&pdev->dev, &mixer_component_ops);
1331        if (ret)
1332                exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
1333
1334        return ret;
1335}
1336
1337static int mixer_remove(struct platform_device *pdev)
1338{
1339        component_del(&pdev->dev, &mixer_component_ops);
1340        exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
1341
1342        return 0;
1343}
1344
1345struct platform_driver mixer_driver = {
1346        .driver = {
1347                .name = "exynos-mixer",
1348                .owner = THIS_MODULE,
1349                .of_match_table = mixer_match_types,
1350        },
1351        .probe = mixer_probe,
1352        .remove = mixer_remove,
1353        .id_table       = mixer_driver_types,
1354};
1355