.. | .. |
---|
643 | 643 | */ |
---|
644 | 644 | uint32_t win_mask; |
---|
645 | 645 | /** |
---|
| 646 | + * @enabled_win_mask: Bitmask of enabled wins attached to the video port; |
---|
| 647 | + */ |
---|
| 648 | + uint32_t enabled_win_mask; |
---|
| 649 | + |
---|
| 650 | + /** |
---|
646 | 651 | * @nr_layers: active layers attached to the video port; |
---|
647 | 652 | */ |
---|
648 | 653 | uint8_t nr_layers; |
---|
.. | .. |
---|
769 | 774 | * will be used to show uboot logo and kernel logo |
---|
770 | 775 | */ |
---|
771 | 776 | enum vop2_layer_phy_id primary_plane_phy_id; |
---|
| 777 | + |
---|
| 778 | + struct post_acm acm_info; |
---|
| 779 | + struct post_csc csc_info; |
---|
772 | 780 | |
---|
773 | 781 | /** |
---|
774 | 782 | * @refresh_rate_change: indicate whether refresh rate change |
---|
.. | .. |
---|
1870 | 1878 | static inline uint32_t vop2_read_lut(struct vop2 *vop2, uint32_t offset) |
---|
1871 | 1879 | { |
---|
1872 | 1880 | return readl(vop2->lut_regs + offset); |
---|
| 1881 | +} |
---|
| 1882 | + |
---|
| 1883 | +static bool is_linear_10bit_yuv(uint32_t format) |
---|
| 1884 | +{ |
---|
| 1885 | + switch (format) { |
---|
| 1886 | + case DRM_FORMAT_NV15: |
---|
| 1887 | + case DRM_FORMAT_NV20: |
---|
| 1888 | + case DRM_FORMAT_NV30: |
---|
| 1889 | + return true; |
---|
| 1890 | + default: |
---|
| 1891 | + return false; |
---|
| 1892 | + } |
---|
1873 | 1893 | } |
---|
1874 | 1894 | |
---|
1875 | 1895 | static enum vop2_data_format vop2_convert_format(uint32_t format) |
---|
.. | .. |
---|
3383 | 3403 | |
---|
3384 | 3404 | VOP_MODULE_SET(vop2, vp, dsp_lut_en, 1); |
---|
3385 | 3405 | vop2_write_reg_uncached(vop2, &vp->regs->gamma_update_en, 1); |
---|
3386 | | - vop2_cfg_done(crtc); |
---|
3387 | 3406 | vp->gamma_lut_active = true; |
---|
3388 | 3407 | |
---|
3389 | 3408 | spin_unlock(&vop2->reg_lock); |
---|
.. | .. |
---|
3430 | 3449 | rk3588_crtc_load_lut(&vp->rockchip_crtc.crtc, vp->lut); |
---|
3431 | 3450 | if (vcstate->splice_mode) |
---|
3432 | 3451 | rk3588_crtc_load_lut(&splice_vp->rockchip_crtc.crtc, vp->lut); |
---|
3433 | | - vop2_cfg_done(crtc); |
---|
3434 | 3452 | } |
---|
3435 | | - /* |
---|
3436 | | - * maybe appear the following case: |
---|
3437 | | - * -> set gamma |
---|
3438 | | - * -> config done |
---|
3439 | | - * -> atomic commit |
---|
3440 | | - * --> update win format |
---|
3441 | | - * --> update win address |
---|
3442 | | - * ---> here maybe meet vop hardware frame start, and triggle some config take affect. |
---|
3443 | | - * ---> as only some config take affect, this maybe lead to iommu pagefault. |
---|
3444 | | - * --> update win size |
---|
3445 | | - * --> update win other parameters |
---|
3446 | | - * -> config done |
---|
3447 | | - * |
---|
3448 | | - * so we add vop2_wait_for_fs_by_done_bit_status() to make sure the first config done take |
---|
3449 | | - * effect and then to do next frame config. |
---|
3450 | | - */ |
---|
3451 | | - if (VOP_MODULE_GET(vop2, vp, standby) == 0) |
---|
3452 | | - vop2_wait_for_fs_by_done_bit_status(vp); |
---|
3453 | 3453 | } |
---|
3454 | 3454 | |
---|
3455 | 3455 | static void rockchip_vop2_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, |
---|
.. | .. |
---|
3491 | 3491 | struct drm_modeset_acquire_ctx *ctx) |
---|
3492 | 3492 | { |
---|
3493 | 3493 | struct vop2_video_port *vp = to_vop2_video_port(crtc); |
---|
| 3494 | + struct vop2 *vop2 = vp->vop2; |
---|
3494 | 3495 | int i; |
---|
3495 | 3496 | |
---|
3496 | 3497 | if (!vp->lut) |
---|
.. | .. |
---|
3505 | 3506 | rockchip_vop2_crtc_fb_gamma_set(crtc, red[i], green[i], |
---|
3506 | 3507 | blue[i], i); |
---|
3507 | 3508 | vop2_crtc_load_lut(crtc); |
---|
| 3509 | + vop2_cfg_done(crtc); |
---|
| 3510 | + /* |
---|
| 3511 | + * maybe appear the following case: |
---|
| 3512 | + * -> set gamma |
---|
| 3513 | + * -> config done |
---|
| 3514 | + * -> atomic commit |
---|
| 3515 | + * --> update win format |
---|
| 3516 | + * --> update win address |
---|
| 3517 | + * ---> here maybe meet vop hardware frame start, and triggle some config take affect. |
---|
| 3518 | + * ---> as only some config take affect, this maybe lead to iommu pagefault. |
---|
| 3519 | + * --> update win size |
---|
| 3520 | + * --> update win other parameters |
---|
| 3521 | + * -> config done |
---|
| 3522 | + * |
---|
| 3523 | + * so we add vop2_wait_for_fs_by_done_bit_status() to make sure the first config done take |
---|
| 3524 | + * effect and then to do next frame config. |
---|
| 3525 | + */ |
---|
| 3526 | + if (VOP_MODULE_GET(vop2, vp, standby) == 0) |
---|
| 3527 | + vop2_wait_for_fs_by_done_bit_status(vp); |
---|
3508 | 3528 | |
---|
3509 | 3529 | return 0; |
---|
3510 | 3530 | } |
---|
.. | .. |
---|
3524 | 3544 | return 0; |
---|
3525 | 3545 | } |
---|
3526 | 3546 | |
---|
3527 | | -#if defined(CONFIG_ROCKCHIP_DRM_CUBIC_LUT) |
---|
3528 | 3547 | static int vop2_crtc_atomic_cubic_lut_set(struct drm_crtc *crtc, |
---|
3529 | 3548 | struct drm_crtc_state *old_state) |
---|
3530 | 3549 | { |
---|
.. | .. |
---|
3597 | 3616 | return 0; |
---|
3598 | 3617 | } |
---|
3599 | 3618 | |
---|
3600 | | -static void drm_crtc_enable_cubic_lut(struct drm_crtc *crtc, unsigned int cubic_lut_size) |
---|
| 3619 | +static void vop2_attach_cubic_lut_prop(struct drm_crtc *crtc, unsigned int cubic_lut_size) |
---|
3601 | 3620 | { |
---|
3602 | | - struct drm_device *dev = crtc->dev; |
---|
3603 | | - struct drm_mode_config *config = &dev->mode_config; |
---|
| 3621 | + struct rockchip_drm_private *private = crtc->dev->dev_private; |
---|
3604 | 3622 | |
---|
3605 | | - if (cubic_lut_size) { |
---|
3606 | | - drm_object_attach_property(&crtc->base, |
---|
3607 | | - config->cubic_lut_property, 0); |
---|
3608 | | - drm_object_attach_property(&crtc->base, |
---|
3609 | | - config->cubic_lut_size_property, |
---|
3610 | | - cubic_lut_size); |
---|
3611 | | - } |
---|
| 3623 | + drm_object_attach_property(&crtc->base, private->cubic_lut_prop, 0); |
---|
| 3624 | + drm_object_attach_property(&crtc->base, private->cubic_lut_size_prop, cubic_lut_size); |
---|
3612 | 3625 | } |
---|
3613 | 3626 | |
---|
3614 | 3627 | static void vop2_cubic_lut_init(struct vop2 *vop2) |
---|
.. | .. |
---|
3628 | 3641 | vp->cubic_lut_len = vp_data->cubic_lut_len; |
---|
3629 | 3642 | |
---|
3630 | 3643 | if (vp->cubic_lut_len) |
---|
3631 | | - drm_crtc_enable_cubic_lut(crtc, vp->cubic_lut_len); |
---|
| 3644 | + vop2_attach_cubic_lut_prop(crtc, vp->cubic_lut_len); |
---|
3632 | 3645 | } |
---|
3633 | 3646 | } |
---|
3634 | | -#else |
---|
3635 | | -static void vop2_cubic_lut_init(struct vop2 *vop2) { } |
---|
3636 | | -#endif |
---|
3637 | 3647 | |
---|
3638 | 3648 | static int vop2_core_clks_prepare_enable(struct vop2 *vop2) |
---|
3639 | 3649 | { |
---|
.. | .. |
---|
4276 | 4286 | return 0; |
---|
4277 | 4287 | } |
---|
4278 | 4288 | |
---|
4279 | | -static void vop2_crtc_atomic_disable_for_psr(struct drm_crtc *crtc, |
---|
4280 | | - struct drm_crtc_state *old_state) |
---|
| 4289 | +static void vop2_crtc_atomic_enter_psr(struct drm_crtc *crtc, struct drm_crtc_state *old_state) |
---|
4281 | 4290 | { |
---|
4282 | 4291 | struct vop2_video_port *vp = to_vop2_video_port(crtc); |
---|
4283 | 4292 | struct vop2 *vop2 = vp->vop2; |
---|
| 4293 | + struct vop2_win *win; |
---|
| 4294 | + unsigned long win_mask = vp->enabled_win_mask; |
---|
| 4295 | + int phys_id; |
---|
4284 | 4296 | |
---|
4285 | | - vop2_disable_all_planes_for_crtc(crtc); |
---|
| 4297 | + for_each_set_bit(phys_id, &win_mask, ROCKCHIP_MAX_LAYER) { |
---|
| 4298 | + win = vop2_find_win_by_phys_id(vop2, phys_id); |
---|
| 4299 | + VOP_WIN_SET(vop2, win, enable, 0); |
---|
| 4300 | + |
---|
| 4301 | + if (win->feature & WIN_FEATURE_CLUSTER_MAIN) |
---|
| 4302 | + VOP_CLUSTER_SET(vop2, win, enable, 0); |
---|
| 4303 | + } |
---|
| 4304 | + |
---|
| 4305 | + vop2_cfg_done(crtc); |
---|
| 4306 | + vop2_wait_for_fs_by_done_bit_status(vp); |
---|
4286 | 4307 | drm_crtc_vblank_off(crtc); |
---|
4287 | 4308 | if (hweight8(vop2->active_vp_mask) == 1) { |
---|
4288 | 4309 | u32 adjust_aclk_rate = 0; |
---|
.. | .. |
---|
4305 | 4326 | } |
---|
4306 | 4327 | } |
---|
4307 | 4328 | |
---|
| 4329 | +static void vop2_crtc_atomic_exit_psr(struct drm_crtc *crtc, struct drm_crtc_state *old_state) |
---|
| 4330 | +{ |
---|
| 4331 | + struct vop2_video_port *vp = to_vop2_video_port(crtc); |
---|
| 4332 | + struct vop2 *vop2 = vp->vop2; |
---|
| 4333 | + u32 phys_id; |
---|
| 4334 | + struct vop2_win *win; |
---|
| 4335 | + unsigned long enabled_win_mask = vp->enabled_win_mask; |
---|
| 4336 | + |
---|
| 4337 | + drm_crtc_vblank_on(crtc); |
---|
| 4338 | + if (vop2->aclk_rate_reset) |
---|
| 4339 | + clk_set_rate(vop2->aclk, vop2->aclk_rate); |
---|
| 4340 | + vop2->aclk_rate_reset = false; |
---|
| 4341 | + |
---|
| 4342 | + for_each_set_bit(phys_id, &enabled_win_mask, ROCKCHIP_MAX_LAYER) { |
---|
| 4343 | + win = vop2_find_win_by_phys_id(vop2, phys_id); |
---|
| 4344 | + VOP_WIN_SET(vop2, win, enable, 1); |
---|
| 4345 | + if (win->feature & WIN_FEATURE_CLUSTER_MAIN) |
---|
| 4346 | + VOP_CLUSTER_SET(vop2, win, enable, 1); |
---|
| 4347 | + } |
---|
| 4348 | + |
---|
| 4349 | + vop2_cfg_done(crtc); |
---|
| 4350 | + vop2_wait_for_fs_by_done_bit_status(vp); |
---|
| 4351 | +} |
---|
| 4352 | + |
---|
4308 | 4353 | static void vop2_crtc_atomic_disable(struct drm_crtc *crtc, |
---|
4309 | 4354 | struct drm_crtc_state *old_state) |
---|
4310 | 4355 | { |
---|
.. | .. |
---|
4319 | 4364 | WARN_ON(vp->event); |
---|
4320 | 4365 | |
---|
4321 | 4366 | if (crtc->state->self_refresh_active) { |
---|
4322 | | - vop2_crtc_atomic_disable_for_psr(crtc, old_state); |
---|
| 4367 | + vop2_crtc_atomic_enter_psr(crtc, old_state); |
---|
4323 | 4368 | goto out; |
---|
4324 | 4369 | } |
---|
4325 | 4370 | |
---|
.. | .. |
---|
4370 | 4415 | if (vp->output_if & VOP_OUTPUT_IF_eDP0) |
---|
4371 | 4416 | VOP_GRF_SET(vop2, grf, grf_edp0_en, 0); |
---|
4372 | 4417 | |
---|
4373 | | - if (vp->output_if & VOP_OUTPUT_IF_eDP1) |
---|
| 4418 | + if (vp->output_if & VOP_OUTPUT_IF_eDP1) { |
---|
4374 | 4419 | VOP_GRF_SET(vop2, grf, grf_edp1_en, 0); |
---|
| 4420 | + if (dual_channel) |
---|
| 4421 | + VOP_CTRL_SET(vop2, edp_dual_en, 0); |
---|
| 4422 | + } |
---|
4375 | 4423 | |
---|
4376 | 4424 | if (vp->output_if & VOP_OUTPUT_IF_HDMI0) { |
---|
4377 | 4425 | VOP_GRF_SET(vop2, grf, grf_hdmi0_dsc_en, 0); |
---|
.. | .. |
---|
4381 | 4429 | if (vp->output_if & VOP_OUTPUT_IF_HDMI1) { |
---|
4382 | 4430 | VOP_GRF_SET(vop2, grf, grf_hdmi1_dsc_en, 0); |
---|
4383 | 4431 | VOP_GRF_SET(vop2, grf, grf_hdmi1_en, 0); |
---|
| 4432 | + if (dual_channel) |
---|
| 4433 | + VOP_CTRL_SET(vop2, hdmi_dual_en, 0); |
---|
4384 | 4434 | } |
---|
| 4435 | + |
---|
| 4436 | + if ((vcstate->output_if & VOP_OUTPUT_IF_DP1) && dual_channel) |
---|
| 4437 | + VOP_CTRL_SET(vop2, dp_dual_en, 0); |
---|
| 4438 | + |
---|
| 4439 | + if ((vcstate->output_if & VOP_OUTPUT_IF_MIPI1) && dual_channel) |
---|
| 4440 | + VOP_CTRL_SET(vop2, mipi_dual_en, 0); |
---|
4385 | 4441 | |
---|
4386 | 4442 | VOP_MODULE_SET(vop2, vp, dual_channel_en, 0); |
---|
4387 | 4443 | VOP_MODULE_SET(vop2, vp, dual_channel_swap, 0); |
---|
.. | .. |
---|
4548 | 4604 | return ret; |
---|
4549 | 4605 | } |
---|
4550 | 4606 | |
---|
| 4607 | +/* |
---|
| 4608 | + * 1. NV12/NV16/YUYV xoffset must aligned as 2 pixel; |
---|
| 4609 | + * 2. NV12/NV15 yoffset must aligned as 2 pixel; |
---|
| 4610 | + * 3. NV30 xoffset must aligned as 4 pixel; |
---|
| 4611 | + * 4. NV15/NV20 xoffset must aligend as 8 pixel at rk3568/rk3588/rk3528/rk3562, |
---|
| 4612 | + * others must aligned as 4 pixel; |
---|
| 4613 | + */ |
---|
| 4614 | +static int vop2_linear_yuv_format_check(struct drm_plane *plane, struct drm_plane_state *state) |
---|
| 4615 | +{ |
---|
| 4616 | + struct vop2_plane_state *vpstate = to_vop2_plane_state(state); |
---|
| 4617 | + struct drm_crtc *crtc = state->crtc; |
---|
| 4618 | + struct vop2_video_port *vp = to_vop2_video_port(crtc); |
---|
| 4619 | + struct vop2_win *win = to_vop2_win(plane); |
---|
| 4620 | + struct drm_framebuffer *fb = state->fb; |
---|
| 4621 | + struct drm_rect *src = &vpstate->src; |
---|
| 4622 | + u32 val = 0; |
---|
| 4623 | + |
---|
| 4624 | + if (vpstate->afbc_en || vpstate->tiled_en || !fb->format->is_yuv) |
---|
| 4625 | + return 0; |
---|
| 4626 | + |
---|
| 4627 | + switch (fb->format->format) { |
---|
| 4628 | + case DRM_FORMAT_NV12: |
---|
| 4629 | + case DRM_FORMAT_NV21: |
---|
| 4630 | + val = src->x1 >> 16; |
---|
| 4631 | + if (val % 2) { |
---|
| 4632 | + src->x1 = ALIGN(val, 2) << 16; |
---|
| 4633 | + DRM_WARN("VP%d %s src x offset[%d] must aligned as 2 pixel at NV12 fmt, and adjust to: %d\n", vp->id, win->name, val, src->x1 >> 16); |
---|
| 4634 | + } |
---|
| 4635 | + val = src->y1 >> 16; |
---|
| 4636 | + if (val % 2) { |
---|
| 4637 | + src->y1 = ALIGN(val, 2) << 16; |
---|
| 4638 | + DRM_WARN("VP%d %s src y offset[%d] must aligned as 2 pixel at NV12 fmt, and adjust to: %d\n", vp->id, win->name, val, src->y1 >> 16); |
---|
| 4639 | + } |
---|
| 4640 | + break; |
---|
| 4641 | + case DRM_FORMAT_NV15: |
---|
| 4642 | + val = src->y1 >> 16; |
---|
| 4643 | + if (val % 2) { |
---|
| 4644 | + src->y1 = ALIGN(val, 2) << 16; |
---|
| 4645 | + DRM_WARN("VP%d %s src y offset[%d] must aligned as 2 pixel at NV15 fmt, and adjust to: %d\n", vp->id, win->name, val, src->y1 >> 16); |
---|
| 4646 | + } |
---|
| 4647 | + if (vp->vop2->version == VOP_VERSION_RK3568 || |
---|
| 4648 | + vp->vop2->version == VOP_VERSION_RK3588 || |
---|
| 4649 | + vp->vop2->version == VOP_VERSION_RK3528 || |
---|
| 4650 | + vp->vop2->version == VOP_VERSION_RK3562) { |
---|
| 4651 | + val = src->x1 >> 16; |
---|
| 4652 | + if (val % 8) { |
---|
| 4653 | + src->x1 = ALIGN(val, 8) << 16; |
---|
| 4654 | + DRM_WARN("VP%d %s src x offset[%d] must aligned as 8 pixel at NV15 fmt, and adjust to: %d\n", vp->id, win->name, val, src->x1 >> 16); |
---|
| 4655 | + } |
---|
| 4656 | + } else { |
---|
| 4657 | + val = src->x1 >> 16; |
---|
| 4658 | + if (val % 4) { |
---|
| 4659 | + src->x1 = ALIGN(val, 4) << 16; |
---|
| 4660 | + DRM_WARN("VP%d %s src x offset[%d] must aligned as 4 pixel at NV15 fmt, and adjust to: %d\n", vp->id, win->name, val, src->x1 >> 16); |
---|
| 4661 | + } |
---|
| 4662 | + } |
---|
| 4663 | + break; |
---|
| 4664 | + case DRM_FORMAT_NV16: |
---|
| 4665 | + case DRM_FORMAT_NV61: |
---|
| 4666 | + case DRM_FORMAT_YUYV: |
---|
| 4667 | + case DRM_FORMAT_YVYU: |
---|
| 4668 | + case DRM_FORMAT_VYUY: |
---|
| 4669 | + case DRM_FORMAT_UYVY: |
---|
| 4670 | + val = src->x1 >> 16; |
---|
| 4671 | + if (val % 2) { |
---|
| 4672 | + src->x1 = ALIGN(val, 2) << 16; |
---|
| 4673 | + DRM_WARN("VP%d %s src x offset[%d] must aligned as 2 pixel at YUYV fmt, and adjust to: %d\n", vp->id, win->name, val, src->x1 >> 16); |
---|
| 4674 | + } |
---|
| 4675 | + break; |
---|
| 4676 | + case DRM_FORMAT_NV20: |
---|
| 4677 | + if (vp->vop2->version == VOP_VERSION_RK3568 || |
---|
| 4678 | + vp->vop2->version == VOP_VERSION_RK3588 || |
---|
| 4679 | + vp->vop2->version == VOP_VERSION_RK3528 || |
---|
| 4680 | + vp->vop2->version == VOP_VERSION_RK3562) { |
---|
| 4681 | + val = src->x1 >> 16; |
---|
| 4682 | + if (val % 8) { |
---|
| 4683 | + src->x1 = ALIGN(val, 8) << 16; |
---|
| 4684 | + DRM_WARN("VP%d %s src x offset[%d] must aligned as 8 pixel at NV20 fmt, and adjust to: %d\n", vp->id, win->name, val, src->x1 >> 16); |
---|
| 4685 | + } |
---|
| 4686 | + } else { |
---|
| 4687 | + val = src->x1 >> 16; |
---|
| 4688 | + if (val % 4) { |
---|
| 4689 | + src->x1 = ALIGN(val, 4) << 16; |
---|
| 4690 | + DRM_WARN("VP%d %s src x offset[%d] must aligned as 4 pixel at NV20 fmt, and adjust to: %d\n", vp->id, win->name, val, src->x1 >> 16); |
---|
| 4691 | + } |
---|
| 4692 | + } |
---|
| 4693 | + break; |
---|
| 4694 | + case DRM_FORMAT_NV30: |
---|
| 4695 | + val = src->x1 >> 16; |
---|
| 4696 | + if (val % 4) { |
---|
| 4697 | + src->x1 = ALIGN(val, 4) << 16; |
---|
| 4698 | + DRM_WARN("VP%d %s src x offset[%d] must aligned as 4 pixel at NV30 fmt, and adjust to: %d\n", vp->id, win->name, val, src->x1 >> 16); |
---|
| 4699 | + } |
---|
| 4700 | + break; |
---|
| 4701 | + default: |
---|
| 4702 | + return 0; |
---|
| 4703 | + } |
---|
| 4704 | + |
---|
| 4705 | + return 0; |
---|
| 4706 | +} |
---|
| 4707 | + |
---|
4551 | 4708 | static int vop2_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) |
---|
4552 | 4709 | { |
---|
4553 | 4710 | struct vop2_plane_state *vpstate = to_vop2_plane_state(state); |
---|
.. | .. |
---|
4712 | 4869 | return ret; |
---|
4713 | 4870 | } |
---|
4714 | 4871 | |
---|
4715 | | - /* |
---|
4716 | | - * Src.x1 can be odd when do clip, but yuv plane start point |
---|
4717 | | - * need align with 2 pixel. |
---|
4718 | | - */ |
---|
4719 | | - if (fb->format->is_yuv && ((state->src.x1 >> 16) % 2)) { |
---|
4720 | | - DRM_ERROR("Invalid Source: Yuv format not support odd xpos\n"); |
---|
| 4872 | + if (vop2_linear_yuv_format_check(plane, state)) |
---|
4721 | 4873 | return -EINVAL; |
---|
4722 | | - } |
---|
4723 | 4874 | |
---|
4724 | 4875 | if (fb->format->char_per_block[0] == 0) |
---|
4725 | 4876 | offset = ALIGN_DOWN(src->x1 >> 16, tile_size) * fb->format->cpp[0] * tile_size; |
---|
.. | .. |
---|
4773 | 4924 | { |
---|
4774 | 4925 | struct vop2_win *win = to_vop2_win(plane); |
---|
4775 | 4926 | struct vop2 *vop2 = win->vop2; |
---|
| 4927 | + struct drm_crtc *crtc; |
---|
| 4928 | + struct vop2_video_port *vp; |
---|
| 4929 | + |
---|
4776 | 4930 | #if defined(CONFIG_ROCKCHIP_DRM_DEBUG) |
---|
4777 | 4931 | struct vop2_plane_state *vpstate = to_vop2_plane_state(plane->state); |
---|
4778 | 4932 | #endif |
---|
.. | .. |
---|
4785 | 4939 | |
---|
4786 | 4940 | spin_lock(&vop2->reg_lock); |
---|
4787 | 4941 | |
---|
| 4942 | + crtc = old_state->crtc; |
---|
| 4943 | + vp = to_vop2_video_port(crtc); |
---|
| 4944 | + |
---|
4788 | 4945 | vop2_win_disable(win, false); |
---|
4789 | | - if (win->splice_win) |
---|
| 4946 | + vp->enabled_win_mask &= ~BIT(win->phys_id); |
---|
| 4947 | + if (win->splice_win) { |
---|
4790 | 4948 | vop2_win_disable(win->splice_win, false); |
---|
| 4949 | + vp->enabled_win_mask &= ~BIT(win->splice_win->phys_id); |
---|
| 4950 | + } |
---|
4791 | 4951 | |
---|
4792 | 4952 | #if defined(CONFIG_ROCKCHIP_DRM_DEBUG) |
---|
4793 | 4953 | kfree(vpstate->planlist); |
---|
.. | .. |
---|
4957 | 5117 | uint32_t actual_w, actual_h, dsp_w, dsp_h; |
---|
4958 | 5118 | uint32_t dsp_stx, dsp_sty; |
---|
4959 | 5119 | uint32_t act_info, dsp_info, dsp_st; |
---|
4960 | | - uint32_t format; |
---|
| 5120 | + uint32_t format, check_size; |
---|
4961 | 5121 | uint32_t afbc_format; |
---|
4962 | 5122 | uint32_t rb_swap; |
---|
4963 | 5123 | uint32_t uv_swap; |
---|
.. | .. |
---|
5010 | 5170 | actual_w = dsp_w * actual_w / drm_rect_width(dst); |
---|
5011 | 5171 | } |
---|
5012 | 5172 | dsp_h = drm_rect_height(dst); |
---|
5013 | | - if (dst->y1 + dsp_h > adjusted_mode->crtc_vdisplay) { |
---|
| 5173 | + check_size = adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE ? adjusted_mode->vdisplay : adjusted_mode->crtc_vdisplay; |
---|
| 5174 | + if (dst->y1 + dsp_h > check_size) { |
---|
5014 | 5175 | DRM_ERROR("vp%d %s dest->y1[%d] + dsp_h[%d] exceed mode vdisplay[%d]\n", |
---|
5015 | 5176 | vp->id, win->name, dst->y1, dsp_h, adjusted_mode->crtc_vdisplay); |
---|
5016 | 5177 | dsp_h = adjusted_mode->crtc_vdisplay - dst->y1; |
---|
.. | .. |
---|
5025 | 5186 | if (vop2->version == VOP_VERSION_RK3568) { |
---|
5026 | 5187 | /* |
---|
5027 | 5188 | * This is workaround solution for IC design: |
---|
5028 | | - * esmart can't support scale down when actual_w % 16 == 1. |
---|
| 5189 | + * esmart can't support scale down when actual_w % 16 == 1; |
---|
| 5190 | + * esmart can't support scale down when dsp_w % 2 == 1; |
---|
| 5191 | + * esmart actual_w should align as 4 pixel when is linear 10 bit yuv format; |
---|
| 5192 | + * |
---|
| 5193 | + * cluster actual_w should align as 4 pixel when enable afbc; |
---|
5029 | 5194 | */ |
---|
5030 | | - if (!(win->feature & WIN_FEATURE_AFBDC)) { |
---|
| 5195 | + if (!vop2_cluster_window(win)) { |
---|
5031 | 5196 | if (actual_w > dsp_w && (actual_w & 0xf) == 1) { |
---|
5032 | | - DRM_WARN("vp%d %s act_w[%d] MODE 16 == 1\n", vp->id, win->name, actual_w); |
---|
| 5197 | + DRM_WARN("vp%d %s act_w[%d] MODE 16 == 1 at scale down mode\n", vp->id, win->name, actual_w); |
---|
5033 | 5198 | actual_w -= 1; |
---|
| 5199 | + } |
---|
| 5200 | + if (actual_w > dsp_w && (dsp_w & 0x1) == 1) { |
---|
| 5201 | + DRM_WARN("vp%d %s dsp_w[%d] MODE 2 == 1 at scale down mode\n", vp->id, win->name, dsp_w); |
---|
| 5202 | + dsp_w -= 1; |
---|
5034 | 5203 | } |
---|
5035 | 5204 | } |
---|
5036 | 5205 | |
---|
5037 | | - if (vpstate->afbc_en && actual_w % 4) { |
---|
5038 | | - DRM_ERROR("vp%d %s actual_w[%d] should align as 4 pixel when enable afbc\n", |
---|
5039 | | - vp->id, win->name, actual_w); |
---|
| 5206 | + if (vop2_cluster_window(win) && actual_w % 4) { |
---|
| 5207 | + DRM_WARN("vp%d %s actual_w[%d] should align as 4 pixel when enable afbc\n", |
---|
| 5208 | + vp->id, win->name, actual_w); |
---|
5040 | 5209 | actual_w = ALIGN_DOWN(actual_w, 4); |
---|
5041 | 5210 | } |
---|
| 5211 | + } |
---|
| 5212 | + |
---|
| 5213 | + if (is_linear_10bit_yuv(fb->format->format) && actual_w & 0x3) { |
---|
| 5214 | + DRM_WARN("vp%d %s actual_w[%d] should align as 4 pixel when is linear 10 bit yuv format\n", vp->id, win->name, actual_w); |
---|
| 5215 | + actual_w = ALIGN_DOWN(actual_w, 4); |
---|
5042 | 5216 | } |
---|
5043 | 5217 | |
---|
5044 | 5218 | act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff); |
---|
.. | .. |
---|
5198 | 5372 | VOP_WIN_SET(vop2, win, dither_up, dither_up); |
---|
5199 | 5373 | |
---|
5200 | 5374 | VOP_WIN_SET(vop2, win, enable, 1); |
---|
| 5375 | + vp->enabled_win_mask |= BIT(win->phys_id); |
---|
5201 | 5376 | if (vop2_cluster_window(win)) { |
---|
5202 | 5377 | lb_mode = vop2_get_cluster_lb_mode(win, vpstate); |
---|
5203 | 5378 | VOP_CLUSTER_SET(vop2, win, lb_mode, lb_mode); |
---|
.. | .. |
---|
5885 | 6060 | spin_unlock_irqrestore(&vop2->irq_lock, flags); |
---|
5886 | 6061 | } |
---|
5887 | 6062 | |
---|
5888 | | -static int vop2_crtc_loader_protect(struct drm_crtc *crtc, bool on) |
---|
| 6063 | +static int vop2_crtc_get_inital_acm_info(struct drm_crtc *crtc) |
---|
| 6064 | +{ |
---|
| 6065 | + struct vop2_video_port *vp = to_vop2_video_port(crtc); |
---|
| 6066 | + struct vop2 *vop2 = vp->vop2; |
---|
| 6067 | + struct post_acm *acm = &vp->acm_info; |
---|
| 6068 | + s16 *lut_y; |
---|
| 6069 | + s16 *lut_h; |
---|
| 6070 | + s16 *lut_s; |
---|
| 6071 | + u32 value; |
---|
| 6072 | + int i; |
---|
| 6073 | + |
---|
| 6074 | + value = readl(vop2->acm_regs + RK3528_ACM_CTRL); |
---|
| 6075 | + acm->acm_enable = value & 0x1; |
---|
| 6076 | + value = readl(vop2->acm_regs + RK3528_ACM_DELTA_RANGE); |
---|
| 6077 | + acm->y_gain = value & 0x3ff; |
---|
| 6078 | + acm->h_gain = (value >> 10) & 0x3ff; |
---|
| 6079 | + acm->s_gain = (value >> 20) & 0x3ff; |
---|
| 6080 | + |
---|
| 6081 | + lut_y = &acm->gain_lut_hy[0]; |
---|
| 6082 | + lut_h = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH]; |
---|
| 6083 | + lut_s = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH * 2]; |
---|
| 6084 | + for (i = 0; i < ACM_GAIN_LUT_HY_LENGTH; i++) { |
---|
| 6085 | + value = readl(vop2->acm_regs + RK3528_ACM_YHS_DEL_HY_SEG0 + (i << 2)); |
---|
| 6086 | + lut_y[i] = value & 0xff; |
---|
| 6087 | + lut_h[i] = (value >> 8) & 0xff; |
---|
| 6088 | + lut_s[i] = (value >> 16) & 0xff; |
---|
| 6089 | + } |
---|
| 6090 | + |
---|
| 6091 | + lut_y = &acm->gain_lut_hs[0]; |
---|
| 6092 | + lut_h = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH]; |
---|
| 6093 | + lut_s = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH * 2]; |
---|
| 6094 | + for (i = 0; i < ACM_GAIN_LUT_HS_LENGTH; i++) { |
---|
| 6095 | + value = readl(vop2->acm_regs + RK3528_ACM_YHS_DEL_HS_SEG0 + (i << 2)); |
---|
| 6096 | + lut_y[i] = value & 0xff; |
---|
| 6097 | + lut_h[i] = (value >> 8) & 0xff; |
---|
| 6098 | + lut_s[i] = (value >> 16) & 0xff; |
---|
| 6099 | + } |
---|
| 6100 | + |
---|
| 6101 | + lut_y = &acm->delta_lut_h[0]; |
---|
| 6102 | + lut_h = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH]; |
---|
| 6103 | + lut_s = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH * 2]; |
---|
| 6104 | + for (i = 0; i < ACM_DELTA_LUT_H_LENGTH; i++) { |
---|
| 6105 | + value = readl(vop2->acm_regs + RK3528_ACM_YHS_DEL_HGAIN_SEG0 + (i << 2)); |
---|
| 6106 | + lut_y[i] = value & 0x3ff; |
---|
| 6107 | + lut_h[i] = (value >> 12) & 0xff; |
---|
| 6108 | + lut_s[i] = (value >> 20) & 0x3ff; |
---|
| 6109 | + } |
---|
| 6110 | + |
---|
| 6111 | + return 0; |
---|
| 6112 | +} |
---|
| 6113 | + |
---|
| 6114 | +static int vop2_crtc_loader_protect(struct drm_crtc *crtc, bool on, void *data) |
---|
5889 | 6115 | { |
---|
5890 | 6116 | struct vop2_video_port *vp = to_vop2_video_port(crtc); |
---|
5891 | 6117 | struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); |
---|
.. | .. |
---|
5916 | 6142 | win->pd->vp_mask |= BIT(vp->id); |
---|
5917 | 6143 | } |
---|
5918 | 6144 | |
---|
| 6145 | + vp->enabled_win_mask |= BIT(win->phys_id); |
---|
5919 | 6146 | crtc_state = drm_atomic_get_crtc_state(crtc->state->state, crtc); |
---|
5920 | 6147 | mode = &crtc_state->adjusted_mode; |
---|
5921 | 6148 | if (mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) { |
---|
.. | .. |
---|
5928 | 6155 | splice_vp->win_mask |= BIT(splice_win->phys_id); |
---|
5929 | 6156 | splice_win->vp_mask = BIT(splice_vp->id); |
---|
5930 | 6157 | vop2->active_vp_mask |= BIT(splice_vp->id); |
---|
| 6158 | + vp->enabled_win_mask |= BIT(splice_win->phys_id); |
---|
5931 | 6159 | |
---|
5932 | 6160 | if (splice_win->pd && |
---|
5933 | 6161 | VOP_WIN_GET(vop2, splice_win, enable)) { |
---|
.. | .. |
---|
5949 | 6177 | ext_pll->vp_mask |= BIT(vp->id); |
---|
5950 | 6178 | } |
---|
5951 | 6179 | drm_crtc_vblank_on(crtc); |
---|
| 6180 | + if (is_vop3(vop2)) { |
---|
| 6181 | + if (vp_data->feature & (VOP_FEATURE_POST_ACM)) |
---|
| 6182 | + vop2_crtc_get_inital_acm_info(crtc); |
---|
| 6183 | + if (data && (vp_data->feature & VOP_FEATURE_POST_CSC)) |
---|
| 6184 | + memcpy(&vp->csc_info, data, sizeof(struct post_csc)); |
---|
| 6185 | + } |
---|
5952 | 6186 | if (private->cubic_lut[vp->id].enable) { |
---|
5953 | 6187 | dma_addr_t cubic_lut_mst; |
---|
5954 | 6188 | struct loader_cubic_lut *cubic_lut = &private->cubic_lut[vp->id]; |
---|
.. | .. |
---|
6359 | 6593 | |
---|
6360 | 6594 | bandwidth = bandwidth * src_width / dst_width; |
---|
6361 | 6595 | bandwidth = bandwidth * src_height / dst_height; |
---|
6362 | | - if (vskiplines == 2) |
---|
| 6596 | + if (vskiplines == 2 && vpstate->afbc_en == 0) |
---|
6363 | 6597 | bandwidth /= 2; |
---|
6364 | | - else if (vskiplines == 4) |
---|
| 6598 | + else if (vskiplines == 4 && vpstate->afbc_en == 0) |
---|
6365 | 6599 | bandwidth /= 4; |
---|
6366 | 6600 | |
---|
6367 | 6601 | return bandwidth; |
---|
.. | .. |
---|
6455 | 6689 | |
---|
6456 | 6690 | act_w = drm_rect_width(&pstate->src) >> 16; |
---|
6457 | 6691 | act_h = drm_rect_height(&pstate->src) >> 16; |
---|
| 6692 | + if (pstate->fb->format->is_yuv && (act_w >= 3840 || act_h >= 3840)) |
---|
| 6693 | + vop_bw_info->plane_num_4k++; |
---|
| 6694 | + |
---|
6458 | 6695 | bpp = rockchip_drm_get_bpp(pstate->fb->format); |
---|
6459 | 6696 | |
---|
6460 | | - vop_bw_info->frame_bw_mbyte += act_w * act_h / 1000 * bpp / 8 * fps / 1000; |
---|
| 6697 | + vop_bw_info->frame_bw_mbyte += act_w * act_h / 1000 * bpp / 8 * fps / 1000 / afbc_fac; |
---|
6461 | 6698 | } |
---|
6462 | 6699 | |
---|
6463 | 6700 | sort(pbandwidth, cnt, sizeof(pbandwidth[0]), vop2_bandwidth_cmp, NULL); |
---|
.. | .. |
---|
6595 | 6832 | if (mode->flags & DRM_MODE_FLAG_DBLCLK || vcstate->output_if & VOP_OUTPUT_IF_BT656) |
---|
6596 | 6833 | adj_mode->crtc_clock *= 2; |
---|
6597 | 6834 | |
---|
6598 | | - if (vp->mcu_timing.mcu_pix_total) { |
---|
6599 | | - if (vcstate->output_mode == ROCKCHIP_OUT_MODE_S888) |
---|
6600 | | - adj_mode->crtc_clock *= 3; |
---|
6601 | | - else if (vcstate->output_mode == ROCKCHIP_OUT_MODE_S888_DUMMY) |
---|
6602 | | - adj_mode->crtc_clock *= 4; |
---|
6603 | | - } |
---|
| 6835 | + if (vp->mcu_timing.mcu_pix_total) |
---|
| 6836 | + adj_mode->crtc_clock *= rockchip_drm_get_cycles_per_pixel(vcstate->bus_format) * |
---|
| 6837 | + (vp->mcu_timing.mcu_pix_total + 1); |
---|
6604 | 6838 | |
---|
6605 | 6839 | drm_connector_list_iter_begin(crtc->dev, &conn_iter); |
---|
6606 | 6840 | drm_for_each_connector_iter(connector, &conn_iter) { |
---|
.. | .. |
---|
6619 | 6853 | return true; |
---|
6620 | 6854 | } |
---|
6621 | 6855 | |
---|
6622 | | -static void vop2_dither_setup(struct drm_crtc *crtc) |
---|
| 6856 | +static void vop2_dither_setup(struct rockchip_crtc_state *vcstate, struct drm_crtc *crtc) |
---|
6623 | 6857 | { |
---|
6624 | | - struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); |
---|
6625 | 6858 | struct vop2_video_port *vp = to_vop2_video_port(crtc); |
---|
6626 | 6859 | struct vop2 *vop2 = vp->vop2; |
---|
| 6860 | + bool pre_dither_down_en = false; |
---|
6627 | 6861 | |
---|
6628 | 6862 | switch (vcstate->bus_format) { |
---|
6629 | 6863 | case MEDIA_BUS_FMT_RGB565_1X16: |
---|
6630 | 6864 | VOP_MODULE_SET(vop2, vp, dither_down_en, 1); |
---|
6631 | 6865 | VOP_MODULE_SET(vop2, vp, dither_down_mode, RGB888_TO_RGB565); |
---|
6632 | | - VOP_MODULE_SET(vop2, vp, pre_dither_down_en, 1); |
---|
| 6866 | + pre_dither_down_en = true; |
---|
6633 | 6867 | break; |
---|
6634 | 6868 | case MEDIA_BUS_FMT_RGB666_1X18: |
---|
6635 | 6869 | case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: |
---|
6636 | 6870 | case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: |
---|
6637 | 6871 | VOP_MODULE_SET(vop2, vp, dither_down_en, 1); |
---|
6638 | 6872 | VOP_MODULE_SET(vop2, vp, dither_down_mode, RGB888_TO_RGB666); |
---|
6639 | | - VOP_MODULE_SET(vop2, vp, pre_dither_down_en, 1); |
---|
| 6873 | + pre_dither_down_en = true; |
---|
6640 | 6874 | break; |
---|
6641 | 6875 | case MEDIA_BUS_FMT_YUYV8_1X16: |
---|
6642 | 6876 | case MEDIA_BUS_FMT_YUV8_1X24: |
---|
6643 | 6877 | case MEDIA_BUS_FMT_UYYVYY8_0_5X24: |
---|
6644 | 6878 | VOP_MODULE_SET(vop2, vp, dither_down_en, 0); |
---|
6645 | | - VOP_MODULE_SET(vop2, vp, pre_dither_down_en, 1); |
---|
| 6879 | + pre_dither_down_en = true; |
---|
6646 | 6880 | break; |
---|
6647 | 6881 | case MEDIA_BUS_FMT_YUYV10_1X20: |
---|
6648 | 6882 | case MEDIA_BUS_FMT_YUV10_1X30: |
---|
6649 | 6883 | case MEDIA_BUS_FMT_UYYVYY10_0_5X30: |
---|
6650 | 6884 | case MEDIA_BUS_FMT_RGB101010_1X30: |
---|
6651 | 6885 | VOP_MODULE_SET(vop2, vp, dither_down_en, 0); |
---|
6652 | | - VOP_MODULE_SET(vop2, vp, pre_dither_down_en, 0); |
---|
| 6886 | + pre_dither_down_en = false; |
---|
6653 | 6887 | break; |
---|
6654 | 6888 | case MEDIA_BUS_FMT_RGB888_3X8: |
---|
6655 | 6889 | case MEDIA_BUS_FMT_RGB888_DUMMY_4X8: |
---|
.. | .. |
---|
6658 | 6892 | case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: |
---|
6659 | 6893 | default: |
---|
6660 | 6894 | VOP_MODULE_SET(vop2, vp, dither_down_en, 0); |
---|
6661 | | - VOP_MODULE_SET(vop2, vp, pre_dither_down_en, 1); |
---|
| 6895 | + pre_dither_down_en = true; |
---|
6662 | 6896 | break; |
---|
6663 | 6897 | } |
---|
6664 | 6898 | |
---|
| 6899 | + if (is_yuv_output(vcstate->bus_format)) |
---|
| 6900 | + pre_dither_down_en = false; |
---|
| 6901 | + |
---|
| 6902 | + VOP_MODULE_SET(vop2, vp, pre_dither_down_en, pre_dither_down_en); |
---|
6665 | 6903 | VOP_MODULE_SET(vop2, vp, dither_down_sel, DITHER_DOWN_ALLEGRO); |
---|
6666 | 6904 | } |
---|
6667 | 6905 | |
---|
.. | .. |
---|
7266 | 7504 | dsc->enabled = true; |
---|
7267 | 7505 | } |
---|
7268 | 7506 | |
---|
| 7507 | +static inline bool vop2_mark_as_left_panel(struct rockchip_crtc_state *vcstate, u32 output_if) |
---|
| 7508 | +{ |
---|
| 7509 | + return vcstate->output_if_left_panel & output_if; |
---|
| 7510 | +} |
---|
| 7511 | + |
---|
7269 | 7512 | static void vop2_setup_dual_channel_if(struct drm_crtc *crtc) |
---|
7270 | 7513 | { |
---|
7271 | 7514 | struct vop2_video_port *vp = to_vop2_video_port(crtc); |
---|
7272 | 7515 | struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); |
---|
7273 | 7516 | struct vop2 *vop2 = vp->vop2; |
---|
7274 | 7517 | |
---|
| 7518 | + if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE) { |
---|
| 7519 | + VOP_CTRL_SET(vop2, lvds_dual_en, 1); |
---|
| 7520 | + VOP_CTRL_SET(vop2, lvds_dual_mode, 0); |
---|
| 7521 | + if (vcstate->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) |
---|
| 7522 | + VOP_CTRL_SET(vop2, lvds_dual_channel_swap, 1); |
---|
| 7523 | + return; |
---|
| 7524 | + } |
---|
| 7525 | + |
---|
7275 | 7526 | VOP_MODULE_SET(vop2, vp, dual_channel_en, 1); |
---|
7276 | 7527 | if (vcstate->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) |
---|
7277 | 7528 | VOP_MODULE_SET(vop2, vp, dual_channel_swap, 1); |
---|
7278 | 7529 | |
---|
7279 | | - if (vcstate->output_if & VOP_OUTPUT_IF_DP1) |
---|
| 7530 | + if (vcstate->output_if & VOP_OUTPUT_IF_DP1 && |
---|
| 7531 | + !vop2_mark_as_left_panel(vcstate, VOP_OUTPUT_IF_DP1)) |
---|
7280 | 7532 | VOP_CTRL_SET(vop2, dp_dual_en, 1); |
---|
7281 | | - else if (vcstate->output_if & VOP_OUTPUT_IF_eDP1) |
---|
| 7533 | + else if (vcstate->output_if & VOP_OUTPUT_IF_eDP1 && |
---|
| 7534 | + !vop2_mark_as_left_panel(vcstate, VOP_OUTPUT_IF_eDP1)) |
---|
7282 | 7535 | VOP_CTRL_SET(vop2, edp_dual_en, 1); |
---|
7283 | | - else if (vcstate->output_if & VOP_OUTPUT_IF_HDMI1) |
---|
| 7536 | + else if (vcstate->output_if & VOP_OUTPUT_IF_HDMI1 && |
---|
| 7537 | + !vop2_mark_as_left_panel(vcstate, VOP_OUTPUT_IF_HDMI1)) |
---|
7284 | 7538 | VOP_CTRL_SET(vop2, hdmi_dual_en, 1); |
---|
7285 | | - else if (vcstate->output_if & VOP_OUTPUT_IF_MIPI1) |
---|
| 7539 | + else if (vcstate->output_if & VOP_OUTPUT_IF_MIPI1 && |
---|
| 7540 | + !vop2_mark_as_left_panel(vcstate, VOP_OUTPUT_IF_MIPI1)) |
---|
7286 | 7541 | VOP_CTRL_SET(vop2, mipi_dual_en, 1); |
---|
| 7542 | + else if (vcstate->output_if & VOP_OUTPUT_IF_LVDS1) { |
---|
| 7543 | + VOP_CTRL_SET(vop2, lvds_dual_en, 1); |
---|
| 7544 | + VOP_CTRL_SET(vop2, lvds_dual_mode, 1); |
---|
| 7545 | + } |
---|
7287 | 7546 | } |
---|
7288 | 7547 | |
---|
7289 | 7548 | /* |
---|
.. | .. |
---|
7443 | 7702 | } |
---|
7444 | 7703 | } |
---|
7445 | 7704 | |
---|
7446 | | -static int vop2_get_vrefresh(struct vop2_video_port *vp, const struct drm_display_mode *mode) |
---|
7447 | | -{ |
---|
7448 | | - if (vp->mcu_timing.mcu_pix_total) |
---|
7449 | | - return drm_mode_vrefresh(mode) / vp->mcu_timing.mcu_pix_total; |
---|
7450 | | - else |
---|
7451 | | - return drm_mode_vrefresh(mode); |
---|
7452 | | -} |
---|
7453 | | - |
---|
7454 | 7705 | static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) |
---|
7455 | 7706 | { |
---|
7456 | 7707 | struct vop2_video_port *vp = to_vop2_video_port(crtc); |
---|
.. | .. |
---|
7485 | 7736 | int ret; |
---|
7486 | 7737 | |
---|
7487 | 7738 | if (old_state && old_state->self_refresh_active) { |
---|
7488 | | - drm_crtc_vblank_on(crtc); |
---|
7489 | | - if (vop2->aclk_rate_reset) |
---|
7490 | | - clk_set_rate(vop2->aclk, vop2->aclk_rate); |
---|
7491 | | - vop2->aclk_rate_reset = false; |
---|
| 7739 | + vop2_crtc_atomic_exit_psr(crtc, old_state); |
---|
7492 | 7740 | |
---|
7493 | 7741 | return; |
---|
7494 | 7742 | } |
---|
.. | .. |
---|
7497 | 7745 | vop2_set_system_status(vop2); |
---|
7498 | 7746 | |
---|
7499 | 7747 | vop2_lock(vop2); |
---|
7500 | | - DRM_DEV_INFO(vop2->dev, "Update mode to %dx%d%s%d, type: %d(if:%x) for vp%d dclk: %d\n", |
---|
| 7748 | + DRM_DEV_INFO(vop2->dev, "Update mode to %dx%d%s%d, type: %d(if:%x, flag:0x%x) for vp%d dclk: %d\n", |
---|
7501 | 7749 | hdisplay, adjusted_mode->vdisplay, interlaced ? "i" : "p", |
---|
7502 | | - vop2_get_vrefresh(vp, adjusted_mode), vcstate->output_type, vcstate->output_if, |
---|
| 7750 | + drm_mode_vrefresh(adjusted_mode), |
---|
| 7751 | + vcstate->output_type, vcstate->output_if, vcstate->output_flags, |
---|
7503 | 7752 | vp->id, adjusted_mode->crtc_clock * 1000); |
---|
7504 | 7753 | |
---|
7505 | 7754 | if (adjusted_mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) { |
---|
.. | .. |
---|
7510 | 7759 | splice_en = 1; |
---|
7511 | 7760 | vop2->active_vp_mask |= BIT(splice_vp->id); |
---|
7512 | 7761 | } |
---|
| 7762 | + |
---|
| 7763 | + if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CONNECTOR_SPLIT_MODE) |
---|
| 7764 | + vcstate->output_flags |= ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE; |
---|
7513 | 7765 | |
---|
7514 | 7766 | if (vcstate->dsc_enable) { |
---|
7515 | 7767 | int k = 1; |
---|
.. | .. |
---|
7600 | 7852 | VOP_CTRL_SET(vop2, lvds_dclk_pol, dclk_inv); |
---|
7601 | 7853 | } |
---|
7602 | 7854 | |
---|
7603 | | - if (vcstate->output_flags & (ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE | |
---|
7604 | | - ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)) { |
---|
7605 | | - VOP_CTRL_SET(vop2, lvds_dual_en, 1); |
---|
7606 | | - if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) |
---|
7607 | | - VOP_CTRL_SET(vop2, lvds_dual_mode, 1); |
---|
7608 | | - if (vcstate->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) |
---|
7609 | | - VOP_CTRL_SET(vop2, lvds_dual_channel_swap, 1); |
---|
7610 | | - } |
---|
7611 | | - |
---|
7612 | 7855 | if (vcstate->output_if & VOP_OUTPUT_IF_MIPI0) { |
---|
7613 | 7856 | ret = vop2_calc_cru_cfg(crtc, VOP_OUTPUT_IF_MIPI0, &if_pixclk, &if_dclk); |
---|
7614 | 7857 | if (ret < 0) |
---|
.. | .. |
---|
7652 | 7895 | } |
---|
7653 | 7896 | } |
---|
7654 | 7897 | |
---|
7655 | | - if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) |
---|
| 7898 | + if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE || |
---|
| 7899 | + vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE) |
---|
7656 | 7900 | vop2_setup_dual_channel_if(crtc); |
---|
7657 | 7901 | |
---|
7658 | 7902 | if (vcstate->output_if & VOP_OUTPUT_IF_eDP0) { |
---|
.. | .. |
---|
7910 | 8154 | /* |
---|
7911 | 8155 | * restore the lut table. |
---|
7912 | 8156 | */ |
---|
7913 | | - if (vp->gamma_lut_active) |
---|
| 8157 | + if (vp->gamma_lut_active) { |
---|
7914 | 8158 | vop2_crtc_load_lut(crtc); |
---|
| 8159 | + vop2_cfg_done(crtc); |
---|
| 8160 | + vop2_wait_for_fs_by_done_bit_status(vp); |
---|
| 8161 | + } |
---|
7915 | 8162 | out: |
---|
7916 | 8163 | vop2_unlock(vop2); |
---|
7917 | 8164 | } |
---|
.. | .. |
---|
9515 | 9762 | u32 value; |
---|
9516 | 9763 | int i; |
---|
9517 | 9764 | |
---|
9518 | | - if (!acm) { |
---|
9519 | | - writel(0x2, vop2->acm_regs + RK3528_ACM_CTRL); |
---|
9520 | | - VOP_MODULE_SET(vop2, vp, acm_bypass_en, 1); |
---|
| 9765 | + writel(0, vop2->acm_regs + RK3528_ACM_CTRL); |
---|
| 9766 | + VOP_MODULE_SET(vop2, vp, acm_bypass_en, 0); |
---|
| 9767 | + |
---|
| 9768 | + if (!acm || !acm->acm_enable) |
---|
9521 | 9769 | return; |
---|
9522 | | - } |
---|
9523 | 9770 | |
---|
9524 | | - writel(1, vop2->acm_regs + RK3528_ACM_FETCH_START); |
---|
| 9771 | + /* |
---|
| 9772 | + * If acm update parameters, it need disable acm in the first frame, |
---|
| 9773 | + * then update parameters and enable acm in second frame. |
---|
| 9774 | + */ |
---|
| 9775 | + vop2_cfg_done(crtc); |
---|
| 9776 | + readx_poll_timeout(readl, vop2->acm_regs + RK3528_ACM_CTRL, value, !value, 200, 50000); |
---|
9525 | 9777 | |
---|
9526 | | - value = (acm->acm_enable & 0x1) + ((adjusted_mode->hdisplay & 0xfff) << 8) + |
---|
| 9778 | + value = RK3528_ACM_ENABLE + ((adjusted_mode->hdisplay & 0xfff) << 8) + |
---|
9527 | 9779 | ((adjusted_mode->vdisplay & 0xfff) << 20); |
---|
9528 | 9780 | writel(value, vop2->acm_regs + RK3528_ACM_CTRL); |
---|
9529 | | - VOP_MODULE_SET(vop2, vp, acm_bypass_en, acm->acm_enable ? 0 : 1); |
---|
| 9781 | + |
---|
| 9782 | + |
---|
| 9783 | + writel(1, vop2->acm_regs + RK3528_ACM_FETCH_START); |
---|
9530 | 9784 | |
---|
9531 | 9785 | value = (acm->y_gain & 0x3ff) + ((acm->h_gain << 10) & 0xffc00) + |
---|
9532 | 9786 | ((acm->s_gain << 20) & 0x3ff00000); |
---|
.. | .. |
---|
9565 | 9819 | static void vop3_post_config(struct drm_crtc *crtc) |
---|
9566 | 9820 | { |
---|
9567 | 9821 | struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); |
---|
| 9822 | + struct vop2_video_port *vp = to_vop2_video_port(crtc); |
---|
9568 | 9823 | struct post_acm *acm; |
---|
9569 | 9824 | struct post_csc *csc; |
---|
9570 | 9825 | |
---|
9571 | | - acm = vcstate->acm_lut_data ? (struct post_acm *)vcstate->acm_lut_data->data : NULL; |
---|
9572 | | - vop3_post_acm_config(crtc, acm); |
---|
9573 | | - |
---|
9574 | 9826 | csc = vcstate->post_csc_data ? (struct post_csc *)vcstate->post_csc_data->data : NULL; |
---|
9575 | | - vop3_post_csc_config(crtc, acm, csc); |
---|
| 9827 | + if (csc && memcmp(&vp->csc_info, csc, sizeof(struct post_csc))) |
---|
| 9828 | + memcpy(&vp->csc_info, csc, sizeof(struct post_csc)); |
---|
| 9829 | + vop3_post_csc_config(crtc, &vp->acm_info, &vp->csc_info); |
---|
| 9830 | + |
---|
| 9831 | + acm = vcstate->acm_lut_data ? (struct post_acm *)vcstate->acm_lut_data->data : NULL; |
---|
| 9832 | + |
---|
| 9833 | + if (acm && memcmp(&vp->acm_info, acm, sizeof(struct post_acm))) { |
---|
| 9834 | + memcpy(&vp->acm_info, acm, sizeof(struct post_acm)); |
---|
| 9835 | + vop3_post_acm_config(crtc, &vp->acm_info); |
---|
| 9836 | + } else if (crtc->state->active_changed) { |
---|
| 9837 | + vop3_post_acm_config(crtc, &vp->acm_info); |
---|
| 9838 | + } |
---|
9576 | 9839 | } |
---|
9577 | 9840 | |
---|
9578 | 9841 | static void vop2_cfg_update(struct drm_crtc *crtc, |
---|
.. | .. |
---|
9600 | 9863 | |
---|
9601 | 9864 | vop2_post_color_swap(crtc); |
---|
9602 | 9865 | |
---|
9603 | | - vop2_dither_setup(crtc); |
---|
| 9866 | + vop2_dither_setup(vcstate, crtc); |
---|
| 9867 | + if (vcstate->splice_mode) |
---|
| 9868 | + vop2_dither_setup(vcstate, &splice_vp->rockchip_crtc.crtc); |
---|
9604 | 9869 | |
---|
9605 | 9870 | VOP_MODULE_SET(vop2, vp, overlay_mode, vcstate->yuv_overlay); |
---|
9606 | 9871 | |
---|
.. | .. |
---|
9633 | 9898 | if (vp_data->feature & VOP_FEATURE_OVERSCAN) |
---|
9634 | 9899 | vop2_post_config(crtc); |
---|
9635 | 9900 | |
---|
| 9901 | + spin_unlock(&vop2->reg_lock); |
---|
| 9902 | + |
---|
9636 | 9903 | if (vp_data->feature & (VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC)) |
---|
9637 | 9904 | vop3_post_config(crtc); |
---|
9638 | | - |
---|
9639 | | - spin_unlock(&vop2->reg_lock); |
---|
9640 | 9905 | } |
---|
9641 | 9906 | |
---|
9642 | 9907 | static void vop2_sleep_scan_line_time(struct vop2_video_port *vp, int scan_line) |
---|
.. | .. |
---|
9755 | 10020 | vp->gamma_lut = crtc->state->gamma_lut->data; |
---|
9756 | 10021 | vop2_crtc_atomic_gamma_set(crtc, crtc->state); |
---|
9757 | 10022 | } |
---|
9758 | | -#if defined(CONFIG_ROCKCHIP_DRM_CUBIC_LUT) |
---|
9759 | | - if (crtc->state->cubic_lut || vp->cubic_lut) { |
---|
9760 | | - if (crtc->state->cubic_lut) |
---|
9761 | | - vp->cubic_lut = crtc->state->cubic_lut->data; |
---|
| 10023 | + if (vcstate->cubic_lut_data || vp->cubic_lut) { |
---|
| 10024 | + if (vcstate->cubic_lut_data) |
---|
| 10025 | + vp->cubic_lut = vcstate->cubic_lut_data->data; |
---|
9762 | 10026 | vop2_crtc_atomic_cubic_lut_set(crtc, crtc->state); |
---|
9763 | 10027 | } |
---|
9764 | | -#endif |
---|
9765 | 10028 | } else { |
---|
9766 | 10029 | VOP_MODULE_SET(vop2, vp, cubic_lut_update_en, 0); |
---|
9767 | 10030 | } |
---|
.. | .. |
---|
9874 | 10137 | drm_property_blob_get(vcstate->acm_lut_data); |
---|
9875 | 10138 | if (vcstate->post_csc_data) |
---|
9876 | 10139 | drm_property_blob_get(vcstate->post_csc_data); |
---|
| 10140 | + if (vcstate->cubic_lut_data) |
---|
| 10141 | + drm_property_blob_get(vcstate->cubic_lut_data); |
---|
9877 | 10142 | |
---|
9878 | 10143 | __drm_atomic_helper_crtc_duplicate_state(crtc, &vcstate->base); |
---|
9879 | 10144 | return &vcstate->base; |
---|
.. | .. |
---|
9888 | 10153 | drm_property_blob_put(vcstate->hdr_ext_data); |
---|
9889 | 10154 | drm_property_blob_put(vcstate->acm_lut_data); |
---|
9890 | 10155 | drm_property_blob_put(vcstate->post_csc_data); |
---|
| 10156 | + drm_property_blob_put(vcstate->cubic_lut_data); |
---|
9891 | 10157 | kfree(vcstate); |
---|
9892 | 10158 | } |
---|
9893 | 10159 | |
---|
.. | .. |
---|
10034 | 10300 | return 0; |
---|
10035 | 10301 | } |
---|
10036 | 10302 | |
---|
| 10303 | + if (property == private->cubic_lut_prop) { |
---|
| 10304 | + *val = (vcstate->cubic_lut_data) ? vcstate->cubic_lut_data->base.id : 0; |
---|
| 10305 | + return 0; |
---|
| 10306 | + } |
---|
| 10307 | + |
---|
10037 | 10308 | DRM_ERROR("failed to get vop2 crtc property: %s\n", property->name); |
---|
10038 | 10309 | |
---|
10039 | 10310 | return -EINVAL; |
---|
.. | .. |
---|
10156 | 10427 | val, |
---|
10157 | 10428 | sizeof(struct post_csc), -1, |
---|
10158 | 10429 | &replaced); |
---|
| 10430 | + return ret; |
---|
| 10431 | + } |
---|
| 10432 | + |
---|
| 10433 | + if (property == private->cubic_lut_prop) { |
---|
| 10434 | + ret = vop2_atomic_replace_property_blob_from_id(drm_dev, |
---|
| 10435 | + &vcstate->cubic_lut_data, |
---|
| 10436 | + val, |
---|
| 10437 | + -1, sizeof(struct drm_color_lut), |
---|
| 10438 | + &replaced); |
---|
| 10439 | + state->color_mgmt_changed |= replaced; |
---|
10159 | 10440 | return ret; |
---|
10160 | 10441 | } |
---|
10161 | 10442 | |
---|
.. | .. |
---|
10790 | 11071 | { ROCKCHIP_DRM_CRTC_FEATURE_ALPHA_SCALE, "ALPHA_SCALE" }, |
---|
10791 | 11072 | { ROCKCHIP_DRM_CRTC_FEATURE_HDR10, "HDR10" }, |
---|
10792 | 11073 | { ROCKCHIP_DRM_CRTC_FEATURE_NEXT_HDR, "NEXT_HDR" }, |
---|
| 11074 | + { ROCKCHIP_DRM_CRTC_FEATURE_VIVID_HDR, "VIVID_HDR" }, |
---|
10793 | 11075 | }; |
---|
10794 | 11076 | |
---|
10795 | 11077 | if (vp_data->feature & VOP_FEATURE_ALPHA_SCALE) |
---|
.. | .. |
---|
10798 | 11080 | feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_HDR10); |
---|
10799 | 11081 | if (vp_data->feature & VOP_FEATURE_NEXT_HDR) |
---|
10800 | 11082 | feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_NEXT_HDR); |
---|
| 11083 | + if (vp_data->feature & VOP_FEATURE_VIVID_HDR) |
---|
| 11084 | + feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_VIVID_HDR); |
---|
10801 | 11085 | |
---|
10802 | 11086 | prop = drm_property_create_bitmask(vop2->drm_dev, |
---|
10803 | 11087 | DRM_MODE_PROP_IMMUTABLE, "FEATURE", |
---|