forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-31 f70575805708cabdedea7498aaa3f710fde4d920
kernel/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
....@@ -20,7 +20,6 @@
2020 #ifdef CONFIG_DRM_ANALOGIX_DP
2121 #include <drm/bridge/analogix_dp.h>
2222 #endif
23
-#include <dt-bindings/soc/rockchip-system-status.h>
2423
2524 #include <linux/debugfs.h>
2625 #include <linux/fixp-arith.h>
....@@ -46,6 +45,7 @@
4645 #include <linux/rockchip/cpu.h>
4746 #include <linux/workqueue.h>
4847 #include <linux/types.h>
48
+#include <soc/rockchip/rockchip_csu.h>
4949 #include <soc/rockchip/rockchip_dmc.h>
5050 #include <soc/rockchip/rockchip-system-status.h>
5151 #include <uapi/linux/videodev2.h>
....@@ -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;
....@@ -770,6 +775,9 @@
770775 */
771776 enum vop2_layer_phy_id primary_plane_phy_id;
772777
778
+ struct post_acm acm_info;
779
+ struct post_csc csc_info;
780
+
773781 /**
774782 * @refresh_rate_change: indicate whether refresh rate change
775783 */
....@@ -877,6 +885,7 @@
877885 struct clk *pclk;
878886 struct reset_control *ahb_rst;
879887 struct reset_control *axi_rst;
888
+ struct csu_clk *csu_aclk;
880889
881890 /* list_head of extend clk */
882891 struct list_head extend_clk_list_head;
....@@ -921,6 +930,7 @@
921930 { MEDIA_BUS_FMT_UYYVYY8_0_5X24, "UYYVYY8_0_5X24" },
922931 { MEDIA_BUS_FMT_YUV10_1X30, "YUV10_1X30" },
923932 { MEDIA_BUS_FMT_UYYVYY10_0_5X30, "UYYVYY10_0_5X30" },
933
+ { MEDIA_BUS_FMT_RGB565_2X8_LE, "RGB565_2X8_LE" },
924934 { MEDIA_BUS_FMT_RGB888_3X8, "RGB888_3X8" },
925935 { MEDIA_BUS_FMT_RGB888_DUMMY_4X8, "RGB888_DUMMY_4X8" },
926936 { MEDIA_BUS_FMT_RGB888_1X24, "RGB888_1X24" },
....@@ -1870,6 +1880,18 @@
18701880 static inline uint32_t vop2_read_lut(struct vop2 *vop2, uint32_t offset)
18711881 {
18721882 return readl(vop2->lut_regs + offset);
1883
+}
1884
+
1885
+static bool is_linear_10bit_yuv(uint32_t format)
1886
+{
1887
+ switch (format) {
1888
+ case DRM_FORMAT_NV15:
1889
+ case DRM_FORMAT_NV20:
1890
+ case DRM_FORMAT_NV30:
1891
+ return true;
1892
+ default:
1893
+ return false;
1894
+ }
18731895 }
18741896
18751897 static enum vop2_data_format vop2_convert_format(uint32_t format)
....@@ -3223,8 +3245,21 @@
32233245 return 0;
32243246 }
32253247
3248
+static void vop2_wb_encoder_atomic_disable(struct drm_encoder *encoder,
3249
+ struct drm_atomic_state *state)
3250
+{
3251
+ struct drm_crtc *crtc = encoder->crtc;
3252
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
3253
+
3254
+ if (!crtc->state->active_changed && !crtc->state->mode_changed) {
3255
+ crtc->state->connectors_changed = false;
3256
+ DRM_DEBUG("VP%d force change connectors_changed to false when disable wb\n", vp->id);
3257
+ }
3258
+}
3259
+
32263260 static const struct drm_encoder_helper_funcs vop2_wb_encoder_helper_funcs = {
32273261 .atomic_check = vop2_wb_encoder_atomic_check,
3262
+ .atomic_disable = vop2_wb_encoder_atomic_disable,
32283263 };
32293264
32303265 static const struct drm_connector_helper_funcs vop2_wb_connector_helper_funcs = {
....@@ -3383,7 +3418,6 @@
33833418
33843419 VOP_MODULE_SET(vop2, vp, dsp_lut_en, 1);
33853420 vop2_write_reg_uncached(vop2, &vp->regs->gamma_update_en, 1);
3386
- vop2_cfg_done(crtc);
33873421 vp->gamma_lut_active = true;
33883422
33893423 spin_unlock(&vop2->reg_lock);
....@@ -3430,26 +3464,7 @@
34303464 rk3588_crtc_load_lut(&vp->rockchip_crtc.crtc, vp->lut);
34313465 if (vcstate->splice_mode)
34323466 rk3588_crtc_load_lut(&splice_vp->rockchip_crtc.crtc, vp->lut);
3433
- vop2_cfg_done(crtc);
34343467 }
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);
34533468 }
34543469
34553470 static void rockchip_vop2_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red,
....@@ -3491,6 +3506,7 @@
34913506 struct drm_modeset_acquire_ctx *ctx)
34923507 {
34933508 struct vop2_video_port *vp = to_vop2_video_port(crtc);
3509
+ struct vop2 *vop2 = vp->vop2;
34943510 int i;
34953511
34963512 if (!vp->lut)
....@@ -3505,6 +3521,25 @@
35053521 rockchip_vop2_crtc_fb_gamma_set(crtc, red[i], green[i],
35063522 blue[i], i);
35073523 vop2_crtc_load_lut(crtc);
3524
+ vop2_cfg_done(crtc);
3525
+ /*
3526
+ * maybe appear the following case:
3527
+ * -> set gamma
3528
+ * -> config done
3529
+ * -> atomic commit
3530
+ * --> update win format
3531
+ * --> update win address
3532
+ * ---> here maybe meet vop hardware frame start, and triggle some config take affect.
3533
+ * ---> as only some config take affect, this maybe lead to iommu pagefault.
3534
+ * --> update win size
3535
+ * --> update win other parameters
3536
+ * -> config done
3537
+ *
3538
+ * so we add vop2_wait_for_fs_by_done_bit_status() to make sure the first config done take
3539
+ * effect and then to do next frame config.
3540
+ */
3541
+ if (VOP_MODULE_GET(vop2, vp, standby) == 0)
3542
+ vop2_wait_for_fs_by_done_bit_status(vp);
35083543
35093544 return 0;
35103545 }
....@@ -3524,7 +3559,6 @@
35243559 return 0;
35253560 }
35263561
3527
-#if defined(CONFIG_ROCKCHIP_DRM_CUBIC_LUT)
35283562 static int vop2_crtc_atomic_cubic_lut_set(struct drm_crtc *crtc,
35293563 struct drm_crtc_state *old_state)
35303564 {
....@@ -3597,18 +3631,12 @@
35973631 return 0;
35983632 }
35993633
3600
-static void drm_crtc_enable_cubic_lut(struct drm_crtc *crtc, unsigned int cubic_lut_size)
3634
+static void vop2_attach_cubic_lut_prop(struct drm_crtc *crtc, unsigned int cubic_lut_size)
36013635 {
3602
- struct drm_device *dev = crtc->dev;
3603
- struct drm_mode_config *config = &dev->mode_config;
3636
+ struct rockchip_drm_private *private = crtc->dev->dev_private;
36043637
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
- }
3638
+ drm_object_attach_property(&crtc->base, private->cubic_lut_prop, 0);
3639
+ drm_object_attach_property(&crtc->base, private->cubic_lut_size_prop, cubic_lut_size);
36123640 }
36133641
36143642 static void vop2_cubic_lut_init(struct vop2 *vop2)
....@@ -3628,12 +3656,9 @@
36283656 vp->cubic_lut_len = vp_data->cubic_lut_len;
36293657
36303658 if (vp->cubic_lut_len)
3631
- drm_crtc_enable_cubic_lut(crtc, vp->cubic_lut_len);
3659
+ vop2_attach_cubic_lut_prop(crtc, vp->cubic_lut_len);
36323660 }
36333661 }
3634
-#else
3635
-static void vop2_cubic_lut_init(struct vop2 *vop2) { }
3636
-#endif
36373662
36383663 static int vop2_core_clks_prepare_enable(struct vop2 *vop2)
36393664 {
....@@ -4276,13 +4301,24 @@
42764301 return 0;
42774302 }
42784303
4279
-static void vop2_crtc_atomic_disable_for_psr(struct drm_crtc *crtc,
4280
- struct drm_crtc_state *old_state)
4304
+static void vop2_crtc_atomic_enter_psr(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
42814305 {
42824306 struct vop2_video_port *vp = to_vop2_video_port(crtc);
42834307 struct vop2 *vop2 = vp->vop2;
4308
+ struct vop2_win *win;
4309
+ unsigned long win_mask = vp->enabled_win_mask;
4310
+ int phys_id;
42844311
4285
- vop2_disable_all_planes_for_crtc(crtc);
4312
+ for_each_set_bit(phys_id, &win_mask, ROCKCHIP_MAX_LAYER) {
4313
+ win = vop2_find_win_by_phys_id(vop2, phys_id);
4314
+ VOP_WIN_SET(vop2, win, enable, 0);
4315
+
4316
+ if (win->feature & WIN_FEATURE_CLUSTER_MAIN)
4317
+ VOP_CLUSTER_SET(vop2, win, enable, 0);
4318
+ }
4319
+
4320
+ vop2_cfg_done(crtc);
4321
+ vop2_wait_for_fs_by_done_bit_status(vp);
42864322 drm_crtc_vblank_off(crtc);
42874323 if (hweight8(vop2->active_vp_mask) == 1) {
42884324 u32 adjust_aclk_rate = 0;
....@@ -4305,6 +4341,30 @@
43054341 }
43064342 }
43074343
4344
+static void vop2_crtc_atomic_exit_psr(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
4345
+{
4346
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
4347
+ struct vop2 *vop2 = vp->vop2;
4348
+ u32 phys_id;
4349
+ struct vop2_win *win;
4350
+ unsigned long enabled_win_mask = vp->enabled_win_mask;
4351
+
4352
+ drm_crtc_vblank_on(crtc);
4353
+ if (vop2->aclk_rate_reset)
4354
+ clk_set_rate(vop2->aclk, vop2->aclk_rate);
4355
+ vop2->aclk_rate_reset = false;
4356
+
4357
+ for_each_set_bit(phys_id, &enabled_win_mask, ROCKCHIP_MAX_LAYER) {
4358
+ win = vop2_find_win_by_phys_id(vop2, phys_id);
4359
+ VOP_WIN_SET(vop2, win, enable, 1);
4360
+ if (win->feature & WIN_FEATURE_CLUSTER_MAIN)
4361
+ VOP_CLUSTER_SET(vop2, win, enable, 1);
4362
+ }
4363
+
4364
+ vop2_cfg_done(crtc);
4365
+ vop2_wait_for_fs_by_done_bit_status(vp);
4366
+}
4367
+
43084368 static void vop2_crtc_atomic_disable(struct drm_crtc *crtc,
43094369 struct drm_crtc_state *old_state)
43104370 {
....@@ -4319,7 +4379,7 @@
43194379 WARN_ON(vp->event);
43204380
43214381 if (crtc->state->self_refresh_active) {
4322
- vop2_crtc_atomic_disable_for_psr(crtc, old_state);
4382
+ vop2_crtc_atomic_enter_psr(crtc, old_state);
43234383 goto out;
43244384 }
43254385
....@@ -4370,8 +4430,11 @@
43704430 if (vp->output_if & VOP_OUTPUT_IF_eDP0)
43714431 VOP_GRF_SET(vop2, grf, grf_edp0_en, 0);
43724432
4373
- if (vp->output_if & VOP_OUTPUT_IF_eDP1)
4433
+ if (vp->output_if & VOP_OUTPUT_IF_eDP1) {
43744434 VOP_GRF_SET(vop2, grf, grf_edp1_en, 0);
4435
+ if (dual_channel)
4436
+ VOP_CTRL_SET(vop2, edp_dual_en, 0);
4437
+ }
43754438
43764439 if (vp->output_if & VOP_OUTPUT_IF_HDMI0) {
43774440 VOP_GRF_SET(vop2, grf, grf_hdmi0_dsc_en, 0);
....@@ -4381,7 +4444,15 @@
43814444 if (vp->output_if & VOP_OUTPUT_IF_HDMI1) {
43824445 VOP_GRF_SET(vop2, grf, grf_hdmi1_dsc_en, 0);
43834446 VOP_GRF_SET(vop2, grf, grf_hdmi1_en, 0);
4447
+ if (dual_channel)
4448
+ VOP_CTRL_SET(vop2, hdmi_dual_en, 0);
43844449 }
4450
+
4451
+ if ((vcstate->output_if & VOP_OUTPUT_IF_DP1) && dual_channel)
4452
+ VOP_CTRL_SET(vop2, dp_dual_en, 0);
4453
+
4454
+ if ((vcstate->output_if & VOP_OUTPUT_IF_MIPI1) && dual_channel)
4455
+ VOP_CTRL_SET(vop2, mipi_dual_en, 0);
43854456
43864457 VOP_MODULE_SET(vop2, vp, dual_channel_en, 0);
43874458 VOP_MODULE_SET(vop2, vp, dual_channel_swap, 0);
....@@ -4548,6 +4619,107 @@
45484619 return ret;
45494620 }
45504621
4622
+/*
4623
+ * 1. NV12/NV16/YUYV xoffset must aligned as 2 pixel;
4624
+ * 2. NV12/NV15 yoffset must aligned as 2 pixel;
4625
+ * 3. NV30 xoffset must aligned as 4 pixel;
4626
+ * 4. NV15/NV20 xoffset must aligend as 8 pixel at rk3568/rk3588/rk3528/rk3562,
4627
+ * others must aligned as 4 pixel;
4628
+ */
4629
+static int vop2_linear_yuv_format_check(struct drm_plane *plane, struct drm_plane_state *state)
4630
+{
4631
+ struct vop2_plane_state *vpstate = to_vop2_plane_state(state);
4632
+ struct drm_crtc *crtc = state->crtc;
4633
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
4634
+ struct vop2_win *win = to_vop2_win(plane);
4635
+ struct drm_framebuffer *fb = state->fb;
4636
+ struct drm_rect *src = &vpstate->src;
4637
+ u32 val = 0;
4638
+
4639
+ if (vpstate->afbc_en || vpstate->tiled_en || !fb->format->is_yuv)
4640
+ return 0;
4641
+
4642
+ switch (fb->format->format) {
4643
+ case DRM_FORMAT_NV12:
4644
+ case DRM_FORMAT_NV21:
4645
+ val = src->x1 >> 16;
4646
+ if (val % 2) {
4647
+ src->x1 = ALIGN(val, 2) << 16;
4648
+ 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);
4649
+ }
4650
+ val = src->y1 >> 16;
4651
+ if (val % 2) {
4652
+ src->y1 = ALIGN(val, 2) << 16;
4653
+ 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);
4654
+ }
4655
+ break;
4656
+ case DRM_FORMAT_NV15:
4657
+ val = src->y1 >> 16;
4658
+ if (val % 2) {
4659
+ src->y1 = ALIGN(val, 2) << 16;
4660
+ 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);
4661
+ }
4662
+ if (vp->vop2->version == VOP_VERSION_RK3568 ||
4663
+ vp->vop2->version == VOP_VERSION_RK3588 ||
4664
+ vp->vop2->version == VOP_VERSION_RK3528 ||
4665
+ vp->vop2->version == VOP_VERSION_RK3562) {
4666
+ val = src->x1 >> 16;
4667
+ if (val % 8) {
4668
+ src->x1 = ALIGN(val, 8) << 16;
4669
+ 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);
4670
+ }
4671
+ } else {
4672
+ val = src->x1 >> 16;
4673
+ if (val % 4) {
4674
+ src->x1 = ALIGN(val, 4) << 16;
4675
+ 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);
4676
+ }
4677
+ }
4678
+ break;
4679
+ case DRM_FORMAT_NV16:
4680
+ case DRM_FORMAT_NV61:
4681
+ case DRM_FORMAT_YUYV:
4682
+ case DRM_FORMAT_YVYU:
4683
+ case DRM_FORMAT_VYUY:
4684
+ case DRM_FORMAT_UYVY:
4685
+ val = src->x1 >> 16;
4686
+ if (val % 2) {
4687
+ src->x1 = ALIGN(val, 2) << 16;
4688
+ 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);
4689
+ }
4690
+ break;
4691
+ case DRM_FORMAT_NV20:
4692
+ if (vp->vop2->version == VOP_VERSION_RK3568 ||
4693
+ vp->vop2->version == VOP_VERSION_RK3588 ||
4694
+ vp->vop2->version == VOP_VERSION_RK3528 ||
4695
+ vp->vop2->version == VOP_VERSION_RK3562) {
4696
+ val = src->x1 >> 16;
4697
+ if (val % 8) {
4698
+ src->x1 = ALIGN(val, 8) << 16;
4699
+ 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);
4700
+ }
4701
+ } else {
4702
+ val = src->x1 >> 16;
4703
+ if (val % 4) {
4704
+ src->x1 = ALIGN(val, 4) << 16;
4705
+ 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);
4706
+ }
4707
+ }
4708
+ break;
4709
+ case DRM_FORMAT_NV30:
4710
+ val = src->x1 >> 16;
4711
+ if (val % 4) {
4712
+ src->x1 = ALIGN(val, 4) << 16;
4713
+ 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);
4714
+ }
4715
+ break;
4716
+ default:
4717
+ return 0;
4718
+ }
4719
+
4720
+ return 0;
4721
+}
4722
+
45514723 static int vop2_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
45524724 {
45534725 struct vop2_plane_state *vpstate = to_vop2_plane_state(state);
....@@ -4712,14 +4884,8 @@
47124884 return ret;
47134885 }
47144886
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");
4887
+ if (vop2_linear_yuv_format_check(plane, state))
47214888 return -EINVAL;
4722
- }
47234889
47244890 if (fb->format->char_per_block[0] == 0)
47254891 offset = ALIGN_DOWN(src->x1 >> 16, tile_size) * fb->format->cpp[0] * tile_size;
....@@ -4773,6 +4939,9 @@
47734939 {
47744940 struct vop2_win *win = to_vop2_win(plane);
47754941 struct vop2 *vop2 = win->vop2;
4942
+ struct drm_crtc *crtc;
4943
+ struct vop2_video_port *vp;
4944
+
47764945 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
47774946 struct vop2_plane_state *vpstate = to_vop2_plane_state(plane->state);
47784947 #endif
....@@ -4785,9 +4954,15 @@
47854954
47864955 spin_lock(&vop2->reg_lock);
47874956
4957
+ crtc = old_state->crtc;
4958
+ vp = to_vop2_video_port(crtc);
4959
+
47884960 vop2_win_disable(win, false);
4789
- if (win->splice_win)
4961
+ vp->enabled_win_mask &= ~BIT(win->phys_id);
4962
+ if (win->splice_win) {
47904963 vop2_win_disable(win->splice_win, false);
4964
+ vp->enabled_win_mask &= ~BIT(win->splice_win->phys_id);
4965
+ }
47914966
47924967 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
47934968 kfree(vpstate->planlist);
....@@ -4957,7 +5132,7 @@
49575132 uint32_t actual_w, actual_h, dsp_w, dsp_h;
49585133 uint32_t dsp_stx, dsp_sty;
49595134 uint32_t act_info, dsp_info, dsp_st;
4960
- uint32_t format;
5135
+ uint32_t format, check_size;
49615136 uint32_t afbc_format;
49625137 uint32_t rb_swap;
49635138 uint32_t uv_swap;
....@@ -4982,7 +5157,7 @@
49825157 actual_w = drm_rect_width(src) >> 16;
49835158 actual_h = drm_rect_height(src) >> 16;
49845159
4985
- if (!actual_w || !actual_h) {
5160
+ if (!actual_w || !actual_h || !bpp) {
49865161 vop2_win_disable(win, true);
49875162 return;
49885163 }
....@@ -5010,7 +5185,8 @@
50105185 actual_w = dsp_w * actual_w / drm_rect_width(dst);
50115186 }
50125187 dsp_h = drm_rect_height(dst);
5013
- if (dst->y1 + dsp_h > adjusted_mode->crtc_vdisplay) {
5188
+ check_size = adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE ? adjusted_mode->vdisplay : adjusted_mode->crtc_vdisplay;
5189
+ if (dst->y1 + dsp_h > check_size) {
50145190 DRM_ERROR("vp%d %s dest->y1[%d] + dsp_h[%d] exceed mode vdisplay[%d]\n",
50155191 vp->id, win->name, dst->y1, dsp_h, adjusted_mode->crtc_vdisplay);
50165192 dsp_h = adjusted_mode->crtc_vdisplay - dst->y1;
....@@ -5025,20 +5201,33 @@
50255201 if (vop2->version == VOP_VERSION_RK3568) {
50265202 /*
50275203 * This is workaround solution for IC design:
5028
- * esmart can't support scale down when actual_w % 16 == 1.
5204
+ * esmart can't support scale down when actual_w % 16 == 1;
5205
+ * esmart can't support scale down when dsp_w % 2 == 1;
5206
+ * esmart actual_w should align as 4 pixel when is linear 10 bit yuv format;
5207
+ *
5208
+ * cluster actual_w should align as 4 pixel when enable afbc;
50295209 */
5030
- if (!(win->feature & WIN_FEATURE_AFBDC)) {
5210
+ if (!vop2_cluster_window(win)) {
50315211 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);
5212
+ DRM_WARN("vp%d %s act_w[%d] MODE 16 == 1 at scale down mode\n", vp->id, win->name, actual_w);
50335213 actual_w -= 1;
5214
+ }
5215
+ if (actual_w > dsp_w && (dsp_w & 0x1) == 1) {
5216
+ DRM_WARN("vp%d %s dsp_w[%d] MODE 2 == 1 at scale down mode\n", vp->id, win->name, dsp_w);
5217
+ dsp_w -= 1;
50345218 }
50355219 }
50365220
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);
5221
+ if (vop2_cluster_window(win) && actual_w % 4) {
5222
+ DRM_WARN("vp%d %s actual_w[%d] should align as 4 pixel when enable afbc\n",
5223
+ vp->id, win->name, actual_w);
50405224 actual_w = ALIGN_DOWN(actual_w, 4);
50415225 }
5226
+ }
5227
+
5228
+ if (is_linear_10bit_yuv(fb->format->format) && actual_w & 0x3) {
5229
+ 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);
5230
+ actual_w = ALIGN_DOWN(actual_w, 4);
50425231 }
50435232
50445233 act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff);
....@@ -5089,10 +5278,6 @@
50895278 /* AFBC pic_vir_width is count by pixel, this is different
50905279 * with WIN_VIR_STRIDE.
50915280 */
5092
- if (!bpp) {
5093
- WARN(1, "bpp is zero\n");
5094
- bpp = 1;
5095
- }
50965281 stride = (fb->pitches[0] << 3) / bpp;
50975282 if ((stride & 0x3f) &&
50985283 (vpstate->xmirror_en || vpstate->rotate_90_en || vpstate->rotate_270_en))
....@@ -5198,6 +5383,7 @@
51985383 VOP_WIN_SET(vop2, win, dither_up, dither_up);
51995384
52005385 VOP_WIN_SET(vop2, win, enable, 1);
5386
+ vp->enabled_win_mask |= BIT(win->phys_id);
52015387 if (vop2_cluster_window(win)) {
52025388 lb_mode = vop2_get_cluster_lb_mode(win, vpstate);
52035389 VOP_CLUSTER_SET(vop2, win, lb_mode, lb_mode);
....@@ -5885,7 +6071,79 @@
58856071 spin_unlock_irqrestore(&vop2->irq_lock, flags);
58866072 }
58876073
5888
-static int vop2_crtc_loader_protect(struct drm_crtc *crtc, bool on)
6074
+static int vop2_crtc_get_inital_acm_info(struct drm_crtc *crtc)
6075
+{
6076
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
6077
+ struct vop2 *vop2 = vp->vop2;
6078
+ struct post_acm *acm = &vp->acm_info;
6079
+ s16 *lut_y;
6080
+ s16 *lut_h;
6081
+ s16 *lut_s;
6082
+ u32 value;
6083
+ int i;
6084
+
6085
+ value = readl(vop2->acm_regs + RK3528_ACM_CTRL);
6086
+ acm->acm_enable = value & 0x1;
6087
+ value = readl(vop2->acm_regs + RK3528_ACM_DELTA_RANGE);
6088
+ acm->y_gain = value & 0x3ff;
6089
+ acm->h_gain = (value >> 10) & 0x3ff;
6090
+ acm->s_gain = (value >> 20) & 0x3ff;
6091
+
6092
+ lut_y = &acm->gain_lut_hy[0];
6093
+ lut_h = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH];
6094
+ lut_s = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH * 2];
6095
+ for (i = 0; i < ACM_GAIN_LUT_HY_LENGTH; i++) {
6096
+ value = readl(vop2->acm_regs + RK3528_ACM_YHS_DEL_HY_SEG0 + (i << 2));
6097
+ lut_y[i] = value & 0xff;
6098
+ lut_h[i] = (value >> 8) & 0xff;
6099
+ lut_s[i] = (value >> 16) & 0xff;
6100
+ }
6101
+
6102
+ lut_y = &acm->gain_lut_hs[0];
6103
+ lut_h = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH];
6104
+ lut_s = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH * 2];
6105
+ for (i = 0; i < ACM_GAIN_LUT_HS_LENGTH; i++) {
6106
+ value = readl(vop2->acm_regs + RK3528_ACM_YHS_DEL_HS_SEG0 + (i << 2));
6107
+ lut_y[i] = value & 0xff;
6108
+ lut_h[i] = (value >> 8) & 0xff;
6109
+ lut_s[i] = (value >> 16) & 0xff;
6110
+ }
6111
+
6112
+ lut_y = &acm->delta_lut_h[0];
6113
+ lut_h = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH];
6114
+ lut_s = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH * 2];
6115
+ for (i = 0; i < ACM_DELTA_LUT_H_LENGTH; i++) {
6116
+ value = readl(vop2->acm_regs + RK3528_ACM_YHS_DEL_HGAIN_SEG0 + (i << 2));
6117
+ lut_y[i] = value & 0x3ff;
6118
+ lut_h[i] = (value >> 12) & 0xff;
6119
+ lut_s[i] = (value >> 20) & 0x3ff;
6120
+ }
6121
+
6122
+ return 0;
6123
+}
6124
+
6125
+static void vop2_crtc_csu_set_rate(struct drm_crtc *crtc)
6126
+{
6127
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
6128
+ struct vop2 *vop2 = vp->vop2;
6129
+ unsigned long aclk_rate = 0, dclk_rate = 0;
6130
+ u32 csu_div = 0;
6131
+
6132
+ if (!vop2->csu_aclk)
6133
+ return;
6134
+
6135
+ aclk_rate = clk_get_rate(vop2->aclk);
6136
+ dclk_rate = clk_get_rate(vp->dclk);
6137
+ if (!dclk_rate)
6138
+ return;
6139
+
6140
+ /* aclk >= 1/2 * dclk */
6141
+ csu_div = aclk_rate * 2 / dclk_rate;
6142
+
6143
+ rockchip_csu_set_div(vop2->csu_aclk, csu_div);
6144
+}
6145
+
6146
+static int vop2_crtc_loader_protect(struct drm_crtc *crtc, bool on, void *data)
58896147 {
58906148 struct vop2_video_port *vp = to_vop2_video_port(crtc);
58916149 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
....@@ -5916,6 +6174,7 @@
59166174 win->pd->vp_mask |= BIT(vp->id);
59176175 }
59186176
6177
+ vp->enabled_win_mask |= BIT(win->phys_id);
59196178 crtc_state = drm_atomic_get_crtc_state(crtc->state->state, crtc);
59206179 mode = &crtc_state->adjusted_mode;
59216180 if (mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) {
....@@ -5928,6 +6187,7 @@
59286187 splice_vp->win_mask |= BIT(splice_win->phys_id);
59296188 splice_win->vp_mask = BIT(splice_vp->id);
59306189 vop2->active_vp_mask |= BIT(splice_vp->id);
6190
+ vp->enabled_win_mask |= BIT(splice_win->phys_id);
59316191
59326192 if (splice_win->pd &&
59336193 VOP_WIN_GET(vop2, splice_win, enable)) {
....@@ -5949,6 +6209,12 @@
59496209 ext_pll->vp_mask |= BIT(vp->id);
59506210 }
59516211 drm_crtc_vblank_on(crtc);
6212
+ if (is_vop3(vop2)) {
6213
+ if (vp_data->feature & (VOP_FEATURE_POST_ACM))
6214
+ vop2_crtc_get_inital_acm_info(crtc);
6215
+ if (data && (vp_data->feature & VOP_FEATURE_POST_CSC))
6216
+ memcpy(&vp->csc_info, data, sizeof(struct post_csc));
6217
+ }
59526218 if (private->cubic_lut[vp->id].enable) {
59536219 dma_addr_t cubic_lut_mst;
59546220 struct loader_cubic_lut *cubic_lut = &private->cubic_lut[vp->id];
....@@ -5956,6 +6222,8 @@
59566222 cubic_lut_mst = cubic_lut->offset + private->cubic_lut_dma_addr;
59576223 VOP_MODULE_SET(vop2, vp, cubic_lut_mst, cubic_lut_mst);
59586224 }
6225
+
6226
+ vop2_crtc_csu_set_rate(crtc);
59596227 } else {
59606228 vop2_crtc_atomic_disable(crtc, NULL);
59616229 }
....@@ -6096,7 +6364,8 @@
60966364
60976365 /* only need to dump once at first active crtc for vop2 */
60986366 for (i = 0; i < vop2_data->nr_vps; i++) {
6099
- if (vop2->vps[i].rockchip_crtc.crtc.state->active) {
6367
+ if (vop2->vps[i].rockchip_crtc.crtc.state &&
6368
+ vop2->vps[i].rockchip_crtc.crtc.state->active) {
61006369 first_active_crtc = &vop2->vps[i].rockchip_crtc.crtc;
61016370 break;
61026371 }
....@@ -6139,7 +6408,8 @@
61396408
61406409 /* only need to dump once at first active crtc for vop2 */
61416410 for (i = 0; i < vop2_data->nr_vps; i++) {
6142
- if (vop2->vps[i].rockchip_crtc.crtc.state->active) {
6411
+ if (vop2->vps[i].rockchip_crtc.crtc.state &&
6412
+ vop2->vps[i].rockchip_crtc.crtc.state->active) {
61436413 first_active_crtc = &vop2->vps[i].rockchip_crtc.crtc;
61446414 break;
61456415 }
....@@ -6309,7 +6579,8 @@
63096579 } else {
63106580 if (request_clock > VOP2_MAX_DCLK_RATE)
63116581 request_clock = request_clock >> 2;
6312
- clock = clk_round_rate(vp->dclk, request_clock * 1000) / 1000;
6582
+ clock = rockchip_drm_dclk_round_rate(vop2->version, vp->dclk,
6583
+ request_clock * 1000) / 1000;
63136584 }
63146585
63156586 /*
....@@ -6352,16 +6623,16 @@
63526623 size_t bandwidth;
63536624
63546625 if (src_width <= 0 || src_height <= 0 || dst_width <= 0 ||
6355
- dst_height <= 0)
6626
+ dst_height <= 0 || !bpp)
63566627 return 0;
63576628
63586629 bandwidth = src_width * bpp / 8;
63596630
63606631 bandwidth = bandwidth * src_width / dst_width;
63616632 bandwidth = bandwidth * src_height / dst_height;
6362
- if (vskiplines == 2)
6633
+ if (vskiplines == 2 && vpstate->afbc_en == 0)
63636634 bandwidth /= 2;
6364
- else if (vskiplines == 4)
6635
+ else if (vskiplines == 4 && vpstate->afbc_en == 0)
63656636 bandwidth /= 4;
63666637
63676638 return bandwidth;
....@@ -6455,9 +6726,12 @@
64556726
64566727 act_w = drm_rect_width(&pstate->src) >> 16;
64576728 act_h = drm_rect_height(&pstate->src) >> 16;
6729
+ if (pstate->fb->format->is_yuv && (act_w >= 3840 || act_h >= 3840))
6730
+ vop_bw_info->plane_num_4k++;
6731
+
64586732 bpp = rockchip_drm_get_bpp(pstate->fb->format);
64596733
6460
- vop_bw_info->frame_bw_mbyte += act_w * act_h / 1000 * bpp / 8 * fps / 1000;
6734
+ vop_bw_info->frame_bw_mbyte += act_w * act_h / 1000 * bpp / 8 * fps / 1000 / afbc_fac;
64616735 }
64626736
64636737 sort(pbandwidth, cnt, sizeof(pbandwidth[0]), vop2_bandwidth_cmp, NULL);
....@@ -6595,12 +6869,17 @@
65956869 if (mode->flags & DRM_MODE_FLAG_DBLCLK || vcstate->output_if & VOP_OUTPUT_IF_BT656)
65966870 adj_mode->crtc_clock *= 2;
65976871
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
- }
6872
+ /*
6873
+ * For RK3528, the path of CVBS output is like:
6874
+ * VOP BT656 ENCODER -> CVBS BT656 DECODER -> CVBS ENCODER -> CVBS VDAC
6875
+ * The vop2 dclk should be four times crtc_clock for CVBS sampling clock needs.
6876
+ */
6877
+ if (vop2->version == VOP_VERSION_RK3528 && vcstate->output_if & VOP_OUTPUT_IF_BT656)
6878
+ adj_mode->crtc_clock *= 4;
6879
+
6880
+ if (vp->mcu_timing.mcu_pix_total)
6881
+ adj_mode->crtc_clock *= rockchip_drm_get_cycles_per_pixel(vcstate->bus_format) *
6882
+ (vp->mcu_timing.mcu_pix_total + 1);
66046883
66056884 drm_connector_list_iter_begin(crtc->dev, &conn_iter);
66066885 drm_for_each_connector_iter(connector, &conn_iter) {
....@@ -6613,43 +6892,45 @@
66136892 }
66146893 drm_connector_list_iter_end(&conn_iter);
66156894
6616
- if (adj_mode->crtc_clock <= VOP2_MAX_DCLK_RATE)
6617
- adj_mode->crtc_clock = DIV_ROUND_UP(clk_round_rate(vp->dclk,
6618
- adj_mode->crtc_clock * 1000), 1000);
6895
+ if (adj_mode->crtc_clock <= VOP2_MAX_DCLK_RATE) {
6896
+ adj_mode->crtc_clock = rockchip_drm_dclk_round_rate(vop2->version, vp->dclk,
6897
+ adj_mode->crtc_clock * 1000);
6898
+ adj_mode->crtc_clock = DIV_ROUND_UP(adj_mode->crtc_clock, 1000);
6899
+ }
66196900 return true;
66206901 }
66216902
6622
-static void vop2_dither_setup(struct drm_crtc *crtc)
6903
+static void vop2_dither_setup(struct rockchip_crtc_state *vcstate, struct drm_crtc *crtc)
66236904 {
6624
- struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
66256905 struct vop2_video_port *vp = to_vop2_video_port(crtc);
66266906 struct vop2 *vop2 = vp->vop2;
6907
+ bool pre_dither_down_en = false;
66276908
66286909 switch (vcstate->bus_format) {
66296910 case MEDIA_BUS_FMT_RGB565_1X16:
66306911 VOP_MODULE_SET(vop2, vp, dither_down_en, 1);
66316912 VOP_MODULE_SET(vop2, vp, dither_down_mode, RGB888_TO_RGB565);
6632
- VOP_MODULE_SET(vop2, vp, pre_dither_down_en, 1);
6913
+ pre_dither_down_en = true;
66336914 break;
66346915 case MEDIA_BUS_FMT_RGB666_1X18:
66356916 case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
66366917 case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
66376918 VOP_MODULE_SET(vop2, vp, dither_down_en, 1);
66386919 VOP_MODULE_SET(vop2, vp, dither_down_mode, RGB888_TO_RGB666);
6639
- VOP_MODULE_SET(vop2, vp, pre_dither_down_en, 1);
6920
+ pre_dither_down_en = true;
66406921 break;
66416922 case MEDIA_BUS_FMT_YUYV8_1X16:
66426923 case MEDIA_BUS_FMT_YUV8_1X24:
66436924 case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
66446925 VOP_MODULE_SET(vop2, vp, dither_down_en, 0);
6645
- VOP_MODULE_SET(vop2, vp, pre_dither_down_en, 1);
6926
+ pre_dither_down_en = true;
66466927 break;
66476928 case MEDIA_BUS_FMT_YUYV10_1X20:
66486929 case MEDIA_BUS_FMT_YUV10_1X30:
66496930 case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
66506931 case MEDIA_BUS_FMT_RGB101010_1X30:
66516932 VOP_MODULE_SET(vop2, vp, dither_down_en, 0);
6652
- VOP_MODULE_SET(vop2, vp, pre_dither_down_en, 0);
6933
+ pre_dither_down_en = false;
66536934 break;
66546935 case MEDIA_BUS_FMT_RGB888_3X8:
66556936 case MEDIA_BUS_FMT_RGB888_DUMMY_4X8:
....@@ -6658,10 +6939,14 @@
66586939 case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
66596940 default:
66606941 VOP_MODULE_SET(vop2, vp, dither_down_en, 0);
6661
- VOP_MODULE_SET(vop2, vp, pre_dither_down_en, 1);
6942
+ pre_dither_down_en = true;
66626943 break;
66636944 }
66646945
6946
+ if (is_yuv_output(vcstate->bus_format))
6947
+ pre_dither_down_en = false;
6948
+
6949
+ VOP_MODULE_SET(vop2, vp, pre_dither_down_en, pre_dither_down_en);
66656950 VOP_MODULE_SET(vop2, vp, dither_down_sel, DITHER_DOWN_ALLEGRO);
66666951 }
66676952
....@@ -7266,24 +7551,45 @@
72667551 dsc->enabled = true;
72677552 }
72687553
7554
+static inline bool vop2_mark_as_left_panel(struct rockchip_crtc_state *vcstate, u32 output_if)
7555
+{
7556
+ return vcstate->output_if_left_panel & output_if;
7557
+}
7558
+
72697559 static void vop2_setup_dual_channel_if(struct drm_crtc *crtc)
72707560 {
72717561 struct vop2_video_port *vp = to_vop2_video_port(crtc);
72727562 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
72737563 struct vop2 *vop2 = vp->vop2;
72747564
7565
+ if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE) {
7566
+ VOP_CTRL_SET(vop2, lvds_dual_en, 1);
7567
+ VOP_CTRL_SET(vop2, lvds_dual_mode, 0);
7568
+ if (vcstate->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
7569
+ VOP_CTRL_SET(vop2, lvds_dual_channel_swap, 1);
7570
+ return;
7571
+ }
7572
+
72757573 VOP_MODULE_SET(vop2, vp, dual_channel_en, 1);
72767574 if (vcstate->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
72777575 VOP_MODULE_SET(vop2, vp, dual_channel_swap, 1);
72787576
7279
- if (vcstate->output_if & VOP_OUTPUT_IF_DP1)
7577
+ if (vcstate->output_if & VOP_OUTPUT_IF_DP1 &&
7578
+ !vop2_mark_as_left_panel(vcstate, VOP_OUTPUT_IF_DP1))
72807579 VOP_CTRL_SET(vop2, dp_dual_en, 1);
7281
- else if (vcstate->output_if & VOP_OUTPUT_IF_eDP1)
7580
+ else if (vcstate->output_if & VOP_OUTPUT_IF_eDP1 &&
7581
+ !vop2_mark_as_left_panel(vcstate, VOP_OUTPUT_IF_eDP1))
72827582 VOP_CTRL_SET(vop2, edp_dual_en, 1);
7283
- else if (vcstate->output_if & VOP_OUTPUT_IF_HDMI1)
7583
+ else if (vcstate->output_if & VOP_OUTPUT_IF_HDMI1 &&
7584
+ !vop2_mark_as_left_panel(vcstate, VOP_OUTPUT_IF_HDMI1))
72847585 VOP_CTRL_SET(vop2, hdmi_dual_en, 1);
7285
- else if (vcstate->output_if & VOP_OUTPUT_IF_MIPI1)
7586
+ else if (vcstate->output_if & VOP_OUTPUT_IF_MIPI1 &&
7587
+ !vop2_mark_as_left_panel(vcstate, VOP_OUTPUT_IF_MIPI1))
72867588 VOP_CTRL_SET(vop2, mipi_dual_en, 1);
7589
+ else if (vcstate->output_if & VOP_OUTPUT_IF_LVDS1) {
7590
+ VOP_CTRL_SET(vop2, lvds_dual_en, 1);
7591
+ VOP_CTRL_SET(vop2, lvds_dual_mode, 1);
7592
+ }
72877593 }
72887594
72897595 /*
....@@ -7443,14 +7749,6 @@
74437749 }
74447750 }
74457751
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
-
74547752 static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
74557753 {
74567754 struct vop2_video_port *vp = to_vop2_video_port(crtc);
....@@ -7485,10 +7783,7 @@
74857783 int ret;
74867784
74877785 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;
7786
+ vop2_crtc_atomic_exit_psr(crtc, old_state);
74927787
74937788 return;
74947789 }
....@@ -7497,10 +7792,11 @@
74977792 vop2_set_system_status(vop2);
74987793
74997794 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",
7795
+ DRM_DEV_INFO(vop2->dev, "Update mode to %dx%d%s%d, type: %d(if:%x, flag:0x%x) for vp%d dclk: %llu\n",
75017796 hdisplay, adjusted_mode->vdisplay, interlaced ? "i" : "p",
7502
- vop2_get_vrefresh(vp, adjusted_mode), vcstate->output_type, vcstate->output_if,
7503
- vp->id, adjusted_mode->crtc_clock * 1000);
7797
+ drm_mode_vrefresh(adjusted_mode),
7798
+ vcstate->output_type, vcstate->output_if, vcstate->output_flags,
7799
+ vp->id, (unsigned long long)adjusted_mode->crtc_clock * 1000);
75047800
75057801 if (adjusted_mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) {
75067802 vcstate->splice_mode = true;
....@@ -7510,6 +7806,9 @@
75107806 splice_en = 1;
75117807 vop2->active_vp_mask |= BIT(splice_vp->id);
75127808 }
7809
+
7810
+ if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CONNECTOR_SPLIT_MODE)
7811
+ vcstate->output_flags |= ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE;
75137812
75147813 if (vcstate->dsc_enable) {
75157814 int k = 1;
....@@ -7600,15 +7899,6 @@
76007899 VOP_CTRL_SET(vop2, lvds_dclk_pol, dclk_inv);
76017900 }
76027901
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
-
76127902 if (vcstate->output_if & VOP_OUTPUT_IF_MIPI0) {
76137903 ret = vop2_calc_cru_cfg(crtc, VOP_OUTPUT_IF_MIPI0, &if_pixclk, &if_dclk);
76147904 if (ret < 0)
....@@ -7652,7 +7942,8 @@
76527942 }
76537943 }
76547944
7655
- if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
7945
+ if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE ||
7946
+ vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE)
76567947 vop2_setup_dual_channel_if(crtc);
76577948
76587949 if (vcstate->output_if & VOP_OUTPUT_IF_eDP0) {
....@@ -7837,19 +8128,12 @@
78378128 if (ret < 0)
78388129 goto out;
78398130
7840
- clk_set_rate(vp->dclk, dclk->rate);
8131
+ rockchip_drm_dclk_set_rate(vop2->version, vp->dclk, dclk->rate);
78418132 DRM_DEV_INFO(vop2->dev, "set %s to %ld, get %ld\n",
78428133 __clk_get_name(vp->dclk), dclk->rate, clk_get_rate(vp->dclk));
78438134 } else {
7844
- /*
7845
- * For RK3528, the path of CVBS output is like:
7846
- * VOP BT656 ENCODER -> CVBS BT656 DECODER -> CVBS ENCODER -> CVBS VDAC
7847
- * The vop2 dclk should be four times crtc_clock for CVBS sampling clock needs.
7848
- */
7849
- if (vop2->version == VOP_VERSION_RK3528 && vcstate->output_if & VOP_OUTPUT_IF_BT656)
7850
- clk_set_rate(vp->dclk, 4 * adjusted_mode->crtc_clock * 1000);
7851
- else
7852
- clk_set_rate(vp->dclk, adjusted_mode->crtc_clock * 1000);
8135
+ rockchip_drm_dclk_set_rate(vop2->version, vp->dclk,
8136
+ adjusted_mode->crtc_clock * 1000);
78538137 }
78548138
78558139 if (vp_data->feature & VOP_FEATURE_OVERSCAN)
....@@ -7878,6 +8162,7 @@
78788162 if (is_vop3(vop2))
78798163 vop3_setup_pipe_dly(vp, NULL);
78808164
8165
+ vop2_crtc_csu_set_rate(crtc);
78818166 vop2_cfg_done(crtc);
78828167
78838168 /*
....@@ -7910,8 +8195,35 @@
79108195 /*
79118196 * restore the lut table.
79128197 */
7913
- if (vp->gamma_lut_active)
8198
+ if (vp->gamma_lut_active) {
79148199 vop2_crtc_load_lut(crtc);
8200
+ vop2_cfg_done(crtc);
8201
+ vop2_wait_for_fs_by_done_bit_status(vp);
8202
+ }
8203
+
8204
+ /*
8205
+ * In RK3588 VOP, HDMI1/eDP1 MUX1 module's reset signal should be released
8206
+ * when PD_VOP turn on. If this reset signal is not be released, the HDMI1
8207
+ * or eDP1 output interface can't work normally.
8208
+ * However, If the deassert signal want to transfer to HDMI1/eDP1 MUX1 and
8209
+ * take effect, it need the video port0 dclk's source clk work a few moment.
8210
+ * In some cases, the video port0 dclk's source clk is disabled(now only the
8211
+ * hdmi0/1 phy pll as the dclk source parent will appear) after PD_VOP turn
8212
+ * on, for example, vidoe port0 dclk source select hdmi phy pll. To fix
8213
+ * this issue, enable video port0 dclk for a few monent when active a video
8214
+ * port which attach to eDP1/HDMI1.
8215
+ */
8216
+ if (vop2->version == VOP_VERSION_RK3588) {
8217
+ if (vp->id != 0 && (vp->output_if & (VOP_OUTPUT_IF_eDP1 | VOP_OUTPUT_IF_HDMI1))) {
8218
+ struct vop2_video_port *vp0 = &vop2->vps[0];
8219
+
8220
+ clk_prepare_enable(vp0->dclk);
8221
+ if (!clk_get_rate(vp0->dclk))
8222
+ clk_set_rate(vp0->dclk, 148500000);
8223
+ udelay(20);
8224
+ clk_disable_unprepare(vp0->dclk);
8225
+ }
8226
+ }
79158227 out:
79168228 vop2_unlock(vop2);
79178229 }
....@@ -9515,18 +9827,25 @@
95159827 u32 value;
95169828 int i;
95179829
9518
- if (!acm) {
9519
- writel(0x2, vop2->acm_regs + RK3528_ACM_CTRL);
9520
- VOP_MODULE_SET(vop2, vp, acm_bypass_en, 1);
9830
+ writel(0, vop2->acm_regs + RK3528_ACM_CTRL);
9831
+ VOP_MODULE_SET(vop2, vp, acm_bypass_en, 0);
9832
+
9833
+ if (!acm || !acm->acm_enable)
95219834 return;
9522
- }
95239835
9524
- writel(1, vop2->acm_regs + RK3528_ACM_FETCH_START);
9836
+ /*
9837
+ * If acm update parameters, it need disable acm in the first frame,
9838
+ * then update parameters and enable acm in second frame.
9839
+ */
9840
+ vop2_cfg_done(crtc);
9841
+ readx_poll_timeout(readl, vop2->acm_regs + RK3528_ACM_CTRL, value, !value, 200, 50000);
95259842
9526
- value = (acm->acm_enable & 0x1) + ((adjusted_mode->hdisplay & 0xfff) << 8) +
9843
+ value = RK3528_ACM_ENABLE + ((adjusted_mode->hdisplay & 0xfff) << 8) +
95279844 ((adjusted_mode->vdisplay & 0xfff) << 20);
95289845 writel(value, vop2->acm_regs + RK3528_ACM_CTRL);
9529
- VOP_MODULE_SET(vop2, vp, acm_bypass_en, acm->acm_enable ? 0 : 1);
9846
+
9847
+
9848
+ writel(1, vop2->acm_regs + RK3528_ACM_FETCH_START);
95309849
95319850 value = (acm->y_gain & 0x3ff) + ((acm->h_gain << 10) & 0xffc00) +
95329851 ((acm->s_gain << 20) & 0x3ff00000);
....@@ -9565,14 +9884,23 @@
95659884 static void vop3_post_config(struct drm_crtc *crtc)
95669885 {
95679886 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
9887
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
95689888 struct post_acm *acm;
95699889 struct post_csc *csc;
95709890
9571
- acm = vcstate->acm_lut_data ? (struct post_acm *)vcstate->acm_lut_data->data : NULL;
9572
- vop3_post_acm_config(crtc, acm);
9573
-
95749891 csc = vcstate->post_csc_data ? (struct post_csc *)vcstate->post_csc_data->data : NULL;
9575
- vop3_post_csc_config(crtc, acm, csc);
9892
+ if (csc && memcmp(&vp->csc_info, csc, sizeof(struct post_csc)))
9893
+ memcpy(&vp->csc_info, csc, sizeof(struct post_csc));
9894
+ vop3_post_csc_config(crtc, &vp->acm_info, &vp->csc_info);
9895
+
9896
+ acm = vcstate->acm_lut_data ? (struct post_acm *)vcstate->acm_lut_data->data : NULL;
9897
+
9898
+ if (acm && memcmp(&vp->acm_info, acm, sizeof(struct post_acm))) {
9899
+ memcpy(&vp->acm_info, acm, sizeof(struct post_acm));
9900
+ vop3_post_acm_config(crtc, &vp->acm_info);
9901
+ } else if (crtc->state->active_changed) {
9902
+ vop3_post_acm_config(crtc, &vp->acm_info);
9903
+ }
95769904 }
95779905
95789906 static void vop2_cfg_update(struct drm_crtc *crtc,
....@@ -9600,7 +9928,9 @@
96009928
96019929 vop2_post_color_swap(crtc);
96029930
9603
- vop2_dither_setup(crtc);
9931
+ vop2_dither_setup(vcstate, crtc);
9932
+ if (vcstate->splice_mode)
9933
+ vop2_dither_setup(vcstate, &splice_vp->rockchip_crtc.crtc);
96049934
96059935 VOP_MODULE_SET(vop2, vp, overlay_mode, vcstate->yuv_overlay);
96069936
....@@ -9633,10 +9963,10 @@
96339963 if (vp_data->feature & VOP_FEATURE_OVERSCAN)
96349964 vop2_post_config(crtc);
96359965
9966
+ spin_unlock(&vop2->reg_lock);
9967
+
96369968 if (vp_data->feature & (VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC))
96379969 vop3_post_config(crtc);
9638
-
9639
- spin_unlock(&vop2->reg_lock);
96409970 }
96419971
96429972 static void vop2_sleep_scan_line_time(struct vop2_video_port *vp, int scan_line)
....@@ -9755,13 +10085,11 @@
975510085 vp->gamma_lut = crtc->state->gamma_lut->data;
975610086 vop2_crtc_atomic_gamma_set(crtc, crtc->state);
975710087 }
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;
10088
+ if (vcstate->cubic_lut_data || vp->cubic_lut) {
10089
+ if (vcstate->cubic_lut_data)
10090
+ vp->cubic_lut = vcstate->cubic_lut_data->data;
976210091 vop2_crtc_atomic_cubic_lut_set(crtc, crtc->state);
976310092 }
9764
-#endif
976510093 } else {
976610094 VOP_MODULE_SET(vop2, vp, cubic_lut_update_en, 0);
976710095 }
....@@ -9874,6 +10202,8 @@
987410202 drm_property_blob_get(vcstate->acm_lut_data);
987510203 if (vcstate->post_csc_data)
987610204 drm_property_blob_get(vcstate->post_csc_data);
10205
+ if (vcstate->cubic_lut_data)
10206
+ drm_property_blob_get(vcstate->cubic_lut_data);
987710207
987810208 __drm_atomic_helper_crtc_duplicate_state(crtc, &vcstate->base);
987910209 return &vcstate->base;
....@@ -9888,6 +10218,7 @@
988810218 drm_property_blob_put(vcstate->hdr_ext_data);
988910219 drm_property_blob_put(vcstate->acm_lut_data);
989010220 drm_property_blob_put(vcstate->post_csc_data);
10221
+ drm_property_blob_put(vcstate->cubic_lut_data);
989110222 kfree(vcstate);
989210223 }
989310224
....@@ -10034,6 +10365,11 @@
1003410365 return 0;
1003510366 }
1003610367
10368
+ if (property == private->cubic_lut_prop) {
10369
+ *val = (vcstate->cubic_lut_data) ? vcstate->cubic_lut_data->base.id : 0;
10370
+ return 0;
10371
+ }
10372
+
1003710373 DRM_ERROR("failed to get vop2 crtc property: %s\n", property->name);
1003810374
1003910375 return -EINVAL;
....@@ -10156,6 +10492,16 @@
1015610492 val,
1015710493 sizeof(struct post_csc), -1,
1015810494 &replaced);
10495
+ return ret;
10496
+ }
10497
+
10498
+ if (property == private->cubic_lut_prop) {
10499
+ ret = vop2_atomic_replace_property_blob_from_id(drm_dev,
10500
+ &vcstate->cubic_lut_data,
10501
+ val,
10502
+ -1, sizeof(struct drm_color_lut),
10503
+ &replaced);
10504
+ state->color_mgmt_changed |= replaced;
1015910505 return ret;
1016010506 }
1016110507
....@@ -10660,25 +11006,14 @@
1066011006 return 0;
1066111007 }
1066211008
10663
-static struct drm_plane *vop2_cursor_plane_init(struct vop2_video_port *vp)
11009
+static struct drm_plane *vop2_cursor_plane_init(struct vop2_video_port *vp, u32 possible_crtcs)
1066411010 {
1066511011 struct vop2 *vop2 = vp->vop2;
1066611012 struct drm_plane *cursor = NULL;
1066711013 struct vop2_win *win;
10668
- unsigned long possible_crtcs = 0;
1066911014
1067011015 win = vop2_find_win_by_phys_id(vop2, vp->cursor_win_id);
1067111016 if (win) {
10672
- if (vop2->disable_win_move) {
10673
- const struct vop2_data *vop2_data = vop2->data;
10674
- struct drm_crtc *crtc = vop2_find_crtc_by_plane_mask(vop2, win->phys_id);
10675
-
10676
- if (crtc)
10677
- possible_crtcs = drm_crtc_mask(crtc);
10678
- else
10679
- possible_crtcs = (1 << vop2_data->nr_vps) - 1;
10680
- }
10681
-
1068211017 if (win->possible_crtcs)
1068311018 possible_crtcs = win->possible_crtcs;
1068411019 win->type = DRM_PLANE_TYPE_CURSOR;
....@@ -10790,6 +11125,7 @@
1079011125 { ROCKCHIP_DRM_CRTC_FEATURE_ALPHA_SCALE, "ALPHA_SCALE" },
1079111126 { ROCKCHIP_DRM_CRTC_FEATURE_HDR10, "HDR10" },
1079211127 { ROCKCHIP_DRM_CRTC_FEATURE_NEXT_HDR, "NEXT_HDR" },
11128
+ { ROCKCHIP_DRM_CRTC_FEATURE_VIVID_HDR, "VIVID_HDR" },
1079311129 };
1079411130
1079511131 if (vp_data->feature & VOP_FEATURE_ALPHA_SCALE)
....@@ -10798,6 +11134,8 @@
1079811134 feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_HDR10);
1079911135 if (vp_data->feature & VOP_FEATURE_NEXT_HDR)
1080011136 feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_NEXT_HDR);
11137
+ if (vp_data->feature & VOP_FEATURE_VIVID_HDR)
11138
+ feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_VIVID_HDR);
1080111139
1080211140 prop = drm_property_create_bitmask(vop2->drm_dev,
1080311141 DRM_MODE_PROP_IMMUTABLE, "FEATURE",
....@@ -10979,11 +11317,13 @@
1097911317 possible_crtcs = BIT(registered_num_crtcs);
1098011318
1098111319 /*
10982
- * we assume a vp with a zere plane_mask(set from dts or bootloader)
11320
+ * we assume a vp with a zero plane_mask(set from dts or bootloader)
1098311321 * as unused.
1098411322 */
10985
- if (!vp->plane_mask && bootloader_initialized)
11323
+ if (!vp->plane_mask && bootloader_initialized) {
11324
+ DRM_DEV_INFO(vop2->dev, "VP%d plane_mask is zero, so ignore register crtc\n", vp->id);
1098611325 continue;
11326
+ }
1098711327
1098811328 if (vop2_soc_is_rk3566())
1098911329 soc_id = vp_data->soc_id[1];
....@@ -11105,7 +11445,7 @@
1110511445 }
1110611446
1110711447 if (vp->cursor_win_id >= 0) {
11108
- cursor = vop2_cursor_plane_init(vp);
11448
+ cursor = vop2_cursor_plane_init(vp, possible_crtcs);
1110911449 if (!cursor)
1111011450 DRM_WARN("failed to init cursor plane for vp%d\n", vp->id);
1111111451 else
....@@ -11303,6 +11643,7 @@
1130311643 struct vop2_win *win;
1130411644 struct vop2_layer *layer;
1130511645 char name[DRM_PROP_NAME_LEN];
11646
+ char area_name[DRM_PROP_NAME_LEN];
1130611647 unsigned int num_wins = 0;
1130711648 uint8_t plane_id = 0;
1130811649 unsigned int i, j;
....@@ -11378,8 +11719,8 @@
1137811719 area->phys_id = win->phys_id;
1137911720 area->area_id = j + 1;
1138011721 area->plane_id = plane_id++;
11381
- snprintf(name, min(sizeof(name), strlen(win->name)), "%s", win->name);
11382
- snprintf(name, sizeof(name), "%s%d", name, area->area_id);
11722
+ snprintf(area_name, min(sizeof(area_name), strlen(win->name)), "%s", win->name);
11723
+ snprintf(name, sizeof(name), "%s%d", area_name, area->area_id);
1138311724 area->name = devm_kstrdup(vop2->dev, name, GFP_KERNEL);
1138411725 num_wins++;
1138511726 }
....@@ -11673,6 +12014,10 @@
1167312014 return PTR_ERR(vop2->axi_rst);
1167412015 }
1167512016
12017
+ vop2->csu_aclk = rockchip_csu_get(dev, "aclk");
12018
+ if (IS_ERR(vop2->csu_aclk))
12019
+ vop2->csu_aclk = NULL;
12020
+
1167612021 vop2->irq = platform_get_irq(pdev, 0);
1167712022 if (vop2->irq < 0) {
1167812023 DRM_DEV_ERROR(dev, "cannot find irq for vop2\n");