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