linux/drivers/gpu/drm/zte/zx_vou.c
<<
>>
Prefs
   1/*
   2 * Copyright 2016 Linaro Ltd.
   3 * Copyright 2016 ZTE Corporation.
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License version 2 as
   7 * published by the Free Software Foundation.
   8 *
   9 */
  10
  11#include <linux/clk.h>
  12#include <linux/component.h>
  13#include <linux/of_address.h>
  14#include <video/videomode.h>
  15
  16#include <drm/drm_atomic_helper.h>
  17#include <drm/drm_crtc.h>
  18#include <drm/drm_crtc_helper.h>
  19#include <drm/drm_fb_cma_helper.h>
  20#include <drm/drm_fb_helper.h>
  21#include <drm/drm_gem_cma_helper.h>
  22#include <drm/drm_of.h>
  23#include <drm/drm_plane_helper.h>
  24#include <drm/drmP.h>
  25
  26#include "zx_common_regs.h"
  27#include "zx_drm_drv.h"
  28#include "zx_plane.h"
  29#include "zx_vou.h"
  30#include "zx_vou_regs.h"
  31
  32#define GL_NUM  2
  33#define VL_NUM  3
  34
  35enum vou_chn_type {
  36        VOU_CHN_MAIN,
  37        VOU_CHN_AUX,
  38};
  39
  40struct zx_crtc_regs {
  41        u32 fir_active;
  42        u32 fir_htiming;
  43        u32 fir_vtiming;
  44        u32 sec_vtiming;
  45        u32 timing_shift;
  46        u32 timing_pi_shift;
  47};
  48
  49static const struct zx_crtc_regs main_crtc_regs = {
  50        .fir_active = FIR_MAIN_ACTIVE,
  51        .fir_htiming = FIR_MAIN_H_TIMING,
  52        .fir_vtiming = FIR_MAIN_V_TIMING,
  53        .sec_vtiming = SEC_MAIN_V_TIMING,
  54        .timing_shift = TIMING_MAIN_SHIFT,
  55        .timing_pi_shift = TIMING_MAIN_PI_SHIFT,
  56};
  57
  58static const struct zx_crtc_regs aux_crtc_regs = {
  59        .fir_active = FIR_AUX_ACTIVE,
  60        .fir_htiming = FIR_AUX_H_TIMING,
  61        .fir_vtiming = FIR_AUX_V_TIMING,
  62        .sec_vtiming = SEC_AUX_V_TIMING,
  63        .timing_shift = TIMING_AUX_SHIFT,
  64        .timing_pi_shift = TIMING_AUX_PI_SHIFT,
  65};
  66
  67struct zx_crtc_bits {
  68        u32 polarity_mask;
  69        u32 polarity_shift;
  70        u32 int_frame_mask;
  71        u32 tc_enable;
  72        u32 sec_vactive_shift;
  73        u32 sec_vactive_mask;
  74        u32 interlace_select;
  75        u32 pi_enable;
  76        u32 div_vga_shift;
  77        u32 div_pic_shift;
  78        u32 div_tvenc_shift;
  79        u32 div_hdmi_pnx_shift;
  80        u32 div_hdmi_shift;
  81        u32 div_inf_shift;
  82        u32 div_layer_shift;
  83};
  84
  85static const struct zx_crtc_bits main_crtc_bits = {
  86        .polarity_mask = MAIN_POL_MASK,
  87        .polarity_shift = MAIN_POL_SHIFT,
  88        .int_frame_mask = TIMING_INT_MAIN_FRAME,
  89        .tc_enable = MAIN_TC_EN,
  90        .sec_vactive_shift = SEC_VACT_MAIN_SHIFT,
  91        .sec_vactive_mask = SEC_VACT_MAIN_MASK,
  92        .interlace_select = MAIN_INTERLACE_SEL,
  93        .pi_enable = MAIN_PI_EN,
  94        .div_vga_shift = VGA_MAIN_DIV_SHIFT,
  95        .div_pic_shift = PIC_MAIN_DIV_SHIFT,
  96        .div_tvenc_shift = TVENC_MAIN_DIV_SHIFT,
  97        .div_hdmi_pnx_shift = HDMI_MAIN_PNX_DIV_SHIFT,
  98        .div_hdmi_shift = HDMI_MAIN_DIV_SHIFT,
  99        .div_inf_shift = INF_MAIN_DIV_SHIFT,
 100        .div_layer_shift = LAYER_MAIN_DIV_SHIFT,
 101};
 102
 103static const struct zx_crtc_bits aux_crtc_bits = {
 104        .polarity_mask = AUX_POL_MASK,
 105        .polarity_shift = AUX_POL_SHIFT,
 106        .int_frame_mask = TIMING_INT_AUX_FRAME,
 107        .tc_enable = AUX_TC_EN,
 108        .sec_vactive_shift = SEC_VACT_AUX_SHIFT,
 109        .sec_vactive_mask = SEC_VACT_AUX_MASK,
 110        .interlace_select = AUX_INTERLACE_SEL,
 111        .pi_enable = AUX_PI_EN,
 112        .div_vga_shift = VGA_AUX_DIV_SHIFT,
 113        .div_pic_shift = PIC_AUX_DIV_SHIFT,
 114        .div_tvenc_shift = TVENC_AUX_DIV_SHIFT,
 115        .div_hdmi_pnx_shift = HDMI_AUX_PNX_DIV_SHIFT,
 116        .div_hdmi_shift = HDMI_AUX_DIV_SHIFT,
 117        .div_inf_shift = INF_AUX_DIV_SHIFT,
 118        .div_layer_shift = LAYER_AUX_DIV_SHIFT,
 119};
 120
 121struct zx_crtc {
 122        struct drm_crtc crtc;
 123        struct drm_plane *primary;
 124        struct zx_vou_hw *vou;
 125        void __iomem *chnreg;
 126        void __iomem *chncsc;
 127        void __iomem *dither;
 128        const struct zx_crtc_regs *regs;
 129        const struct zx_crtc_bits *bits;
 130        enum vou_chn_type chn_type;
 131        struct clk *pixclk;
 132};
 133
 134#define to_zx_crtc(x) container_of(x, struct zx_crtc, crtc)
 135
 136struct vou_layer_bits {
 137        u32 enable;
 138        u32 chnsel;
 139        u32 clksel;
 140};
 141
 142static const struct vou_layer_bits zx_gl_bits[GL_NUM] = {
 143        {
 144                .enable = OSD_CTRL0_GL0_EN,
 145                .chnsel = OSD_CTRL0_GL0_SEL,
 146                .clksel = VOU_CLK_GL0_SEL,
 147        }, {
 148                .enable = OSD_CTRL0_GL1_EN,
 149                .chnsel = OSD_CTRL0_GL1_SEL,
 150                .clksel = VOU_CLK_GL1_SEL,
 151        },
 152};
 153
 154static const struct vou_layer_bits zx_vl_bits[VL_NUM] = {
 155        {
 156                .enable = OSD_CTRL0_VL0_EN,
 157                .chnsel = OSD_CTRL0_VL0_SEL,
 158                .clksel = VOU_CLK_VL0_SEL,
 159        }, {
 160                .enable = OSD_CTRL0_VL1_EN,
 161                .chnsel = OSD_CTRL0_VL1_SEL,
 162                .clksel = VOU_CLK_VL1_SEL,
 163        }, {
 164                .enable = OSD_CTRL0_VL2_EN,
 165                .chnsel = OSD_CTRL0_VL2_SEL,
 166                .clksel = VOU_CLK_VL2_SEL,
 167        },
 168};
 169
 170struct zx_vou_hw {
 171        struct device *dev;
 172        void __iomem *osd;
 173        void __iomem *timing;
 174        void __iomem *vouctl;
 175        void __iomem *otfppu;
 176        void __iomem *dtrc;
 177        struct clk *axi_clk;
 178        struct clk *ppu_clk;
 179        struct clk *main_clk;
 180        struct clk *aux_clk;
 181        struct zx_crtc *main_crtc;
 182        struct zx_crtc *aux_crtc;
 183};
 184
 185enum vou_inf_data_sel {
 186        VOU_YUV444      = 0,
 187        VOU_RGB_101010  = 1,
 188        VOU_RGB_888     = 2,
 189        VOU_RGB_666     = 3,
 190};
 191
 192struct vou_inf {
 193        enum vou_inf_id id;
 194        enum vou_inf_data_sel data_sel;
 195        u32 clocks_en_bits;
 196        u32 clocks_sel_bits;
 197};
 198
 199static struct vou_inf vou_infs[] = {
 200        [VOU_HDMI] = {
 201                .data_sel = VOU_YUV444,
 202                .clocks_en_bits = BIT(24) | BIT(18) | BIT(6),
 203                .clocks_sel_bits = BIT(13) | BIT(2),
 204        },
 205        [VOU_TV_ENC] = {
 206                .data_sel = VOU_YUV444,
 207                .clocks_en_bits = BIT(15),
 208                .clocks_sel_bits = BIT(11) | BIT(0),
 209        },
 210        [VOU_VGA] = {
 211                .data_sel = VOU_RGB_888,
 212                .clocks_en_bits = BIT(1),
 213                .clocks_sel_bits = BIT(10),
 214        },
 215};
 216
 217static inline struct zx_vou_hw *crtc_to_vou(struct drm_crtc *crtc)
 218{
 219        struct zx_crtc *zcrtc = to_zx_crtc(crtc);
 220
 221        return zcrtc->vou;
 222}
 223
 224void vou_inf_hdmi_audio_sel(struct drm_crtc *crtc,
 225                            enum vou_inf_hdmi_audio aud)
 226{
 227        struct zx_crtc *zcrtc = to_zx_crtc(crtc);
 228        struct zx_vou_hw *vou = zcrtc->vou;
 229
 230        zx_writel_mask(vou->vouctl + VOU_INF_HDMI_CTRL, VOU_HDMI_AUD_MASK, aud);
 231}
 232
 233void vou_inf_enable(enum vou_inf_id id, struct drm_crtc *crtc)
 234{
 235        struct zx_crtc *zcrtc = to_zx_crtc(crtc);
 236        struct zx_vou_hw *vou = zcrtc->vou;
 237        struct vou_inf *inf = &vou_infs[id];
 238        void __iomem *dither = zcrtc->dither;
 239        void __iomem *csc = zcrtc->chncsc;
 240        bool is_main = zcrtc->chn_type == VOU_CHN_MAIN;
 241        u32 data_sel_shift = id << 1;
 242
 243        if (inf->data_sel != VOU_YUV444) {
 244                /* Enable channel CSC for RGB output */
 245                zx_writel_mask(csc + CSC_CTRL0, CSC_COV_MODE_MASK,
 246                               CSC_BT709_IMAGE_YCBCR2RGB << CSC_COV_MODE_SHIFT);
 247                zx_writel_mask(csc + CSC_CTRL0, CSC_WORK_ENABLE,
 248                               CSC_WORK_ENABLE);
 249
 250                /* Bypass Dither block for RGB output */
 251                zx_writel_mask(dither + OSD_DITHER_CTRL0, DITHER_BYSPASS,
 252                               DITHER_BYSPASS);
 253        } else {
 254                zx_writel_mask(csc + CSC_CTRL0, CSC_WORK_ENABLE, 0);
 255                zx_writel_mask(dither + OSD_DITHER_CTRL0, DITHER_BYSPASS, 0);
 256        }
 257
 258        /* Select data format */
 259        zx_writel_mask(vou->vouctl + VOU_INF_DATA_SEL, 0x3 << data_sel_shift,
 260                       inf->data_sel << data_sel_shift);
 261
 262        /* Select channel */
 263        zx_writel_mask(vou->vouctl + VOU_INF_CH_SEL, 0x1 << id,
 264                       zcrtc->chn_type << id);
 265
 266        /* Select interface clocks */
 267        zx_writel_mask(vou->vouctl + VOU_CLK_SEL, inf->clocks_sel_bits,
 268                       is_main ? 0 : inf->clocks_sel_bits);
 269
 270        /* Enable interface clocks */
 271        zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits,
 272                       inf->clocks_en_bits);
 273
 274        /* Enable the device */
 275        zx_writel_mask(vou->vouctl + VOU_INF_EN, 1 << id, 1 << id);
 276}
 277
 278void vou_inf_disable(enum vou_inf_id id, struct drm_crtc *crtc)
 279{
 280        struct zx_vou_hw *vou = crtc_to_vou(crtc);
 281        struct vou_inf *inf = &vou_infs[id];
 282
 283        /* Disable the device */
 284        zx_writel_mask(vou->vouctl + VOU_INF_EN, 1 << id, 0);
 285
 286        /* Disable interface clocks */
 287        zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits, 0);
 288}
 289
 290void zx_vou_config_dividers(struct drm_crtc *crtc,
 291                            struct vou_div_config *configs, int num)
 292{
 293        struct zx_crtc *zcrtc = to_zx_crtc(crtc);
 294        struct zx_vou_hw *vou = zcrtc->vou;
 295        const struct zx_crtc_bits *bits = zcrtc->bits;
 296        int i;
 297
 298        /* Clear update flag bit */
 299        zx_writel_mask(vou->vouctl + VOU_DIV_PARA, DIV_PARA_UPDATE, 0);
 300
 301        for (i = 0; i < num; i++) {
 302                struct vou_div_config *cfg = configs + i;
 303                u32 reg, shift;
 304
 305                switch (cfg->id) {
 306                case VOU_DIV_VGA:
 307                        reg = VOU_CLK_SEL;
 308                        shift = bits->div_vga_shift;
 309                        break;
 310                case VOU_DIV_PIC:
 311                        reg = VOU_CLK_SEL;
 312                        shift = bits->div_pic_shift;
 313                        break;
 314                case VOU_DIV_TVENC:
 315                        reg = VOU_DIV_PARA;
 316                        shift = bits->div_tvenc_shift;
 317                        break;
 318                case VOU_DIV_HDMI_PNX:
 319                        reg = VOU_DIV_PARA;
 320                        shift = bits->div_hdmi_pnx_shift;
 321                        break;
 322                case VOU_DIV_HDMI:
 323                        reg = VOU_DIV_PARA;
 324                        shift = bits->div_hdmi_shift;
 325                        break;
 326                case VOU_DIV_INF:
 327                        reg = VOU_DIV_PARA;
 328                        shift = bits->div_inf_shift;
 329                        break;
 330                case VOU_DIV_LAYER:
 331                        reg = VOU_DIV_PARA;
 332                        shift = bits->div_layer_shift;
 333                        break;
 334                default:
 335                        continue;
 336                }
 337
 338                /* Each divider occupies 3 bits */
 339                zx_writel_mask(vou->vouctl + reg, 0x7 << shift,
 340                               cfg->val << shift);
 341        }
 342
 343        /* Set update flag bit to get dividers effected */
 344        zx_writel_mask(vou->vouctl + VOU_DIV_PARA, DIV_PARA_UPDATE,
 345                       DIV_PARA_UPDATE);
 346}
 347
 348static inline void vou_chn_set_update(struct zx_crtc *zcrtc)
 349{
 350        zx_writel(zcrtc->chnreg + CHN_UPDATE, 1);
 351}
 352
 353static void zx_crtc_atomic_enable(struct drm_crtc *crtc,
 354                                  struct drm_crtc_state *old_state)
 355{
 356        struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 357        bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
 358        struct zx_crtc *zcrtc = to_zx_crtc(crtc);
 359        struct zx_vou_hw *vou = zcrtc->vou;
 360        const struct zx_crtc_regs *regs = zcrtc->regs;
 361        const struct zx_crtc_bits *bits = zcrtc->bits;
 362        struct videomode vm;
 363        u32 scan_mask;
 364        u32 pol = 0;
 365        u32 val;
 366        int ret;
 367
 368        drm_display_mode_to_videomode(mode, &vm);
 369
 370        /* Set up timing parameters */
 371        val = V_ACTIVE((interlaced ? vm.vactive / 2 : vm.vactive) - 1);
 372        val |= H_ACTIVE(vm.hactive - 1);
 373        zx_writel(vou->timing + regs->fir_active, val);
 374
 375        val = SYNC_WIDE(vm.hsync_len - 1);
 376        val |= BACK_PORCH(vm.hback_porch - 1);
 377        val |= FRONT_PORCH(vm.hfront_porch - 1);
 378        zx_writel(vou->timing + regs->fir_htiming, val);
 379
 380        val = SYNC_WIDE(vm.vsync_len - 1);
 381        val |= BACK_PORCH(vm.vback_porch - 1);
 382        val |= FRONT_PORCH(vm.vfront_porch - 1);
 383        zx_writel(vou->timing + regs->fir_vtiming, val);
 384
 385        if (interlaced) {
 386                u32 shift = bits->sec_vactive_shift;
 387                u32 mask = bits->sec_vactive_mask;
 388
 389                val = zx_readl(vou->timing + SEC_V_ACTIVE);
 390                val &= ~mask;
 391                val |= ((vm.vactive / 2 - 1) << shift) & mask;
 392                zx_writel(vou->timing + SEC_V_ACTIVE, val);
 393
 394                val = SYNC_WIDE(vm.vsync_len - 1);
 395                /*
 396                 * The vback_porch for the second field needs to shift one on
 397                 * the value for the first field.
 398                 */
 399                val |= BACK_PORCH(vm.vback_porch);
 400                val |= FRONT_PORCH(vm.vfront_porch - 1);
 401                zx_writel(vou->timing + regs->sec_vtiming, val);
 402        }
 403
 404        /* Set up polarities */
 405        if (vm.flags & DISPLAY_FLAGS_VSYNC_LOW)
 406                pol |= 1 << POL_VSYNC_SHIFT;
 407        if (vm.flags & DISPLAY_FLAGS_HSYNC_LOW)
 408                pol |= 1 << POL_HSYNC_SHIFT;
 409
 410        zx_writel_mask(vou->timing + TIMING_CTRL, bits->polarity_mask,
 411                       pol << bits->polarity_shift);
 412
 413        /* Setup SHIFT register by following what ZTE BSP does */
 414        val = H_SHIFT_VAL;
 415        if (interlaced)
 416                val |= V_SHIFT_VAL << 16;
 417        zx_writel(vou->timing + regs->timing_shift, val);
 418        zx_writel(vou->timing + regs->timing_pi_shift, H_PI_SHIFT_VAL);
 419
 420        /* Progressive or interlace scan select */
 421        scan_mask = bits->interlace_select | bits->pi_enable;
 422        zx_writel_mask(vou->timing + SCAN_CTRL, scan_mask,
 423                       interlaced ? scan_mask : 0);
 424
 425        /* Enable TIMING_CTRL */
 426        zx_writel_mask(vou->timing + TIMING_TC_ENABLE, bits->tc_enable,
 427                       bits->tc_enable);
 428
 429        /* Configure channel screen size */
 430        zx_writel_mask(zcrtc->chnreg + CHN_CTRL1, CHN_SCREEN_W_MASK,
 431                       vm.hactive << CHN_SCREEN_W_SHIFT);
 432        zx_writel_mask(zcrtc->chnreg + CHN_CTRL1, CHN_SCREEN_H_MASK,
 433                       vm.vactive << CHN_SCREEN_H_SHIFT);
 434
 435        /* Configure channel interlace buffer control */
 436        zx_writel_mask(zcrtc->chnreg + CHN_INTERLACE_BUF_CTRL, CHN_INTERLACE_EN,
 437                       interlaced ? CHN_INTERLACE_EN : 0);
 438
 439        /* Update channel */
 440        vou_chn_set_update(zcrtc);
 441
 442        /* Enable channel */
 443        zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, CHN_ENABLE);
 444
 445        drm_crtc_vblank_on(crtc);
 446
 447        ret = clk_set_rate(zcrtc->pixclk, mode->clock * 1000);
 448        if (ret) {
 449                DRM_DEV_ERROR(vou->dev, "failed to set pixclk rate: %d\n", ret);
 450                return;
 451        }
 452
 453        ret = clk_prepare_enable(zcrtc->pixclk);
 454        if (ret)
 455                DRM_DEV_ERROR(vou->dev, "failed to enable pixclk: %d\n", ret);
 456}
 457
 458static void zx_crtc_atomic_disable(struct drm_crtc *crtc,
 459                                   struct drm_crtc_state *old_state)
 460{
 461        struct zx_crtc *zcrtc = to_zx_crtc(crtc);
 462        const struct zx_crtc_bits *bits = zcrtc->bits;
 463        struct zx_vou_hw *vou = zcrtc->vou;
 464
 465        clk_disable_unprepare(zcrtc->pixclk);
 466
 467        drm_crtc_vblank_off(crtc);
 468
 469        /* Disable channel */
 470        zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, 0);
 471
 472        /* Disable TIMING_CTRL */
 473        zx_writel_mask(vou->timing + TIMING_TC_ENABLE, bits->tc_enable, 0);
 474}
 475
 476static void zx_crtc_atomic_flush(struct drm_crtc *crtc,
 477                                  struct drm_crtc_state *old_state)
 478{
 479        struct drm_pending_vblank_event *event = crtc->state->event;
 480
 481        if (!event)
 482                return;
 483
 484        crtc->state->event = NULL;
 485
 486        spin_lock_irq(&crtc->dev->event_lock);
 487        if (drm_crtc_vblank_get(crtc) == 0)
 488                drm_crtc_arm_vblank_event(crtc, event);
 489        else
 490                drm_crtc_send_vblank_event(crtc, event);
 491        spin_unlock_irq(&crtc->dev->event_lock);
 492}
 493
 494static const struct drm_crtc_helper_funcs zx_crtc_helper_funcs = {
 495        .atomic_flush = zx_crtc_atomic_flush,
 496        .atomic_enable = zx_crtc_atomic_enable,
 497        .atomic_disable = zx_crtc_atomic_disable,
 498};
 499
 500static int zx_vou_enable_vblank(struct drm_crtc *crtc)
 501{
 502        struct zx_crtc *zcrtc = to_zx_crtc(crtc);
 503        struct zx_vou_hw *vou = crtc_to_vou(crtc);
 504        u32 int_frame_mask = zcrtc->bits->int_frame_mask;
 505
 506        zx_writel_mask(vou->timing + TIMING_INT_CTRL, int_frame_mask,
 507                       int_frame_mask);
 508
 509        return 0;
 510}
 511
 512static void zx_vou_disable_vblank(struct drm_crtc *crtc)
 513{
 514        struct zx_crtc *zcrtc = to_zx_crtc(crtc);
 515        struct zx_vou_hw *vou = crtc_to_vou(crtc);
 516
 517        zx_writel_mask(vou->timing + TIMING_INT_CTRL,
 518                       zcrtc->bits->int_frame_mask, 0);
 519}
 520
 521static const struct drm_crtc_funcs zx_crtc_funcs = {
 522        .destroy = drm_crtc_cleanup,
 523        .set_config = drm_atomic_helper_set_config,
 524        .page_flip = drm_atomic_helper_page_flip,
 525        .reset = drm_atomic_helper_crtc_reset,
 526        .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
 527        .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
 528        .enable_vblank = zx_vou_enable_vblank,
 529        .disable_vblank = zx_vou_disable_vblank,
 530};
 531
 532static int zx_crtc_init(struct drm_device *drm, struct zx_vou_hw *vou,
 533                        enum vou_chn_type chn_type)
 534{
 535        struct device *dev = vou->dev;
 536        struct zx_plane *zplane;
 537        struct zx_crtc *zcrtc;
 538        int ret;
 539
 540        zcrtc = devm_kzalloc(dev, sizeof(*zcrtc), GFP_KERNEL);
 541        if (!zcrtc)
 542                return -ENOMEM;
 543
 544        zcrtc->vou = vou;
 545        zcrtc->chn_type = chn_type;
 546
 547        zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL);
 548        if (!zplane)
 549                return -ENOMEM;
 550
 551        zplane->dev = dev;
 552
 553        if (chn_type == VOU_CHN_MAIN) {
 554                zplane->layer = vou->osd + MAIN_GL_OFFSET;
 555                zplane->csc = vou->osd + MAIN_GL_CSC_OFFSET;
 556                zplane->hbsc = vou->osd + MAIN_HBSC_OFFSET;
 557                zplane->rsz = vou->otfppu + MAIN_RSZ_OFFSET;
 558                zplane->bits = &zx_gl_bits[0];
 559                zcrtc->chnreg = vou->osd + OSD_MAIN_CHN;
 560                zcrtc->chncsc = vou->osd + MAIN_CHN_CSC_OFFSET;
 561                zcrtc->dither = vou->osd + MAIN_DITHER_OFFSET;
 562                zcrtc->regs = &main_crtc_regs;
 563                zcrtc->bits = &main_crtc_bits;
 564        } else {
 565                zplane->layer = vou->osd + AUX_GL_OFFSET;
 566                zplane->csc = vou->osd + AUX_GL_CSC_OFFSET;
 567                zplane->hbsc = vou->osd + AUX_HBSC_OFFSET;
 568                zplane->rsz = vou->otfppu + AUX_RSZ_OFFSET;
 569                zplane->bits = &zx_gl_bits[1];
 570                zcrtc->chnreg = vou->osd + OSD_AUX_CHN;
 571                zcrtc->chncsc = vou->osd + AUX_CHN_CSC_OFFSET;
 572                zcrtc->dither = vou->osd + AUX_DITHER_OFFSET;
 573                zcrtc->regs = &aux_crtc_regs;
 574                zcrtc->bits = &aux_crtc_bits;
 575        }
 576
 577        zcrtc->pixclk = devm_clk_get(dev, (chn_type == VOU_CHN_MAIN) ?
 578                                          "main_wclk" : "aux_wclk");
 579        if (IS_ERR(zcrtc->pixclk)) {
 580                ret = PTR_ERR(zcrtc->pixclk);
 581                DRM_DEV_ERROR(dev, "failed to get pix clk: %d\n", ret);
 582                return ret;
 583        }
 584
 585        ret = zx_plane_init(drm, zplane, DRM_PLANE_TYPE_PRIMARY);
 586        if (ret) {
 587                DRM_DEV_ERROR(dev, "failed to init primary plane: %d\n", ret);
 588                return ret;
 589        }
 590
 591        zcrtc->primary = &zplane->plane;
 592
 593        ret = drm_crtc_init_with_planes(drm, &zcrtc->crtc, zcrtc->primary, NULL,
 594                                        &zx_crtc_funcs, NULL);
 595        if (ret) {
 596                DRM_DEV_ERROR(dev, "failed to init drm crtc: %d\n", ret);
 597                return ret;
 598        }
 599
 600        drm_crtc_helper_add(&zcrtc->crtc, &zx_crtc_helper_funcs);
 601
 602        if (chn_type == VOU_CHN_MAIN)
 603                vou->main_crtc = zcrtc;
 604        else
 605                vou->aux_crtc = zcrtc;
 606
 607        return 0;
 608}
 609
 610void zx_vou_layer_enable(struct drm_plane *plane)
 611{
 612        struct zx_crtc *zcrtc = to_zx_crtc(plane->state->crtc);
 613        struct zx_vou_hw *vou = zcrtc->vou;
 614        struct zx_plane *zplane = to_zx_plane(plane);
 615        const struct vou_layer_bits *bits = zplane->bits;
 616
 617        if (zcrtc->chn_type == VOU_CHN_MAIN) {
 618                zx_writel_mask(vou->osd + OSD_CTRL0, bits->chnsel, 0);
 619                zx_writel_mask(vou->vouctl + VOU_CLK_SEL, bits->clksel, 0);
 620        } else {
 621                zx_writel_mask(vou->osd + OSD_CTRL0, bits->chnsel,
 622                               bits->chnsel);
 623                zx_writel_mask(vou->vouctl + VOU_CLK_SEL, bits->clksel,
 624                               bits->clksel);
 625        }
 626
 627        zx_writel_mask(vou->osd + OSD_CTRL0, bits->enable, bits->enable);
 628}
 629
 630void zx_vou_layer_disable(struct drm_plane *plane)
 631{
 632        struct zx_crtc *zcrtc = to_zx_crtc(plane->crtc);
 633        struct zx_vou_hw *vou = zcrtc->vou;
 634        struct zx_plane *zplane = to_zx_plane(plane);
 635        const struct vou_layer_bits *bits = zplane->bits;
 636
 637        zx_writel_mask(vou->osd + OSD_CTRL0, bits->enable, 0);
 638}
 639
 640static void zx_overlay_init(struct drm_device *drm, struct zx_vou_hw *vou)
 641{
 642        struct device *dev = vou->dev;
 643        struct zx_plane *zplane;
 644        int i;
 645        int ret;
 646
 647        /*
 648         * VL0 has some quirks on scaling support which need special handling.
 649         * Let's leave it out for now.
 650         */
 651        for (i = 1; i < VL_NUM; i++) {
 652                zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL);
 653                if (!zplane) {
 654                        DRM_DEV_ERROR(dev, "failed to allocate zplane %d\n", i);
 655                        return;
 656                }
 657
 658                zplane->layer = vou->osd + OSD_VL_OFFSET(i);
 659                zplane->hbsc = vou->osd + HBSC_VL_OFFSET(i);
 660                zplane->rsz = vou->otfppu + RSZ_VL_OFFSET(i);
 661                zplane->bits = &zx_vl_bits[i];
 662
 663                ret = zx_plane_init(drm, zplane, DRM_PLANE_TYPE_OVERLAY);
 664                if (ret) {
 665                        DRM_DEV_ERROR(dev, "failed to init overlay %d\n", i);
 666                        continue;
 667                }
 668        }
 669}
 670
 671static inline void zx_osd_int_update(struct zx_crtc *zcrtc)
 672{
 673        struct drm_crtc *crtc = &zcrtc->crtc;
 674        struct drm_plane *plane;
 675
 676        vou_chn_set_update(zcrtc);
 677
 678        drm_for_each_plane_mask(plane, crtc->dev, crtc->state->plane_mask)
 679                zx_plane_set_update(plane);
 680}
 681
 682static irqreturn_t vou_irq_handler(int irq, void *dev_id)
 683{
 684        struct zx_vou_hw *vou = dev_id;
 685        u32 state;
 686
 687        /* Handle TIMING_CTRL frame interrupts */
 688        state = zx_readl(vou->timing + TIMING_INT_STATE);
 689        zx_writel(vou->timing + TIMING_INT_STATE, state);
 690
 691        if (state & TIMING_INT_MAIN_FRAME)
 692                drm_crtc_handle_vblank(&vou->main_crtc->crtc);
 693
 694        if (state & TIMING_INT_AUX_FRAME)
 695                drm_crtc_handle_vblank(&vou->aux_crtc->crtc);
 696
 697        /* Handle OSD interrupts */
 698        state = zx_readl(vou->osd + OSD_INT_STA);
 699        zx_writel(vou->osd + OSD_INT_CLRSTA, state);
 700
 701        if (state & OSD_INT_MAIN_UPT)
 702                zx_osd_int_update(vou->main_crtc);
 703
 704        if (state & OSD_INT_AUX_UPT)
 705                zx_osd_int_update(vou->aux_crtc);
 706
 707        if (state & OSD_INT_ERROR)
 708                DRM_DEV_ERROR(vou->dev, "OSD ERROR: 0x%08x!\n", state);
 709
 710        return IRQ_HANDLED;
 711}
 712
 713static void vou_dtrc_init(struct zx_vou_hw *vou)
 714{
 715        /* Clear bit for bypass by ID */
 716        zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL,
 717                       TILE2RASTESCAN_BYPASS_MODE, 0);
 718
 719        /* Select ARIDR mode */
 720        zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL, DETILE_ARIDR_MODE_MASK,
 721                       DETILE_ARID_IN_ARIDR);
 722
 723        /* Bypass decompression for both frames */
 724        zx_writel_mask(vou->dtrc + DTRC_F0_CTRL, DTRC_DECOMPRESS_BYPASS,
 725                       DTRC_DECOMPRESS_BYPASS);
 726        zx_writel_mask(vou->dtrc + DTRC_F1_CTRL, DTRC_DECOMPRESS_BYPASS,
 727                       DTRC_DECOMPRESS_BYPASS);
 728
 729        /* Set up ARID register */
 730        zx_writel(vou->dtrc + DTRC_ARID, DTRC_ARID3(0xf) | DTRC_ARID2(0xe) |
 731                  DTRC_ARID1(0xf) | DTRC_ARID0(0xe));
 732}
 733
 734static void vou_hw_init(struct zx_vou_hw *vou)
 735{
 736        /* Release reset for all VOU modules */
 737        zx_writel(vou->vouctl + VOU_SOFT_RST, ~0);
 738
 739        /* Enable all VOU module clocks */
 740        zx_writel(vou->vouctl + VOU_CLK_EN, ~0);
 741
 742        /* Clear both OSD and TIMING_CTRL interrupt state */
 743        zx_writel(vou->osd + OSD_INT_CLRSTA, ~0);
 744        zx_writel(vou->timing + TIMING_INT_STATE, ~0);
 745
 746        /* Enable OSD and TIMING_CTRL interrrupts */
 747        zx_writel(vou->osd + OSD_INT_MSK, OSD_INT_ENABLE);
 748        zx_writel(vou->timing + TIMING_INT_CTRL, TIMING_INT_ENABLE);
 749
 750        /* Select GPC as input to gl/vl scaler as a sane default setting */
 751        zx_writel(vou->otfppu + OTFPPU_RSZ_DATA_SOURCE, 0x2a);
 752
 753        /*
 754         * Needs to reset channel and layer logic per frame when frame starts
 755         * to get VOU work properly.
 756         */
 757        zx_writel_mask(vou->osd + OSD_RST_CLR, RST_PER_FRAME, RST_PER_FRAME);
 758
 759        vou_dtrc_init(vou);
 760}
 761
 762static int zx_crtc_bind(struct device *dev, struct device *master, void *data)
 763{
 764        struct platform_device *pdev = to_platform_device(dev);
 765        struct drm_device *drm = data;
 766        struct zx_vou_hw *vou;
 767        struct resource *res;
 768        int irq;
 769        int ret;
 770
 771        vou = devm_kzalloc(dev, sizeof(*vou), GFP_KERNEL);
 772        if (!vou)
 773                return -ENOMEM;
 774
 775        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "osd");
 776        vou->osd = devm_ioremap_resource(dev, res);
 777        if (IS_ERR(vou->osd)) {
 778                ret = PTR_ERR(vou->osd);
 779                DRM_DEV_ERROR(dev, "failed to remap osd region: %d\n", ret);
 780                return ret;
 781        }
 782
 783        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "timing_ctrl");
 784        vou->timing = devm_ioremap_resource(dev, res);
 785        if (IS_ERR(vou->timing)) {
 786                ret = PTR_ERR(vou->timing);
 787                DRM_DEV_ERROR(dev, "failed to remap timing_ctrl region: %d\n",
 788                              ret);
 789                return ret;
 790        }
 791
 792        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dtrc");
 793        vou->dtrc = devm_ioremap_resource(dev, res);
 794        if (IS_ERR(vou->dtrc)) {
 795                ret = PTR_ERR(vou->dtrc);
 796                DRM_DEV_ERROR(dev, "failed to remap dtrc region: %d\n", ret);
 797                return ret;
 798        }
 799
 800        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vou_ctrl");
 801        vou->vouctl = devm_ioremap_resource(dev, res);
 802        if (IS_ERR(vou->vouctl)) {
 803                ret = PTR_ERR(vou->vouctl);
 804                DRM_DEV_ERROR(dev, "failed to remap vou_ctrl region: %d\n",
 805                              ret);
 806                return ret;
 807        }
 808
 809        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "otfppu");
 810        vou->otfppu = devm_ioremap_resource(dev, res);
 811        if (IS_ERR(vou->otfppu)) {
 812                ret = PTR_ERR(vou->otfppu);
 813                DRM_DEV_ERROR(dev, "failed to remap otfppu region: %d\n", ret);
 814                return ret;
 815        }
 816
 817        irq = platform_get_irq(pdev, 0);
 818        if (irq < 0)
 819                return irq;
 820
 821        vou->axi_clk = devm_clk_get(dev, "aclk");
 822        if (IS_ERR(vou->axi_clk)) {
 823                ret = PTR_ERR(vou->axi_clk);
 824                DRM_DEV_ERROR(dev, "failed to get axi_clk: %d\n", ret);
 825                return ret;
 826        }
 827
 828        vou->ppu_clk = devm_clk_get(dev, "ppu_wclk");
 829        if (IS_ERR(vou->ppu_clk)) {
 830                ret = PTR_ERR(vou->ppu_clk);
 831                DRM_DEV_ERROR(dev, "failed to get ppu_clk: %d\n", ret);
 832                return ret;
 833        }
 834
 835        ret = clk_prepare_enable(vou->axi_clk);
 836        if (ret) {
 837                DRM_DEV_ERROR(dev, "failed to enable axi_clk: %d\n", ret);
 838                return ret;
 839        }
 840
 841        clk_prepare_enable(vou->ppu_clk);
 842        if (ret) {
 843                DRM_DEV_ERROR(dev, "failed to enable ppu_clk: %d\n", ret);
 844                goto disable_axi_clk;
 845        }
 846
 847        vou->dev = dev;
 848        dev_set_drvdata(dev, vou);
 849
 850        vou_hw_init(vou);
 851
 852        ret = devm_request_irq(dev, irq, vou_irq_handler, 0, "zx_vou", vou);
 853        if (ret < 0) {
 854                DRM_DEV_ERROR(dev, "failed to request vou irq: %d\n", ret);
 855                goto disable_ppu_clk;
 856        }
 857
 858        ret = zx_crtc_init(drm, vou, VOU_CHN_MAIN);
 859        if (ret) {
 860                DRM_DEV_ERROR(dev, "failed to init main channel crtc: %d\n",
 861                              ret);
 862                goto disable_ppu_clk;
 863        }
 864
 865        ret = zx_crtc_init(drm, vou, VOU_CHN_AUX);
 866        if (ret) {
 867                DRM_DEV_ERROR(dev, "failed to init aux channel crtc: %d\n",
 868                              ret);
 869                goto disable_ppu_clk;
 870        }
 871
 872        zx_overlay_init(drm, vou);
 873
 874        return 0;
 875
 876disable_ppu_clk:
 877        clk_disable_unprepare(vou->ppu_clk);
 878disable_axi_clk:
 879        clk_disable_unprepare(vou->axi_clk);
 880        return ret;
 881}
 882
 883static void zx_crtc_unbind(struct device *dev, struct device *master,
 884                           void *data)
 885{
 886        struct zx_vou_hw *vou = dev_get_drvdata(dev);
 887
 888        clk_disable_unprepare(vou->axi_clk);
 889        clk_disable_unprepare(vou->ppu_clk);
 890}
 891
 892static const struct component_ops zx_crtc_component_ops = {
 893        .bind = zx_crtc_bind,
 894        .unbind = zx_crtc_unbind,
 895};
 896
 897static int zx_crtc_probe(struct platform_device *pdev)
 898{
 899        return component_add(&pdev->dev, &zx_crtc_component_ops);
 900}
 901
 902static int zx_crtc_remove(struct platform_device *pdev)
 903{
 904        component_del(&pdev->dev, &zx_crtc_component_ops);
 905        return 0;
 906}
 907
 908static const struct of_device_id zx_crtc_of_match[] = {
 909        { .compatible = "zte,zx296718-dpc", },
 910        { /* end */ },
 911};
 912MODULE_DEVICE_TABLE(of, zx_crtc_of_match);
 913
 914struct platform_driver zx_crtc_driver = {
 915        .probe = zx_crtc_probe,
 916        .remove = zx_crtc_remove,
 917        .driver = {
 918                .name = "zx-crtc",
 919                .of_match_table = zx_crtc_of_match,
 920        },
 921};
 922