hc
2023-11-06 e3e12f52b214121840b44c91de5b3e5af5d3eb84
kernel/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
....@@ -35,6 +35,8 @@
3535 #include <linux/swab.h>
3636 #include <linux/sort.h>
3737 #include <linux/rockchip/cpu.h>
38
+#include <linux/workqueue.h>
39
+#include <linux/types.h>
3840 #include <soc/rockchip/rockchip_dmc.h>
3941 #include <soc/rockchip/rockchip-system-status.h>
4042 #include <uapi/linux/videodev2.h>
....@@ -47,6 +49,7 @@
4749 #include "rockchip_drm_psr.h"
4850 #include "rockchip_drm_vop.h"
4951 #include "rockchip_vop_reg.h"
52
+#include "rockchip_post_csc.h"
5053
5154 #define _REG_SET(vop2, name, off, reg, mask, v, relaxed) \
5255 vop2_mask_write(vop2, off + reg.offset, mask, reg.shift, v, reg.write_mask, relaxed)
....@@ -78,6 +81,8 @@
7881
7982 #define VOP_CTRL_SET(x, name, v) \
8083 REG_SET(x, name, 0, (x)->data->ctrl->name, v, false)
84
+
85
+#define VOP_CTRL_GET(x, name) vop2_read_reg(x, 0, &(x)->data->ctrl->name)
8186
8287 #define VOP_INTR_GET(vop2, name) \
8388 vop2_read_reg(vop2, 0, &vop2->data->ctrl->name)
....@@ -477,6 +482,8 @@
477482 uint8_t id;
478483 bool layer_sel_update;
479484 bool xmirror_en;
485
+ bool need_reset_p2i_flag;
486
+ atomic_t post_buf_empty_flag;
480487 const struct vop2_video_port_regs *regs;
481488
482489 struct completion dsp_hold_completion;
....@@ -555,6 +562,11 @@
555562 bool gamma_lut_active;
556563
557564 /**
565
+ * @lut_dma_rid: lut dma id
566
+ */
567
+ u16 lut_dma_rid;
568
+
569
+ /**
558570 * @gamma_lut: atomic gamma look up table
559571 */
560572 struct drm_color_lut *gamma_lut;
....@@ -568,6 +580,11 @@
568580 * @cubic_lut_gem_obj: gem obj to store cubic lut
569581 */
570582 struct rockchip_gem_object *cubic_lut_gem_obj;
583
+
584
+ /**
585
+ * @hdr_lut_gem_obj: gem obj to store hdr lut
586
+ */
587
+ struct rockchip_gem_object *hdr_lut_gem_obj;
571588
572589 /**
573590 * @cubic_lut: cubic look up table
....@@ -591,10 +608,29 @@
591608 struct drm_property *plane_mask_prop;
592609
593610 /**
611
+ * @hdr_ext_data_prop: hdr extend data interaction with userspace
612
+ */
613
+ struct drm_property *hdr_ext_data_prop;
614
+
615
+ int hdrvivid_mode;
616
+
617
+ /**
618
+ * @acm_lut_data_prop: acm lut data interaction with userspace
619
+ */
620
+ struct drm_property *acm_lut_data_prop;
621
+ /**
622
+ * @post_csc_data_prop: post csc data interaction with userspace
623
+ */
624
+ struct drm_property *post_csc_data_prop;
625
+
626
+ /**
594627 * @primary_plane_phy_id: vp primary plane phy id, the primary plane
595628 * will be used to show uboot logo and kernel logo
596629 */
597630 enum vop2_layer_phy_id primary_plane_phy_id;
631
+
632
+ struct post_acm acm_info;
633
+ struct post_csc csc_info;
598634 };
599635
600636 struct vop2 {
....@@ -652,6 +688,7 @@
652688 */
653689 uint32_t registered_num_wins;
654690 uint8_t used_mixers;
691
+ uint8_t esmart_lb_mode;
655692 /**
656693 * @active_vp_mask: Bitmask of active video ports;
657694 */
....@@ -684,6 +721,8 @@
684721 unsigned int enable_count;
685722 struct clk *hclk;
686723 struct clk *aclk;
724
+ struct work_struct post_buf_empty_work;
725
+ struct workqueue_struct *workqueue;
687726
688727 struct vop2_layer layers[ROCKCHIP_MAX_LAYER];
689728 /* must put at the end of the struct */
....@@ -717,6 +756,7 @@
717756 { MEDIA_BUS_FMT_UYVY8_2X8, "UYVY8_2X8" },
718757 { MEDIA_BUS_FMT_YUYV8_1X16, "YUYV8_1X16" },
719758 { MEDIA_BUS_FMT_UYVY8_1X16, "UYVY8_1X16" },
759
+ { MEDIA_BUS_FMT_RGB101010_1X30, "RGB101010_1x30" },
720760 };
721761
722762 static DRM_ENUM_NAME_FN(drm_get_bus_format_name, drm_bus_format_enum_list)
....@@ -991,8 +1031,23 @@
9911031 static uint32_t vop2_read_vcnt(struct vop2_video_port *vp)
9921032 {
9931033 uint32_t offset = RK3568_SYS_STATUS0 + (vp->id << 2);
1034
+ uint32_t vcnt0, vcnt1;
1035
+ int i = 0;
9941036
995
- return vop2_readl(vp->vop2, offset) >> 16;
1037
+ for (i = 0; i < 10; i++) {
1038
+ vcnt0 = vop2_readl(vp->vop2, offset) >> 16;
1039
+ vcnt1 = vop2_readl(vp->vop2, offset) >> 16;
1040
+
1041
+ if ((vcnt1 - vcnt0) <= 1)
1042
+ break;
1043
+ }
1044
+
1045
+ if (i == 10) {
1046
+ DRM_DEV_ERROR(vp->vop2->dev, "read VP%d vcnt error: %d %d\n", vp->id, vcnt0, vcnt1);
1047
+ vcnt1 = vop2_readl(vp->vop2, offset) >> 16;
1048
+ }
1049
+
1050
+ return vcnt1;
9961051 }
9971052
9981053 static void vop2_wait_for_irq_handler(struct drm_crtc *crtc)
....@@ -1864,7 +1919,7 @@
18641919 #define VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac) \
18651920 (fac * (dst - 1) >> 16 < (src - 1))
18661921 #define VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac) \
1867
- (fac * (dst - 1) >> 16 <= (src - 1))
1922
+ (fac * (dst - 1) >> 16 < (src - 1))
18681923
18691924 static uint16_t vop2_scale_factor(enum scale_mode mode,
18701925 int32_t filter_mode,
....@@ -1983,12 +2038,30 @@
19832038 }
19842039 }
19852040
1986
- if (src_h >= (4 * dst_h)) {
1987
- ygt4 = 1;
1988
- src_h >>= 2;
1989
- } else if (src_h >= (2 * dst_h)) {
1990
- ygt2 = 1;
1991
- src_h >>= 1;
2041
+ /**
2042
+ * The rk3528 is processed as 2 pixel/cycle,
2043
+ * so ygt2/ygt4 needs to be triggered in advance to improve performance
2044
+ * when src_w is bigger than 1920.
2045
+ * dst_h / src_h is at [1, 0.65) ygt2=0; ygt4=0;
2046
+ * dst_h / src_h is at [0.65, 0.35) ygt2=1; ygt4=0;
2047
+ * dst_h / src_h is at [0.35, 0) ygt2=0; ygt4=1;
2048
+ */
2049
+ if (vop2->version == VOP_VERSION_RK3528 && src_w > 1920) {
2050
+ if (src_h >= (100 * dst_h / 35)) {
2051
+ ygt4 = 1;
2052
+ src_h >>= 2;
2053
+ } else if ((src_h >= 100 * dst_h / 65) && (src_h < 100 * dst_h / 35)) {
2054
+ ygt2 = 1;
2055
+ src_h >>= 1;
2056
+ }
2057
+ } else {
2058
+ if (src_h >= (4 * dst_h)) {
2059
+ ygt4 = 1;
2060
+ src_h >>= 2;
2061
+ } else if (src_h >= (2 * dst_h)) {
2062
+ ygt2 = 1;
2063
+ src_h >>= 1;
2064
+ }
19922065 }
19932066
19942067 yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
....@@ -2065,10 +2138,17 @@
20652138 if (!is_vop3(vop2) ||
20662139 (!vpstate->afbc_en && !vpstate->tiled_en) ||
20672140 win_data->vsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_GT) {
2068
- if (cbcr_src_h >= (4 * dst_h))
2069
- ygt4 = 1;
2070
- else if (cbcr_src_h >= (2 * dst_h))
2071
- ygt2 = 1;
2141
+ if (vop2->version == VOP_VERSION_RK3528 && src_w > 1920) {
2142
+ if (cbcr_src_h >= (100 * dst_h / 35))
2143
+ ygt4 = 1;
2144
+ else if ((cbcr_src_h >= 100 * dst_h / 65) && (cbcr_src_h < 100 * dst_h / 35))
2145
+ ygt2 = 1;
2146
+ } else {
2147
+ if (cbcr_src_h >= (4 * dst_h))
2148
+ ygt4 = 1;
2149
+ else if (cbcr_src_h >= (2 * dst_h))
2150
+ ygt2 = 1;
2151
+ }
20722152
20732153 if (ygt4)
20742154 cbcr_src_h >>= 2;
....@@ -2230,29 +2310,49 @@
22302310 vpstate->r2y_en = 0;
22312311 vpstate->csc_mode = 0;
22322312
2233
- /* hdr2sdr and sdr2hdr will do csc itself */
2234
- if (vpstate->hdr2sdr_en) {
2235
- /*
2236
- * This is hdr2sdr enabled plane
2237
- * If it's RGB layer do hdr2sdr, we need to do r2y before send to hdr2sdr,
2238
- * because hdr2sdr only support yuv input.
2239
- */
2240
- if (!is_input_yuv) {
2241
- vpstate->r2y_en = 1;
2242
- vpstate->csc_mode = vop2_convert_csc_mode(output_csc, CSC_10BIT_DEPTH);
2313
+ if (is_vop3(vp->vop2)) {
2314
+ if (vpstate->hdr_in) {
2315
+ if (is_input_yuv) {
2316
+ vpstate->y2r_en = 1;
2317
+ vpstate->csc_mode = vop2_convert_csc_mode(input_csc,
2318
+ CSC_13BIT_DEPTH);
2319
+ }
2320
+ return;
2321
+ } else if (vp->sdr2hdr_en) {
2322
+ if (is_input_yuv) {
2323
+ vpstate->y2r_en = 1;
2324
+ vpstate->csc_mode = vop2_convert_csc_mode(input_csc,
2325
+ csc_y2r_bit_depth);
2326
+ }
2327
+ return;
22432328 }
2244
- return;
2245
- } else if (!vpstate->hdr_in && vp->sdr2hdr_en) {
2246
- /*
2247
- * This is sdr2hdr enabled plane
2248
- * If it's YUV layer do sdr2hdr, we need to do y2r before send to sdr2hdr,
2249
- * because sdr2hdr only support rgb input.
2250
- */
2251
- if (is_input_yuv) {
2252
- vpstate->y2r_en = 1;
2253
- vpstate->csc_mode = vop2_convert_csc_mode(input_csc, csc_y2r_bit_depth);
2329
+ } else {
2330
+ /* hdr2sdr and sdr2hdr will do csc itself */
2331
+ if (vpstate->hdr2sdr_en) {
2332
+ /*
2333
+ * This is hdr2sdr enabled plane
2334
+ * If it's RGB layer do hdr2sdr, we need to do r2y before send to hdr2sdr,
2335
+ * because hdr2sdr only support yuv input.
2336
+ */
2337
+ if (!is_input_yuv) {
2338
+ vpstate->r2y_en = 1;
2339
+ vpstate->csc_mode = vop2_convert_csc_mode(output_csc,
2340
+ CSC_10BIT_DEPTH);
2341
+ }
2342
+ return;
2343
+ } else if (!vpstate->hdr_in && vp->sdr2hdr_en) {
2344
+ /*
2345
+ * This is sdr2hdr enabled plane
2346
+ * If it's YUV layer do sdr2hdr, we need to do y2r before send to sdr2hdr,
2347
+ * because sdr2hdr only support rgb input.
2348
+ */
2349
+ if (is_input_yuv) {
2350
+ vpstate->y2r_en = 1;
2351
+ vpstate->csc_mode = vop2_convert_csc_mode(input_csc,
2352
+ csc_y2r_bit_depth);
2353
+ }
2354
+ return;
22542355 }
2255
- return;
22562356 }
22572357
22582358 if (is_input_yuv && !is_output_yuv) {
....@@ -2657,7 +2757,7 @@
26572757 fifo_throd = fb->pitches[0] >> 4;
26582758 if (fifo_throd >= vop2->data->wb->fifo_depth)
26592759 fifo_throd = vop2->data->wb->fifo_depth;
2660
- r2y = fb->format->is_yuv && (!is_yuv_output(vcstate->bus_format));
2760
+ r2y = !vcstate->yuv_overlay && fb->format->is_yuv;
26612761
26622762 /*
26632763 * the vp_id register config done immediately
....@@ -2963,25 +3063,16 @@
29633063 */
29643064 static void vop3_layer_map_initial(struct vop2 *vop2, uint32_t current_vp_id)
29653065 {
2966
- struct vop2_video_port *vp;
2967
- struct vop2_win *win;
2968
- unsigned long win_mask;
29693066 uint16_t vp_id;
2970
- int phys_id;
2971
- int i;
3067
+ struct drm_plane *plane = NULL;
29723068
2973
- for (i = 0; i < vop2->data->nr_vps; i++) {
2974
- vp_id = i;
2975
- vp = &vop2->vps[vp_id];
2976
- vp->win_mask = vp->plane_mask;
2977
- win_mask = vp->win_mask;
2978
- for_each_set_bit(phys_id, &win_mask, ROCKCHIP_MAX_LAYER) {
2979
- win = vop2_find_win_by_phys_id(vop2, phys_id);
2980
- VOP_CTRL_SET(vop2, win_vp_id[phys_id], vp_id);
2981
- win->vp_mask = BIT(vp_id);
2982
- win->old_vp_mask = win->vp_mask;
2983
- DRM_DEV_DEBUG(vop2->dev, "%s attach to vp%d\n", win->name, vp_id);
2984
- }
3069
+ drm_for_each_plane(plane, vop2->drm_dev) {
3070
+ struct vop2_win *win = to_vop2_win(plane);
3071
+
3072
+ vp_id = VOP_CTRL_GET(vop2, win_vp_id[win->phys_id]);
3073
+ win->vp_mask = BIT(vp_id);
3074
+ win->old_vp_mask = win->vp_mask;
3075
+ vop2->vps[vp_id].win_mask |= BIT(win->phys_id);
29853076 }
29863077 }
29873078
....@@ -3081,8 +3172,17 @@
30813172 VOP_MODULE_SET(vop2, wb, axi_uv_id, 0xe);
30823173 vop2_wb_cfg_done(vp);
30833174
3084
- if (is_vop3(vop2))
3085
- VOP_CTRL_SET(vop2, esmart_lb_mode, vop2->data->esmart_lb_mode);
3175
+ if (is_vop3(vop2)) {
3176
+ VOP_CTRL_SET(vop2, dsp_vs_t_sel, 0);
3177
+ VOP_CTRL_SET(vop2, esmart_lb_mode, vop2->esmart_lb_mode);
3178
+ }
3179
+
3180
+ /*
3181
+ * This is unused and error init value for rk3528 vp1, if less of this config,
3182
+ * vp1 can't display normally.
3183
+ */
3184
+ if (vop2->version == VOP_VERSION_RK3528)
3185
+ vop2_mask_write(vop2, 0x700, 0x3, 4, 0, 0, true);
30863186
30873187 VOP_CTRL_SET(vop2, cfg_done_en, 1);
30883188 /*
....@@ -3151,6 +3251,7 @@
31513251 {
31523252 struct vop2_video_port *vp = to_vop2_video_port(crtc);
31533253 struct vop2 *vop2 = vp->vop2;
3254
+ const struct vop2_video_port_data *vp_data = &vop2->data->vp[vp->id];
31543255 int ret;
31553256
31563257 WARN_ON(vp->event);
....@@ -3163,6 +3264,8 @@
31633264 VOP_MODULE_SET(vop2, vp, cubic_lut_en, 0);
31643265 }
31653266
3267
+ if (vp_data->feature & VOP_FEATURE_VIVID_HDR)
3268
+ VOP_MODULE_SET(vop2, vp, hdr_lut_update_en, 0);
31663269 vop2_disable_all_planes_for_crtc(crtc);
31673270
31683271 /*
....@@ -3188,6 +3291,7 @@
31883291 vop2_dsp_hold_valid_irq_disable(crtc);
31893292
31903293 vop2_disable(crtc);
3294
+ memset(&vp->active_tv_state, 0, sizeof(vp->active_tv_state));
31913295 vop2_unlock(vop2);
31923296
31933297 vop2->active_vp_mask &= ~BIT(vp->id);
....@@ -3500,7 +3604,7 @@
35003604 uint32_t actual_w, actual_h, dsp_w, dsp_h;
35013605 uint32_t dsp_stx, dsp_sty;
35023606 uint32_t act_info, dsp_info, dsp_st;
3503
- uint32_t format;
3607
+ uint32_t format, check_size;
35043608 uint32_t afbc_format;
35053609 uint32_t rb_swap;
35063610 uint32_t uv_swap;
....@@ -3569,18 +3673,19 @@
35693673 actual_w = drm_rect_width(src) >> 16;
35703674 actual_h = drm_rect_height(src) >> 16;
35713675 dsp_w = drm_rect_width(dest);
3572
- if (dest->x1 + dsp_w > adjusted_mode->hdisplay) {
3676
+ if (dest->x1 + dsp_w > adjusted_mode->crtc_hdisplay) {
35733677 DRM_ERROR("vp%d %s dest->x1[%d] + dsp_w[%d] exceed mode hdisplay[%d]\n",
3574
- vp->id, win->name, dest->x1, dsp_w, adjusted_mode->hdisplay);
3678
+ vp->id, win->name, dest->x1, dsp_w, adjusted_mode->crtc_hdisplay);
35753679 dsp_w = adjusted_mode->hdisplay - dest->x1;
35763680 if (dsp_w < 4)
35773681 dsp_w = 4;
35783682 actual_w = dsp_w * actual_w / drm_rect_width(dest);
35793683 }
35803684 dsp_h = drm_rect_height(dest);
3581
- if (dest->y1 + dsp_h > adjusted_mode->vdisplay) {
3685
+ check_size = adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE ? adjusted_mode->vdisplay : adjusted_mode->crtc_vdisplay;
3686
+ if (dest->y1 + dsp_h > check_size) {
35823687 DRM_ERROR("vp%d %s dest->y1[%d] + dsp_h[%d] exceed mode vdisplay[%d]\n",
3583
- vp->id, win->name, dest->y1, dsp_h, adjusted_mode->vdisplay);
3688
+ vp->id, win->name, dest->y1, dsp_h, adjusted_mode->crtc_vdisplay);
35843689 dsp_h = adjusted_mode->vdisplay - dest->y1;
35853690 if (dsp_h < 4)
35863691 dsp_h = 4;
....@@ -3588,20 +3693,25 @@
35883693 }
35893694
35903695 /*
3591
- * This is workaround solution for IC design:
3592
- * esmart can't support scale down when actual_w % 16 == 1.
3696
+ * Workaround only for rk3568 vop
35933697 */
3594
- if (!(win->feature & WIN_FEATURE_AFBDC)) {
3595
- if (actual_w > dsp_w && (actual_w & 0xf) == 1) {
3596
- DRM_WARN("vp%d %s act_w[%d] MODE 16 == 1\n", vp->id, win->name, actual_w);
3597
- actual_w -= 1;
3698
+ if (vop2->version == VOP_VERSION_RK3568) {
3699
+ /*
3700
+ * This is workaround solution for IC design:
3701
+ * esmart can't support scale down when actual_w % 16 == 1.
3702
+ */
3703
+ if (!(win->feature & WIN_FEATURE_AFBDC)) {
3704
+ if (actual_w > dsp_w && (actual_w & 0xf) == 1) {
3705
+ DRM_WARN("vp%d %s act_w[%d] MODE 16 == 1\n", vp->id, win->name, actual_w);
3706
+ actual_w -= 1;
3707
+ }
35983708 }
3599
- }
36003709
3601
- if (vpstate->afbc_en && actual_w % 4) {
3602
- DRM_ERROR("vp%d %s actual_w[%d] should align as 4 pixel when enable afbc\n",
3603
- vp->id, win->name, actual_w);
3604
- actual_w = ALIGN_DOWN(actual_w, 4);
3710
+ if (vpstate->afbc_en && actual_w % 4) {
3711
+ DRM_ERROR("vp%d %s actual_w[%d] should align as 4 pixel when enable afbc\n",
3712
+ vp->id, win->name, actual_w);
3713
+ actual_w = ALIGN_DOWN(actual_w, 4);
3714
+ }
36053715 }
36063716
36073717 act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff);
....@@ -3633,7 +3743,7 @@
36333743 if (vop2->version != VOP_VERSION_RK3568)
36343744 rk3588_vop2_win_cfg_axi(win);
36353745
3636
- if (is_vop3(vop2) && !vop2_cluster_window(win))
3746
+ if (is_vop3(vop2) && !vop2_cluster_window(win) && !win->parent)
36373747 VOP_WIN_SET(vop2, win, scale_engine_num, win->scale_engine_num);
36383748
36393749 if (vpstate->afbc_en) {
....@@ -3765,7 +3875,9 @@
37653875 if (vop2_cluster_window(win)) {
37663876 lb_mode = vop2_get_cluster_lb_mode(win, vpstate);
37673877 VOP_CLUSTER_SET(vop2, win, lb_mode, lb_mode);
3878
+ VOP_CLUSTER_SET(vop2, win, scl_lb_mode, lb_mode == 1 ? 3 : 0);
37683879 VOP_CLUSTER_SET(vop2, win, enable, 1);
3880
+ VOP_CLUSTER_SET(vop2, win, frm_reset_en, 1);
37693881 }
37703882 if (vcstate->output_if & VOP_OUTPUT_IF_BT1120 ||
37713883 vcstate->output_if & VOP_OUTPUT_IF_BT656)
....@@ -4736,6 +4848,27 @@
47364848 struct drm_display_mode *adj_mode)
47374849 {
47384850 struct vop2_video_port *vp = to_vop2_video_port(crtc);
4851
+ struct vop2 *vop2 = vp->vop2;
4852
+
4853
+ /*
4854
+ * For RK3568 and RK3588, the hactive of video timing must
4855
+ * be 4-pixel aligned.
4856
+ */
4857
+ if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3588) {
4858
+ if (adj_mode->hdisplay % 4) {
4859
+ u16 old_hdisplay = adj_mode->hdisplay;
4860
+ u16 align;
4861
+
4862
+ align = 4 - (adj_mode->hdisplay % 4);
4863
+ adj_mode->hdisplay += align;
4864
+ adj_mode->hsync_start += align;
4865
+ adj_mode->hsync_end += align;
4866
+ adj_mode->htotal += align;
4867
+
4868
+ DRM_WARN("VP%d: hactive need to be aligned with 4-pixel, %d -> %d\n",
4869
+ vp->id, old_hdisplay, adj_mode->hdisplay);
4870
+ }
4871
+ }
47394872
47404873 drm_mode_set_crtcinfo(adj_mode, CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE);
47414874
....@@ -4799,6 +4932,8 @@
47994932 to_rockchip_crtc_state(crtc->state);
48004933 struct vop2_video_port *vp = to_vop2_video_port(crtc);
48014934 struct vop2 *vop2 = vp->vop2;
4935
+ const struct vop2_data *vop2_data = vop2->data;
4936
+ const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
48024937 struct drm_display_mode *mode = &crtc->state->adjusted_mode;
48034938 u16 vtotal = mode->crtc_vtotal;
48044939 u16 hdisplay = mode->crtc_hdisplay;
....@@ -4838,8 +4973,16 @@
48384973 val = vact_st_f1 << 16 | vact_end_f1;
48394974 VOP_MODULE_SET(vop2, vp, vpost_st_end_f1, val);
48404975 }
4841
- VOP_MODULE_SET(vop2, vp, post_dsp_out_r2y,
4842
- is_yuv_output(vcstate->bus_format));
4976
+
4977
+ /*
4978
+ * BCSH[R2Y] -> POST Linebuffer[post scale] -> the background R2Y will be deal by post_dsp_out_r2y
4979
+ *
4980
+ * POST Linebuffer[post scale] -> ACM[R2Y] -> the background R2Y will be deal by ACM[R2Y]
4981
+ */
4982
+ if (vp_data->feature & VOP_FEATURE_POST_ACM)
4983
+ VOP_MODULE_SET(vop2, vp, post_dsp_out_r2y, vcstate->yuv_overlay);
4984
+ else
4985
+ VOP_MODULE_SET(vop2, vp, post_dsp_out_r2y, is_yuv_output(vcstate->bus_format));
48434986 }
48444987
48454988 /*
....@@ -4880,6 +5023,107 @@
48805023 return false;
48815024 }
48825025
5026
+/*
5027
+ * For vop3 video port0, if hdr_vivid is not enable, the pipe delay time as follow:
5028
+ * win_dly + config_win_dly + layer_mix_dly + sdr2hdr_dly + * hdr_mix_dly = config_bg_dly
5029
+ *
5030
+ * if hdr_vivid is enable, the hdr layer's pipe delay time as follow:
5031
+ * win_dly + config_win_dly +hdrvivid_dly + hdr_mix_dly = config_bg_dly
5032
+ *
5033
+ * If hdrvivid and sdr2hdr bot enable, the time arrivr hdr_mix should be the same:
5034
+ * win_dly + config_win_dly0 + hdrvivid_dly = win_dly + config_win_dly1 + laer_mix_dly +
5035
+ * sdr2hdr_dly
5036
+ *
5037
+ * For vop3 video port1, the pipe delay time as follow:
5038
+ * win_dly + config_win_dly + layer_mix_dly = config_bg_dly
5039
+ *
5040
+ * Here, win_dly, layer_mix_dly, sdr2hdr_dly, hdr_mix_dly, hdrvivid_dly is the hardware
5041
+ * delay cycles. Config_win_dly and config_bg_dly is the register value that we can config.
5042
+ * Different hdr vivid mode have different hdrvivid_dly. For sdr2hdr_dly, only sde2hdr
5043
+ * enable, it will delay, otherwise, the sdr2hdr_dly is 0.
5044
+ *
5045
+ * For default, the config_win_dly will be 0, it just user to make the pipe to arrive
5046
+ * hdr_mix at the same time.
5047
+ */
5048
+static void vop3_setup_pipe_dly(struct vop2_video_port *vp, const struct vop2_zpos *vop2_zpos)
5049
+{
5050
+ struct vop2 *vop2 = vp->vop2;
5051
+ struct drm_crtc *crtc = &vp->crtc;
5052
+ const struct vop2_zpos *zpos;
5053
+ struct drm_plane *plane;
5054
+ struct vop2_plane_state *vpstate;
5055
+ struct vop2_win *win;
5056
+ const struct vop2_data *vop2_data = vop2->data;
5057
+ const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
5058
+ struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
5059
+ u16 hsync_len = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
5060
+ u16 hdisplay = adjusted_mode->crtc_hdisplay;
5061
+ int bg_dly = 0x0;
5062
+ int dly = 0x0;
5063
+ int hdr_win_dly;
5064
+ int sdr_win_dly;
5065
+ int sdr2hdr_dly;
5066
+ int pre_scan_dly;
5067
+ int i;
5068
+
5069
+ /**
5070
+ * config bg dly, select the max delay num of hdrvivid and sdr2hdr module
5071
+ * as the increase value of bg delay num. If hdrvivid and sdr2hdr is not
5072
+ * work, the default bg_dly is 0x10. and the default win delay num is 0.
5073
+ */
5074
+ if ((vp->hdr_en || vp->sdr2hdr_en) &&
5075
+ (vp->hdrvivid_mode >= 0 && vp->hdrvivid_mode <= SDR2HLG)) {
5076
+ /* set sdr2hdr_dly to 0 if sdr2hdr is disable */
5077
+ sdr2hdr_dly = vp->sdr2hdr_en ? vp_data->sdr2hdr_dly : 0;
5078
+
5079
+ /* set the max delay pipe's config_win_dly as 0 */
5080
+ if (vp_data->hdrvivid_dly[vp->hdrvivid_mode] >=
5081
+ sdr2hdr_dly + vp_data->layer_mix_dly) {
5082
+ bg_dly = vp_data->win_dly + vp_data->hdrvivid_dly[vp->hdrvivid_mode] +
5083
+ vp_data->hdr_mix_dly;
5084
+ hdr_win_dly = 0;
5085
+ sdr_win_dly = vp_data->hdrvivid_dly[vp->hdrvivid_mode] -
5086
+ vp_data->layer_mix_dly - sdr2hdr_dly;
5087
+ } else {
5088
+ bg_dly = vp_data->win_dly + vp_data->layer_mix_dly + sdr2hdr_dly +
5089
+ vp_data->hdr_mix_dly;
5090
+ hdr_win_dly = sdr2hdr_dly + vp_data->layer_mix_dly -
5091
+ vp_data->hdrvivid_dly[vp->hdrvivid_mode];
5092
+ sdr_win_dly = 0;
5093
+ }
5094
+ } else {
5095
+ bg_dly = vp_data->win_dly + vp_data->layer_mix_dly + vp_data->hdr_mix_dly;
5096
+ sdr_win_dly = 0;
5097
+ }
5098
+
5099
+ pre_scan_dly = bg_dly + (hdisplay >> 1) - 1;
5100
+ pre_scan_dly = (pre_scan_dly << 16) | hsync_len;
5101
+ VOP_MODULE_SET(vop2, vp, bg_dly, bg_dly);
5102
+ VOP_MODULE_SET(vop2, vp, pre_scan_htiming, pre_scan_dly);
5103
+
5104
+ /**
5105
+ * config win dly
5106
+ */
5107
+ if (!vop2_zpos)
5108
+ return;
5109
+
5110
+ for (i = 0; i < vp->nr_layers; i++) {
5111
+ zpos = &vop2_zpos[i];
5112
+ win = vop2_find_win_by_phys_id(vop2, zpos->win_phys_id);
5113
+ plane = &win->base;
5114
+ vpstate = to_vop2_plane_state(plane->state);
5115
+
5116
+ if ((vp->hdr_en || vp->sdr2hdr_en) &&
5117
+ (vp->hdrvivid_mode >= 0 && vp->hdrvivid_mode <= SDR2HLG)) {
5118
+ dly = vpstate->hdr_in ? hdr_win_dly : sdr_win_dly;
5119
+ }
5120
+ if (vop2_cluster_window(win))
5121
+ dly |= dly << 8;
5122
+
5123
+ VOP_CTRL_SET(vop2, win_dly[win->phys_id], dly);
5124
+ }
5125
+}
5126
+
48835127 static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
48845128 {
48855129 struct vop2_video_port *vp = to_vop2_video_port(crtc);
....@@ -4900,7 +5144,6 @@
49005144 u16 vact_st = adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vsync_start;
49015145 u16 vact_end = vact_st + vdisplay;
49025146 bool interlaced = !!(adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE);
4903
- uint8_t out_mode;
49045147 bool dclk_inv, yc_swap = false;
49055148 int act_end;
49065149 uint32_t val;
....@@ -4925,6 +5168,7 @@
49255168 if (vcstate->output_if & VOP_OUTPUT_IF_RGB) {
49265169 VOP_CTRL_SET(vop2, rgb_en, 1);
49275170 VOP_CTRL_SET(vop2, rgb_mux, vp_data->id);
5171
+ VOP_CTRL_SET(vop2, rgb_pin_pol, val);
49285172 VOP_GRF_SET(vop2, grf_dclk_inv, dclk_inv);
49295173 }
49305174
....@@ -5038,21 +5282,6 @@
50385282 VOP_CTRL_SET(vop2, hdmi_dclk_pol, 1);
50395283 }
50405284
5041
- if ((vcstate->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
5042
- !(vp_data->feature & VOP_FEATURE_OUTPUT_10BIT)) ||
5043
- vcstate->output_if & VOP_OUTPUT_IF_BT656)
5044
- out_mode = ROCKCHIP_OUT_MODE_P888;
5045
- else
5046
- out_mode = vcstate->output_mode;
5047
- VOP_MODULE_SET(vop2, vp, out_mode, out_mode);
5048
-
5049
- if (vop2_output_uv_swap(vcstate->bus_format, vcstate->output_mode))
5050
- VOP_MODULE_SET(vop2, vp, dsp_data_swap, DSP_RB_SWAP);
5051
- else
5052
- VOP_MODULE_SET(vop2, vp, dsp_data_swap, 0);
5053
-
5054
- vop2_dither_setup(crtc);
5055
-
50565285 VOP_MODULE_SET(vop2, vp, htotal_pw, (htotal << 16) | hsync_len);
50575286 val = hact_st << 16;
50585287 val |= hact_end;
....@@ -5105,9 +5334,20 @@
51055334 VOP_MODULE_SET(vop2, vp, dclk_div2_phase_lock, 0);
51065335 }
51075336
5108
- clk_set_rate(vp->dclk, adjusted_mode->crtc_clock * 1000);
5337
+ /*
5338
+ * For RK3528, the path of CVBS output is like:
5339
+ * VOP BT656 ENCODER -> CVBS BT656 DECODER -> CVBS ENCODER -> CVBS VDAC
5340
+ * The vop2 dclk should be four times crtc_clock for CVBS sampling clock needs.
5341
+ */
5342
+ if (vop2->version == VOP_VERSION_RK3528 && vcstate->output_if & VOP_OUTPUT_IF_BT656)
5343
+ clk_set_rate(vp->dclk, 4 * adjusted_mode->crtc_clock * 1000);
5344
+ else
5345
+ clk_set_rate(vp->dclk, adjusted_mode->crtc_clock * 1000);
51095346
51105347 vop2_post_config(crtc);
5348
+
5349
+ if (is_vop3(vop2))
5350
+ vop3_setup_pipe_dly(vp, NULL);
51115351
51125352 vop2_cfg_done(crtc);
51135353
....@@ -5154,6 +5394,224 @@
51545394 struct drm_crtc_state *crtc_state)
51555395 {
51565396 return 0;
5397
+}
5398
+
5399
+static void vop3_disable_dynamic_hdr(struct vop2_video_port *vp, uint8_t win_phys_id)
5400
+{
5401
+ struct vop2 *vop2 = vp->vop2;
5402
+ struct vop2_win *win = vop2_find_win_by_phys_id(vop2, win_phys_id);
5403
+ struct drm_plane *plane = &win->base;
5404
+ struct drm_plane_state *pstate = plane->state;
5405
+ struct vop2_plane_state *vpstate = to_vop2_plane_state(pstate);
5406
+
5407
+ VOP_MODULE_SET(vop2, vp, hdr10_en, 0);
5408
+ VOP_MODULE_SET(vop2, vp, hdr_vivid_en, 0);
5409
+ VOP_MODULE_SET(vop2, vp, hdr_vivid_bypass_en, 0);
5410
+ VOP_MODULE_SET(vop2, vp, hdr_lut_update_en, 0);
5411
+ VOP_MODULE_SET(vop2, vp, sdr2hdr_en, 0);
5412
+ VOP_MODULE_SET(vop2, vp, sdr2hdr_path_en, 0);
5413
+ VOP_MODULE_SET(vop2, vp, sdr2hdr_auto_gating_en, 1);
5414
+
5415
+ vp->hdr_en = false;
5416
+ vp->hdr_in = false;
5417
+ vp->hdr_out = false;
5418
+ vp->sdr2hdr_en = false;
5419
+ vpstate->hdr_in = false;
5420
+ vpstate->hdr2sdr_en = false;
5421
+}
5422
+
5423
+static void vop3_setup_hdrvivid(struct vop2_video_port *vp, uint8_t win_phys_id)
5424
+{
5425
+ struct vop2 *vop2 = vp->vop2;
5426
+ struct vop2_win *win = vop2_find_win_by_phys_id(vop2, win_phys_id);
5427
+ struct drm_plane *plane = &win->base;
5428
+ struct drm_plane_state *pstate = plane->state;
5429
+ struct vop2_plane_state *vpstate = to_vop2_plane_state(pstate);
5430
+ struct drm_crtc_state *cstate = vp->crtc.state;
5431
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(cstate);
5432
+ unsigned long win_mask = vp->win_mask;
5433
+ int phys_id;
5434
+ struct hdrvivid_regs *hdrvivid_data;
5435
+ struct hdr_extend *hdr_data;
5436
+ bool have_sdr_layer = false;
5437
+ uint32_t hdr_mode;
5438
+ int i;
5439
+ u32 *tone_lut_kvaddr;
5440
+ dma_addr_t tone_lut_mst;
5441
+
5442
+ vp->hdr_en = false;
5443
+ vp->hdr_in = false;
5444
+ vp->hdr_out = false;
5445
+ vp->sdr2hdr_en = false;
5446
+ vpstate->hdr_in = false;
5447
+ vpstate->hdr2sdr_en = false;
5448
+
5449
+ hdr_data = (struct hdr_extend *)vcstate->hdr_ext_data->data;
5450
+ hdrvivid_data = &hdr_data->hdrvivid_data;
5451
+
5452
+ hdr_mode = hdrvivid_data->hdr_mode;
5453
+
5454
+ if (hdr_mode > SDR2HLG && hdr_mode != SDR2HDR10_USERSPACE &&
5455
+ hdr_mode != SDR2HLG_USERSPACE) {
5456
+ DRM_ERROR("Invalid HDR mode:%d, beyond the mode range\n", hdr_mode);
5457
+ return;
5458
+ }
5459
+
5460
+ /* adjust userspace hdr mode value to kernel value */
5461
+ if (hdr_mode == SDR2HDR10_USERSPACE)
5462
+ hdr_mode = SDR2HDR10;
5463
+ if (hdr_mode == SDR2HLG_USERSPACE)
5464
+ hdr_mode = SDR2HLG;
5465
+
5466
+ if (hdr_mode <= HDR102SDR && vpstate->eotf != SMPTE_ST2084 && vpstate->eotf != HLG) {
5467
+ DRM_ERROR("Invalid HDR mode:%d, mismatch plane eotf:%d\n", hdr_mode,
5468
+ vpstate->eotf);
5469
+ return;
5470
+ }
5471
+
5472
+ vp->hdrvivid_mode = hdr_mode;
5473
+ vcstate->yuv_overlay = false;
5474
+
5475
+ if (hdr_mode <= HDR102SDR) {
5476
+ vp->hdr_en = true;
5477
+ vp->hdr_in = true;
5478
+ vpstate->hdr_in = true;
5479
+ } else {
5480
+ vp->sdr2hdr_en = true;
5481
+ }
5482
+
5483
+ /*
5484
+ * To confirm whether need to enable sdr2hdr.
5485
+ */
5486
+ for_each_set_bit(phys_id, &win_mask, ROCKCHIP_MAX_LAYER) {
5487
+ win = vop2_find_win_by_phys_id(vop2, phys_id);
5488
+ plane = &win->base;
5489
+ pstate = plane->state;
5490
+ vpstate = to_vop2_plane_state(pstate);
5491
+
5492
+ /* skip inactive plane */
5493
+ if (!vop2_plane_active(pstate))
5494
+ continue;
5495
+
5496
+ if (vpstate->eotf != SMPTE_ST2084 && vpstate->eotf != HLG) {
5497
+ have_sdr_layer = true;
5498
+ break;
5499
+ }
5500
+ }
5501
+
5502
+ if (hdr_mode == PQHDR2SDR_WITH_DYNAMIC || hdr_mode == HLG2SDR_WITH_DYNAMIC ||
5503
+ hdr_mode == HLG2SDR_WITHOUT_DYNAMIC || hdr_mode == HDR102SDR) {
5504
+ vpstate->hdr2sdr_en = true;
5505
+ } else {
5506
+ vp->hdr_out = true;
5507
+ if (have_sdr_layer)
5508
+ vp->sdr2hdr_en = true;
5509
+ }
5510
+
5511
+ /**
5512
+ * Config hdr ctrl registers
5513
+ */
5514
+ vop2_writel(vop2, RK3528_SDR2HDR_CTRL, hdrvivid_data->sdr2hdr_ctrl);
5515
+ vop2_writel(vop2, RK3528_HDRVIVID_CTRL, hdrvivid_data->hdrvivid_ctrl);
5516
+
5517
+ VOP_MODULE_SET(vop2, vp, hdr10_en, vp->hdr_en);
5518
+ if (vp->hdr_en) {
5519
+ VOP_MODULE_SET(vop2, vp, hdr_vivid_en, (hdr_mode == HDR_BYPASS) ? 0 : 1);
5520
+ VOP_MODULE_SET(vop2, vp, hdr_vivid_path_mode,
5521
+ (hdr_mode == HDR102SDR) ? PQHDR2SDR_WITH_DYNAMIC : hdr_mode);
5522
+ VOP_MODULE_SET(vop2, vp, hdr_vivid_bypass_en, (hdr_mode == HDR_BYPASS) ? 1 : 0);
5523
+ } else {
5524
+ VOP_MODULE_SET(vop2, vp, hdr_vivid_en, 0);
5525
+ }
5526
+ VOP_MODULE_SET(vop2, vp, sdr2hdr_en, vp->sdr2hdr_en);
5527
+ VOP_MODULE_SET(vop2, vp, sdr2hdr_path_en, vp->sdr2hdr_en);
5528
+ VOP_MODULE_SET(vop2, vp, sdr2hdr_auto_gating_en, vp->sdr2hdr_en ? 0 : 1);
5529
+
5530
+ vop2_writel(vop2, RK3528_SDR_CFG_COE0, hdrvivid_data->sdr2hdr_coe0);
5531
+ vop2_writel(vop2, RK3528_SDR_CFG_COE1, hdrvivid_data->sdr2hdr_coe1);
5532
+ vop2_writel(vop2, RK3528_SDR_CSC_COE00_01, hdrvivid_data->sdr2hdr_csc_coe00_01);
5533
+ vop2_writel(vop2, RK3528_SDR_CSC_COE02_10, hdrvivid_data->sdr2hdr_csc_coe02_10);
5534
+ vop2_writel(vop2, RK3528_SDR_CSC_COE11_12, hdrvivid_data->sdr2hdr_csc_coe11_12);
5535
+ vop2_writel(vop2, RK3528_SDR_CSC_COE20_21, hdrvivid_data->sdr2hdr_csc_coe20_21);
5536
+ vop2_writel(vop2, RK3528_SDR_CSC_COE22, hdrvivid_data->sdr2hdr_csc_coe22);
5537
+
5538
+ vop2_writel(vop2, RK3528_HDR_PQ_GAMMA, hdrvivid_data->hdr_pq_gamma);
5539
+ vop2_writel(vop2, RK3528_HLG_RFIX_SCALEFAC, hdrvivid_data->hlg_rfix_scalefac);
5540
+ vop2_writel(vop2, RK3528_HLG_MAXLUMA, hdrvivid_data->hlg_maxluma);
5541
+ vop2_writel(vop2, RK3528_HLG_R_TM_LIN2NON, hdrvivid_data->hlg_r_tm_lin2non);
5542
+
5543
+ vop2_writel(vop2, RK3528_HDR_CSC_COE00_01, hdrvivid_data->hdr_csc_coe00_01);
5544
+ vop2_writel(vop2, RK3528_HDR_CSC_COE02_10, hdrvivid_data->hdr_csc_coe02_10);
5545
+ vop2_writel(vop2, RK3528_HDR_CSC_COE11_12, hdrvivid_data->hdr_csc_coe11_12);
5546
+ vop2_writel(vop2, RK3528_HDR_CSC_COE20_21, hdrvivid_data->hdr_csc_coe20_21);
5547
+ vop2_writel(vop2, RK3528_HDR_CSC_COE22, hdrvivid_data->hdr_csc_coe22);
5548
+
5549
+ tone_lut_kvaddr = (u32 *)vp->hdr_lut_gem_obj->kvaddr;
5550
+ tone_lut_mst = vp->hdr_lut_gem_obj->dma_addr;
5551
+
5552
+ for (i = 0; i < RK_HDRVIVID_TONE_SCA_AXI_TAB_LENGTH; i++)
5553
+ *tone_lut_kvaddr++ = hdrvivid_data->tone_sca_axi_tab[i];
5554
+
5555
+ VOP_MODULE_SET(vop2, vp, lut_dma_rid, vp->lut_dma_rid - vp->id);
5556
+ VOP_MODULE_SET(vop2, vp, hdr_lut_mode, 1);
5557
+ VOP_MODULE_SET(vop2, vp, hdr_lut_mst, tone_lut_mst);
5558
+ VOP_MODULE_SET(vop2, vp, hdr_lut_update_en, 1);
5559
+ VOP_CTRL_SET(vop2, lut_dma_en, 1);
5560
+
5561
+ for (i = 0; i < RK_HDRVIVID_GAMMA_CURVE_LENGTH; i++)
5562
+ vop2_writel(vop2, RK3528_HDRGAMMA_CURVE + i * 4, hdrvivid_data->hdrgamma_curve[i]);
5563
+
5564
+ for (i = 0; i < RK_HDRVIVID_GAMMA_MDFVALUE_LENGTH; i++)
5565
+ vop2_writel(vop2, RK3528_HDRGAMMA_MDFVALUE + i * 4,
5566
+ hdrvivid_data->hdrgamma_mdfvalue[i]);
5567
+
5568
+ for (i = 0; i < RK_SDR2HDR_INVGAMMA_CURVE_LENGTH; i++)
5569
+ vop2_writel(vop2, RK3528_SDRINVGAMMA_CURVE + i * 4,
5570
+ hdrvivid_data->sdrinvgamma_curve[i]);
5571
+
5572
+ for (i = 0; i < RK_SDR2HDR_INVGAMMA_S_IDX_LENGTH; i++)
5573
+ vop2_writel(vop2, RK3528_SDRINVGAMMA_STARTIDX + i * 4,
5574
+ hdrvivid_data->sdrinvgamma_startidx[i]);
5575
+
5576
+ for (i = 0; i < RK_SDR2HDR_INVGAMMA_C_IDX_LENGTH; i++)
5577
+ vop2_writel(vop2, RK3528_SDRINVGAMMA_CHANGEIDX + i * 4,
5578
+ hdrvivid_data->sdrinvgamma_changeidx[i]);
5579
+
5580
+ for (i = 0; i < RK_SDR2HDR_SMGAIN_LENGTH; i++)
5581
+ vop2_writel(vop2, RK3528_SDR_SMGAIN + i * 4, hdrvivid_data->sdr_smgain[i]);
5582
+}
5583
+
5584
+static void vop3_setup_dynamic_hdr(struct vop2_video_port *vp, uint8_t win_phys_id)
5585
+{
5586
+ struct drm_crtc_state *cstate = vp->crtc.state;
5587
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(cstate);
5588
+ struct hdr_extend *hdr_data;
5589
+ uint32_t hdr_format;
5590
+
5591
+ /* If hdr extend data is null, exit hdr mode */
5592
+ if (!vcstate->hdr_ext_data) {
5593
+ vop3_disable_dynamic_hdr(vp, win_phys_id);
5594
+ return;
5595
+ }
5596
+
5597
+ hdr_data = (struct hdr_extend *)vcstate->hdr_ext_data->data;
5598
+ hdr_format = hdr_data->hdr_type;
5599
+
5600
+ switch (hdr_format) {
5601
+ case HDR_NONE:
5602
+ case HDR_HDR10:
5603
+ case HDR_HLGSTATIC:
5604
+ case HDR_HDRVIVID:
5605
+ /*
5606
+ * hdr module support hdr10, hlg, vividhdr
5607
+ * sdr2hdr module support hdrnone for sdr2hdr
5608
+ */
5609
+ vop3_setup_hdrvivid(vp, win_phys_id);
5610
+ break;
5611
+ default:
5612
+ DRM_DEBUG("unsupprot hdr format:%u\n", hdr_format);
5613
+ break;
5614
+ }
51575615 }
51585616
51595617 static void vop2_setup_hdr10(struct vop2_video_port *vp, uint8_t win_phys_id)
....@@ -5648,7 +6106,7 @@
56486106 vop2_writel(vop2, dst_alpha_ctrl_offset + offset, alpha.dst_alpha_ctrl.val);
56496107 }
56506108
5651
- if (vp_data->feature & VOP_FEATURE_HDR10) {
6109
+ if (vp_data->feature & (VOP_FEATURE_HDR10 | VOP_FEATURE_VIVID_HDR)) {
56526110 src_color_ctrl_offset = ovl_regs->hdr_mix_regs->src_color_ctrl.offset;
56536111 dst_color_ctrl_offset = ovl_regs->hdr_mix_regs->dst_color_ctrl.offset;
56546112 src_alpha_ctrl_offset = ovl_regs->hdr_mix_regs->src_alpha_ctrl.offset;
....@@ -5923,6 +6381,7 @@
59236381 struct vop2_cluster cluster;
59246382 uint8_t nr_layers = 0;
59256383 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
6384
+ const struct vop2_video_port_data *vp_data = &vop2->data->vp[vp->id];
59266385
59276386 vcstate->yuv_overlay = is_yuv_output(vcstate->bus_format);
59286387 vop2_zpos = kmalloc_array(vop2->data->win_size, sizeof(*vop2_zpos), GFP_KERNEL);
....@@ -5982,21 +6441,26 @@
59826441
59836442 sort(vop2_zpos, nr_layers, sizeof(vop2_zpos[0]), vop2_zpos_cmp, NULL);
59846443
5985
- if (is_vop3(vop2))
6444
+ if (is_vop3(vop2)) {
59866445 vop3_setup_layer_sel_for_vp(vp, vop2_zpos);
5987
- else
5988
- vop2_setup_layer_mixer_for_vp(vp, vop2_zpos);
5989
- vop2_setup_hdr10(vp, vop2_zpos[0].win_phys_id);
5990
- if (is_vop3(vop2))
6446
+ if (vp_data->feature & VOP_FEATURE_VIVID_HDR)
6447
+ vop3_setup_dynamic_hdr(vp, vop2_zpos[0].win_phys_id);
59916448 vop3_setup_alpha(vp, vop2_zpos);
5992
- else
6449
+ vop3_setup_pipe_dly(vp, vop2_zpos);
6450
+ } else {
6451
+ vop2_setup_layer_mixer_for_vp(vp, vop2_zpos);
6452
+ vop2_setup_hdr10(vp, vop2_zpos[0].win_phys_id);
59936453 vop2_setup_alpha(vp, vop2_zpos);
5994
- vop2_setup_dly_for_vp(vp);
5995
- vop2_setup_dly_for_window(vp, vop2_zpos);
6454
+ vop2_setup_dly_for_vp(vp);
6455
+ vop2_setup_dly_for_window(vp, vop2_zpos);
6456
+ }
59966457 } else {
5997
- if (!is_vop3(vop2))
6458
+ if (!is_vop3(vop2)) {
59986459 vop2_calc_bg_ovl_and_port_mux(vp);
5999
- vop2_setup_dly_for_vp(vp);
6460
+ vop2_setup_dly_for_vp(vp);
6461
+ } else {
6462
+ vop3_setup_pipe_dly(vp, NULL);
6463
+ }
60006464 }
60016465
60026466 /* The pre alpha overlay of Cluster still need process in one win mode. */
....@@ -6124,16 +6588,193 @@
61246588 vop2_bcsh_reg_update(vcstate, vp, &bcsh_state);
61256589 }
61266590
6591
+static void vop3_post_csc_config(struct drm_crtc *crtc, struct post_acm *acm, struct post_csc *csc)
6592
+{
6593
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
6594
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
6595
+ struct vop2 *vop2 = vp->vop2;
6596
+ struct post_csc_coef csc_coef;
6597
+ bool acm_enable;
6598
+ bool is_input_yuv = false;
6599
+ bool is_output_yuv = false;
6600
+ bool post_r2y_en = false;
6601
+ bool post_csc_en = false;
6602
+ int range_type;
6603
+
6604
+ if (!acm)
6605
+ acm_enable = false;
6606
+ else
6607
+ acm_enable = acm->acm_enable;
6608
+
6609
+ if (acm_enable) {
6610
+ if (!vcstate->yuv_overlay)
6611
+ post_r2y_en = true;
6612
+
6613
+ /* do y2r in csc module */
6614
+ if (!is_yuv_output(vcstate->bus_format))
6615
+ post_csc_en = true;
6616
+ } else {
6617
+ if (!vcstate->yuv_overlay && is_yuv_output(vcstate->bus_format))
6618
+ post_r2y_en = true;
6619
+
6620
+ /* do y2r in csc module */
6621
+ if (vcstate->yuv_overlay && !is_yuv_output(vcstate->bus_format))
6622
+ post_csc_en = true;
6623
+ }
6624
+
6625
+ if (csc && csc->csc_enable)
6626
+ post_csc_en = true;
6627
+
6628
+ if (vcstate->yuv_overlay || post_r2y_en)
6629
+ is_input_yuv = true;
6630
+
6631
+ if (is_yuv_output(vcstate->bus_format))
6632
+ is_output_yuv = true;
6633
+
6634
+ vcstate->post_csc_mode = vop2_convert_csc_mode(vcstate->color_space, CSC_13BIT_DEPTH);
6635
+
6636
+ if (post_csc_en) {
6637
+ rockchip_calc_post_csc(csc, &csc_coef, vcstate->post_csc_mode, is_input_yuv,
6638
+ is_output_yuv);
6639
+
6640
+ VOP_MODULE_SET(vop2, vp, csc_coe00, csc_coef.csc_coef00);
6641
+ VOP_MODULE_SET(vop2, vp, csc_coe01, csc_coef.csc_coef01);
6642
+ VOP_MODULE_SET(vop2, vp, csc_coe02, csc_coef.csc_coef02);
6643
+ VOP_MODULE_SET(vop2, vp, csc_coe10, csc_coef.csc_coef10);
6644
+ VOP_MODULE_SET(vop2, vp, csc_coe11, csc_coef.csc_coef11);
6645
+ VOP_MODULE_SET(vop2, vp, csc_coe12, csc_coef.csc_coef12);
6646
+ VOP_MODULE_SET(vop2, vp, csc_coe20, csc_coef.csc_coef20);
6647
+ VOP_MODULE_SET(vop2, vp, csc_coe21, csc_coef.csc_coef21);
6648
+ VOP_MODULE_SET(vop2, vp, csc_coe22, csc_coef.csc_coef22);
6649
+ VOP_MODULE_SET(vop2, vp, csc_offset0, csc_coef.csc_dc0);
6650
+ VOP_MODULE_SET(vop2, vp, csc_offset1, csc_coef.csc_dc1);
6651
+ VOP_MODULE_SET(vop2, vp, csc_offset2, csc_coef.csc_dc2);
6652
+
6653
+ range_type = csc_coef.range_type ? 0 : 1;
6654
+ range_type <<= is_input_yuv ? 0 : 1;
6655
+ VOP_MODULE_SET(vop2, vp, csc_mode, range_type);
6656
+ }
6657
+
6658
+ VOP_MODULE_SET(vop2, vp, acm_r2y_en, post_r2y_en ? 1 : 0);
6659
+ VOP_MODULE_SET(vop2, vp, csc_en, post_csc_en ? 1 : 0);
6660
+ VOP_MODULE_SET(vop2, vp, acm_r2y_mode, vcstate->post_csc_mode);
6661
+}
6662
+
6663
+static void vop3_post_acm_config(struct drm_crtc *crtc, struct post_acm *acm)
6664
+{
6665
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
6666
+ struct vop2 *vop2 = vp->vop2;
6667
+ struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
6668
+ s16 *lut_y;
6669
+ s16 *lut_h;
6670
+ s16 *lut_s;
6671
+ u32 value;
6672
+ int i;
6673
+
6674
+ writel(0, vop2->acm_regs + RK3528_ACM_CTRL);
6675
+ VOP_MODULE_SET(vop2, vp, acm_bypass_en, 0);
6676
+
6677
+ if (!acm || !acm->acm_enable)
6678
+ return;
6679
+
6680
+ /*
6681
+ * If acm update parameters, it need disable acm in the first frame,
6682
+ * then update parameters and enable acm in second frame.
6683
+ */
6684
+ vop2_cfg_done(crtc);
6685
+ readx_poll_timeout(readl, vop2->acm_regs + RK3528_ACM_CTRL, value, !value, 200, 50000);
6686
+
6687
+ value = RK3528_ACM_ENABLE + ((adjusted_mode->hdisplay & 0xfff) << 8) +
6688
+ ((adjusted_mode->vdisplay & 0xfff) << 20);
6689
+ writel(value, vop2->acm_regs + RK3528_ACM_CTRL);
6690
+
6691
+
6692
+ writel(1, vop2->acm_regs + RK3528_ACM_FETCH_START);
6693
+
6694
+ value = (acm->y_gain & 0x3ff) + ((acm->h_gain << 10) & 0xffc00) +
6695
+ ((acm->s_gain << 20) & 0x3ff00000);
6696
+ writel(value, vop2->acm_regs + RK3528_ACM_DELTA_RANGE);
6697
+
6698
+ lut_y = &acm->gain_lut_hy[0];
6699
+ lut_h = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH];
6700
+ lut_s = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH * 2];
6701
+ for (i = 0; i < ACM_GAIN_LUT_HY_LENGTH; i++) {
6702
+ value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) +
6703
+ ((lut_s[i] << 16) & 0xff0000);
6704
+ writel(value, vop2->acm_regs + RK3528_ACM_YHS_DEL_HY_SEG0 + (i << 2));
6705
+ }
6706
+
6707
+ lut_y = &acm->gain_lut_hs[0];
6708
+ lut_h = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH];
6709
+ lut_s = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH * 2];
6710
+ for (i = 0; i < ACM_GAIN_LUT_HS_LENGTH; i++) {
6711
+ value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) +
6712
+ ((lut_s[i] << 16) & 0xff0000);
6713
+ writel(value, vop2->acm_regs + RK3528_ACM_YHS_DEL_HS_SEG0 + (i << 2));
6714
+ }
6715
+
6716
+ lut_y = &acm->delta_lut_h[0];
6717
+ lut_h = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH];
6718
+ lut_s = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH * 2];
6719
+ for (i = 0; i < ACM_DELTA_LUT_H_LENGTH; i++) {
6720
+ value = (lut_y[i] & 0x3ff) + ((lut_h[i] << 12) & 0xff000) +
6721
+ ((lut_s[i] << 20) & 0x3ff00000);
6722
+ writel(value, vop2->acm_regs + RK3528_ACM_YHS_DEL_HGAIN_SEG0 + (i << 2));
6723
+ }
6724
+
6725
+ writel(1, vop2->acm_regs + RK3528_ACM_FETCH_DONE);
6726
+}
6727
+
6728
+static void vop3_post_config(struct drm_crtc *crtc)
6729
+{
6730
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
6731
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
6732
+ struct post_acm *acm;
6733
+ struct post_csc *csc;
6734
+
6735
+ csc = vcstate->post_csc_data ? (struct post_csc *)vcstate->post_csc_data->data : NULL;
6736
+ if (csc && memcmp(&vp->csc_info, csc, sizeof(struct post_csc)))
6737
+ memcpy(&vp->csc_info, csc, sizeof(struct post_csc));
6738
+ vop3_post_csc_config(crtc, &vp->acm_info, &vp->csc_info);
6739
+
6740
+ acm = vcstate->acm_lut_data ? (struct post_acm *)vcstate->acm_lut_data->data : NULL;
6741
+
6742
+ if (acm && memcmp(&vp->acm_info, acm, sizeof(struct post_acm))) {
6743
+ memcpy(&vp->acm_info, acm, sizeof(struct post_acm));
6744
+ vop3_post_acm_config(crtc, &vp->acm_info);
6745
+ } else if (crtc->state->active_changed) {
6746
+ vop3_post_acm_config(crtc, &vp->acm_info);
6747
+ }
6748
+}
6749
+
61276750 static void vop2_cfg_update(struct drm_crtc *crtc,
61286751 struct drm_crtc_state *old_crtc_state)
61296752 {
61306753 struct vop2_video_port *vp = to_vop2_video_port(crtc);
61316754 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
61326755 struct vop2 *vop2 = vp->vop2;
6756
+ const struct vop2_data *vop2_data = vop2->data;
6757
+ const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
61336758 uint32_t val;
61346759 uint32_t r, g, b;
6760
+ uint8_t out_mode;
61356761
61366762 spin_lock(&vop2->reg_lock);
6763
+
6764
+ if ((vcstate->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
6765
+ !(vp_data->feature & VOP_FEATURE_OUTPUT_10BIT)) ||
6766
+ vcstate->output_if & VOP_OUTPUT_IF_BT656)
6767
+ out_mode = ROCKCHIP_OUT_MODE_P888;
6768
+ else
6769
+ out_mode = vcstate->output_mode;
6770
+ VOP_MODULE_SET(vop2, vp, out_mode, out_mode);
6771
+
6772
+ if (vop2_output_uv_swap(vcstate->bus_format, vcstate->output_mode))
6773
+ VOP_MODULE_SET(vop2, vp, dsp_data_swap, DSP_RB_SWAP);
6774
+ else
6775
+ VOP_MODULE_SET(vop2, vp, dsp_data_swap, 0);
6776
+
6777
+ vop2_dither_setup(crtc);
61376778
61386779 VOP_MODULE_SET(vop2, vp, overlay_mode, vcstate->yuv_overlay);
61396780
....@@ -6162,6 +6803,9 @@
61626803 vop2_post_config(crtc);
61636804
61646805 spin_unlock(&vop2->reg_lock);
6806
+
6807
+ if (vp_data->feature & (VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC))
6808
+ vop3_post_config(crtc);
61656809 }
61666810
61676811 static void vop2_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_cstate)
....@@ -6304,6 +6948,13 @@
63046948 return NULL;
63056949
63066950 vcstate->vp_id = vp->id;
6951
+ if (vcstate->hdr_ext_data)
6952
+ drm_property_blob_get(vcstate->hdr_ext_data);
6953
+ if (vcstate->acm_lut_data)
6954
+ drm_property_blob_get(vcstate->acm_lut_data);
6955
+ if (vcstate->post_csc_data)
6956
+ drm_property_blob_get(vcstate->post_csc_data);
6957
+
63076958 __drm_atomic_helper_crtc_duplicate_state(crtc, &vcstate->base);
63086959 return &vcstate->base;
63096960 }
....@@ -6314,6 +6965,9 @@
63146965 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(state);
63156966
63166967 __drm_atomic_helper_crtc_destroy_state(&vcstate->base);
6968
+ drm_property_blob_put(vcstate->hdr_ext_data);
6969
+ drm_property_blob_put(vcstate->acm_lut_data);
6970
+ drm_property_blob_put(vcstate->post_csc_data);
63176971 kfree(vcstate);
63186972 }
63196973
....@@ -6436,9 +7090,52 @@
64367090 return 0;
64377091 }
64387092
7093
+ if (property == vp->hdr_ext_data_prop)
7094
+ return 0;
7095
+
7096
+ if (property == vp->acm_lut_data_prop)
7097
+ return 0;
7098
+
7099
+ if (property == vp->post_csc_data_prop)
7100
+ return 0;
7101
+
64397102 DRM_ERROR("failed to get vop2 crtc property: %s\n", property->name);
64407103
64417104 return -EINVAL;
7105
+}
7106
+
7107
+/* copied from drm_atomic.c */
7108
+static int
7109
+vop2_atomic_replace_property_blob_from_id(struct drm_device *dev,
7110
+ struct drm_property_blob **blob,
7111
+ uint64_t blob_id,
7112
+ ssize_t expected_size,
7113
+ ssize_t expected_elem_size,
7114
+ bool *replaced)
7115
+{
7116
+ struct drm_property_blob *new_blob = NULL;
7117
+
7118
+ if (blob_id != 0) {
7119
+ new_blob = drm_property_lookup_blob(dev, blob_id);
7120
+ if (new_blob == NULL)
7121
+ return -EINVAL;
7122
+
7123
+ if (expected_size > 0 &&
7124
+ new_blob->length != expected_size) {
7125
+ drm_property_blob_put(new_blob);
7126
+ return -EINVAL;
7127
+ }
7128
+ if (expected_elem_size > 0 &&
7129
+ new_blob->length % expected_elem_size != 0) {
7130
+ drm_property_blob_put(new_blob);
7131
+ return -EINVAL;
7132
+ }
7133
+ }
7134
+
7135
+ *replaced |= drm_property_replace_blob(blob, new_blob);
7136
+ drm_property_blob_put(new_blob);
7137
+
7138
+ return 0;
64427139 }
64437140
64447141 static int vop2_crtc_atomic_set_property(struct drm_crtc *crtc,
....@@ -6451,6 +7148,8 @@
64517148 struct drm_mode_config *mode_config = &drm_dev->mode_config;
64527149 struct vop2_video_port *vp = to_vop2_video_port(crtc);
64537150 struct vop2 *vop2 = vp->vop2;
7151
+ bool replaced = false;
7152
+ int ret;
64547153
64557154 if (property == mode_config->tv_left_margin_property) {
64567155 vcstate->left_margin = val;
....@@ -6481,6 +7180,33 @@
64817180 if (property == vop2->line_flag_prop) {
64827181 vcstate->line_flag = val;
64837182 return 0;
7183
+ }
7184
+
7185
+ if (property == vp->hdr_ext_data_prop) {
7186
+ ret = vop2_atomic_replace_property_blob_from_id(drm_dev,
7187
+ &vcstate->hdr_ext_data,
7188
+ val,
7189
+ -1, -1,
7190
+ &replaced);
7191
+ return ret;
7192
+ }
7193
+
7194
+ if (property == vp->acm_lut_data_prop) {
7195
+ ret = vop2_atomic_replace_property_blob_from_id(drm_dev,
7196
+ &vcstate->acm_lut_data,
7197
+ val,
7198
+ sizeof(struct post_acm), -1,
7199
+ &replaced);
7200
+ return ret;
7201
+ }
7202
+
7203
+ if (property == vp->post_csc_data_prop) {
7204
+ ret = vop2_atomic_replace_property_blob_from_id(drm_dev,
7205
+ &vcstate->post_csc_data,
7206
+ val,
7207
+ sizeof(struct post_csc), -1,
7208
+ &replaced);
7209
+ return ret;
64847210 }
64857211
64867212 DRM_ERROR("failed to set vop2 crtc property %s\n", property->name);
....@@ -6694,6 +7420,16 @@
66947420 ret = IRQ_HANDLED;
66957421 }
66967422
7423
+ if (vop2->version == VOP_VERSION_RK3528 && vp->id == 1) {
7424
+ if (active_irqs & POST_BUF_EMPTY_INTR)
7425
+ atomic_inc(&vp->post_buf_empty_flag);
7426
+
7427
+ if (active_irqs & FS_FIELD_INTR &&
7428
+ (atomic_read(&vp->post_buf_empty_flag) > 0 ||
7429
+ vp->need_reset_p2i_flag == true))
7430
+ queue_work(vop2->workqueue, &vop2->post_buf_empty_work);
7431
+ }
7432
+
66977433 if (active_irqs & FS_FIELD_INTR) {
66987434 vop2_wb_handler(vp);
66997435 if (likely(!vp->skip_vsync) || (vp->layer_sel_update == false)) {
....@@ -6784,6 +7520,51 @@
67847520 return 0;
67857521 }
67867522
7523
+static bool vop3_ignore_plane(struct vop2 *vop2, struct vop2_win *win)
7524
+{
7525
+ if (!is_vop3(vop2))
7526
+ return false;
7527
+
7528
+ if (vop2->esmart_lb_mode == VOP3_ESMART_8K_MODE &&
7529
+ win->phys_id != ROCKCHIP_VOP2_ESMART0)
7530
+ return true;
7531
+ else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_MODE &&
7532
+ (win->phys_id == ROCKCHIP_VOP2_ESMART1 || win->phys_id == ROCKCHIP_VOP2_ESMART3))
7533
+ return true;
7534
+ else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_2K_2K_MODE &&
7535
+ win->phys_id == ROCKCHIP_VOP2_ESMART1)
7536
+ return true;
7537
+ else
7538
+ return false;
7539
+}
7540
+
7541
+static u32 vop3_esmart_linebuffer_size(struct vop2 *vop2, struct vop2_win *win)
7542
+{
7543
+ if (!is_vop3(vop2) || vop2_cluster_window(win))
7544
+ return vop2->data->max_output.width;
7545
+
7546
+ if (vop2->esmart_lb_mode == VOP3_ESMART_2K_2K_2K_2K_MODE ||
7547
+ (vop2->esmart_lb_mode == VOP3_ESMART_4K_2K_2K_MODE && win->phys_id != ROCKCHIP_VOP2_ESMART0))
7548
+ return vop2->data->max_output.width / 2;
7549
+ else
7550
+ return vop2->data->max_output.width;
7551
+}
7552
+
7553
+static void vop3_init_esmart_scale_engine(struct vop2 *vop2)
7554
+{
7555
+ u8 scale_engine_num = 0;
7556
+ struct drm_plane *plane = NULL;
7557
+
7558
+ drm_for_each_plane(plane, vop2->drm_dev) {
7559
+ struct vop2_win *win = to_vop2_win(plane);
7560
+
7561
+ if (win->parent || vop2_cluster_window(win))
7562
+ continue;
7563
+
7564
+ win->scale_engine_num = scale_engine_num++;
7565
+ }
7566
+}
7567
+
67877568 static int vop2_plane_init(struct vop2 *vop2, struct vop2_win *win, unsigned long possible_crtcs)
67887569 {
67897570 struct rockchip_drm_private *private = vop2->drm_dev->dev_private;
....@@ -6807,6 +7588,10 @@
68077588 if (win->feature & WIN_FEATURE_CLUSTER_SUB)
68087589 return -EACCES;
68097590 }
7591
+
7592
+ /* ignore some plane register according vop3 esmart lb mode */
7593
+ if (vop3_ignore_plane(vop2, win))
7594
+ return -EACCES;
68107595
68117596 ret = drm_universal_plane_init(vop2->drm_dev, &win->base, possible_crtcs,
68127597 &vop2_plane_funcs, win->formats, win->nformats,
....@@ -6847,7 +7632,7 @@
68477632 "INPUT_WIDTH", 0, max_width);
68487633 win->input_height_prop = drm_property_create_range(vop2->drm_dev, DRM_MODE_PROP_IMMUTABLE,
68497634 "INPUT_HEIGHT", 0, max_height);
6850
- max_width = vop2->data->max_output.width;
7635
+ max_width = vop3_esmart_linebuffer_size(vop2, win);
68517636 max_height = vop2->data->max_output.height;
68527637 if (win->feature & WIN_FEATURE_CLUSTER_SUB)
68537638 max_width >>= 1;
....@@ -6883,15 +7668,27 @@
68837668 return 0;
68847669 }
68857670
6886
-static struct drm_plane *vop2_cursor_plane_init(struct vop2_video_port *vp,
6887
- unsigned long possible_crtcs)
7671
+static struct drm_plane *vop2_cursor_plane_init(struct vop2_video_port *vp)
68887672 {
68897673 struct vop2 *vop2 = vp->vop2;
68907674 struct drm_plane *cursor = NULL;
68917675 struct vop2_win *win;
7676
+ unsigned long possible_crtcs = 0;
68927677
68937678 win = vop2_find_win_by_phys_id(vop2, vp->cursor_win_id);
68947679 if (win) {
7680
+ if (vop2->disable_win_move) {
7681
+ const struct vop2_data *vop2_data = vop2->data;
7682
+ struct drm_crtc *crtc = vop2_find_crtc_by_plane_mask(vop2, win->phys_id);
7683
+
7684
+ if (crtc)
7685
+ possible_crtcs = drm_crtc_mask(crtc);
7686
+ else
7687
+ possible_crtcs = (1 << vop2_data->nr_vps) - 1;
7688
+ }
7689
+
7690
+ if (win->possible_crtcs)
7691
+ possible_crtcs = win->possible_crtcs;
68957692 win->type = DRM_PLANE_TYPE_CURSOR;
68967693 win->zpos = vop2->registered_num_wins - 1;
68977694 if (!vop2_plane_init(vop2, win, possible_crtcs))
....@@ -6925,6 +7722,7 @@
69257722 if (!lut_len)
69267723 continue;
69277724 vp->gamma_lut_len = vp_data->gamma_lut_len;
7725
+ vp->lut_dma_rid = vp_data->lut_dma_rid;
69287726 vp->lut = devm_kmalloc_array(dev, lut_len, sizeof(*vp->lut),
69297727 GFP_KERNEL);
69307728 if (!vp->lut)
....@@ -7009,6 +7807,53 @@
70097807 return 0;
70107808 }
70117809
7810
+static int vop2_crtc_create_hdr_property(struct vop2 *vop2, struct drm_crtc *crtc)
7811
+{
7812
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
7813
+ struct drm_property *prop;
7814
+
7815
+ prop = drm_property_create(vop2->drm_dev, DRM_MODE_PROP_BLOB, "HDR_EXT_DATA", 0);
7816
+ if (!prop) {
7817
+ DRM_DEV_ERROR(vop2->dev, "create hdr ext data prop for vp%d failed\n", vp->id);
7818
+ return -ENOMEM;
7819
+ }
7820
+ vp->hdr_ext_data_prop = prop;
7821
+ drm_object_attach_property(&crtc->base, vp->hdr_ext_data_prop, 0);
7822
+
7823
+ return 0;
7824
+}
7825
+
7826
+static int vop2_crtc_create_post_acm_property(struct vop2 *vop2, struct drm_crtc *crtc)
7827
+{
7828
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
7829
+ struct drm_property *prop;
7830
+
7831
+ prop = drm_property_create(vop2->drm_dev, DRM_MODE_PROP_BLOB, "ACM_LUT_DATA", 0);
7832
+ if (!prop) {
7833
+ DRM_DEV_ERROR(vop2->dev, "create acm lut data prop for vp%d failed\n", vp->id);
7834
+ return -ENOMEM;
7835
+ }
7836
+ vp->acm_lut_data_prop = prop;
7837
+ drm_object_attach_property(&crtc->base, vp->acm_lut_data_prop, 0);
7838
+
7839
+ return 0;
7840
+}
7841
+
7842
+static int vop2_crtc_create_post_csc_property(struct vop2 *vop2, struct drm_crtc *crtc)
7843
+{
7844
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
7845
+ struct drm_property *prop;
7846
+
7847
+ prop = drm_property_create(vop2->drm_dev, DRM_MODE_PROP_BLOB, "POST_CSC_DATA", 0);
7848
+ if (!prop) {
7849
+ DRM_DEV_ERROR(vop2->dev, "create post csc data prop for vp%d failed\n", vp->id);
7850
+ return -ENOMEM;
7851
+ }
7852
+ vp->post_csc_data_prop = prop;
7853
+ drm_object_attach_property(&crtc->base, vp->post_csc_data_prop, 0);
7854
+
7855
+ return 0;
7856
+}
70127857 #define RK3566_MIRROR_PLANE_MASK (BIT(ROCKCHIP_VOP2_CLUSTER1) | BIT(ROCKCHIP_VOP2_ESMART1) | \
70137858 BIT(ROCKCHIP_VOP2_SMART1))
70147859
....@@ -7021,7 +7866,7 @@
70217866 const struct vop2_data *vop2_data = vop2->data;
70227867 struct drm_device *drm_dev = vop2->drm_dev;
70237868 struct device *dev = vop2->dev;
7024
- struct drm_plane *plane;
7869
+ struct drm_plane *primary;
70257870 struct drm_plane *cursor = NULL;
70267871 struct drm_crtc *crtc;
70277872 struct device_node *port;
....@@ -7069,6 +7914,9 @@
70697914 vp->id = vp_data->id;
70707915 vp->regs = vp_data->regs;
70717916 vp->cursor_win_id = -1;
7917
+ primary = NULL;
7918
+ cursor = NULL;
7919
+
70727920 if (vop2->disable_win_move)
70737921 possible_crtcs = BIT(registered_num_crtcs);
70747922
....@@ -7116,6 +7964,7 @@
71167964 win->type = DRM_PLANE_TYPE_PRIMARY;
71177965 }
71187966 } else {
7967
+ j = 0;
71197968 while (j < vop2->registered_num_wins) {
71207969 be_used_for_primary_plane = false;
71217970 win = &vop2->win[j];
....@@ -7157,24 +8006,43 @@
71578006 DRM_DEV_ERROR(vop2->dev, "failed to init primary plane\n");
71588007 break;
71598008 }
7160
- plane = &win->base;
8009
+ primary = &win->base;
71618010 }
71628011
71638012 /* some times we want a cursor window for some vp */
8013
+ if (vp->cursor_win_id < 0) {
8014
+ bool be_used_for_cursor_plane = false;
8015
+
8016
+ j = 0;
8017
+ while (j < vop2->registered_num_wins) {
8018
+ win = &vop2->win[j++];
8019
+
8020
+ if (win->parent || (win->feature & WIN_FEATURE_CLUSTER_SUB))
8021
+ continue;
8022
+
8023
+ if (win->type != DRM_PLANE_TYPE_CURSOR)
8024
+ continue;
8025
+
8026
+ for (k = 0; k < vop2_data->nr_vps; k++) {
8027
+ if (vop2->vps[k].cursor_win_id == win->phys_id)
8028
+ be_used_for_cursor_plane = true;
8029
+ }
8030
+ if (be_used_for_cursor_plane)
8031
+ continue;
8032
+ vp->cursor_win_id = win->phys_id;
8033
+ }
8034
+ }
8035
+
71648036 if (vp->cursor_win_id >= 0) {
7165
- if (win->possible_crtcs)
7166
- possible_crtcs = win->possible_crtcs;
7167
- cursor = vop2_cursor_plane_init(vp, possible_crtcs);
8037
+ cursor = vop2_cursor_plane_init(vp);
71688038 if (!cursor)
71698039 DRM_WARN("failed to init cursor plane for vp%d\n", vp->id);
71708040 else
71718041 DRM_DEV_INFO(vop2->dev, "%s as cursor plane for vp%d\n",
71728042 cursor->name, vp->id);
7173
- } else {
7174
- cursor = NULL;
71758043 }
71768044
7177
- ret = drm_crtc_init_with_planes(drm_dev, crtc, plane, cursor, &vop2_crtc_funcs,
8045
+ ret = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor, &vop2_crtc_funcs,
71788046 "video_port%d", vp->id);
71798047 if (ret) {
71808048 DRM_DEV_ERROR(vop2->dev, "crtc init for video_port%d failed\n", i);
....@@ -7202,7 +8070,23 @@
72028070 drm_dev->mode_config.tv_top_margin_property, 100);
72038071 drm_object_attach_property(&crtc->base,
72048072 drm_dev->mode_config.tv_bottom_margin_property, 100);
7205
- vop2_crtc_create_plane_mask_property(vop2, crtc, plane_mask);
8073
+ if (plane_mask)
8074
+ vop2_crtc_create_plane_mask_property(vop2, crtc, plane_mask);
8075
+
8076
+ if (vp_data->feature & VOP_FEATURE_VIVID_HDR) {
8077
+ vop2_crtc_create_hdr_property(vop2, crtc);
8078
+ vp->hdr_lut_gem_obj = rockchip_gem_create_object(vop2->drm_dev,
8079
+ RK_HDRVIVID_TONE_SCA_AXI_TAB_LENGTH * 4, true, 0);
8080
+ if (IS_ERR(vp->hdr_lut_gem_obj)) {
8081
+ DRM_ERROR("create hdr lut obj failed\n");
8082
+ return -ENOMEM;
8083
+ }
8084
+ }
8085
+ if (vp_data->feature & VOP_FEATURE_POST_ACM)
8086
+ vop2_crtc_create_post_acm_property(vop2, crtc);
8087
+ if (vp_data->feature & VOP_FEATURE_POST_CSC)
8088
+ vop2_crtc_create_post_csc_property(vop2, crtc);
8089
+
72068090 registered_num_crtcs++;
72078091 }
72088092
....@@ -7260,12 +8144,18 @@
72608144 DRM_WARN("failed to init overlay plane %s, ret:%d\n", win->name, ret);
72618145 }
72628146
8147
+ if (is_vop3(vop2))
8148
+ vop3_init_esmart_scale_engine(vop2);
8149
+
72638150 return registered_num_crtcs;
72648151 }
72658152
72668153 static void vop2_destroy_crtc(struct drm_crtc *crtc)
72678154 {
72688155 struct vop2_video_port *vp = to_vop2_video_port(crtc);
8156
+
8157
+ if (vp->hdr_lut_gem_obj)
8158
+ rockchip_gem_free_object(&vp->hdr_lut_gem_obj->base);
72698159
72708160 of_node_put(crtc->port);
72718161
....@@ -7322,7 +8212,6 @@
73228212 win->axi_id = win_data->axi_id;
73238213 win->axi_yrgb_id = win_data->axi_yrgb_id;
73248214 win->axi_uv_id = win_data->axi_uv_id;
7325
- win->scale_engine_num = win_data->scale_engine_num;
73268215 win->possible_crtcs = win_data->possible_crtcs;
73278216
73288217 num_wins++;
....@@ -7351,6 +8240,7 @@
73518240 area->vsd_filter_mode = win_data->vsd_filter_mode;
73528241 area->hsd_pre_filter_mode = win_data->hsd_pre_filter_mode;
73538242 area->vsd_pre_filter_mode = win_data->vsd_pre_filter_mode;
8243
+ area->possible_crtcs = win->possible_crtcs;
73548244
73558245 area->vop2 = vop2;
73568246 area->win_id = i;
....@@ -7414,6 +8304,43 @@
74148304 return 0;
74158305 }
74168306
8307
+static void post_buf_empty_work_event(struct work_struct *work)
8308
+{
8309
+ struct vop2 *vop2 = container_of(work, struct vop2, post_buf_empty_work);
8310
+ struct rockchip_drm_private *private = vop2->drm_dev->dev_private;
8311
+ struct vop2_video_port *vp = &vop2->vps[1];
8312
+
8313
+ /*
8314
+ * For RK3528, VP1 only supports NTSC and PAL mode(both interlace). If
8315
+ * POST_BUF_EMPTY_INTR comes, it is needed to reset the p2i_en bit, in
8316
+ * order to update the line parity flag, which ensures the correct order
8317
+ * of odd and even lines.
8318
+ */
8319
+ if (vop2->version == VOP_VERSION_RK3528) {
8320
+ if (atomic_read(&vp->post_buf_empty_flag) > 0) {
8321
+ atomic_set(&vp->post_buf_empty_flag, 0);
8322
+
8323
+ mutex_lock(&private->ovl_lock);
8324
+ vop2_wait_for_fs_by_done_bit_status(vp);
8325
+ VOP_MODULE_SET(vop2, vp, p2i_en, 0);
8326
+ vop2_cfg_done(&vp->crtc);
8327
+ vop2_wait_for_fs_by_done_bit_status(vp);
8328
+ mutex_unlock(&private->ovl_lock);
8329
+
8330
+ vp->need_reset_p2i_flag = true;
8331
+ } else if (vp->need_reset_p2i_flag == true) {
8332
+ mutex_lock(&private->ovl_lock);
8333
+ vop2_wait_for_fs_by_done_bit_status(vp);
8334
+ VOP_MODULE_SET(vop2, vp, p2i_en, 1);
8335
+ vop2_cfg_done(&vp->crtc);
8336
+ vop2_wait_for_fs_by_done_bit_status(vp);
8337
+ mutex_unlock(&private->ovl_lock);
8338
+
8339
+ vp->need_reset_p2i_flag = false;
8340
+ }
8341
+ }
8342
+}
8343
+
74178344 static int vop2_bind(struct device *dev, struct device *master, void *data)
74188345 {
74198346 struct platform_device *pdev = to_platform_device(dev);
....@@ -7454,6 +8381,23 @@
74548381 vop2->disable_afbc_win = of_property_read_bool(dev->of_node, "disable-afbc-win");
74558382 vop2->disable_win_move = of_property_read_bool(dev->of_node, "disable-win-move");
74568383 vop2->skip_ref_fb = of_property_read_bool(dev->of_node, "skip-ref-fb");
8384
+
8385
+ /*
8386
+ * esmart lb mode default config at vop2_reg.c vop2_data.esmart_lb_mode,
8387
+ * you can rewrite at dts vop node:
8388
+ *
8389
+ * VOP3_ESMART_8K_MODE = 0,
8390
+ * VOP3_ESMART_4K_4K_MODE = 1,
8391
+ * VOP3_ESMART_4K_2K_2K_MODE = 2,
8392
+ * VOP3_ESMART_2K_2K_2K_2K_MODE = 3,
8393
+ *
8394
+ * &vop {
8395
+ * esmart_lb_mode = /bits/ 8 <2>;
8396
+ * };
8397
+ */
8398
+ ret = of_property_read_u8(dev->of_node, "esmart_lb_mode", &vop2->esmart_lb_mode);
8399
+ if (ret < 0)
8400
+ vop2->esmart_lb_mode = vop2->data->esmart_lb_mode;
74578401
74588402 ret = vop2_win_init(vop2);
74598403 if (ret)
....@@ -7538,6 +8482,12 @@
75388482 spin_lock_init(&vop2->irq_lock);
75398483 mutex_init(&vop2->vop2_lock);
75408484
8485
+ if (vop2->version == VOP_VERSION_RK3528) {
8486
+ atomic_set(&vop2->vps[1].post_buf_empty_flag, 0);
8487
+ vop2->workqueue = create_workqueue("post_buf_empty_wq");
8488
+ INIT_WORK(&vop2->post_buf_empty_work, post_buf_empty_work_event);
8489
+ }
8490
+
75418491 ret = devm_request_irq(dev, vop2->irq, vop2_isr, IRQF_SHARED, dev_name(dev), vop2);
75428492 if (ret)
75438493 return ret;