root/drivers/gpu/drm/zte/zx_vou.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. crtc_to_vou
  2. vou_inf_hdmi_audio_sel
  3. vou_inf_enable
  4. vou_inf_disable
  5. zx_vou_config_dividers
  6. vou_chn_set_update
  7. zx_crtc_atomic_enable
  8. zx_crtc_atomic_disable
  9. zx_crtc_atomic_flush
  10. zx_vou_enable_vblank
  11. zx_vou_disable_vblank
  12. zx_crtc_init
  13. zx_vou_layer_enable
  14. zx_vou_layer_disable
  15. zx_overlay_init
  16. zx_osd_int_update
  17. vou_irq_handler
  18. vou_dtrc_init
  19. vou_hw_init
  20. zx_crtc_bind
  21. zx_crtc_unbind
  22. zx_crtc_probe
  23. zx_crtc_remove

   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/module.h>
  10 #include <linux/of_address.h>
  11 #include <linux/platform_device.h>
  12 
  13 #include <video/videomode.h>
  14 
  15 #include <drm/drm_atomic_helper.h>
  16 #include <drm/drm_crtc.h>
  17 #include <drm/drm_fb_cma_helper.h>
  18 #include <drm/drm_fb_helper.h>
  19 #include <drm/drm_gem_cma_helper.h>
  20 #include <drm/drm_of.h>
  21 #include <drm/drm_plane_helper.h>
  22 #include <drm/drm_probe_helper.h>
  23 #include <drm/drm_vblank.h>
  24 
  25 #include "zx_common_regs.h"
  26 #include "zx_drm_drv.h"
  27 #include "zx_plane.h"
  28 #include "zx_vou.h"
  29 #include "zx_vou_regs.h"
  30 
  31 #define GL_NUM  2
  32 #define VL_NUM  3
  33 
  34 enum vou_chn_type {
  35         VOU_CHN_MAIN,
  36         VOU_CHN_AUX,
  37 };
  38 
  39 struct zx_crtc_regs {
  40         u32 fir_active;
  41         u32 fir_htiming;
  42         u32 fir_vtiming;
  43         u32 sec_vtiming;
  44         u32 timing_shift;
  45         u32 timing_pi_shift;
  46 };
  47 
  48 static const struct zx_crtc_regs main_crtc_regs = {
  49         .fir_active = FIR_MAIN_ACTIVE,
  50         .fir_htiming = FIR_MAIN_H_TIMING,
  51         .fir_vtiming = FIR_MAIN_V_TIMING,
  52         .sec_vtiming = SEC_MAIN_V_TIMING,
  53         .timing_shift = TIMING_MAIN_SHIFT,
  54         .timing_pi_shift = TIMING_MAIN_PI_SHIFT,
  55 };
  56 
  57 static const struct zx_crtc_regs aux_crtc_regs = {
  58         .fir_active = FIR_AUX_ACTIVE,
  59         .fir_htiming = FIR_AUX_H_TIMING,
  60         .fir_vtiming = FIR_AUX_V_TIMING,
  61         .sec_vtiming = SEC_AUX_V_TIMING,
  62         .timing_shift = TIMING_AUX_SHIFT,
  63         .timing_pi_shift = TIMING_AUX_PI_SHIFT,
  64 };
  65 
  66 struct zx_crtc_bits {
  67         u32 polarity_mask;
  68         u32 polarity_shift;
  69         u32 int_frame_mask;
  70         u32 tc_enable;
  71         u32 sec_vactive_shift;
  72         u32 sec_vactive_mask;
  73         u32 interlace_select;
  74         u32 pi_enable;
  75         u32 div_vga_shift;
  76         u32 div_pic_shift;
  77         u32 div_tvenc_shift;
  78         u32 div_hdmi_pnx_shift;
  79         u32 div_hdmi_shift;
  80         u32 div_inf_shift;
  81         u32 div_layer_shift;
  82 };
  83 
  84 static const struct zx_crtc_bits main_crtc_bits = {
  85         .polarity_mask = MAIN_POL_MASK,
  86         .polarity_shift = MAIN_POL_SHIFT,
  87         .int_frame_mask = TIMING_INT_MAIN_FRAME,
  88         .tc_enable = MAIN_TC_EN,
  89         .sec_vactive_shift = SEC_VACT_MAIN_SHIFT,
  90         .sec_vactive_mask = SEC_VACT_MAIN_MASK,
  91         .interlace_select = MAIN_INTERLACE_SEL,
  92         .pi_enable = MAIN_PI_EN,
  93         .div_vga_shift = VGA_MAIN_DIV_SHIFT,
  94         .div_pic_shift = PIC_MAIN_DIV_SHIFT,
  95         .div_tvenc_shift = TVENC_MAIN_DIV_SHIFT,
  96         .div_hdmi_pnx_shift = HDMI_MAIN_PNX_DIV_SHIFT,
  97         .div_hdmi_shift = HDMI_MAIN_DIV_SHIFT,
  98         .div_inf_shift = INF_MAIN_DIV_SHIFT,
  99         .div_layer_shift = LAYER_MAIN_DIV_SHIFT,
 100 };
 101 
 102 static const struct zx_crtc_bits aux_crtc_bits = {
 103         .polarity_mask = AUX_POL_MASK,
 104         .polarity_shift = AUX_POL_SHIFT,
 105         .int_frame_mask = TIMING_INT_AUX_FRAME,
 106         .tc_enable = AUX_TC_EN,
 107         .sec_vactive_shift = SEC_VACT_AUX_SHIFT,
 108         .sec_vactive_mask = SEC_VACT_AUX_MASK,
 109         .interlace_select = AUX_INTERLACE_SEL,
 110         .pi_enable = AUX_PI_EN,
 111         .div_vga_shift = VGA_AUX_DIV_SHIFT,
 112         .div_pic_shift = PIC_AUX_DIV_SHIFT,
 113         .div_tvenc_shift = TVENC_AUX_DIV_SHIFT,
 114         .div_hdmi_pnx_shift = HDMI_AUX_PNX_DIV_SHIFT,
 115         .div_hdmi_shift = HDMI_AUX_DIV_SHIFT,
 116         .div_inf_shift = INF_AUX_DIV_SHIFT,
 117         .div_layer_shift = LAYER_AUX_DIV_SHIFT,
 118 };
 119 
 120 struct zx_crtc {
 121         struct drm_crtc crtc;
 122         struct drm_plane *primary;
 123         struct zx_vou_hw *vou;
 124         void __iomem *chnreg;
 125         void __iomem *chncsc;
 126         void __iomem *dither;
 127         const struct zx_crtc_regs *regs;
 128         const struct zx_crtc_bits *bits;
 129         enum vou_chn_type chn_type;
 130         struct clk *pixclk;
 131 };
 132 
 133 #define to_zx_crtc(x) container_of(x, struct zx_crtc, crtc)
 134 
 135 struct vou_layer_bits {
 136         u32 enable;
 137         u32 chnsel;
 138         u32 clksel;
 139 };
 140 
 141 static const struct vou_layer_bits zx_gl_bits[GL_NUM] = {
 142         {
 143                 .enable = OSD_CTRL0_GL0_EN,
 144                 .chnsel = OSD_CTRL0_GL0_SEL,
 145                 .clksel = VOU_CLK_GL0_SEL,
 146         }, {
 147                 .enable = OSD_CTRL0_GL1_EN,
 148                 .chnsel = OSD_CTRL0_GL1_SEL,
 149                 .clksel = VOU_CLK_GL1_SEL,
 150         },
 151 };
 152 
 153 static const struct vou_layer_bits zx_vl_bits[VL_NUM] = {
 154         {
 155                 .enable = OSD_CTRL0_VL0_EN,
 156                 .chnsel = OSD_CTRL0_VL0_SEL,
 157                 .clksel = VOU_CLK_VL0_SEL,
 158         }, {
 159                 .enable = OSD_CTRL0_VL1_EN,
 160                 .chnsel = OSD_CTRL0_VL1_SEL,
 161                 .clksel = VOU_CLK_VL1_SEL,
 162         }, {
 163                 .enable = OSD_CTRL0_VL2_EN,
 164                 .chnsel = OSD_CTRL0_VL2_SEL,
 165                 .clksel = VOU_CLK_VL2_SEL,
 166         },
 167 };
 168 
 169 struct zx_vou_hw {
 170         struct device *dev;
 171         void __iomem *osd;
 172         void __iomem *timing;
 173         void __iomem *vouctl;
 174         void __iomem *otfppu;
 175         void __iomem *dtrc;
 176         struct clk *axi_clk;
 177         struct clk *ppu_clk;
 178         struct clk *main_clk;
 179         struct clk *aux_clk;
 180         struct zx_crtc *main_crtc;
 181         struct zx_crtc *aux_crtc;
 182 };
 183 
 184 enum vou_inf_data_sel {
 185         VOU_YUV444      = 0,
 186         VOU_RGB_101010  = 1,
 187         VOU_RGB_888     = 2,
 188         VOU_RGB_666     = 3,
 189 };
 190 
 191 struct vou_inf {
 192         enum vou_inf_id id;
 193         enum vou_inf_data_sel data_sel;
 194         u32 clocks_en_bits;
 195         u32 clocks_sel_bits;
 196 };
 197 
 198 static struct vou_inf vou_infs[] = {
 199         [VOU_HDMI] = {
 200                 .data_sel = VOU_YUV444,
 201                 .clocks_en_bits = BIT(24) | BIT(18) | BIT(6),
 202                 .clocks_sel_bits = BIT(13) | BIT(2),
 203         },
 204         [VOU_TV_ENC] = {
 205                 .data_sel = VOU_YUV444,
 206                 .clocks_en_bits = BIT(15),
 207                 .clocks_sel_bits = BIT(11) | BIT(0),
 208         },
 209         [VOU_VGA] = {
 210                 .data_sel = VOU_RGB_888,
 211                 .clocks_en_bits = BIT(1),
 212                 .clocks_sel_bits = BIT(10),
 213         },
 214 };
 215 
 216 static inline struct zx_vou_hw *crtc_to_vou(struct drm_crtc *crtc)
 217 {
 218         struct zx_crtc *zcrtc = to_zx_crtc(crtc);
 219 
 220         return zcrtc->vou;
 221 }
 222 
 223 void vou_inf_hdmi_audio_sel(struct drm_crtc *crtc,
 224                             enum vou_inf_hdmi_audio aud)
 225 {
 226         struct zx_crtc *zcrtc = to_zx_crtc(crtc);
 227         struct zx_vou_hw *vou = zcrtc->vou;
 228 
 229         zx_writel_mask(vou->vouctl + VOU_INF_HDMI_CTRL, VOU_HDMI_AUD_MASK, aud);
 230 }
 231 
 232 void vou_inf_enable(enum vou_inf_id id, struct drm_crtc *crtc)
 233 {
 234         struct zx_crtc *zcrtc = to_zx_crtc(crtc);
 235         struct zx_vou_hw *vou = zcrtc->vou;
 236         struct vou_inf *inf = &vou_infs[id];
 237         void __iomem *dither = zcrtc->dither;
 238         void __iomem *csc = zcrtc->chncsc;
 239         bool is_main = zcrtc->chn_type == VOU_CHN_MAIN;
 240         u32 data_sel_shift = id << 1;
 241 
 242         if (inf->data_sel != VOU_YUV444) {
 243                 /* Enable channel CSC for RGB output */
 244                 zx_writel_mask(csc + CSC_CTRL0, CSC_COV_MODE_MASK,
 245                                CSC_BT709_IMAGE_YCBCR2RGB << CSC_COV_MODE_SHIFT);
 246                 zx_writel_mask(csc + CSC_CTRL0, CSC_WORK_ENABLE,
 247                                CSC_WORK_ENABLE);
 248 
 249                 /* Bypass Dither block for RGB output */
 250                 zx_writel_mask(dither + OSD_DITHER_CTRL0, DITHER_BYSPASS,
 251                                DITHER_BYSPASS);
 252         } else {
 253                 zx_writel_mask(csc + CSC_CTRL0, CSC_WORK_ENABLE, 0);
 254                 zx_writel_mask(dither + OSD_DITHER_CTRL0, DITHER_BYSPASS, 0);
 255         }
 256 
 257         /* Select data format */
 258         zx_writel_mask(vou->vouctl + VOU_INF_DATA_SEL, 0x3 << data_sel_shift,
 259                        inf->data_sel << data_sel_shift);
 260 
 261         /* Select channel */
 262         zx_writel_mask(vou->vouctl + VOU_INF_CH_SEL, 0x1 << id,
 263                        zcrtc->chn_type << id);
 264 
 265         /* Select interface clocks */
 266         zx_writel_mask(vou->vouctl + VOU_CLK_SEL, inf->clocks_sel_bits,
 267                        is_main ? 0 : inf->clocks_sel_bits);
 268 
 269         /* Enable interface clocks */
 270         zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits,
 271                        inf->clocks_en_bits);
 272 
 273         /* Enable the device */
 274         zx_writel_mask(vou->vouctl + VOU_INF_EN, 1 << id, 1 << id);
 275 }
 276 
 277 void vou_inf_disable(enum vou_inf_id id, struct drm_crtc *crtc)
 278 {
 279         struct zx_vou_hw *vou = crtc_to_vou(crtc);
 280         struct vou_inf *inf = &vou_infs[id];
 281 
 282         /* Disable the device */
 283         zx_writel_mask(vou->vouctl + VOU_INF_EN, 1 << id, 0);
 284 
 285         /* Disable interface clocks */
 286         zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits, 0);
 287 }
 288 
 289 void zx_vou_config_dividers(struct drm_crtc *crtc,
 290                             struct vou_div_config *configs, int num)
 291 {
 292         struct zx_crtc *zcrtc = to_zx_crtc(crtc);
 293         struct zx_vou_hw *vou = zcrtc->vou;
 294         const struct zx_crtc_bits *bits = zcrtc->bits;
 295         int i;
 296 
 297         /* Clear update flag bit */
 298         zx_writel_mask(vou->vouctl + VOU_DIV_PARA, DIV_PARA_UPDATE, 0);
 299 
 300         for (i = 0; i < num; i++) {
 301                 struct vou_div_config *cfg = configs + i;
 302                 u32 reg, shift;
 303 
 304                 switch (cfg->id) {
 305                 case VOU_DIV_VGA:
 306                         reg = VOU_CLK_SEL;
 307                         shift = bits->div_vga_shift;
 308                         break;
 309                 case VOU_DIV_PIC:
 310                         reg = VOU_CLK_SEL;
 311                         shift = bits->div_pic_shift;
 312                         break;
 313                 case VOU_DIV_TVENC:
 314                         reg = VOU_DIV_PARA;
 315                         shift = bits->div_tvenc_shift;
 316                         break;
 317                 case VOU_DIV_HDMI_PNX:
 318                         reg = VOU_DIV_PARA;
 319                         shift = bits->div_hdmi_pnx_shift;
 320                         break;
 321                 case VOU_DIV_HDMI:
 322                         reg = VOU_DIV_PARA;
 323                         shift = bits->div_hdmi_shift;
 324                         break;
 325                 case VOU_DIV_INF:
 326                         reg = VOU_DIV_PARA;
 327                         shift = bits->div_inf_shift;
 328                         break;
 329                 case VOU_DIV_LAYER:
 330                         reg = VOU_DIV_PARA;
 331                         shift = bits->div_layer_shift;
 332                         break;
 333                 default:
 334                         continue;
 335                 }
 336 
 337                 /* Each divider occupies 3 bits */
 338                 zx_writel_mask(vou->vouctl + reg, 0x7 << shift,
 339                                cfg->val << shift);
 340         }
 341 
 342         /* Set update flag bit to get dividers effected */
 343         zx_writel_mask(vou->vouctl + VOU_DIV_PARA, DIV_PARA_UPDATE,
 344                        DIV_PARA_UPDATE);
 345 }
 346 
 347 static inline void vou_chn_set_update(struct zx_crtc *zcrtc)
 348 {
 349         zx_writel(zcrtc->chnreg + CHN_UPDATE, 1);
 350 }
 351 
 352 static void zx_crtc_atomic_enable(struct drm_crtc *crtc,
 353                                   struct drm_crtc_state *old_state)
 354 {
 355         struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 356         bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
 357         struct zx_crtc *zcrtc = to_zx_crtc(crtc);
 358         struct zx_vou_hw *vou = zcrtc->vou;
 359         const struct zx_crtc_regs *regs = zcrtc->regs;
 360         const struct zx_crtc_bits *bits = zcrtc->bits;
 361         struct videomode vm;
 362         u32 scan_mask;
 363         u32 pol = 0;
 364         u32 val;
 365         int ret;
 366 
 367         drm_display_mode_to_videomode(mode, &vm);
 368 
 369         /* Set up timing parameters */
 370         val = V_ACTIVE((interlaced ? vm.vactive / 2 : vm.vactive) - 1);
 371         val |= H_ACTIVE(vm.hactive - 1);
 372         zx_writel(vou->timing + regs->fir_active, val);
 373 
 374         val = SYNC_WIDE(vm.hsync_len - 1);
 375         val |= BACK_PORCH(vm.hback_porch - 1);
 376         val |= FRONT_PORCH(vm.hfront_porch - 1);
 377         zx_writel(vou->timing + regs->fir_htiming, val);
 378 
 379         val = SYNC_WIDE(vm.vsync_len - 1);
 380         val |= BACK_PORCH(vm.vback_porch - 1);
 381         val |= FRONT_PORCH(vm.vfront_porch - 1);
 382         zx_writel(vou->timing + regs->fir_vtiming, val);
 383 
 384         if (interlaced) {
 385                 u32 shift = bits->sec_vactive_shift;
 386                 u32 mask = bits->sec_vactive_mask;
 387 
 388                 val = zx_readl(vou->timing + SEC_V_ACTIVE);
 389                 val &= ~mask;
 390                 val |= ((vm.vactive / 2 - 1) << shift) & mask;
 391                 zx_writel(vou->timing + SEC_V_ACTIVE, val);
 392 
 393                 val = SYNC_WIDE(vm.vsync_len - 1);
 394                 /*
 395                  * The vback_porch for the second field needs to shift one on
 396                  * the value for the first field.
 397                  */
 398                 val |= BACK_PORCH(vm.vback_porch);
 399                 val |= FRONT_PORCH(vm.vfront_porch - 1);
 400                 zx_writel(vou->timing + regs->sec_vtiming, val);
 401         }
 402 
 403         /* Set up polarities */
 404         if (vm.flags & DISPLAY_FLAGS_VSYNC_LOW)
 405                 pol |= 1 << POL_VSYNC_SHIFT;
 406         if (vm.flags & DISPLAY_FLAGS_HSYNC_LOW)
 407                 pol |= 1 << POL_HSYNC_SHIFT;
 408 
 409         zx_writel_mask(vou->timing + TIMING_CTRL, bits->polarity_mask,
 410                        pol << bits->polarity_shift);
 411 
 412         /* Setup SHIFT register by following what ZTE BSP does */
 413         val = H_SHIFT_VAL;
 414         if (interlaced)
 415                 val |= V_SHIFT_VAL << 16;
 416         zx_writel(vou->timing + regs->timing_shift, val);
 417         zx_writel(vou->timing + regs->timing_pi_shift, H_PI_SHIFT_VAL);
 418 
 419         /* Progressive or interlace scan select */
 420         scan_mask = bits->interlace_select | bits->pi_enable;
 421         zx_writel_mask(vou->timing + SCAN_CTRL, scan_mask,
 422                        interlaced ? scan_mask : 0);
 423 
 424         /* Enable TIMING_CTRL */
 425         zx_writel_mask(vou->timing + TIMING_TC_ENABLE, bits->tc_enable,
 426                        bits->tc_enable);
 427 
 428         /* Configure channel screen size */
 429         zx_writel_mask(zcrtc->chnreg + CHN_CTRL1, CHN_SCREEN_W_MASK,
 430                        vm.hactive << CHN_SCREEN_W_SHIFT);
 431         zx_writel_mask(zcrtc->chnreg + CHN_CTRL1, CHN_SCREEN_H_MASK,
 432                        vm.vactive << CHN_SCREEN_H_SHIFT);
 433 
 434         /* Configure channel interlace buffer control */
 435         zx_writel_mask(zcrtc->chnreg + CHN_INTERLACE_BUF_CTRL, CHN_INTERLACE_EN,
 436                        interlaced ? CHN_INTERLACE_EN : 0);
 437 
 438         /* Update channel */
 439         vou_chn_set_update(zcrtc);
 440 
 441         /* Enable channel */
 442         zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, CHN_ENABLE);
 443 
 444         drm_crtc_vblank_on(crtc);
 445 
 446         ret = clk_set_rate(zcrtc->pixclk, mode->clock * 1000);
 447         if (ret) {
 448                 DRM_DEV_ERROR(vou->dev, "failed to set pixclk rate: %d\n", ret);
 449                 return;
 450         }
 451 
 452         ret = clk_prepare_enable(zcrtc->pixclk);
 453         if (ret)
 454                 DRM_DEV_ERROR(vou->dev, "failed to enable pixclk: %d\n", ret);
 455 }
 456 
 457 static void zx_crtc_atomic_disable(struct drm_crtc *crtc,
 458                                    struct drm_crtc_state *old_state)
 459 {
 460         struct zx_crtc *zcrtc = to_zx_crtc(crtc);
 461         const struct zx_crtc_bits *bits = zcrtc->bits;
 462         struct zx_vou_hw *vou = zcrtc->vou;
 463 
 464         clk_disable_unprepare(zcrtc->pixclk);
 465 
 466         drm_crtc_vblank_off(crtc);
 467 
 468         /* Disable channel */
 469         zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, 0);
 470 
 471         /* Disable TIMING_CTRL */
 472         zx_writel_mask(vou->timing + TIMING_TC_ENABLE, bits->tc_enable, 0);
 473 }
 474 
 475 static void zx_crtc_atomic_flush(struct drm_crtc *crtc,
 476                                   struct drm_crtc_state *old_state)
 477 {
 478         struct drm_pending_vblank_event *event = crtc->state->event;
 479 
 480         if (!event)
 481                 return;
 482 
 483         crtc->state->event = NULL;
 484 
 485         spin_lock_irq(&crtc->dev->event_lock);
 486         if (drm_crtc_vblank_get(crtc) == 0)
 487                 drm_crtc_arm_vblank_event(crtc, event);
 488         else
 489                 drm_crtc_send_vblank_event(crtc, event);
 490         spin_unlock_irq(&crtc->dev->event_lock);
 491 }
 492 
 493 static const struct drm_crtc_helper_funcs zx_crtc_helper_funcs = {
 494         .atomic_flush = zx_crtc_atomic_flush,
 495         .atomic_enable = zx_crtc_atomic_enable,
 496         .atomic_disable = zx_crtc_atomic_disable,
 497 };
 498 
 499 static int zx_vou_enable_vblank(struct drm_crtc *crtc)
 500 {
 501         struct zx_crtc *zcrtc = to_zx_crtc(crtc);
 502         struct zx_vou_hw *vou = crtc_to_vou(crtc);
 503         u32 int_frame_mask = zcrtc->bits->int_frame_mask;
 504 
 505         zx_writel_mask(vou->timing + TIMING_INT_CTRL, int_frame_mask,
 506                        int_frame_mask);
 507 
 508         return 0;
 509 }
 510 
 511 static void zx_vou_disable_vblank(struct drm_crtc *crtc)
 512 {
 513         struct zx_crtc *zcrtc = to_zx_crtc(crtc);
 514         struct zx_vou_hw *vou = crtc_to_vou(crtc);
 515 
 516         zx_writel_mask(vou->timing + TIMING_INT_CTRL,
 517                        zcrtc->bits->int_frame_mask, 0);
 518 }
 519 
 520 static const struct drm_crtc_funcs zx_crtc_funcs = {
 521         .destroy = drm_crtc_cleanup,
 522         .set_config = drm_atomic_helper_set_config,
 523         .page_flip = drm_atomic_helper_page_flip,
 524         .reset = drm_atomic_helper_crtc_reset,
 525         .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
 526         .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
 527         .enable_vblank = zx_vou_enable_vblank,
 528         .disable_vblank = zx_vou_disable_vblank,
 529 };
 530 
 531 static int zx_crtc_init(struct drm_device *drm, struct zx_vou_hw *vou,
 532                         enum vou_chn_type chn_type)
 533 {
 534         struct device *dev = vou->dev;
 535         struct zx_plane *zplane;
 536         struct zx_crtc *zcrtc;
 537         int ret;
 538 
 539         zcrtc = devm_kzalloc(dev, sizeof(*zcrtc), GFP_KERNEL);
 540         if (!zcrtc)
 541                 return -ENOMEM;
 542 
 543         zcrtc->vou = vou;
 544         zcrtc->chn_type = chn_type;
 545 
 546         zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL);
 547         if (!zplane)
 548                 return -ENOMEM;
 549 
 550         zplane->dev = dev;
 551 
 552         if (chn_type == VOU_CHN_MAIN) {
 553                 zplane->layer = vou->osd + MAIN_GL_OFFSET;
 554                 zplane->csc = vou->osd + MAIN_GL_CSC_OFFSET;
 555                 zplane->hbsc = vou->osd + MAIN_HBSC_OFFSET;
 556                 zplane->rsz = vou->otfppu + MAIN_RSZ_OFFSET;
 557                 zplane->bits = &zx_gl_bits[0];
 558                 zcrtc->chnreg = vou->osd + OSD_MAIN_CHN;
 559                 zcrtc->chncsc = vou->osd + MAIN_CHN_CSC_OFFSET;
 560                 zcrtc->dither = vou->osd + MAIN_DITHER_OFFSET;
 561                 zcrtc->regs = &main_crtc_regs;
 562                 zcrtc->bits = &main_crtc_bits;
 563         } else {
 564                 zplane->layer = vou->osd + AUX_GL_OFFSET;
 565                 zplane->csc = vou->osd + AUX_GL_CSC_OFFSET;
 566                 zplane->hbsc = vou->osd + AUX_HBSC_OFFSET;
 567                 zplane->rsz = vou->otfppu + AUX_RSZ_OFFSET;
 568                 zplane->bits = &zx_gl_bits[1];
 569                 zcrtc->chnreg = vou->osd + OSD_AUX_CHN;
 570                 zcrtc->chncsc = vou->osd + AUX_CHN_CSC_OFFSET;
 571                 zcrtc->dither = vou->osd + AUX_DITHER_OFFSET;
 572                 zcrtc->regs = &aux_crtc_regs;
 573                 zcrtc->bits = &aux_crtc_bits;
 574         }
 575 
 576         zcrtc->pixclk = devm_clk_get(dev, (chn_type == VOU_CHN_MAIN) ?
 577                                           "main_wclk" : "aux_wclk");
 578         if (IS_ERR(zcrtc->pixclk)) {
 579                 ret = PTR_ERR(zcrtc->pixclk);
 580                 DRM_DEV_ERROR(dev, "failed to get pix clk: %d\n", ret);
 581                 return ret;
 582         }
 583 
 584         ret = zx_plane_init(drm, zplane, DRM_PLANE_TYPE_PRIMARY);
 585         if (ret) {
 586                 DRM_DEV_ERROR(dev, "failed to init primary plane: %d\n", ret);
 587                 return ret;
 588         }
 589 
 590         zcrtc->primary = &zplane->plane;
 591 
 592         ret = drm_crtc_init_with_planes(drm, &zcrtc->crtc, zcrtc->primary, NULL,
 593                                         &zx_crtc_funcs, NULL);
 594         if (ret) {
 595                 DRM_DEV_ERROR(dev, "failed to init drm crtc: %d\n", ret);
 596                 return ret;
 597         }
 598 
 599         drm_crtc_helper_add(&zcrtc->crtc, &zx_crtc_helper_funcs);
 600 
 601         if (chn_type == VOU_CHN_MAIN)
 602                 vou->main_crtc = zcrtc;
 603         else
 604                 vou->aux_crtc = zcrtc;
 605 
 606         return 0;
 607 }
 608 
 609 void zx_vou_layer_enable(struct drm_plane *plane)
 610 {
 611         struct zx_crtc *zcrtc = to_zx_crtc(plane->state->crtc);
 612         struct zx_vou_hw *vou = zcrtc->vou;
 613         struct zx_plane *zplane = to_zx_plane(plane);
 614         const struct vou_layer_bits *bits = zplane->bits;
 615 
 616         if (zcrtc->chn_type == VOU_CHN_MAIN) {
 617                 zx_writel_mask(vou->osd + OSD_CTRL0, bits->chnsel, 0);
 618                 zx_writel_mask(vou->vouctl + VOU_CLK_SEL, bits->clksel, 0);
 619         } else {
 620                 zx_writel_mask(vou->osd + OSD_CTRL0, bits->chnsel,
 621                                bits->chnsel);
 622                 zx_writel_mask(vou->vouctl + VOU_CLK_SEL, bits->clksel,
 623                                bits->clksel);
 624         }
 625 
 626         zx_writel_mask(vou->osd + OSD_CTRL0, bits->enable, bits->enable);
 627 }
 628 
 629 void zx_vou_layer_disable(struct drm_plane *plane,
 630                           struct drm_plane_state *old_state)
 631 {
 632         struct zx_crtc *zcrtc = to_zx_crtc(old_state->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 
 640 static 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 
 671 static 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 
 682 static 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 
 713 static 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 
 734 static 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 
 762 static 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 
 876 disable_ppu_clk:
 877         clk_disable_unprepare(vou->ppu_clk);
 878 disable_axi_clk:
 879         clk_disable_unprepare(vou->axi_clk);
 880         return ret;
 881 }
 882 
 883 static 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 
 892 static const struct component_ops zx_crtc_component_ops = {
 893         .bind = zx_crtc_bind,
 894         .unbind = zx_crtc_unbind,
 895 };
 896 
 897 static int zx_crtc_probe(struct platform_device *pdev)
 898 {
 899         return component_add(&pdev->dev, &zx_crtc_component_ops);
 900 }
 901 
 902 static int zx_crtc_remove(struct platform_device *pdev)
 903 {
 904         component_del(&pdev->dev, &zx_crtc_component_ops);
 905         return 0;
 906 }
 907 
 908 static const struct of_device_id zx_crtc_of_match[] = {
 909         { .compatible = "zte,zx296718-dpc", },
 910         { /* end */ },
 911 };
 912 MODULE_DEVICE_TABLE(of, zx_crtc_of_match);
 913 
 914 struct 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 };

/* [<][>][^][v][top][bottom][index][help] */