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.10-rc4 661 lines 17 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 timing_shift; 44 u32 timing_pi_shift; 45}; 46 47static const struct zx_crtc_regs main_crtc_regs = { 48 .fir_active = FIR_MAIN_ACTIVE, 49 .fir_htiming = FIR_MAIN_H_TIMING, 50 .fir_vtiming = FIR_MAIN_V_TIMING, 51 .timing_shift = TIMING_MAIN_SHIFT, 52 .timing_pi_shift = TIMING_MAIN_PI_SHIFT, 53}; 54 55static const struct zx_crtc_regs aux_crtc_regs = { 56 .fir_active = FIR_AUX_ACTIVE, 57 .fir_htiming = FIR_AUX_H_TIMING, 58 .fir_vtiming = FIR_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 gl_enable; 69}; 70 71static const struct zx_crtc_bits main_crtc_bits = { 72 .polarity_mask = MAIN_POL_MASK, 73 .polarity_shift = MAIN_POL_SHIFT, 74 .int_frame_mask = TIMING_INT_MAIN_FRAME, 75 .tc_enable = MAIN_TC_EN, 76 .gl_enable = OSD_CTRL0_GL0_EN, 77}; 78 79static const struct zx_crtc_bits aux_crtc_bits = { 80 .polarity_mask = AUX_POL_MASK, 81 .polarity_shift = AUX_POL_SHIFT, 82 .int_frame_mask = TIMING_INT_AUX_FRAME, 83 .tc_enable = AUX_TC_EN, 84 .gl_enable = OSD_CTRL0_GL1_EN, 85}; 86 87struct zx_crtc { 88 struct drm_crtc crtc; 89 struct drm_plane *primary; 90 struct zx_vou_hw *vou; 91 void __iomem *chnreg; 92 const struct zx_crtc_regs *regs; 93 const struct zx_crtc_bits *bits; 94 enum vou_chn_type chn_type; 95 struct clk *pixclk; 96}; 97 98#define to_zx_crtc(x) container_of(x, struct zx_crtc, crtc) 99 100struct zx_vou_hw { 101 struct device *dev; 102 void __iomem *osd; 103 void __iomem *timing; 104 void __iomem *vouctl; 105 void __iomem *otfppu; 106 void __iomem *dtrc; 107 struct clk *axi_clk; 108 struct clk *ppu_clk; 109 struct clk *main_clk; 110 struct clk *aux_clk; 111 struct zx_crtc *main_crtc; 112 struct zx_crtc *aux_crtc; 113}; 114 115static inline struct zx_vou_hw *crtc_to_vou(struct drm_crtc *crtc) 116{ 117 struct zx_crtc *zcrtc = to_zx_crtc(crtc); 118 119 return zcrtc->vou; 120} 121 122void vou_inf_enable(const struct vou_inf *inf, struct drm_crtc *crtc) 123{ 124 struct zx_crtc *zcrtc = to_zx_crtc(crtc); 125 struct zx_vou_hw *vou = zcrtc->vou; 126 bool is_main = zcrtc->chn_type == VOU_CHN_MAIN; 127 u32 data_sel_shift = inf->id << 1; 128 129 /* Select data format */ 130 zx_writel_mask(vou->vouctl + VOU_INF_DATA_SEL, 0x3 << data_sel_shift, 131 inf->data_sel << data_sel_shift); 132 133 /* Select channel */ 134 zx_writel_mask(vou->vouctl + VOU_INF_CH_SEL, 0x1 << inf->id, 135 zcrtc->chn_type << inf->id); 136 137 /* Select interface clocks */ 138 zx_writel_mask(vou->vouctl + VOU_CLK_SEL, inf->clocks_sel_bits, 139 is_main ? 0 : inf->clocks_sel_bits); 140 141 /* Enable interface clocks */ 142 zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits, 143 inf->clocks_en_bits); 144 145 /* Enable the device */ 146 zx_writel_mask(vou->vouctl + VOU_INF_EN, 1 << inf->id, 1 << inf->id); 147} 148 149void vou_inf_disable(const struct vou_inf *inf, struct drm_crtc *crtc) 150{ 151 struct zx_vou_hw *vou = crtc_to_vou(crtc); 152 153 /* Disable the device */ 154 zx_writel_mask(vou->vouctl + VOU_INF_EN, 1 << inf->id, 0); 155 156 /* Disable interface clocks */ 157 zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits, 0); 158} 159 160static inline void vou_chn_set_update(struct zx_crtc *zcrtc) 161{ 162 zx_writel(zcrtc->chnreg + CHN_UPDATE, 1); 163} 164 165static void zx_crtc_enable(struct drm_crtc *crtc) 166{ 167 struct drm_display_mode *mode = &crtc->state->adjusted_mode; 168 struct zx_crtc *zcrtc = to_zx_crtc(crtc); 169 struct zx_vou_hw *vou = zcrtc->vou; 170 const struct zx_crtc_regs *regs = zcrtc->regs; 171 const struct zx_crtc_bits *bits = zcrtc->bits; 172 struct videomode vm; 173 u32 pol = 0; 174 u32 val; 175 int ret; 176 177 drm_display_mode_to_videomode(mode, &vm); 178 179 /* Set up timing parameters */ 180 val = V_ACTIVE(vm.vactive - 1); 181 val |= H_ACTIVE(vm.hactive - 1); 182 zx_writel(vou->timing + regs->fir_active, val); 183 184 val = SYNC_WIDE(vm.hsync_len - 1); 185 val |= BACK_PORCH(vm.hback_porch - 1); 186 val |= FRONT_PORCH(vm.hfront_porch - 1); 187 zx_writel(vou->timing + regs->fir_htiming, val); 188 189 val = SYNC_WIDE(vm.vsync_len - 1); 190 val |= BACK_PORCH(vm.vback_porch - 1); 191 val |= FRONT_PORCH(vm.vfront_porch - 1); 192 zx_writel(vou->timing + regs->fir_vtiming, val); 193 194 /* Set up polarities */ 195 if (vm.flags & DISPLAY_FLAGS_VSYNC_LOW) 196 pol |= 1 << POL_VSYNC_SHIFT; 197 if (vm.flags & DISPLAY_FLAGS_HSYNC_LOW) 198 pol |= 1 << POL_HSYNC_SHIFT; 199 200 zx_writel_mask(vou->timing + TIMING_CTRL, bits->polarity_mask, 201 pol << bits->polarity_shift); 202 203 /* Setup SHIFT register by following what ZTE BSP does */ 204 zx_writel(vou->timing + regs->timing_shift, H_SHIFT_VAL); 205 zx_writel(vou->timing + regs->timing_pi_shift, H_PI_SHIFT_VAL); 206 207 /* Enable TIMING_CTRL */ 208 zx_writel_mask(vou->timing + TIMING_TC_ENABLE, bits->tc_enable, 209 bits->tc_enable); 210 211 /* Configure channel screen size */ 212 zx_writel_mask(zcrtc->chnreg + CHN_CTRL1, CHN_SCREEN_W_MASK, 213 vm.hactive << CHN_SCREEN_W_SHIFT); 214 zx_writel_mask(zcrtc->chnreg + CHN_CTRL1, CHN_SCREEN_H_MASK, 215 vm.vactive << CHN_SCREEN_H_SHIFT); 216 217 /* Update channel */ 218 vou_chn_set_update(zcrtc); 219 220 /* Enable channel */ 221 zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, CHN_ENABLE); 222 223 /* Enable Graphic Layer */ 224 zx_writel_mask(vou->osd + OSD_CTRL0, bits->gl_enable, 225 bits->gl_enable); 226 227 drm_crtc_vblank_on(crtc); 228 229 ret = clk_set_rate(zcrtc->pixclk, mode->clock * 1000); 230 if (ret) { 231 DRM_DEV_ERROR(vou->dev, "failed to set pixclk rate: %d\n", ret); 232 return; 233 } 234 235 ret = clk_prepare_enable(zcrtc->pixclk); 236 if (ret) 237 DRM_DEV_ERROR(vou->dev, "failed to enable pixclk: %d\n", ret); 238} 239 240static void zx_crtc_disable(struct drm_crtc *crtc) 241{ 242 struct zx_crtc *zcrtc = to_zx_crtc(crtc); 243 const struct zx_crtc_bits *bits = zcrtc->bits; 244 struct zx_vou_hw *vou = zcrtc->vou; 245 246 clk_disable_unprepare(zcrtc->pixclk); 247 248 drm_crtc_vblank_off(crtc); 249 250 /* Disable Graphic Layer */ 251 zx_writel_mask(vou->osd + OSD_CTRL0, bits->gl_enable, 0); 252 253 /* Disable channel */ 254 zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, 0); 255 256 /* Disable TIMING_CTRL */ 257 zx_writel_mask(vou->timing + TIMING_TC_ENABLE, bits->tc_enable, 0); 258} 259 260static void zx_crtc_atomic_flush(struct drm_crtc *crtc, 261 struct drm_crtc_state *old_state) 262{ 263 struct drm_pending_vblank_event *event = crtc->state->event; 264 265 if (!event) 266 return; 267 268 crtc->state->event = NULL; 269 270 spin_lock_irq(&crtc->dev->event_lock); 271 if (drm_crtc_vblank_get(crtc) == 0) 272 drm_crtc_arm_vblank_event(crtc, event); 273 else 274 drm_crtc_send_vblank_event(crtc, event); 275 spin_unlock_irq(&crtc->dev->event_lock); 276} 277 278static const struct drm_crtc_helper_funcs zx_crtc_helper_funcs = { 279 .enable = zx_crtc_enable, 280 .disable = zx_crtc_disable, 281 .atomic_flush = zx_crtc_atomic_flush, 282}; 283 284static const struct drm_crtc_funcs zx_crtc_funcs = { 285 .destroy = drm_crtc_cleanup, 286 .set_config = drm_atomic_helper_set_config, 287 .page_flip = drm_atomic_helper_page_flip, 288 .reset = drm_atomic_helper_crtc_reset, 289 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, 290 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, 291}; 292 293static int zx_crtc_init(struct drm_device *drm, struct zx_vou_hw *vou, 294 enum vou_chn_type chn_type) 295{ 296 struct device *dev = vou->dev; 297 struct zx_layer_data data; 298 struct zx_crtc *zcrtc; 299 int ret; 300 301 zcrtc = devm_kzalloc(dev, sizeof(*zcrtc), GFP_KERNEL); 302 if (!zcrtc) 303 return -ENOMEM; 304 305 zcrtc->vou = vou; 306 zcrtc->chn_type = chn_type; 307 308 if (chn_type == VOU_CHN_MAIN) { 309 data.layer = vou->osd + MAIN_GL_OFFSET; 310 data.csc = vou->osd + MAIN_CSC_OFFSET; 311 data.hbsc = vou->osd + MAIN_HBSC_OFFSET; 312 data.rsz = vou->otfppu + MAIN_RSZ_OFFSET; 313 zcrtc->chnreg = vou->osd + OSD_MAIN_CHN; 314 zcrtc->regs = &main_crtc_regs; 315 zcrtc->bits = &main_crtc_bits; 316 } else { 317 data.layer = vou->osd + AUX_GL_OFFSET; 318 data.csc = vou->osd + AUX_CSC_OFFSET; 319 data.hbsc = vou->osd + AUX_HBSC_OFFSET; 320 data.rsz = vou->otfppu + AUX_RSZ_OFFSET; 321 zcrtc->chnreg = vou->osd + OSD_AUX_CHN; 322 zcrtc->regs = &aux_crtc_regs; 323 zcrtc->bits = &aux_crtc_bits; 324 } 325 326 zcrtc->pixclk = devm_clk_get(dev, (chn_type == VOU_CHN_MAIN) ? 327 "main_wclk" : "aux_wclk"); 328 if (IS_ERR(zcrtc->pixclk)) { 329 ret = PTR_ERR(zcrtc->pixclk); 330 DRM_DEV_ERROR(dev, "failed to get pix clk: %d\n", ret); 331 return ret; 332 } 333 334 zcrtc->primary = zx_plane_init(drm, dev, &data, DRM_PLANE_TYPE_PRIMARY); 335 if (IS_ERR(zcrtc->primary)) { 336 ret = PTR_ERR(zcrtc->primary); 337 DRM_DEV_ERROR(dev, "failed to init primary plane: %d\n", ret); 338 return ret; 339 } 340 341 ret = drm_crtc_init_with_planes(drm, &zcrtc->crtc, zcrtc->primary, NULL, 342 &zx_crtc_funcs, NULL); 343 if (ret) { 344 DRM_DEV_ERROR(dev, "failed to init drm crtc: %d\n", ret); 345 return ret; 346 } 347 348 drm_crtc_helper_add(&zcrtc->crtc, &zx_crtc_helper_funcs); 349 350 if (chn_type == VOU_CHN_MAIN) 351 vou->main_crtc = zcrtc; 352 else 353 vou->aux_crtc = zcrtc; 354 355 return 0; 356} 357 358static inline struct drm_crtc *zx_find_crtc(struct drm_device *drm, int pipe) 359{ 360 struct drm_crtc *crtc; 361 362 list_for_each_entry(crtc, &drm->mode_config.crtc_list, head) 363 if (crtc->index == pipe) 364 return crtc; 365 366 return NULL; 367} 368 369int zx_vou_enable_vblank(struct drm_device *drm, unsigned int pipe) 370{ 371 struct drm_crtc *crtc; 372 struct zx_crtc *zcrtc; 373 struct zx_vou_hw *vou; 374 u32 int_frame_mask; 375 376 crtc = zx_find_crtc(drm, pipe); 377 if (!crtc) 378 return 0; 379 380 vou = crtc_to_vou(crtc); 381 zcrtc = to_zx_crtc(crtc); 382 int_frame_mask = zcrtc->bits->int_frame_mask; 383 384 zx_writel_mask(vou->timing + TIMING_INT_CTRL, int_frame_mask, 385 int_frame_mask); 386 387 return 0; 388} 389 390void zx_vou_disable_vblank(struct drm_device *drm, unsigned int pipe) 391{ 392 struct drm_crtc *crtc; 393 struct zx_crtc *zcrtc; 394 struct zx_vou_hw *vou; 395 396 crtc = zx_find_crtc(drm, pipe); 397 if (!crtc) 398 return; 399 400 vou = crtc_to_vou(crtc); 401 zcrtc = to_zx_crtc(crtc); 402 403 zx_writel_mask(vou->timing + TIMING_INT_CTRL, 404 zcrtc->bits->int_frame_mask, 0); 405} 406 407static irqreturn_t vou_irq_handler(int irq, void *dev_id) 408{ 409 struct zx_vou_hw *vou = dev_id; 410 u32 state; 411 412 /* Handle TIMING_CTRL frame interrupts */ 413 state = zx_readl(vou->timing + TIMING_INT_STATE); 414 zx_writel(vou->timing + TIMING_INT_STATE, state); 415 416 if (state & TIMING_INT_MAIN_FRAME) 417 drm_crtc_handle_vblank(&vou->main_crtc->crtc); 418 419 if (state & TIMING_INT_AUX_FRAME) 420 drm_crtc_handle_vblank(&vou->aux_crtc->crtc); 421 422 /* Handle OSD interrupts */ 423 state = zx_readl(vou->osd + OSD_INT_STA); 424 zx_writel(vou->osd + OSD_INT_CLRSTA, state); 425 426 if (state & OSD_INT_MAIN_UPT) { 427 vou_chn_set_update(vou->main_crtc); 428 zx_plane_set_update(vou->main_crtc->primary); 429 } 430 431 if (state & OSD_INT_AUX_UPT) { 432 vou_chn_set_update(vou->aux_crtc); 433 zx_plane_set_update(vou->aux_crtc->primary); 434 } 435 436 if (state & OSD_INT_ERROR) 437 DRM_DEV_ERROR(vou->dev, "OSD ERROR: 0x%08x!\n", state); 438 439 return IRQ_HANDLED; 440} 441 442static void vou_dtrc_init(struct zx_vou_hw *vou) 443{ 444 /* Clear bit for bypass by ID */ 445 zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL, 446 TILE2RASTESCAN_BYPASS_MODE, 0); 447 448 /* Select ARIDR mode */ 449 zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL, DETILE_ARIDR_MODE_MASK, 450 DETILE_ARID_IN_ARIDR); 451 452 /* Bypass decompression for both frames */ 453 zx_writel_mask(vou->dtrc + DTRC_F0_CTRL, DTRC_DECOMPRESS_BYPASS, 454 DTRC_DECOMPRESS_BYPASS); 455 zx_writel_mask(vou->dtrc + DTRC_F1_CTRL, DTRC_DECOMPRESS_BYPASS, 456 DTRC_DECOMPRESS_BYPASS); 457 458 /* Set up ARID register */ 459 zx_writel(vou->dtrc + DTRC_ARID, DTRC_ARID3(0xf) | DTRC_ARID2(0xe) | 460 DTRC_ARID1(0xf) | DTRC_ARID0(0xe)); 461} 462 463static void vou_hw_init(struct zx_vou_hw *vou) 464{ 465 /* Set GL0 to main channel and GL1 to aux channel */ 466 zx_writel_mask(vou->osd + OSD_CTRL0, OSD_CTRL0_GL0_SEL, 0); 467 zx_writel_mask(vou->osd + OSD_CTRL0, OSD_CTRL0_GL1_SEL, 468 OSD_CTRL0_GL1_SEL); 469 470 /* Release reset for all VOU modules */ 471 zx_writel(vou->vouctl + VOU_SOFT_RST, ~0); 472 473 /* Select main clock for GL0 and aux clock for GL1 module */ 474 zx_writel_mask(vou->vouctl + VOU_CLK_SEL, VOU_CLK_GL0_SEL, 0); 475 zx_writel_mask(vou->vouctl + VOU_CLK_SEL, VOU_CLK_GL1_SEL, 476 VOU_CLK_GL1_SEL); 477 478 /* Enable clock auto-gating for all VOU modules */ 479 zx_writel(vou->vouctl + VOU_CLK_REQEN, ~0); 480 481 /* Enable all VOU module clocks */ 482 zx_writel(vou->vouctl + VOU_CLK_EN, ~0); 483 484 /* Clear both OSD and TIMING_CTRL interrupt state */ 485 zx_writel(vou->osd + OSD_INT_CLRSTA, ~0); 486 zx_writel(vou->timing + TIMING_INT_STATE, ~0); 487 488 /* Enable OSD and TIMING_CTRL interrrupts */ 489 zx_writel(vou->osd + OSD_INT_MSK, OSD_INT_ENABLE); 490 zx_writel(vou->timing + TIMING_INT_CTRL, TIMING_INT_ENABLE); 491 492 /* Select GPC as input to gl/vl scaler as a sane default setting */ 493 zx_writel(vou->otfppu + OTFPPU_RSZ_DATA_SOURCE, 0x2a); 494 495 /* 496 * Needs to reset channel and layer logic per frame when frame starts 497 * to get VOU work properly. 498 */ 499 zx_writel_mask(vou->osd + OSD_RST_CLR, RST_PER_FRAME, RST_PER_FRAME); 500 501 vou_dtrc_init(vou); 502} 503 504static int zx_crtc_bind(struct device *dev, struct device *master, void *data) 505{ 506 struct platform_device *pdev = to_platform_device(dev); 507 struct drm_device *drm = data; 508 struct zx_vou_hw *vou; 509 struct resource *res; 510 int irq; 511 int ret; 512 513 vou = devm_kzalloc(dev, sizeof(*vou), GFP_KERNEL); 514 if (!vou) 515 return -ENOMEM; 516 517 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "osd"); 518 vou->osd = devm_ioremap_resource(dev, res); 519 if (IS_ERR(vou->osd)) { 520 ret = PTR_ERR(vou->osd); 521 DRM_DEV_ERROR(dev, "failed to remap osd region: %d\n", ret); 522 return ret; 523 } 524 525 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "timing_ctrl"); 526 vou->timing = devm_ioremap_resource(dev, res); 527 if (IS_ERR(vou->timing)) { 528 ret = PTR_ERR(vou->timing); 529 DRM_DEV_ERROR(dev, "failed to remap timing_ctrl region: %d\n", 530 ret); 531 return ret; 532 } 533 534 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dtrc"); 535 vou->dtrc = devm_ioremap_resource(dev, res); 536 if (IS_ERR(vou->dtrc)) { 537 ret = PTR_ERR(vou->dtrc); 538 DRM_DEV_ERROR(dev, "failed to remap dtrc region: %d\n", ret); 539 return ret; 540 } 541 542 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vou_ctrl"); 543 vou->vouctl = devm_ioremap_resource(dev, res); 544 if (IS_ERR(vou->vouctl)) { 545 ret = PTR_ERR(vou->vouctl); 546 DRM_DEV_ERROR(dev, "failed to remap vou_ctrl region: %d\n", 547 ret); 548 return ret; 549 } 550 551 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "otfppu"); 552 vou->otfppu = devm_ioremap_resource(dev, res); 553 if (IS_ERR(vou->otfppu)) { 554 ret = PTR_ERR(vou->otfppu); 555 DRM_DEV_ERROR(dev, "failed to remap otfppu region: %d\n", ret); 556 return ret; 557 } 558 559 irq = platform_get_irq(pdev, 0); 560 if (irq < 0) 561 return irq; 562 563 vou->axi_clk = devm_clk_get(dev, "aclk"); 564 if (IS_ERR(vou->axi_clk)) { 565 ret = PTR_ERR(vou->axi_clk); 566 DRM_DEV_ERROR(dev, "failed to get axi_clk: %d\n", ret); 567 return ret; 568 } 569 570 vou->ppu_clk = devm_clk_get(dev, "ppu_wclk"); 571 if (IS_ERR(vou->ppu_clk)) { 572 ret = PTR_ERR(vou->ppu_clk); 573 DRM_DEV_ERROR(dev, "failed to get ppu_clk: %d\n", ret); 574 return ret; 575 } 576 577 ret = clk_prepare_enable(vou->axi_clk); 578 if (ret) { 579 DRM_DEV_ERROR(dev, "failed to enable axi_clk: %d\n", ret); 580 return ret; 581 } 582 583 clk_prepare_enable(vou->ppu_clk); 584 if (ret) { 585 DRM_DEV_ERROR(dev, "failed to enable ppu_clk: %d\n", ret); 586 goto disable_axi_clk; 587 } 588 589 vou->dev = dev; 590 dev_set_drvdata(dev, vou); 591 592 vou_hw_init(vou); 593 594 ret = devm_request_irq(dev, irq, vou_irq_handler, 0, "zx_vou", vou); 595 if (ret < 0) { 596 DRM_DEV_ERROR(dev, "failed to request vou irq: %d\n", ret); 597 goto disable_ppu_clk; 598 } 599 600 ret = zx_crtc_init(drm, vou, VOU_CHN_MAIN); 601 if (ret) { 602 DRM_DEV_ERROR(dev, "failed to init main channel crtc: %d\n", 603 ret); 604 goto disable_ppu_clk; 605 } 606 607 ret = zx_crtc_init(drm, vou, VOU_CHN_AUX); 608 if (ret) { 609 DRM_DEV_ERROR(dev, "failed to init aux channel crtc: %d\n", 610 ret); 611 goto disable_ppu_clk; 612 } 613 614 return 0; 615 616disable_ppu_clk: 617 clk_disable_unprepare(vou->ppu_clk); 618disable_axi_clk: 619 clk_disable_unprepare(vou->axi_clk); 620 return ret; 621} 622 623static void zx_crtc_unbind(struct device *dev, struct device *master, 624 void *data) 625{ 626 struct zx_vou_hw *vou = dev_get_drvdata(dev); 627 628 clk_disable_unprepare(vou->axi_clk); 629 clk_disable_unprepare(vou->ppu_clk); 630} 631 632static const struct component_ops zx_crtc_component_ops = { 633 .bind = zx_crtc_bind, 634 .unbind = zx_crtc_unbind, 635}; 636 637static int zx_crtc_probe(struct platform_device *pdev) 638{ 639 return component_add(&pdev->dev, &zx_crtc_component_ops); 640} 641 642static int zx_crtc_remove(struct platform_device *pdev) 643{ 644 component_del(&pdev->dev, &zx_crtc_component_ops); 645 return 0; 646} 647 648static const struct of_device_id zx_crtc_of_match[] = { 649 { .compatible = "zte,zx296718-dpc", }, 650 { /* end */ }, 651}; 652MODULE_DEVICE_TABLE(of, zx_crtc_of_match); 653 654struct platform_driver zx_crtc_driver = { 655 .probe = zx_crtc_probe, 656 .remove = zx_crtc_remove, 657 .driver = { 658 .name = "zx-crtc", 659 .of_match_table = zx_crtc_of_match, 660 }, 661};