Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.0-rc1 922 lines 24 kB view raw
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 struct drm_plane_state *old_state) 632{ 633 struct zx_crtc *zcrtc = to_zx_crtc(old_state->crtc); 634 struct zx_vou_hw *vou = zcrtc->vou; 635 struct zx_plane *zplane = to_zx_plane(plane); 636 const struct vou_layer_bits *bits = zplane->bits; 637 638 zx_writel_mask(vou->osd + OSD_CTRL0, bits->enable, 0); 639} 640 641static void zx_overlay_init(struct drm_device *drm, struct zx_vou_hw *vou) 642{ 643 struct device *dev = vou->dev; 644 struct zx_plane *zplane; 645 int i; 646 int ret; 647 648 /* 649 * VL0 has some quirks on scaling support which need special handling. 650 * Let's leave it out for now. 651 */ 652 for (i = 1; i < VL_NUM; i++) { 653 zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL); 654 if (!zplane) { 655 DRM_DEV_ERROR(dev, "failed to allocate zplane %d\n", i); 656 return; 657 } 658 659 zplane->layer = vou->osd + OSD_VL_OFFSET(i); 660 zplane->hbsc = vou->osd + HBSC_VL_OFFSET(i); 661 zplane->rsz = vou->otfppu + RSZ_VL_OFFSET(i); 662 zplane->bits = &zx_vl_bits[i]; 663 664 ret = zx_plane_init(drm, zplane, DRM_PLANE_TYPE_OVERLAY); 665 if (ret) { 666 DRM_DEV_ERROR(dev, "failed to init overlay %d\n", i); 667 continue; 668 } 669 } 670} 671 672static inline void zx_osd_int_update(struct zx_crtc *zcrtc) 673{ 674 struct drm_crtc *crtc = &zcrtc->crtc; 675 struct drm_plane *plane; 676 677 vou_chn_set_update(zcrtc); 678 679 drm_for_each_plane_mask(plane, crtc->dev, crtc->state->plane_mask) 680 zx_plane_set_update(plane); 681} 682 683static irqreturn_t vou_irq_handler(int irq, void *dev_id) 684{ 685 struct zx_vou_hw *vou = dev_id; 686 u32 state; 687 688 /* Handle TIMING_CTRL frame interrupts */ 689 state = zx_readl(vou->timing + TIMING_INT_STATE); 690 zx_writel(vou->timing + TIMING_INT_STATE, state); 691 692 if (state & TIMING_INT_MAIN_FRAME) 693 drm_crtc_handle_vblank(&vou->main_crtc->crtc); 694 695 if (state & TIMING_INT_AUX_FRAME) 696 drm_crtc_handle_vblank(&vou->aux_crtc->crtc); 697 698 /* Handle OSD interrupts */ 699 state = zx_readl(vou->osd + OSD_INT_STA); 700 zx_writel(vou->osd + OSD_INT_CLRSTA, state); 701 702 if (state & OSD_INT_MAIN_UPT) 703 zx_osd_int_update(vou->main_crtc); 704 705 if (state & OSD_INT_AUX_UPT) 706 zx_osd_int_update(vou->aux_crtc); 707 708 if (state & OSD_INT_ERROR) 709 DRM_DEV_ERROR(vou->dev, "OSD ERROR: 0x%08x!\n", state); 710 711 return IRQ_HANDLED; 712} 713 714static void vou_dtrc_init(struct zx_vou_hw *vou) 715{ 716 /* Clear bit for bypass by ID */ 717 zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL, 718 TILE2RASTESCAN_BYPASS_MODE, 0); 719 720 /* Select ARIDR mode */ 721 zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL, DETILE_ARIDR_MODE_MASK, 722 DETILE_ARID_IN_ARIDR); 723 724 /* Bypass decompression for both frames */ 725 zx_writel_mask(vou->dtrc + DTRC_F0_CTRL, DTRC_DECOMPRESS_BYPASS, 726 DTRC_DECOMPRESS_BYPASS); 727 zx_writel_mask(vou->dtrc + DTRC_F1_CTRL, DTRC_DECOMPRESS_BYPASS, 728 DTRC_DECOMPRESS_BYPASS); 729 730 /* Set up ARID register */ 731 zx_writel(vou->dtrc + DTRC_ARID, DTRC_ARID3(0xf) | DTRC_ARID2(0xe) | 732 DTRC_ARID1(0xf) | DTRC_ARID0(0xe)); 733} 734 735static void vou_hw_init(struct zx_vou_hw *vou) 736{ 737 /* Release reset for all VOU modules */ 738 zx_writel(vou->vouctl + VOU_SOFT_RST, ~0); 739 740 /* Enable all VOU module clocks */ 741 zx_writel(vou->vouctl + VOU_CLK_EN, ~0); 742 743 /* Clear both OSD and TIMING_CTRL interrupt state */ 744 zx_writel(vou->osd + OSD_INT_CLRSTA, ~0); 745 zx_writel(vou->timing + TIMING_INT_STATE, ~0); 746 747 /* Enable OSD and TIMING_CTRL interrrupts */ 748 zx_writel(vou->osd + OSD_INT_MSK, OSD_INT_ENABLE); 749 zx_writel(vou->timing + TIMING_INT_CTRL, TIMING_INT_ENABLE); 750 751 /* Select GPC as input to gl/vl scaler as a sane default setting */ 752 zx_writel(vou->otfppu + OTFPPU_RSZ_DATA_SOURCE, 0x2a); 753 754 /* 755 * Needs to reset channel and layer logic per frame when frame starts 756 * to get VOU work properly. 757 */ 758 zx_writel_mask(vou->osd + OSD_RST_CLR, RST_PER_FRAME, RST_PER_FRAME); 759 760 vou_dtrc_init(vou); 761} 762 763static int zx_crtc_bind(struct device *dev, struct device *master, void *data) 764{ 765 struct platform_device *pdev = to_platform_device(dev); 766 struct drm_device *drm = data; 767 struct zx_vou_hw *vou; 768 struct resource *res; 769 int irq; 770 int ret; 771 772 vou = devm_kzalloc(dev, sizeof(*vou), GFP_KERNEL); 773 if (!vou) 774 return -ENOMEM; 775 776 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "osd"); 777 vou->osd = devm_ioremap_resource(dev, res); 778 if (IS_ERR(vou->osd)) { 779 ret = PTR_ERR(vou->osd); 780 DRM_DEV_ERROR(dev, "failed to remap osd region: %d\n", ret); 781 return ret; 782 } 783 784 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "timing_ctrl"); 785 vou->timing = devm_ioremap_resource(dev, res); 786 if (IS_ERR(vou->timing)) { 787 ret = PTR_ERR(vou->timing); 788 DRM_DEV_ERROR(dev, "failed to remap timing_ctrl region: %d\n", 789 ret); 790 return ret; 791 } 792 793 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dtrc"); 794 vou->dtrc = devm_ioremap_resource(dev, res); 795 if (IS_ERR(vou->dtrc)) { 796 ret = PTR_ERR(vou->dtrc); 797 DRM_DEV_ERROR(dev, "failed to remap dtrc region: %d\n", ret); 798 return ret; 799 } 800 801 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vou_ctrl"); 802 vou->vouctl = devm_ioremap_resource(dev, res); 803 if (IS_ERR(vou->vouctl)) { 804 ret = PTR_ERR(vou->vouctl); 805 DRM_DEV_ERROR(dev, "failed to remap vou_ctrl region: %d\n", 806 ret); 807 return ret; 808 } 809 810 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "otfppu"); 811 vou->otfppu = devm_ioremap_resource(dev, res); 812 if (IS_ERR(vou->otfppu)) { 813 ret = PTR_ERR(vou->otfppu); 814 DRM_DEV_ERROR(dev, "failed to remap otfppu region: %d\n", ret); 815 return ret; 816 } 817 818 irq = platform_get_irq(pdev, 0); 819 if (irq < 0) 820 return irq; 821 822 vou->axi_clk = devm_clk_get(dev, "aclk"); 823 if (IS_ERR(vou->axi_clk)) { 824 ret = PTR_ERR(vou->axi_clk); 825 DRM_DEV_ERROR(dev, "failed to get axi_clk: %d\n", ret); 826 return ret; 827 } 828 829 vou->ppu_clk = devm_clk_get(dev, "ppu_wclk"); 830 if (IS_ERR(vou->ppu_clk)) { 831 ret = PTR_ERR(vou->ppu_clk); 832 DRM_DEV_ERROR(dev, "failed to get ppu_clk: %d\n", ret); 833 return ret; 834 } 835 836 ret = clk_prepare_enable(vou->axi_clk); 837 if (ret) { 838 DRM_DEV_ERROR(dev, "failed to enable axi_clk: %d\n", ret); 839 return ret; 840 } 841 842 clk_prepare_enable(vou->ppu_clk); 843 if (ret) { 844 DRM_DEV_ERROR(dev, "failed to enable ppu_clk: %d\n", ret); 845 goto disable_axi_clk; 846 } 847 848 vou->dev = dev; 849 dev_set_drvdata(dev, vou); 850 851 vou_hw_init(vou); 852 853 ret = devm_request_irq(dev, irq, vou_irq_handler, 0, "zx_vou", vou); 854 if (ret < 0) { 855 DRM_DEV_ERROR(dev, "failed to request vou irq: %d\n", ret); 856 goto disable_ppu_clk; 857 } 858 859 ret = zx_crtc_init(drm, vou, VOU_CHN_MAIN); 860 if (ret) { 861 DRM_DEV_ERROR(dev, "failed to init main channel crtc: %d\n", 862 ret); 863 goto disable_ppu_clk; 864 } 865 866 ret = zx_crtc_init(drm, vou, VOU_CHN_AUX); 867 if (ret) { 868 DRM_DEV_ERROR(dev, "failed to init aux channel crtc: %d\n", 869 ret); 870 goto disable_ppu_clk; 871 } 872 873 zx_overlay_init(drm, vou); 874 875 return 0; 876 877disable_ppu_clk: 878 clk_disable_unprepare(vou->ppu_clk); 879disable_axi_clk: 880 clk_disable_unprepare(vou->axi_clk); 881 return ret; 882} 883 884static void zx_crtc_unbind(struct device *dev, struct device *master, 885 void *data) 886{ 887 struct zx_vou_hw *vou = dev_get_drvdata(dev); 888 889 clk_disable_unprepare(vou->axi_clk); 890 clk_disable_unprepare(vou->ppu_clk); 891} 892 893static const struct component_ops zx_crtc_component_ops = { 894 .bind = zx_crtc_bind, 895 .unbind = zx_crtc_unbind, 896}; 897 898static int zx_crtc_probe(struct platform_device *pdev) 899{ 900 return component_add(&pdev->dev, &zx_crtc_component_ops); 901} 902 903static int zx_crtc_remove(struct platform_device *pdev) 904{ 905 component_del(&pdev->dev, &zx_crtc_component_ops); 906 return 0; 907} 908 909static const struct of_device_id zx_crtc_of_match[] = { 910 { .compatible = "zte,zx296718-dpc", }, 911 { /* end */ }, 912}; 913MODULE_DEVICE_TABLE(of, zx_crtc_of_match); 914 915struct platform_driver zx_crtc_driver = { 916 .probe = zx_crtc_probe, 917 .remove = zx_crtc_remove, 918 .driver = { 919 .name = "zx-crtc", 920 .of_match_table = zx_crtc_of_match, 921 }, 922};