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