hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
kernel/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
....@@ -643,6 +643,11 @@
643643 */
644644 uint32_t win_mask;
645645 /**
646
+ * @enabled_win_mask: Bitmask of enabled wins attached to the video port;
647
+ */
648
+ uint32_t enabled_win_mask;
649
+
650
+ /**
646651 * @nr_layers: active layers attached to the video port;
647652 */
648653 uint8_t nr_layers;
....@@ -769,6 +774,9 @@
769774 * will be used to show uboot logo and kernel logo
770775 */
771776 enum vop2_layer_phy_id primary_plane_phy_id;
777
+
778
+ struct post_acm acm_info;
779
+ struct post_csc csc_info;
772780
773781 /**
774782 * @refresh_rate_change: indicate whether refresh rate change
....@@ -1870,6 +1878,18 @@
18701878 static inline uint32_t vop2_read_lut(struct vop2 *vop2, uint32_t offset)
18711879 {
18721880 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
+ }
18731893 }
18741894
18751895 static enum vop2_data_format vop2_convert_format(uint32_t format)
....@@ -3383,7 +3403,6 @@
33833403
33843404 VOP_MODULE_SET(vop2, vp, dsp_lut_en, 1);
33853405 vop2_write_reg_uncached(vop2, &vp->regs->gamma_update_en, 1);
3386
- vop2_cfg_done(crtc);
33873406 vp->gamma_lut_active = true;
33883407
33893408 spin_unlock(&vop2->reg_lock);
....@@ -3430,26 +3449,7 @@
34303449 rk3588_crtc_load_lut(&vp->rockchip_crtc.crtc, vp->lut);
34313450 if (vcstate->splice_mode)
34323451 rk3588_crtc_load_lut(&splice_vp->rockchip_crtc.crtc, vp->lut);
3433
- vop2_cfg_done(crtc);
34343452 }
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);
34533453 }
34543454
34553455 static void rockchip_vop2_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red,
....@@ -3491,6 +3491,7 @@
34913491 struct drm_modeset_acquire_ctx *ctx)
34923492 {
34933493 struct vop2_video_port *vp = to_vop2_video_port(crtc);
3494
+ struct vop2 *vop2 = vp->vop2;
34943495 int i;
34953496
34963497 if (!vp->lut)
....@@ -3505,6 +3506,25 @@
35053506 rockchip_vop2_crtc_fb_gamma_set(crtc, red[i], green[i],
35063507 blue[i], i);
35073508 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);
35083528
35093529 return 0;
35103530 }
....@@ -3524,7 +3544,6 @@
35243544 return 0;
35253545 }
35263546
3527
-#if defined(CONFIG_ROCKCHIP_DRM_CUBIC_LUT)
35283547 static int vop2_crtc_atomic_cubic_lut_set(struct drm_crtc *crtc,
35293548 struct drm_crtc_state *old_state)
35303549 {
....@@ -3597,18 +3616,12 @@
35973616 return 0;
35983617 }
35993618
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)
36013620 {
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;
36043622
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);
36123625 }
36133626
36143627 static void vop2_cubic_lut_init(struct vop2 *vop2)
....@@ -3628,12 +3641,9 @@
36283641 vp->cubic_lut_len = vp_data->cubic_lut_len;
36293642
36303643 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);
36323645 }
36333646 }
3634
-#else
3635
-static void vop2_cubic_lut_init(struct vop2 *vop2) { }
3636
-#endif
36373647
36383648 static int vop2_core_clks_prepare_enable(struct vop2 *vop2)
36393649 {
....@@ -4276,13 +4286,24 @@
42764286 return 0;
42774287 }
42784288
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)
42814290 {
42824291 struct vop2_video_port *vp = to_vop2_video_port(crtc);
42834292 struct vop2 *vop2 = vp->vop2;
4293
+ struct vop2_win *win;
4294
+ unsigned long win_mask = vp->enabled_win_mask;
4295
+ int phys_id;
42844296
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);
42864307 drm_crtc_vblank_off(crtc);
42874308 if (hweight8(vop2->active_vp_mask) == 1) {
42884309 u32 adjust_aclk_rate = 0;
....@@ -4305,6 +4326,30 @@
43054326 }
43064327 }
43074328
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
+
43084353 static void vop2_crtc_atomic_disable(struct drm_crtc *crtc,
43094354 struct drm_crtc_state *old_state)
43104355 {
....@@ -4319,7 +4364,7 @@
43194364 WARN_ON(vp->event);
43204365
43214366 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);
43234368 goto out;
43244369 }
43254370
....@@ -4370,8 +4415,11 @@
43704415 if (vp->output_if & VOP_OUTPUT_IF_eDP0)
43714416 VOP_GRF_SET(vop2, grf, grf_edp0_en, 0);
43724417
4373
- if (vp->output_if & VOP_OUTPUT_IF_eDP1)
4418
+ if (vp->output_if & VOP_OUTPUT_IF_eDP1) {
43744419 VOP_GRF_SET(vop2, grf, grf_edp1_en, 0);
4420
+ if (dual_channel)
4421
+ VOP_CTRL_SET(vop2, edp_dual_en, 0);
4422
+ }
43754423
43764424 if (vp->output_if & VOP_OUTPUT_IF_HDMI0) {
43774425 VOP_GRF_SET(vop2, grf, grf_hdmi0_dsc_en, 0);
....@@ -4381,7 +4429,15 @@
43814429 if (vp->output_if & VOP_OUTPUT_IF_HDMI1) {
43824430 VOP_GRF_SET(vop2, grf, grf_hdmi1_dsc_en, 0);
43834431 VOP_GRF_SET(vop2, grf, grf_hdmi1_en, 0);
4432
+ if (dual_channel)
4433
+ VOP_CTRL_SET(vop2, hdmi_dual_en, 0);
43844434 }
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);
43854441
43864442 VOP_MODULE_SET(vop2, vp, dual_channel_en, 0);
43874443 VOP_MODULE_SET(vop2, vp, dual_channel_swap, 0);
....@@ -4548,6 +4604,107 @@
45484604 return ret;
45494605 }
45504606
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
+
45514708 static int vop2_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
45524709 {
45534710 struct vop2_plane_state *vpstate = to_vop2_plane_state(state);
....@@ -4712,14 +4869,8 @@
47124869 return ret;
47134870 }
47144871
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))
47214873 return -EINVAL;
4722
- }
47234874
47244875 if (fb->format->char_per_block[0] == 0)
47254876 offset = ALIGN_DOWN(src->x1 >> 16, tile_size) * fb->format->cpp[0] * tile_size;
....@@ -4773,6 +4924,9 @@
47734924 {
47744925 struct vop2_win *win = to_vop2_win(plane);
47754926 struct vop2 *vop2 = win->vop2;
4927
+ struct drm_crtc *crtc;
4928
+ struct vop2_video_port *vp;
4929
+
47764930 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
47774931 struct vop2_plane_state *vpstate = to_vop2_plane_state(plane->state);
47784932 #endif
....@@ -4785,9 +4939,15 @@
47854939
47864940 spin_lock(&vop2->reg_lock);
47874941
4942
+ crtc = old_state->crtc;
4943
+ vp = to_vop2_video_port(crtc);
4944
+
47884945 vop2_win_disable(win, false);
4789
- if (win->splice_win)
4946
+ vp->enabled_win_mask &= ~BIT(win->phys_id);
4947
+ if (win->splice_win) {
47904948 vop2_win_disable(win->splice_win, false);
4949
+ vp->enabled_win_mask &= ~BIT(win->splice_win->phys_id);
4950
+ }
47914951
47924952 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
47934953 kfree(vpstate->planlist);
....@@ -4957,7 +5117,7 @@
49575117 uint32_t actual_w, actual_h, dsp_w, dsp_h;
49585118 uint32_t dsp_stx, dsp_sty;
49595119 uint32_t act_info, dsp_info, dsp_st;
4960
- uint32_t format;
5120
+ uint32_t format, check_size;
49615121 uint32_t afbc_format;
49625122 uint32_t rb_swap;
49635123 uint32_t uv_swap;
....@@ -5010,7 +5170,8 @@
50105170 actual_w = dsp_w * actual_w / drm_rect_width(dst);
50115171 }
50125172 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) {
50145175 DRM_ERROR("vp%d %s dest->y1[%d] + dsp_h[%d] exceed mode vdisplay[%d]\n",
50155176 vp->id, win->name, dst->y1, dsp_h, adjusted_mode->crtc_vdisplay);
50165177 dsp_h = adjusted_mode->crtc_vdisplay - dst->y1;
....@@ -5025,20 +5186,33 @@
50255186 if (vop2->version == VOP_VERSION_RK3568) {
50265187 /*
50275188 * 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;
50295194 */
5030
- if (!(win->feature & WIN_FEATURE_AFBDC)) {
5195
+ if (!vop2_cluster_window(win)) {
50315196 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);
50335198 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;
50345203 }
50355204 }
50365205
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);
50405209 actual_w = ALIGN_DOWN(actual_w, 4);
50415210 }
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);
50425216 }
50435217
50445218 act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff);
....@@ -5198,6 +5372,7 @@
51985372 VOP_WIN_SET(vop2, win, dither_up, dither_up);
51995373
52005374 VOP_WIN_SET(vop2, win, enable, 1);
5375
+ vp->enabled_win_mask |= BIT(win->phys_id);
52015376 if (vop2_cluster_window(win)) {
52025377 lb_mode = vop2_get_cluster_lb_mode(win, vpstate);
52035378 VOP_CLUSTER_SET(vop2, win, lb_mode, lb_mode);
....@@ -5885,7 +6060,58 @@
58856060 spin_unlock_irqrestore(&vop2->irq_lock, flags);
58866061 }
58876062
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)
58896115 {
58906116 struct vop2_video_port *vp = to_vop2_video_port(crtc);
58916117 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
....@@ -5916,6 +6142,7 @@
59166142 win->pd->vp_mask |= BIT(vp->id);
59176143 }
59186144
6145
+ vp->enabled_win_mask |= BIT(win->phys_id);
59196146 crtc_state = drm_atomic_get_crtc_state(crtc->state->state, crtc);
59206147 mode = &crtc_state->adjusted_mode;
59216148 if (mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) {
....@@ -5928,6 +6155,7 @@
59286155 splice_vp->win_mask |= BIT(splice_win->phys_id);
59296156 splice_win->vp_mask = BIT(splice_vp->id);
59306157 vop2->active_vp_mask |= BIT(splice_vp->id);
6158
+ vp->enabled_win_mask |= BIT(splice_win->phys_id);
59316159
59326160 if (splice_win->pd &&
59336161 VOP_WIN_GET(vop2, splice_win, enable)) {
....@@ -5949,6 +6177,12 @@
59496177 ext_pll->vp_mask |= BIT(vp->id);
59506178 }
59516179 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
+ }
59526186 if (private->cubic_lut[vp->id].enable) {
59536187 dma_addr_t cubic_lut_mst;
59546188 struct loader_cubic_lut *cubic_lut = &private->cubic_lut[vp->id];
....@@ -6359,9 +6593,9 @@
63596593
63606594 bandwidth = bandwidth * src_width / dst_width;
63616595 bandwidth = bandwidth * src_height / dst_height;
6362
- if (vskiplines == 2)
6596
+ if (vskiplines == 2 && vpstate->afbc_en == 0)
63636597 bandwidth /= 2;
6364
- else if (vskiplines == 4)
6598
+ else if (vskiplines == 4 && vpstate->afbc_en == 0)
63656599 bandwidth /= 4;
63666600
63676601 return bandwidth;
....@@ -6455,9 +6689,12 @@
64556689
64566690 act_w = drm_rect_width(&pstate->src) >> 16;
64576691 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
+
64586695 bpp = rockchip_drm_get_bpp(pstate->fb->format);
64596696
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;
64616698 }
64626699
64636700 sort(pbandwidth, cnt, sizeof(pbandwidth[0]), vop2_bandwidth_cmp, NULL);
....@@ -6595,12 +6832,9 @@
65956832 if (mode->flags & DRM_MODE_FLAG_DBLCLK || vcstate->output_if & VOP_OUTPUT_IF_BT656)
65966833 adj_mode->crtc_clock *= 2;
65976834
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);
66046838
66056839 drm_connector_list_iter_begin(crtc->dev, &conn_iter);
66066840 drm_for_each_connector_iter(connector, &conn_iter) {
....@@ -6619,37 +6853,37 @@
66196853 return true;
66206854 }
66216855
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)
66236857 {
6624
- struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
66256858 struct vop2_video_port *vp = to_vop2_video_port(crtc);
66266859 struct vop2 *vop2 = vp->vop2;
6860
+ bool pre_dither_down_en = false;
66276861
66286862 switch (vcstate->bus_format) {
66296863 case MEDIA_BUS_FMT_RGB565_1X16:
66306864 VOP_MODULE_SET(vop2, vp, dither_down_en, 1);
66316865 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;
66336867 break;
66346868 case MEDIA_BUS_FMT_RGB666_1X18:
66356869 case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
66366870 case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
66376871 VOP_MODULE_SET(vop2, vp, dither_down_en, 1);
66386872 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;
66406874 break;
66416875 case MEDIA_BUS_FMT_YUYV8_1X16:
66426876 case MEDIA_BUS_FMT_YUV8_1X24:
66436877 case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
66446878 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;
66466880 break;
66476881 case MEDIA_BUS_FMT_YUYV10_1X20:
66486882 case MEDIA_BUS_FMT_YUV10_1X30:
66496883 case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
66506884 case MEDIA_BUS_FMT_RGB101010_1X30:
66516885 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;
66536887 break;
66546888 case MEDIA_BUS_FMT_RGB888_3X8:
66556889 case MEDIA_BUS_FMT_RGB888_DUMMY_4X8:
....@@ -6658,10 +6892,14 @@
66586892 case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
66596893 default:
66606894 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;
66626896 break;
66636897 }
66646898
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);
66656903 VOP_MODULE_SET(vop2, vp, dither_down_sel, DITHER_DOWN_ALLEGRO);
66666904 }
66676905
....@@ -7266,24 +7504,45 @@
72667504 dsc->enabled = true;
72677505 }
72687506
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
+
72697512 static void vop2_setup_dual_channel_if(struct drm_crtc *crtc)
72707513 {
72717514 struct vop2_video_port *vp = to_vop2_video_port(crtc);
72727515 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
72737516 struct vop2 *vop2 = vp->vop2;
72747517
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
+
72757526 VOP_MODULE_SET(vop2, vp, dual_channel_en, 1);
72767527 if (vcstate->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
72777528 VOP_MODULE_SET(vop2, vp, dual_channel_swap, 1);
72787529
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))
72807532 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))
72827535 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))
72847538 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))
72867541 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
+ }
72877546 }
72887547
72897548 /*
....@@ -7443,14 +7702,6 @@
74437702 }
74447703 }
74457704
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
-
74547705 static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
74557706 {
74567707 struct vop2_video_port *vp = to_vop2_video_port(crtc);
....@@ -7485,10 +7736,7 @@
74857736 int ret;
74867737
74877738 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);
74927740
74937741 return;
74947742 }
....@@ -7497,9 +7745,10 @@
74977745 vop2_set_system_status(vop2);
74987746
74997747 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",
75017749 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,
75037752 vp->id, adjusted_mode->crtc_clock * 1000);
75047753
75057754 if (adjusted_mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) {
....@@ -7510,6 +7759,9 @@
75107759 splice_en = 1;
75117760 vop2->active_vp_mask |= BIT(splice_vp->id);
75127761 }
7762
+
7763
+ if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CONNECTOR_SPLIT_MODE)
7764
+ vcstate->output_flags |= ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE;
75137765
75147766 if (vcstate->dsc_enable) {
75157767 int k = 1;
....@@ -7600,15 +7852,6 @@
76007852 VOP_CTRL_SET(vop2, lvds_dclk_pol, dclk_inv);
76017853 }
76027854
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
-
76127855 if (vcstate->output_if & VOP_OUTPUT_IF_MIPI0) {
76137856 ret = vop2_calc_cru_cfg(crtc, VOP_OUTPUT_IF_MIPI0, &if_pixclk, &if_dclk);
76147857 if (ret < 0)
....@@ -7652,7 +7895,8 @@
76527895 }
76537896 }
76547897
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)
76567900 vop2_setup_dual_channel_if(crtc);
76577901
76587902 if (vcstate->output_if & VOP_OUTPUT_IF_eDP0) {
....@@ -7910,8 +8154,11 @@
79108154 /*
79118155 * restore the lut table.
79128156 */
7913
- if (vp->gamma_lut_active)
8157
+ if (vp->gamma_lut_active) {
79148158 vop2_crtc_load_lut(crtc);
8159
+ vop2_cfg_done(crtc);
8160
+ vop2_wait_for_fs_by_done_bit_status(vp);
8161
+ }
79158162 out:
79168163 vop2_unlock(vop2);
79178164 }
....@@ -9515,18 +9762,25 @@
95159762 u32 value;
95169763 int i;
95179764
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)
95219769 return;
9522
- }
95239770
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);
95259777
9526
- value = (acm->acm_enable & 0x1) + ((adjusted_mode->hdisplay & 0xfff) << 8) +
9778
+ value = RK3528_ACM_ENABLE + ((adjusted_mode->hdisplay & 0xfff) << 8) +
95279779 ((adjusted_mode->vdisplay & 0xfff) << 20);
95289780 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);
95309784
95319785 value = (acm->y_gain & 0x3ff) + ((acm->h_gain << 10) & 0xffc00) +
95329786 ((acm->s_gain << 20) & 0x3ff00000);
....@@ -9565,14 +9819,23 @@
95659819 static void vop3_post_config(struct drm_crtc *crtc)
95669820 {
95679821 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
9822
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
95689823 struct post_acm *acm;
95699824 struct post_csc *csc;
95709825
9571
- acm = vcstate->acm_lut_data ? (struct post_acm *)vcstate->acm_lut_data->data : NULL;
9572
- vop3_post_acm_config(crtc, acm);
9573
-
95749826 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
+ }
95769839 }
95779840
95789841 static void vop2_cfg_update(struct drm_crtc *crtc,
....@@ -9600,7 +9863,9 @@
96009863
96019864 vop2_post_color_swap(crtc);
96029865
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);
96049869
96059870 VOP_MODULE_SET(vop2, vp, overlay_mode, vcstate->yuv_overlay);
96069871
....@@ -9633,10 +9898,10 @@
96339898 if (vp_data->feature & VOP_FEATURE_OVERSCAN)
96349899 vop2_post_config(crtc);
96359900
9901
+ spin_unlock(&vop2->reg_lock);
9902
+
96369903 if (vp_data->feature & (VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC))
96379904 vop3_post_config(crtc);
9638
-
9639
- spin_unlock(&vop2->reg_lock);
96409905 }
96419906
96429907 static void vop2_sleep_scan_line_time(struct vop2_video_port *vp, int scan_line)
....@@ -9755,13 +10020,11 @@
975510020 vp->gamma_lut = crtc->state->gamma_lut->data;
975610021 vop2_crtc_atomic_gamma_set(crtc, crtc->state);
975710022 }
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;
976210026 vop2_crtc_atomic_cubic_lut_set(crtc, crtc->state);
976310027 }
9764
-#endif
976510028 } else {
976610029 VOP_MODULE_SET(vop2, vp, cubic_lut_update_en, 0);
976710030 }
....@@ -9874,6 +10137,8 @@
987410137 drm_property_blob_get(vcstate->acm_lut_data);
987510138 if (vcstate->post_csc_data)
987610139 drm_property_blob_get(vcstate->post_csc_data);
10140
+ if (vcstate->cubic_lut_data)
10141
+ drm_property_blob_get(vcstate->cubic_lut_data);
987710142
987810143 __drm_atomic_helper_crtc_duplicate_state(crtc, &vcstate->base);
987910144 return &vcstate->base;
....@@ -9888,6 +10153,7 @@
988810153 drm_property_blob_put(vcstate->hdr_ext_data);
988910154 drm_property_blob_put(vcstate->acm_lut_data);
989010155 drm_property_blob_put(vcstate->post_csc_data);
10156
+ drm_property_blob_put(vcstate->cubic_lut_data);
989110157 kfree(vcstate);
989210158 }
989310159
....@@ -10034,6 +10300,11 @@
1003410300 return 0;
1003510301 }
1003610302
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
+
1003710308 DRM_ERROR("failed to get vop2 crtc property: %s\n", property->name);
1003810309
1003910310 return -EINVAL;
....@@ -10156,6 +10427,16 @@
1015610427 val,
1015710428 sizeof(struct post_csc), -1,
1015810429 &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;
1015910440 return ret;
1016010441 }
1016110442
....@@ -10790,6 +11071,7 @@
1079011071 { ROCKCHIP_DRM_CRTC_FEATURE_ALPHA_SCALE, "ALPHA_SCALE" },
1079111072 { ROCKCHIP_DRM_CRTC_FEATURE_HDR10, "HDR10" },
1079211073 { ROCKCHIP_DRM_CRTC_FEATURE_NEXT_HDR, "NEXT_HDR" },
11074
+ { ROCKCHIP_DRM_CRTC_FEATURE_VIVID_HDR, "VIVID_HDR" },
1079311075 };
1079411076
1079511077 if (vp_data->feature & VOP_FEATURE_ALPHA_SCALE)
....@@ -10798,6 +11080,8 @@
1079811080 feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_HDR10);
1079911081 if (vp_data->feature & VOP_FEATURE_NEXT_HDR)
1080011082 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);
1080111085
1080211086 prop = drm_property_create_bitmask(vop2->drm_dev,
1080311087 DRM_MODE_PROP_IMMUTABLE, "FEATURE",