forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-09 95099d4622f8cb224d94e314c7a8e0df60b13f87
kernel/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
....@@ -4,12 +4,18 @@
44 * Author: Andy Yan <andy.yan@rock-chips.com>
55 */
66 #include <drm/drm.h>
7
-#include <drm/drmP.h>
87 #include <drm/drm_atomic.h>
8
+#include <drm/drm_atomic_uapi.h>
99 #include <drm/drm_crtc.h>
1010 #include <drm/drm_crtc_helper.h>
11
+#include <drm/drm_debugfs.h>
1112 #include <drm/drm_flip_work.h>
13
+#include <drm/drm_fourcc.h>
14
+#include <drm/drm_gem_framebuffer_helper.h>
1215 #include <drm/drm_plane_helper.h>
16
+#include <drm/drm_probe_helper.h>
17
+#include <drm/drm_self_refresh_helper.h>
18
+
1319 #include <drm/drm_writeback.h>
1420 #ifdef CONFIG_DRM_ANALOGIX_DP
1521 #include <drm/bridge/analogix_dp.h>
....@@ -23,6 +29,8 @@
2329 #include <linux/module.h>
2430 #include <linux/platform_device.h>
2531 #include <linux/clk.h>
32
+#include <linux/clk-provider.h>
33
+#include <linux/clk/clk-conf.h>
2634 #include <linux/iopoll.h>
2735 #include <linux/of.h>
2836 #include <linux/of_device.h>
....@@ -30,6 +38,7 @@
3038 #include <linux/pm_runtime.h>
3139 #include <linux/component.h>
3240 #include <linux/regmap.h>
41
+#include <linux/reset.h>
3342 #include <linux/mfd/syscon.h>
3443 #include <linux/delay.h>
3544 #include <linux/swab.h>
....@@ -41,12 +50,12 @@
4150 #include <soc/rockchip/rockchip-system-status.h>
4251 #include <uapi/linux/videodev2.h>
4352
53
+#include "../drm_crtc_internal.h"
4454 #include "../drm_internal.h"
4555
4656 #include "rockchip_drm_drv.h"
4757 #include "rockchip_drm_gem.h"
4858 #include "rockchip_drm_fb.h"
49
-#include "rockchip_drm_psr.h"
5059 #include "rockchip_drm_vop.h"
5160 #include "rockchip_vop_reg.h"
5261 #include "rockchip_post_csc.h"
....@@ -117,27 +126,32 @@
117126 #define VOP_WIN_GET(vop2, win, name) \
118127 vop2_read_reg(vop2, win->offset, &VOP_WIN_NAME(win, name))
119128
129
+#define VOP_WIN_GET_REG_BAK(vop2, win, name) \
130
+ vop2_read_reg_bak(vop2, win->offset, &VOP_WIN_NAME(win, name))
131
+
120132 #define VOP_WIN_NAME(win, name) \
121133 (vop2_get_win_regs(win, &win->regs->name)->name)
122134
123135 #define VOP_WIN_TO_INDEX(vop2_win) \
124136 ((vop2_win) - (vop2_win)->vop2->win)
125137
126
-#define VOP_GRF_SET(vop2, reg, v) \
138
+#define VOP_GRF_SET(vop2, grf, reg, v) \
127139 do { \
128
- if (vop2->data->grf_ctrl) { \
129
- vop2_grf_writel(vop2, vop2->data->grf_ctrl->reg, v); \
140
+ if (vop2->data->grf) { \
141
+ vop2_grf_writel(vop2->grf, vop2->data->grf->reg, v); \
130142 } \
131143 } while (0)
132144
133
-#define to_vop2_video_port(c) container_of(c, struct vop2_video_port, crtc)
134145 #define to_vop2_win(x) container_of(x, struct vop2_win, base)
135146 #define to_vop2_plane_state(x) container_of(x, struct vop2_plane_state, base)
136147 #define to_wb_state(x) container_of(x, struct vop2_wb_connector_state, base)
137
-
138
-#ifndef drm_is_afbc
139
-#define drm_is_afbc(modifier) (((modifier) >> 56) == DRM_FORMAT_MOD_VENDOR_ARM)
140
-#endif
148
+#define output_if_is_hdmi(x) (x & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1))
149
+#define output_if_is_dp(x) (x & (VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1))
150
+#define output_if_is_edp(x) (x & (VOP_OUTPUT_IF_eDP0 | VOP_OUTPUT_IF_eDP1))
151
+#define output_if_is_mipi(x) (x & (VOP_OUTPUT_IF_MIPI0 | VOP_OUTPUT_IF_MIPI1))
152
+#define output_if_is_lvds(x) (x & (VOP_OUTPUT_IF_LVDS0 | VOP_OUTPUT_IF_LVDS1))
153
+#define output_if_is_dpi(x) (x & (VOP_OUTPUT_IF_BT656 | VOP_OUTPUT_IF_BT1120 | \
154
+ VOP_OUTPUT_IF_RGB))
141155
142156 /*
143157 * max two jobs a time, one is running(writing back),
....@@ -146,7 +160,11 @@
146160 #define VOP2_WB_JOB_MAX 2
147161 #define VOP2_SYS_AXI_BUS_NUM 2
148162
149
-#define VOP2_CLUSTER_YUV444_10 0x12
163
+#define VOP2_MAX_VP_OUTPUT_WIDTH 4096
164
+/* KHZ */
165
+#define VOP2_MAX_DCLK_RATE 600000
166
+/* KHZ */
167
+#define VOP2_COMMON_ACLK_RATE 500000
150168
151169 enum vop2_data_format {
152170 VOP2_FMT_ARGB8888 = 0,
....@@ -238,6 +256,36 @@
238256 ROCKCHIP_VOP2_PHY_ID_INVALID = -1,
239257 };
240258
259
+struct vop2_power_domain {
260
+ struct vop2_power_domain *parent;
261
+ struct vop2 *vop2;
262
+ /*
263
+ * @lock: protect power up/down procedure.
264
+ * power on take effect immediately,
265
+ * power down take effect by vsync.
266
+ * we must check power_domain_status register
267
+ * to make sure the power domain is down before
268
+ * send a power on request.
269
+ *
270
+ */
271
+ spinlock_t lock;
272
+ unsigned int ref_count;
273
+ bool on;
274
+ /* @vp_mask: Bit mask of video port of the power domain's
275
+ * module attached to.
276
+ * For example: PD_CLUSTER0 belongs to module Cluster0, it's
277
+ * bitmask is the VP which Cluster0 attached to. PD_ESMART is
278
+ * shared between Esmart1/2/3, it's bitmask will be all the VP
279
+ * which Esmart1/2/3 attached to.
280
+ * This is used to check if we can power off a PD by vsync.
281
+ */
282
+ uint8_t vp_mask;
283
+
284
+ const struct vop2_power_domain_data *data;
285
+ struct list_head list;
286
+ struct delayed_work power_off_work;
287
+};
288
+
241289 struct vop2_zpos {
242290 struct drm_plane *plane;
243291 int win_phys_id;
....@@ -321,7 +369,6 @@
321369 int global_alpha;
322370 int blend_mode;
323371 uint64_t color_key;
324
- void *yrgb_kvaddr;
325372 unsigned long offset;
326373 int pdaf_data_type;
327374 bool async_commit;
....@@ -343,11 +390,37 @@
343390 bool two_win_mode;
344391
345392 /**
393
+ * ---------------------------
394
+ * | | |
395
+ * | Left | Right |
396
+ * | | |
397
+ * | Cluster0 | Cluster1 |
398
+ * ---------------------------
399
+ */
400
+
401
+ /*
402
+ * @splice_mode_right: As right part of the screen in splice mode.
403
+ */
404
+ bool splice_mode_right;
405
+
406
+ /**
407
+ * @splice_win: splice win which used to splice for a plane
408
+ * hdisplay > 4096
409
+ */
410
+ struct vop2_win *splice_win;
411
+ struct vop2_win *left_win;
412
+
413
+ uint8_t splice_win_id;
414
+
415
+ struct vop2_power_domain *pd;
416
+
417
+ /**
346418 * @phys_id: physical id for cluster0/1, esmart0/1, smart0/1
347419 * Will be used as a identification for some register
348420 * configuration such as OVL_LAYER_SEL/OVL_PORT_SEL.
349421 */
350422 uint8_t phys_id;
423
+
351424 /**
352425 * @win_id: graphic window id, a cluster maybe split into two
353426 * graphics windows.
....@@ -415,6 +488,7 @@
415488 };
416489
417490 struct vop2_cluster {
491
+ bool splice_mode;
418492 struct vop2_win *main;
419493 struct vop2_win *sub;
420494 };
....@@ -456,6 +530,17 @@
456530
457531 };
458532
533
+struct vop2_dsc {
534
+ uint8_t id;
535
+ uint8_t max_slice_num;
536
+ uint8_t max_linebuf_depth; /* used to generate the bitstream */
537
+ uint8_t min_bits_per_pixel; /* bit num after encoder compress */
538
+ bool enabled;
539
+ char attach_vp_id;
540
+ const struct vop2_dsc_regs *regs;
541
+ struct vop2_power_domain *pd;
542
+};
543
+
459544 enum vop2_wb_format {
460545 VOP2_WB_ARGB8888,
461546 VOP2_WB_BGR888,
....@@ -476,9 +561,12 @@
476561 };
477562
478563 struct vop2_video_port {
479
- struct drm_crtc crtc;
564
+ struct rockchip_crtc rockchip_crtc;
565
+ struct rockchip_mcu_timing mcu_timing;
480566 struct vop2 *vop2;
567
+ struct reset_control *dclk_rst;
481568 struct clk *dclk;
569
+ struct clk *dclk_parent;
482570 uint8_t id;
483571 bool layer_sel_update;
484572 bool xmirror_en;
....@@ -531,6 +619,26 @@
531619 int hdr_en;
532620
533621 /**
622
+ * -----------------
623
+ * | | |
624
+ * | Left | Right |
625
+ * | | |
626
+ * | VP0 | VP1 |
627
+ * -----------------
628
+ * @splice_mode_right: As right part of the screen in splice mode.
629
+ */
630
+ bool splice_mode_right;
631
+
632
+ /**
633
+ * @hdr10_at_splice_mode: enable hdr10 at splice mode on rk3588.
634
+ */
635
+ bool hdr10_at_splice_mode;
636
+ /**
637
+ * @left_vp: VP as left part of the screen in splice mode.
638
+ */
639
+ struct vop2_video_port *left_vp;
640
+
641
+ /**
534642 * @win_mask: Bitmask of wins attached to the video port;
535643 */
536644 uint32_t win_mask;
....@@ -540,6 +648,12 @@
540648 uint8_t nr_layers;
541649
542650 int cursor_win_id;
651
+ /**
652
+ * @output_if: output connector attached to the video port,
653
+ * this flag is maintained in vop driver, updated in crtc_atomic_enable,
654
+ * cleared in crtc_atomic_disable;
655
+ */
656
+ u32 output_if;
543657
544658 /**
545659 * @active_tv_state: TV connector related states
....@@ -606,6 +720,25 @@
606720 * @plane_mask_prop: plane mask interaction with userspace
607721 */
608722 struct drm_property *plane_mask_prop;
723
+ /**
724
+ * @feature_prop: crtc feature interaction with userspace
725
+ */
726
+ struct drm_property *feature_prop;
727
+
728
+ /**
729
+ * @variable_refresh_rate_prop: crtc variable refresh rate interaction with userspace
730
+ */
731
+ struct drm_property *variable_refresh_rate_prop;
732
+
733
+ /**
734
+ * @max_refresh_rate_prop: crtc max refresh rate interaction with userspace
735
+ */
736
+ struct drm_property *max_refresh_rate_prop;
737
+
738
+ /**
739
+ * @min_refresh_rate_prop: crtc min refresh rate interaction with userspace
740
+ */
741
+ struct drm_property *min_refresh_rate_prop;
609742
610743 /**
611744 * @hdr_ext_data_prop: hdr extend data interaction with userspace
....@@ -622,6 +755,14 @@
622755 * @post_csc_data_prop: post csc data interaction with userspace
623756 */
624757 struct drm_property *post_csc_data_prop;
758
+ /**
759
+ * @output_width_prop: vp max output width prop
760
+ */
761
+ struct drm_property *output_width_prop;
762
+ /**
763
+ * @output_dclk_prop: vp max output dclk prop
764
+ */
765
+ struct drm_property *output_dclk_prop;
625766
626767 /**
627768 * @primary_plane_phy_id: vp primary plane phy id, the primary plane
....@@ -629,23 +770,28 @@
629770 */
630771 enum vop2_layer_phy_id primary_plane_phy_id;
631772
632
- struct post_acm acm_info;
633
- struct post_csc csc_info;
773
+ /**
774
+ * @refresh_rate_change: indicate whether refresh rate change
775
+ */
776
+ bool refresh_rate_change;
777
+};
778
+
779
+struct vop2_extend_pll {
780
+ struct list_head list;
781
+ struct clk *clk;
782
+ char clk_name[32];
783
+ u32 vp_mask;
634784 };
635785
636786 struct vop2 {
637787 u32 version;
638788 struct device *dev;
639789 struct drm_device *drm_dev;
790
+ struct vop2_dsc dscs[ROCKCHIP_MAX_CRTC];
640791 struct vop2_video_port vps[ROCKCHIP_MAX_CRTC];
641792 struct vop2_wb wb;
642793 struct dentry *debugfs;
643794 struct drm_info_list *debugfs_files;
644
- struct drm_property *soc_id_prop;
645
- struct drm_property *vp_id_prop;
646
- struct drm_property *aclk_prop;
647
- struct drm_property *bg_prop;
648
- struct drm_property *line_flag_prop;
649795 struct drm_prop_enum_list *plane_name_list;
650796 bool is_iommu_enabled;
651797 bool is_iommu_needed;
....@@ -681,6 +827,9 @@
681827
682828 bool loader_protect;
683829
830
+ bool aclk_rate_reset;
831
+ unsigned long aclk_rate;
832
+
684833 const struct vop2_data *data;
685834 /* Number of win that registered as plane,
686835 * maybe less than the total number of hardware
....@@ -699,6 +848,10 @@
699848 struct resource *res;
700849 void __iomem *regs;
701850 struct regmap *grf;
851
+ struct regmap *sys_grf;
852
+ struct regmap *vo0_grf;
853
+ struct regmap *vo1_grf;
854
+ struct regmap *sys_pmu;
702855
703856 /* physical map length of vop2 register */
704857 uint32_t len;
....@@ -721,6 +874,15 @@
721874 unsigned int enable_count;
722875 struct clk *hclk;
723876 struct clk *aclk;
877
+ struct clk *pclk;
878
+ struct reset_control *ahb_rst;
879
+ struct reset_control *axi_rst;
880
+
881
+ /* list_head of extend clk */
882
+ struct list_head extend_clk_list_head;
883
+ /* list_head of internal clk */
884
+ struct list_head clk_list_head;
885
+ struct list_head pd_list_head;
724886 struct work_struct post_buf_empty_work;
725887 struct workqueue_struct *workqueue;
726888
....@@ -728,6 +890,18 @@
728890 /* must put at the end of the struct */
729891 struct vop2_win win[];
730892 };
893
+
894
+struct vop2_clk {
895
+ struct vop2 *vop2;
896
+ struct list_head list;
897
+ unsigned long rate;
898
+ struct clk_hw hw;
899
+ struct clk_divider div;
900
+ int div_val;
901
+ u8 parent_index;
902
+};
903
+
904
+#define to_vop2_clk(_hw) container_of(_hw, struct vop2_clk, hw)
731905
732906 /*
733907 * bus-format types.
....@@ -743,23 +917,32 @@
743917 { MEDIA_BUS_FMT_RGB666_1X18, "RGB666_1X18" },
744918 { MEDIA_BUS_FMT_RGB666_1X24_CPADHI, "RGB666_1X24_CPADHI" },
745919 { MEDIA_BUS_FMT_RGB666_1X7X3_SPWG, "RGB666_1X7X3_SPWG" },
746
- { MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA, "RGB666_1X7X3_JEIDA" },
747920 { MEDIA_BUS_FMT_YUV8_1X24, "YUV8_1X24" },
748921 { MEDIA_BUS_FMT_UYYVYY8_0_5X24, "UYYVYY8_0_5X24" },
749922 { MEDIA_BUS_FMT_YUV10_1X30, "YUV10_1X30" },
750923 { MEDIA_BUS_FMT_UYYVYY10_0_5X30, "UYYVYY10_0_5X30" },
751
- { MEDIA_BUS_FMT_SRGB888_3X8, "SRGB888_3X8" },
752
- { MEDIA_BUS_FMT_SRGB888_DUMMY_4X8, "SRGB888_DUMMY_4X8" },
924
+ { MEDIA_BUS_FMT_RGB888_3X8, "RGB888_3X8" },
925
+ { MEDIA_BUS_FMT_RGB888_DUMMY_4X8, "RGB888_DUMMY_4X8" },
753926 { MEDIA_BUS_FMT_RGB888_1X24, "RGB888_1X24" },
754927 { MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, "RGB888_1X7X4_SPWG" },
755928 { MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, "RGB888_1X7X4_JEIDA" },
756929 { MEDIA_BUS_FMT_UYVY8_2X8, "UYVY8_2X8" },
757930 { MEDIA_BUS_FMT_YUYV8_1X16, "YUYV8_1X16" },
758931 { MEDIA_BUS_FMT_UYVY8_1X16, "UYVY8_1X16" },
759
- { MEDIA_BUS_FMT_RGB101010_1X30, "RGB101010_1x30" },
932
+ { MEDIA_BUS_FMT_RGB101010_1X30, "RGB101010_1X30" },
933
+ { MEDIA_BUS_FMT_YUYV10_1X20, "YUYV10_1X20" },
760934 };
761935
762936 static DRM_ENUM_NAME_FN(drm_get_bus_format_name, drm_bus_format_enum_list)
937
+
938
+static inline struct vop2_video_port *to_vop2_video_port(struct drm_crtc *crtc)
939
+{
940
+ struct rockchip_crtc *rockchip_crtc;
941
+
942
+ rockchip_crtc = container_of(crtc, struct rockchip_crtc, crtc);
943
+
944
+ return container_of(rockchip_crtc, struct vop2_video_port, rockchip_crtc);
945
+}
763946
764947 static void vop2_lock(struct vop2 *vop2)
765948 {
....@@ -773,17 +956,26 @@
773956 mutex_unlock(&vop2->vop2_lock);
774957 }
775958
776
-static inline void vop2_grf_writel(struct vop2 *vop2, struct vop_reg reg, u32 v)
959
+static inline void vop2_grf_writel(struct regmap *regmap, struct vop_reg reg, u32 v)
777960 {
778961 u32 val = 0;
779962
780
- if (IS_ERR_OR_NULL(vop2->grf))
963
+ if (IS_ERR_OR_NULL(regmap))
781964 return;
782965
783966 if (reg.mask) {
784967 val = (v << reg.shift) | (reg.mask << (reg.shift + 16));
785
- regmap_write(vop2->grf, reg.offset, val);
968
+ regmap_write(regmap, reg.offset, val);
786969 }
970
+}
971
+
972
+static inline uint32_t vop2_grf_readl(struct regmap *regmap, const struct vop_reg *reg)
973
+{
974
+ uint32_t v;
975
+
976
+ regmap_read(regmap, reg->offset, &v);
977
+
978
+ return v;
787979 }
788980
789981 static inline void vop2_writel(struct vop2 *vop2, uint32_t offset, uint32_t v)
....@@ -801,6 +993,26 @@
801993 const struct vop_reg *reg)
802994 {
803995 return (vop2_readl(vop2, base + reg->offset) >> reg->shift) & reg->mask;
996
+}
997
+
998
+static inline uint32_t vop2_read_reg_bak(struct vop2 *vop2, uint32_t base,
999
+ const struct vop_reg *reg)
1000
+{
1001
+ return (vop2->regsbak[(base + reg->offset) >> 2] >> reg->shift) & reg->mask;
1002
+}
1003
+
1004
+static inline uint32_t vop2_read_grf_reg(struct regmap *regmap, const struct vop_reg *reg)
1005
+{
1006
+ return (vop2_grf_readl(regmap, reg) >> reg->shift) & reg->mask;
1007
+}
1008
+
1009
+static inline void vop2_write_reg_uncached(struct vop2 *vop2, const struct vop_reg *reg, uint32_t v)
1010
+{
1011
+ uint32_t offset = reg->offset;
1012
+ uint32_t cached_val = vop2->regsbak[offset >> 2];
1013
+
1014
+ v = (cached_val & ~(reg->mask << reg->shift)) | ((v & reg->mask) << reg->shift);
1015
+ writel(v, vop2->regs + offset);
8041016 }
8051017
8061018 static inline void vop2_mask_write(struct vop2 *vop2, uint32_t offset,
....@@ -881,7 +1093,7 @@
8811093 }
8821094 }
8831095
884
-void vop2_standby(struct drm_crtc *crtc, bool standby)
1096
+static void vop2_crtc_standby(struct drm_crtc *crtc, bool standby)
8851097 {
8861098 struct vop2_video_port *vp = to_vop2_video_port(crtc);
8871099 struct vop2 *vop2 = vp->vop2;
....@@ -893,7 +1105,6 @@
8931105 VOP_MODULE_SET(vop2, vp, standby, 0);
8941106 }
8951107 }
896
-EXPORT_SYMBOL(vop2_standby);
8971108
8981109 static inline const struct vop2_win_regs *vop2_get_win_regs(struct vop2_win *win,
8991110 const struct vop_reg *reg)
....@@ -939,6 +1150,32 @@
9391150 return NULL;
9401151 }
9411152
1153
+static struct vop2_power_domain *vop2_find_pd_by_id(struct vop2 *vop2, uint8_t id)
1154
+{
1155
+ struct vop2_power_domain *pd, *n;
1156
+
1157
+ list_for_each_entry_safe(pd, n, &vop2->pd_list_head, list) {
1158
+ if (pd->data->id == id)
1159
+ return pd;
1160
+ }
1161
+
1162
+ return NULL;
1163
+}
1164
+
1165
+static const struct vop2_connector_if_data *vop2_find_connector_if_data(struct vop2 *vop2, int id)
1166
+{
1167
+ const struct vop2_connector_if_data *if_data;
1168
+ int i;
1169
+
1170
+ for (i = 0; i < vop2->data->nr_conns; i++) {
1171
+ if_data = &vop2->data->conn[i];
1172
+ if (if_data->id == id)
1173
+ return if_data;
1174
+ }
1175
+
1176
+ return NULL;
1177
+}
1178
+
9421179 static struct drm_crtc *vop2_find_crtc_by_plane_mask(struct vop2 *vop2, uint8_t phys_id)
9431180 {
9441181 struct vop2_video_port *vp;
....@@ -947,10 +1184,28 @@
9471184 for (i = 0; i < vop2->data->nr_vps; i++) {
9481185 vp = &vop2->vps[i];
9491186 if (vp->plane_mask & BIT(phys_id))
950
- return &vp->crtc;
1187
+ return &vp->rockchip_crtc.crtc;
9511188 }
9521189
9531190 return NULL;
1191
+}
1192
+
1193
+static int vop2_clk_reset(struct reset_control *rstc)
1194
+{
1195
+ int ret;
1196
+
1197
+ if (!rstc)
1198
+ return 0;
1199
+
1200
+ ret = reset_control_assert(rstc);
1201
+ if (ret < 0)
1202
+ DRM_WARN("failed to assert reset\n");
1203
+ udelay(10);
1204
+ ret = reset_control_deassert(rstc);
1205
+ if (ret < 0)
1206
+ DRM_WARN("failed to deassert reset\n");
1207
+
1208
+ return ret;
9541209 }
9551210
9561211 static void vop2_load_hdr2sdr_table(struct vop2_video_port *vp)
....@@ -1167,7 +1422,7 @@
11671422 done_bits &= ~BIT(vp->id);
11681423 vp_id = ffs(done_bits) - 1;
11691424 done_vp = &vop2->vps[vp_id];
1170
- adjusted_mode = &done_vp->crtc.state->adjusted_mode;
1425
+ adjusted_mode = &done_vp->rockchip_crtc.crtc.state->adjusted_mode;
11711426 vcnt = vop2_read_vcnt(done_vp);
11721427 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
11731428 vcnt >>= 1;
....@@ -1188,7 +1443,7 @@
11881443
11891444 first_vp_id = ffs(done_bits) - 1;
11901445 first_done_vp = &vop2->vps[first_vp_id];
1191
- first_mode = &first_done_vp->crtc.state->adjusted_mode;
1446
+ first_mode = &first_done_vp->rockchip_crtc.crtc.state->adjusted_mode;
11921447 /* set last 1/8 frame time as safe section */
11931448 vrefresh = drm_mode_vrefresh(first_mode);
11941449 if (!vrefresh) {
....@@ -1200,7 +1455,7 @@
12001455 done_bits &= ~BIT(first_vp_id);
12011456 second_vp_id = ffs(done_bits) - 1;
12021457 second_done_vp = &vop2->vps[second_vp_id];
1203
- second_mode = &second_done_vp->crtc.state->adjusted_mode;
1458
+ second_mode = &second_done_vp->rockchip_crtc.crtc.state->adjusted_mode;
12041459 /* set last 1/8 frame time as safe section */
12051460 vrefresh = drm_mode_vrefresh(second_mode);
12061461 if (!vrefresh) {
....@@ -1245,6 +1500,26 @@
12451500 return done_bits;
12461501 }
12471502
1503
+static inline void rk3588_vop2_dsc_cfg_done(struct drm_crtc *crtc)
1504
+{
1505
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
1506
+ struct vop2 *vop2 = vp->vop2;
1507
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
1508
+ struct vop2_dsc *dsc = &vop2->dscs[vcstate->dsc_id];
1509
+
1510
+ if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
1511
+ dsc = &vop2->dscs[0];
1512
+ if (vcstate->dsc_enable)
1513
+ VOP_MODULE_SET(vop2, dsc, dsc_cfg_done, 1);
1514
+ dsc = &vop2->dscs[1];
1515
+ if (vcstate->dsc_enable)
1516
+ VOP_MODULE_SET(vop2, dsc, dsc_cfg_done, 1);
1517
+ } else {
1518
+ if (vcstate->dsc_enable)
1519
+ VOP_MODULE_SET(vop2, dsc, dsc_cfg_done, 1);
1520
+ }
1521
+}
1522
+
12481523 static inline void rk3568_vop2_cfg_done(struct drm_crtc *crtc)
12491524 {
12501525 struct vop2_video_port *vp = to_vop2_video_port(crtc);
....@@ -1279,6 +1554,9 @@
12791554 * This is rather low probability for miss some done bit.
12801555 */
12811556 val |= vop2_readl(vop2, RK3568_REG_CFG_DONE) & 0x7;
1557
+
1558
+ rockchip_drm_dbg(vop2->dev, VOP_DEBUG_CFG_DONE, "cfg_done: 0x%x\n", val);
1559
+
12821560 vop2_writel(vop2, 0, val);
12831561
12841562 /**
....@@ -1295,10 +1573,16 @@
12951573 static inline void rk3588_vop2_cfg_done(struct drm_crtc *crtc)
12961574 {
12971575 struct vop2_video_port *vp = to_vop2_video_port(crtc);
1576
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
1577
+ const struct vop2_video_port_data *vp_data = &vp->vop2->data->vp[vp->id];
12981578 struct vop2 *vop2 = vp->vop2;
12991579 uint32_t val;
13001580
13011581 val = RK3568_VOP2_GLB_CFG_DONE_EN | BIT(vp->id) | (BIT(vp->id) << 16);
1582
+ if (vcstate->splice_mode)
1583
+ val |= BIT(vp_data->splice_vp_id) | (BIT(vp_data->splice_vp_id) << 16);
1584
+
1585
+ rockchip_drm_dbg(vop2->dev, VOP_DEBUG_CFG_DONE, "cfg_done: 0x%x\n", val);
13021586
13031587 vop2_writel(vop2, 0, val);
13041588 }
....@@ -1320,6 +1604,7 @@
13201604 } else {
13211605 vop2_writel(vop2, 0, val);
13221606 }
1607
+
13231608 }
13241609
13251610 static inline void vop2_cfg_done(struct drm_crtc *crtc)
....@@ -1331,6 +1616,178 @@
13311616 return rk3568_vop2_cfg_done(crtc);
13321617 else
13331618 return rk3588_vop2_cfg_done(crtc);
1619
+}
1620
+
1621
+/*
1622
+ * A PD can power off by vsync when it's module attached to
1623
+ * a activated VP.
1624
+ */
1625
+static uint32_t vop2_power_domain_can_off_by_vsync(struct vop2_power_domain *pd)
1626
+{
1627
+ struct vop2 *vop2 = pd->vop2;
1628
+
1629
+ if (vop2->active_vp_mask & pd->vp_mask)
1630
+ return true;
1631
+ else
1632
+ return false;
1633
+}
1634
+
1635
+/*
1636
+ * Read VOP internal power domain on/off status.
1637
+ * We should query BISR_STS register in PMU for
1638
+ * power up/down status when memory repair is enabled.
1639
+ * Return value: 1 for power on, 0 for power off;
1640
+ */
1641
+static uint32_t vop2_power_domain_status(struct vop2_power_domain *pd)
1642
+{
1643
+ struct vop2 *vop2 = pd->vop2;
1644
+
1645
+ if (vop2_read_grf_reg(vop2->sys_pmu, &pd->data->regs->bisr_en_status))
1646
+ return vop2_read_grf_reg(vop2->sys_pmu, &pd->data->regs->pmu_status);
1647
+ else
1648
+ return vop2_read_reg(vop2, 0, &pd->data->regs->status) ? 0 : 1;
1649
+}
1650
+
1651
+static void vop2_wait_power_domain_off(struct vop2_power_domain *pd)
1652
+{
1653
+ struct vop2 *vop2 = pd->vop2;
1654
+ int val;
1655
+ int ret;
1656
+
1657
+ ret = readx_poll_timeout_atomic(vop2_power_domain_status, pd, val, !val, 0, 50 * 1000);
1658
+
1659
+ if (ret)
1660
+ DRM_DEV_ERROR(vop2->dev, "wait pd%d off timeout power_ctrl: 0x%x\n",
1661
+ ffs(pd->data->id) - 1, vop2_readl(vop2, 0x34));
1662
+}
1663
+
1664
+static void vop2_wait_power_domain_on(struct vop2_power_domain *pd)
1665
+{
1666
+ struct vop2 *vop2 = pd->vop2;
1667
+ int val;
1668
+ int ret;
1669
+
1670
+ ret = readx_poll_timeout_atomic(vop2_power_domain_status, pd, val, val, 0, 50 * 1000);
1671
+ if (ret)
1672
+ DRM_DEV_ERROR(vop2->dev, "wait pd%d on timeout power_ctrl: 0x%x\n",
1673
+ ffs(pd->data->id) - 1, vop2_readl(vop2, 0x34));
1674
+}
1675
+
1676
+/*
1677
+ * Power domain on take effect immediately
1678
+ */
1679
+static void vop2_power_domain_on(struct vop2_power_domain *pd)
1680
+{
1681
+ struct vop2 *vop2 = pd->vop2;
1682
+
1683
+ if (!pd->on) {
1684
+ dev_dbg(vop2->dev, "pd%d on\n", ffs(pd->data->id) - 1);
1685
+ vop2_wait_power_domain_off(pd);
1686
+ VOP_MODULE_SET(vop2, pd->data, pd, 0);
1687
+ vop2_wait_power_domain_on(pd);
1688
+ pd->on = true;
1689
+ }
1690
+}
1691
+
1692
+/*
1693
+ * Power domain off take effect by vsync.
1694
+ */
1695
+static void vop2_power_domain_off(struct vop2_power_domain *pd)
1696
+{
1697
+ struct vop2 *vop2 = pd->vop2;
1698
+
1699
+ dev_dbg(vop2->dev, "pd%d off\n", ffs(pd->data->id) - 1);
1700
+ pd->on = false;
1701
+ VOP_MODULE_SET(vop2, pd->data, pd, 1);
1702
+}
1703
+
1704
+static void vop2_power_domain_get(struct vop2_power_domain *pd)
1705
+{
1706
+ if (pd->parent)
1707
+ vop2_power_domain_get(pd->parent);
1708
+
1709
+ spin_lock(&pd->lock);
1710
+ if (pd->ref_count == 0) {
1711
+ if (pd->vop2->data->delayed_pd)
1712
+ cancel_delayed_work(&pd->power_off_work);
1713
+ vop2_power_domain_on(pd);
1714
+ }
1715
+ pd->ref_count++;
1716
+ spin_unlock(&pd->lock);
1717
+}
1718
+
1719
+static void vop2_power_domain_put(struct vop2_power_domain *pd)
1720
+{
1721
+ spin_lock(&pd->lock);
1722
+
1723
+ /*
1724
+ * For a nested power domain(PD_Cluster0 is the parent of PD_CLuster1/2/3)
1725
+ * the parent power domain must be enabled before child power domain
1726
+ * is on.
1727
+ *
1728
+ * So we may met this condition: Cluster0 is not on a activated VP,
1729
+ * but PD_Cluster0 must enabled as one of the child PD_CLUSTER1/2/3 is enabled.
1730
+ * when all child PD is disabled, we want disable the parent
1731
+ * PD(PD_CLUSTER0), but as module CLUSTER0 is not attcthed on a activated VP,
1732
+ * the turn off operation(which is take effect by vsync) will never take effect.
1733
+ * so we will see a "wait pd0 off timeout" log when we turn on PD_CLUSTER0 next time.
1734
+ *
1735
+ * So we have a check here
1736
+ */
1737
+ if (--pd->ref_count == 0 && vop2_power_domain_can_off_by_vsync(pd)) {
1738
+ if (pd->vop2->data->delayed_pd)
1739
+ schedule_delayed_work(&pd->power_off_work, msecs_to_jiffies(2500));
1740
+ else
1741
+ vop2_power_domain_off(pd);
1742
+ }
1743
+
1744
+ spin_unlock(&pd->lock);
1745
+ if (pd->parent)
1746
+ vop2_power_domain_put(pd->parent);
1747
+}
1748
+
1749
+/*
1750
+ * Called if the pd ref_count reach 0 after 2.5
1751
+ * seconds.
1752
+ */
1753
+static void vop2_power_domain_off_work(struct work_struct *work)
1754
+{
1755
+ struct vop2_power_domain *pd;
1756
+
1757
+ pd = container_of(to_delayed_work(work), struct vop2_power_domain, power_off_work);
1758
+
1759
+ spin_lock(&pd->lock);
1760
+ if (pd->ref_count == 0)
1761
+ vop2_power_domain_off(pd);
1762
+ spin_unlock(&pd->lock);
1763
+}
1764
+
1765
+static void vop2_win_enable(struct vop2_win *win)
1766
+{
1767
+ /*
1768
+ * a win such as cursor update by async:
1769
+ * first frame enable win pd, enable win, return without wait vsync
1770
+ * second frame come, but the first frame may still not enabled
1771
+ * in this case, the win pd is turn on by fist frame, so we don't
1772
+ * need get pd again.
1773
+ *
1774
+ * another case:
1775
+ * first frame: disable win, disable pd, return without wait vsync
1776
+ * second frame come very soon, the previous win disable may still not
1777
+ * take effect, but the pd is disable in progress, we should do pd_get
1778
+ * at this situation.
1779
+ *
1780
+ * check the backup register for previous enable operation.
1781
+ */
1782
+ if (!VOP_WIN_GET_REG_BAK(win->vop2, win, enable)) {
1783
+ if (win->pd) {
1784
+ if (win->pd->data->id == VOP2_PD_ESMART)
1785
+ return;
1786
+
1787
+ vop2_power_domain_get(win->pd);
1788
+ win->pd->vp_mask |= win->vp_mask;
1789
+ }
1790
+ }
13341791 }
13351792
13361793 static void vop2_win_multi_area_disable(struct vop2_win *parent)
....@@ -1346,31 +1803,63 @@
13461803 }
13471804 }
13481805
1349
-static void vop2_win_disable(struct vop2_win *win)
1806
+static void vop2_win_disable(struct vop2_win *win, bool skip_splice_win)
13501807 {
13511808 struct vop2 *vop2 = win->vop2;
13521809
1353
- VOP_WIN_SET(vop2, win, enable, 0);
1354
- if (win->feature & WIN_FEATURE_CLUSTER_MAIN) {
1355
- struct vop2_win *sub_win;
1356
- int i = 0;
1357
-
1358
- for (i = 0; i < vop2->registered_num_wins; i++) {
1359
- sub_win = &vop2->win[i];
1360
-
1361
- if ((sub_win->phys_id == win->phys_id) &&
1362
- (sub_win->feature & WIN_FEATURE_CLUSTER_SUB))
1363
- VOP_WIN_SET(vop2, sub_win, enable, 0);
1364
- }
1365
-
1366
- VOP_CLUSTER_SET(vop2, win, enable, 0);
1810
+ /* Disable the right splice win */
1811
+ if (win->splice_win && !skip_splice_win) {
1812
+ vop2_win_disable(win->splice_win, false);
1813
+ win->splice_win = NULL;
13671814 }
13681815
1369
- /*
1370
- * disable all other multi area win if we want disable area0 here
1371
- */
1372
- if (!win->parent && (win->feature & WIN_FEATURE_MULTI_AREA))
1373
- vop2_win_multi_area_disable(win);
1816
+ if (VOP_WIN_GET(vop2, win, enable) || VOP_WIN_GET_REG_BAK(vop2, win, enable)) {
1817
+ VOP_WIN_SET(vop2, win, enable, 0);
1818
+ if (win->feature & WIN_FEATURE_CLUSTER_MAIN) {
1819
+ struct vop2_win *sub_win;
1820
+ int i = 0;
1821
+
1822
+ for (i = 0; i < vop2->registered_num_wins; i++) {
1823
+ sub_win = &vop2->win[i];
1824
+
1825
+ if ((sub_win->phys_id == win->phys_id) &&
1826
+ (sub_win->feature & WIN_FEATURE_CLUSTER_SUB))
1827
+ VOP_WIN_SET(vop2, sub_win, enable, 0);
1828
+ }
1829
+
1830
+ VOP_CLUSTER_SET(vop2, win, enable, 0);
1831
+ }
1832
+
1833
+ /*
1834
+ * disable all other multi area win if we want disable area0 here
1835
+ */
1836
+ if (!win->parent && (win->feature & WIN_FEATURE_MULTI_AREA))
1837
+ vop2_win_multi_area_disable(win);
1838
+
1839
+ if (win->pd) {
1840
+
1841
+ /*
1842
+ * Don't dynamic turn on/off PD_ESMART.
1843
+ * (1) There is a design issue for PD_EMSART when attached
1844
+ * on VP1/2/3, we found it will trigger POST_BUF_EMPTY irq at vp0
1845
+ * in splice mode.
1846
+ * (2) PD_ESMART will be closed at esmart layers attathed on VPs
1847
+ * config done + FS, but different VP FS time is different, this
1848
+ * maybe lead to PD_ESMART closed at wrong time and display error.
1849
+ * (3) PD_ESMART power up maybe have 4 us delay, this will lead to POST_BUF_EMPTY.
1850
+ */
1851
+ if (win->pd->data->id == VOP2_PD_ESMART)
1852
+ return;
1853
+
1854
+ vop2_power_domain_put(win->pd);
1855
+ win->pd->vp_mask &= ~win->vp_mask;
1856
+ }
1857
+ }
1858
+
1859
+ if (win->left_win && win->splice_mode_right) {
1860
+ win->left_win = NULL;
1861
+ win->splice_mode_right = false;
1862
+ }
13741863 }
13751864
13761865 static inline void vop2_write_lut(struct vop2 *vop2, uint32_t offset, uint32_t v)
....@@ -1386,6 +1875,11 @@
13861875 static enum vop2_data_format vop2_convert_format(uint32_t format)
13871876 {
13881877 switch (format) {
1878
+ case DRM_FORMAT_XRGB2101010:
1879
+ case DRM_FORMAT_ARGB2101010:
1880
+ case DRM_FORMAT_XBGR2101010:
1881
+ case DRM_FORMAT_ABGR2101010:
1882
+ return VOP2_FMT_XRGB101010;
13891883 case DRM_FORMAT_XRGB8888:
13901884 case DRM_FORMAT_ARGB8888:
13911885 case DRM_FORMAT_XBGR8888:
....@@ -1398,16 +1892,22 @@
13981892 case DRM_FORMAT_BGR565:
13991893 return VOP2_FMT_RGB565;
14001894 case DRM_FORMAT_NV12:
1895
+ case DRM_FORMAT_NV21:
1896
+ case DRM_FORMAT_YUV420_8BIT:
14011897 return VOP2_FMT_YUV420SP;
1402
- case DRM_FORMAT_NV12_10:
1898
+ case DRM_FORMAT_NV15:
1899
+ case DRM_FORMAT_YUV420_10BIT:
14031900 return VOP2_FMT_YUV420SP_10;
14041901 case DRM_FORMAT_NV16:
1902
+ case DRM_FORMAT_NV61:
14051903 return VOP2_FMT_YUV422SP;
1406
- case DRM_FORMAT_NV16_10:
1904
+ case DRM_FORMAT_NV20:
1905
+ case DRM_FORMAT_Y210:
14071906 return VOP2_FMT_YUV422SP_10;
14081907 case DRM_FORMAT_NV24:
1908
+ case DRM_FORMAT_NV42:
14091909 return VOP2_FMT_YUV444SP;
1410
- case DRM_FORMAT_NV24_10:
1910
+ case DRM_FORMAT_NV30:
14111911 return VOP2_FMT_YUV444SP_10;
14121912 case DRM_FORMAT_YUYV:
14131913 case DRM_FORMAT_YVYU:
....@@ -1424,6 +1924,11 @@
14241924 static enum vop2_afbc_format vop2_convert_afbc_format(uint32_t format)
14251925 {
14261926 switch (format) {
1927
+ case DRM_FORMAT_XRGB2101010:
1928
+ case DRM_FORMAT_ARGB2101010:
1929
+ case DRM_FORMAT_XBGR2101010:
1930
+ case DRM_FORMAT_ABGR2101010:
1931
+ return VOP2_AFBC_FMT_ARGB2101010;
14271932 case DRM_FORMAT_XRGB8888:
14281933 case DRM_FORMAT_ARGB8888:
14291934 case DRM_FORMAT_XBGR8888:
....@@ -1435,14 +1940,16 @@
14351940 case DRM_FORMAT_RGB565:
14361941 case DRM_FORMAT_BGR565:
14371942 return VOP2_AFBC_FMT_RGB565;
1438
- case DRM_FORMAT_NV12:
1943
+ case DRM_FORMAT_YUV420_8BIT:
14391944 return VOP2_AFBC_FMT_YUV420;
1440
- case DRM_FORMAT_NV12_10:
1945
+ case DRM_FORMAT_YUV420_10BIT:
14411946 return VOP2_AFBC_FMT_YUV420_10BIT;
1442
- case DRM_FORMAT_NV16:
1947
+ case DRM_FORMAT_YVYU:
14431948 case DRM_FORMAT_YUYV:
1949
+ case DRM_FORMAT_VYUY:
1950
+ case DRM_FORMAT_UYVY:
14441951 return VOP2_AFBC_FMT_YUV422;
1445
- case DRM_FORMAT_NV16_10:
1952
+ case DRM_FORMAT_Y210:
14461953 return VOP2_AFBC_FMT_YUV422_10BIT;
14471954
14481955 /* either of the below should not be reachable */
....@@ -1466,11 +1973,11 @@
14661973 case DRM_FORMAT_NV24:
14671974 case DRM_FORMAT_NV42:
14681975 return VOP2_TILED_8X8_FMT_YUV444SP;
1469
- case DRM_FORMAT_NV12_10:
1976
+ case DRM_FORMAT_NV15:
14701977 return VOP2_TILED_8X8_FMT_YUV420SP_10;
1471
- case DRM_FORMAT_NV16_10:
1978
+ case DRM_FORMAT_NV20:
14721979 return VOP2_TILED_8X8_FMT_YUV422SP_10;
1473
- case DRM_FORMAT_NV24_10:
1980
+ case DRM_FORMAT_NV30:
14741981 return VOP2_TILED_8X8_FMT_YUV444SP_10;
14751982 default:
14761983 DRM_WARN_ONCE("unsupported tiled format[%08x]\n", format);
....@@ -1495,13 +2002,13 @@
14952002 case DRM_FORMAT_NV42:
14962003 return tile_mode == ROCKCHIP_TILED_BLOCK_SIZE_8x8 ?
14972004 VOP3_TILED_8X8_FMT_YUV444SP : VOP3_TILED_4X4_FMT_YUV444SP;
1498
- case DRM_FORMAT_NV12_10:
2005
+ case DRM_FORMAT_NV15:
14992006 return tile_mode == ROCKCHIP_TILED_BLOCK_SIZE_8x8 ?
15002007 VOP3_TILED_8X8_FMT_YUV420SP_10 : VOP3_TILED_4X4_FMT_YUV420SP_10;
1501
- case DRM_FORMAT_NV16_10:
2008
+ case DRM_FORMAT_NV20:
15022009 return tile_mode == ROCKCHIP_TILED_BLOCK_SIZE_8x8 ?
15032010 VOP3_TILED_8X8_FMT_YUV422SP_10 : VOP3_TILED_4X4_FMT_YUV422SP_10;
1504
- case DRM_FORMAT_NV24_10:
2011
+ case DRM_FORMAT_NV30:
15052012 return tile_mode == ROCKCHIP_TILED_BLOCK_SIZE_8x8 ?
15062013 VOP3_TILED_8X8_FMT_YUV444SP_10 : VOP3_TILED_4X4_FMT_YUV444SP_10;
15072014 default:
....@@ -1540,6 +2047,8 @@
15402047 static bool vop2_win_rb_swap(uint32_t format)
15412048 {
15422049 switch (format) {
2050
+ case DRM_FORMAT_XBGR2101010:
2051
+ case DRM_FORMAT_ABGR2101010:
15432052 case DRM_FORMAT_XBGR8888:
15442053 case DRM_FORMAT_ABGR8888:
15452054 case DRM_FORMAT_BGR888:
....@@ -1554,7 +2063,7 @@
15542063 {
15552064 switch (format) {
15562065 case DRM_FORMAT_NV24:
1557
- case DRM_FORMAT_NV24_10:
2066
+ case DRM_FORMAT_NV30:
15582067 return true;
15592068 default:
15602069 return false;
....@@ -1567,8 +2076,9 @@
15672076 case DRM_FORMAT_NV12:
15682077 case DRM_FORMAT_NV16:
15692078 case DRM_FORMAT_YUYV:
1570
- case DRM_FORMAT_NV12_10:
1571
- case DRM_FORMAT_NV16_10:
2079
+ case DRM_FORMAT_Y210:
2080
+ case DRM_FORMAT_YUV420_8BIT:
2081
+ case DRM_FORMAT_YUV420_10BIT:
15722082 return true;
15732083 default:
15742084 return false;
....@@ -1581,9 +2091,9 @@
15812091 case DRM_FORMAT_NV12:
15822092 case DRM_FORMAT_NV16:
15832093 case DRM_FORMAT_NV24:
1584
- case DRM_FORMAT_NV12_10:
1585
- case DRM_FORMAT_NV16_10:
1586
- case DRM_FORMAT_NV24_10:
2094
+ case DRM_FORMAT_NV15:
2095
+ case DRM_FORMAT_NV20:
2096
+ case DRM_FORMAT_NV30:
15872097 case DRM_FORMAT_YUYV:
15882098 case DRM_FORMAT_UYVY:
15892099 return true;
....@@ -1627,6 +2137,19 @@
16272137 return false;
16282138 }
16292139
2140
+static bool vop3_output_rb_swap(uint32_t bus_format, uint32_t output_mode)
2141
+{
2142
+ /*
2143
+ * The default component order of serial rgb3x8 formats
2144
+ * is BGR. So it is needed to enable RB swap.
2145
+ */
2146
+ if (bus_format == MEDIA_BUS_FMT_RGB888_3X8 ||
2147
+ bus_format == MEDIA_BUS_FMT_RGB888_DUMMY_4X8)
2148
+ return true;
2149
+ else
2150
+ return false;
2151
+}
2152
+
16302153 static bool vop2_output_yc_swap(uint32_t bus_format)
16312154 {
16322155 switch (bus_format) {
....@@ -1645,6 +2168,7 @@
16452168 switch (bus_format) {
16462169 case MEDIA_BUS_FMT_YUV8_1X24:
16472170 case MEDIA_BUS_FMT_YUV10_1X30:
2171
+ case MEDIA_BUS_FMT_YUYV10_1X20:
16482172 case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
16492173 case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
16502174 case MEDIA_BUS_FMT_YUYV8_2X8:
....@@ -1740,6 +2264,15 @@
17402264 return (win->feature & WIN_FEATURE_CLUSTER_SUB);
17412265 }
17422266
2267
+static inline bool vop2_has_feature(struct vop2 *vop2, uint64_t feature)
2268
+{
2269
+ return (vop2->data->feature & feature);
2270
+}
2271
+
2272
+/*
2273
+ * 0: Full mode, 16 lines for one tail
2274
+ * 1: half block mode
2275
+ */
17432276 static int vop2_afbc_half_block_enable(struct vop2_plane_state *vpstate)
17442277 {
17452278 if (vpstate->rotate_270_en || vpstate->rotate_90_en)
....@@ -1748,11 +2281,15 @@
17482281 return 1;
17492282 }
17502283
1751
-static uint32_t vop2_afbc_transform_offset(struct vop2_plane_state *vpstate)
2284
+/*
2285
+ * @xoffset: the src x offset of the right win in splice mode, other wise it
2286
+ * must be zero.
2287
+ */
2288
+static uint32_t vop2_afbc_transform_offset(struct vop2_plane_state *vpstate, int xoffset)
17522289 {
17532290 struct drm_rect *src = &vpstate->src;
17542291 struct drm_framebuffer *fb = vpstate->base.fb;
1755
- uint32_t bpp = fb->format->bpp[0];
2292
+ uint32_t bpp = rockchip_drm_get_bpp(fb->format);
17562293 uint32_t vir_width = (fb->pitches[0] << 3) / (bpp ? bpp : 1);
17572294 uint32_t width = drm_rect_width(src) >> 16;
17582295 uint32_t height = drm_rect_height(src) >> 16;
....@@ -1768,6 +2305,7 @@
17682305 uint8_t top_crop_line_num = 0;
17692306 uint8_t bottom_crop_line_num = 0;
17702307
2308
+ act_xoffset += xoffset;
17712309 /* 16 pixel align */
17722310 if (height & 0xf)
17732311 align16_crop = 16 - (height & 0xf);
....@@ -2011,12 +2549,12 @@
20112549 {
20122550 const struct vop2_data *vop2_data = vop2->data;
20132551 const struct vop2_win_data *win_data = &vop2_data->win[win->win_id];
2014
- const struct drm_format_info *info;
20152552 struct vop2_plane_state *vpstate = to_vop2_plane_state(pstate);
20162553 struct drm_framebuffer *fb = pstate->fb;
20172554 uint32_t pixel_format = fb->format->format;
2018
- int hsub = drm_format_horz_chroma_subsampling(pixel_format);
2019
- int vsub = drm_format_vert_chroma_subsampling(pixel_format);
2555
+ const struct drm_format_info *info = drm_format_info(pixel_format);
2556
+ uint8_t hsub = info->hsub;
2557
+ uint8_t vsub = info->vsub;
20202558 uint16_t cbcr_src_w = src_w / hsub;
20212559 uint16_t cbcr_src_h = src_h / vsub;
20222560 uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;
....@@ -2025,8 +2563,6 @@
20252563 uint8_t xgt2 = 0, xgt4 = 0;
20262564 uint8_t ygt2 = 0, ygt4 = 0;
20272565 uint32_t val;
2028
-
2029
- info = drm_format_info(pixel_format);
20302566
20312567 if (is_vop3(vop2)) {
20322568 if (src_w >= (4 * dst_w)) {
....@@ -2246,7 +2782,7 @@
22462782 for_each_set_bit(phys_id, &win_mask, ROCKCHIP_MAX_LAYER) {
22472783 win = vop2_find_win_by_phys_id(vop2, phys_id);
22482784 need_wait_win_disabled |= VOP_WIN_GET(vop2, win, enable);
2249
- vop2_win_disable(win);
2785
+ vop2_win_disable(win, false);
22502786 }
22512787
22522788 if (need_wait_win_disabled) {
....@@ -2295,7 +2831,7 @@
22952831 struct vop2_plane_state *vpstate)
22962832 {
22972833 struct drm_plane_state *pstate = &vpstate->base;
2298
- struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state);
2834
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->rockchip_crtc.crtc.state);
22992835 int is_input_yuv = pstate->fb->format->is_yuv;
23002836 int is_output_yuv = vcstate->yuv_overlay;
23012837 int input_csc = vpstate->color_space;
....@@ -2480,8 +3016,14 @@
24803016 if (ret < 0)
24813017 goto err_disable_hclk;
24823018
3019
+ ret = clk_enable(vop2->pclk);
3020
+ if (ret < 0)
3021
+ goto err_disable_aclk;
3022
+
24833023 return 0;
24843024
3025
+err_disable_aclk:
3026
+ clk_disable(vop2->aclk);
24853027 err_disable_hclk:
24863028 clk_disable(vop2->hclk);
24873029 return ret;
....@@ -2489,6 +3031,7 @@
24893031
24903032 static void vop2_core_clks_disable(struct vop2 *vop2)
24913033 {
3034
+ clk_disable(vop2->pclk);
24923035 clk_disable(vop2->aclk);
24933036 clk_disable(vop2->hclk);
24943037 }
....@@ -2599,6 +3142,18 @@
25993142 return MODE_OK;
26003143 }
26013144
3145
+static inline bool
3146
+vop2_wb_connector_changed_only(struct drm_crtc_state *cstate, struct drm_connector *conn)
3147
+{
3148
+ struct drm_crtc_state *old_state;
3149
+ u32 changed_connectors;
3150
+
3151
+ old_state = drm_atomic_get_old_crtc_state(cstate->state, cstate->crtc);
3152
+ changed_connectors = cstate->connector_mask ^ old_state->connector_mask;
3153
+
3154
+ return BIT(drm_connector_index(conn)) == changed_connectors;
3155
+}
3156
+
26023157 static int vop2_wb_encoder_atomic_check(struct drm_encoder *encoder,
26033158 struct drm_crtc_state *cstate,
26043159 struct drm_connector_state *conn_state)
....@@ -2607,7 +3162,18 @@
26073162 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(cstate);
26083163 struct vop2_video_port *vp = to_vop2_video_port(cstate->crtc);
26093164 struct drm_framebuffer *fb;
3165
+ struct drm_gem_object *obj, *uv_obj;
3166
+ struct rockchip_gem_object *rk_obj, *rk_uv_obj;
26103167
3168
+ /*
3169
+ * No need for a full modested when the only connector changed is the
3170
+ * writeback connector.
3171
+ */
3172
+ if (cstate->connectors_changed &&
3173
+ vop2_wb_connector_changed_only(cstate, conn_state->connector)) {
3174
+ cstate->connectors_changed = false;
3175
+ DRM_DEBUG("VP%d force change connectors_changed to false when only wb changed\n", vp->id);
3176
+ }
26113177 if (!conn_state->writeback_job || !conn_state->writeback_job->fb)
26123178 return 0;
26133179
....@@ -2620,7 +3186,7 @@
26203186 }
26213187
26223188 if ((fb->width > cstate->mode.hdisplay) ||
2623
- ((fb->height != cstate->mode.vdisplay) &&
3189
+ ((fb->height < cstate->mode.vdisplay) &&
26243190 (fb->height != (cstate->mode.vdisplay >> 1)))) {
26253191 DRM_DEBUG_KMS("Invalid framebuffer size %ux%u, Only support x scale down and 1/2 y scale down\n",
26263192 fb->width, fb->height);
....@@ -2628,7 +3194,7 @@
26283194 }
26293195
26303196 wb_state->scale_x_factor = vop2_scale_factor(SCALE_DOWN, VOP2_SCALE_DOWN_BIL,
2631
- cstate->mode.hdisplay, fb->width);
3197
+ cstate->mode.hdisplay, fb->width);
26323198 wb_state->scale_x_en = (fb->width < cstate->mode.hdisplay) ? 1 : 0;
26333199 wb_state->scale_y_en = (fb->height < cstate->mode.vdisplay) ? 1 : 0;
26343200
....@@ -2643,15 +3209,15 @@
26433209 }
26443210
26453211 wb_state->vp_id = vp->id;
2646
- wb_state->yrgb_addr = rockchip_fb_get_dma_addr(fb, 0);
2647
- /*
2648
- * uv address must follow yrgb address without gap.
2649
- * the fb->offsets is include stride, so we should
2650
- * not use it.
2651
- */
3212
+ obj = fb->obj[0];
3213
+ rk_obj = to_rockchip_obj(obj);
3214
+ wb_state->yrgb_addr = rk_obj->dma_addr + fb->offsets[0];
3215
+
26523216 if (fb->format->is_yuv) {
2653
- wb_state->uv_addr = wb_state->yrgb_addr;
2654
- wb_state->uv_addr += DIV_ROUND_UP(fb->width * fb->format->bpp[0], 8) * fb->height;
3217
+ uv_obj = fb->obj[1];
3218
+ rk_uv_obj = to_rockchip_obj(uv_obj);
3219
+
3220
+ wb_state->uv_addr = rk_uv_obj->dma_addr + fb->offsets[1];
26553221 }
26563222
26573223 return 0;
....@@ -2741,10 +3307,12 @@
27413307 if (conn_state->writeback_job && conn_state->writeback_job->fb) {
27423308 struct drm_framebuffer *fb = conn_state->writeback_job->fb;
27433309
2744
- DRM_DEV_DEBUG(vop2->dev, "Enable wb %ux%u fmt: %u pitches: %d addr: %pad\n",
2745
- fb->width, fb->height, wb_state->format, fb->pitches[0], &wb_state->yrgb_addr);
3310
+ rockchip_drm_dbg(vop2->dev, VOP_DEBUG_WB,
3311
+ "Enable wb %ux%u fmt: %u pitches: %d addr: %pad\n",
3312
+ fb->width, fb->height, wb_state->format,
3313
+ fb->pitches[0], &wb_state->yrgb_addr);
27463314
2747
- drm_writeback_queue_job(wb_conn, conn_state->writeback_job);
3315
+ drm_writeback_queue_job(wb_conn, conn_state);
27483316 conn_state->writeback_job = NULL;
27493317
27503318 spin_lock_irqsave(&wb->job_lock, flags);
....@@ -2773,6 +3341,7 @@
27733341 VOP_MODULE_SET(vop2, wb, r2y_en, r2y);
27743342 VOP_MODULE_SET(vop2, wb, enable, 1);
27753343 vop2_wb_irqs_enable(vop2);
3344
+ VOP_CTRL_SET(vop2, wb_dma_finish_and_en, 1);
27763345 }
27773346 }
27783347
....@@ -2797,6 +3366,7 @@
27973366
27983367 return;
27993368 }
3369
+
28003370 spin_lock(&vop2->reg_lock);
28013371 VOP_MODULE_SET(vop2, vp, dsp_lut_en, 0);
28023372 vop2_cfg_done(crtc);
....@@ -2812,7 +3382,7 @@
28123382 spin_lock(&vop2->reg_lock);
28133383
28143384 VOP_MODULE_SET(vop2, vp, dsp_lut_en, 1);
2815
- VOP_MODULE_SET(vop2, vp, gamma_update_en, 1);
3385
+ vop2_write_reg_uncached(vop2, &vp->regs->gamma_update_en, 1);
28163386 vop2_cfg_done(crtc);
28173387 vp->gamma_lut_active = true;
28183388
....@@ -2833,7 +3403,7 @@
28333403 vop2_write_lut(vop2, i << 2, lut[i]);
28343404
28353405 VOP_MODULE_SET(vop2, vp, dsp_lut_en, 1);
2836
- VOP_MODULE_SET(vop2, vp, gamma_update_en, 1);
3406
+ vop2_write_reg_uncached(vop2, &vp->regs->gamma_update_en, 1);
28373407 vp->gamma_lut_active = true;
28383408
28393409 spin_unlock(&vop2->reg_lock);
....@@ -2853,7 +3423,13 @@
28533423 if (vop2->version == VOP_VERSION_RK3568) {
28543424 rk3568_crtc_load_lut(crtc);
28553425 } else {
2856
- rk3588_crtc_load_lut(crtc, vp->lut);
3426
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
3427
+ const struct vop2_video_port_data *vp_data = &vop2->data->vp[vp->id];
3428
+ struct vop2_video_port *splice_vp = &vop2->vps[vp_data->splice_vp_id];
3429
+
3430
+ rk3588_crtc_load_lut(&vp->rockchip_crtc.crtc, vp->lut);
3431
+ if (vcstate->splice_mode)
3432
+ rk3588_crtc_load_lut(&splice_vp->rockchip_crtc.crtc, vp->lut);
28573433 vop2_cfg_done(crtc);
28583434 }
28593435 /*
....@@ -2948,9 +3524,11 @@
29483524 return 0;
29493525 }
29503526
3527
+#if defined(CONFIG_ROCKCHIP_DRM_CUBIC_LUT)
29513528 static int vop2_crtc_atomic_cubic_lut_set(struct drm_crtc *crtc,
29523529 struct drm_crtc_state *old_state)
29533530 {
3531
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
29543532 struct vop2_video_port *vp = to_vop2_video_port(crtc);
29553533 struct rockchip_drm_private *private = crtc->dev->dev_private;
29563534 struct drm_color_lut *lut = vp->cubic_lut;
....@@ -3001,13 +3579,61 @@
30013579 *cubic_lut_kvaddr = 0;
30023580 }
30033581
3582
+ VOP_MODULE_SET(vop2, vp, lut_dma_rid, vp->lut_dma_rid);
30043583 VOP_MODULE_SET(vop2, vp, cubic_lut_mst, cubic_lut_mst);
30053584 VOP_MODULE_SET(vop2, vp, cubic_lut_update_en, 1);
30063585 VOP_MODULE_SET(vop2, vp, cubic_lut_en, 1);
30073586 VOP_CTRL_SET(vop2, lut_dma_en, 1);
30083587
3588
+ if (vcstate->splice_mode) {
3589
+ const struct vop2_video_port_data *vp_data = &vop2->data->vp[vp->id];
3590
+ struct vop2_video_port *splice_vp = &vop2->vps[vp_data->splice_vp_id];
3591
+
3592
+ VOP_MODULE_SET(vop2, splice_vp, cubic_lut_mst, cubic_lut_mst);
3593
+ VOP_MODULE_SET(vop2, splice_vp, cubic_lut_update_en, 1);
3594
+ VOP_MODULE_SET(vop2, splice_vp, cubic_lut_en, 1);
3595
+ }
3596
+
30093597 return 0;
30103598 }
3599
+
3600
+static void drm_crtc_enable_cubic_lut(struct drm_crtc *crtc, unsigned int cubic_lut_size)
3601
+{
3602
+ struct drm_device *dev = crtc->dev;
3603
+ struct drm_mode_config *config = &dev->mode_config;
3604
+
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
+ }
3612
+}
3613
+
3614
+static void vop2_cubic_lut_init(struct vop2 *vop2)
3615
+{
3616
+ const struct vop2_data *vop2_data = vop2->data;
3617
+ const struct vop2_video_port_data *vp_data;
3618
+ struct vop2_video_port *vp;
3619
+ struct drm_crtc *crtc;
3620
+ int i;
3621
+
3622
+ for (i = 0; i < vop2_data->nr_vps; i++) {
3623
+ vp = &vop2->vps[i];
3624
+ crtc = &vp->rockchip_crtc.crtc;
3625
+ if (!crtc->dev)
3626
+ continue;
3627
+ vp_data = &vop2_data->vp[vp->id];
3628
+ vp->cubic_lut_len = vp_data->cubic_lut_len;
3629
+
3630
+ if (vp->cubic_lut_len)
3631
+ drm_crtc_enable_cubic_lut(crtc, vp->cubic_lut_len);
3632
+ }
3633
+}
3634
+#else
3635
+static void vop2_cubic_lut_init(struct vop2 *vop2) { }
3636
+#endif
30113637
30123638 static int vop2_core_clks_prepare_enable(struct vop2 *vop2)
30133639 {
....@@ -3025,7 +3651,15 @@
30253651 goto err;
30263652 }
30273653
3654
+ ret = clk_prepare_enable(vop2->pclk);
3655
+ if (ret < 0) {
3656
+ dev_err(vop2->dev, "failed to enable pclk - %d\n", ret);
3657
+ goto err1;
3658
+ }
3659
+
30283660 return 0;
3661
+err1:
3662
+ clk_disable_unprepare(vop2->aclk);
30293663 err:
30303664 clk_disable_unprepare(vop2->hclk);
30313665
....@@ -3142,6 +3776,18 @@
31423776
31433777 }
31443778
3779
+static void rk3588_vop2_regsbak(struct vop2 *vop2)
3780
+{
3781
+ uint32_t *base = vop2->regs;
3782
+ int i;
3783
+
3784
+ /*
3785
+ * No need to backup DSC/GAMMA_LUT/BPP_LUT/MMU
3786
+ */
3787
+ for (i = 0; i < (0x2000 >> 2); i++)
3788
+ vop2->regsbak[i] = base[i];
3789
+}
3790
+
31453791 static void vop2_initial(struct drm_crtc *crtc)
31463792 {
31473793 struct vop2_video_port *vp = to_vop2_video_port(crtc);
....@@ -3166,7 +3812,13 @@
31663812 if (vop2_soc_is_rk3566())
31673813 VOP_CTRL_SET(vop2, otp_en, 1);
31683814
3169
- memcpy(vop2->regsbak, vop2->regs, vop2->len);
3815
+ /*
3816
+ * rk3588 don't support access mmio by memcpy
3817
+ */
3818
+ if (vop2->version == VOP_VERSION_RK3588)
3819
+ rk3588_vop2_regsbak(vop2);
3820
+ else
3821
+ memcpy(vop2->regsbak, vop2->regs, vop2->len);
31703822
31713823 VOP_MODULE_SET(vop2, wb, axi_yrgb_id, 0xd);
31723824 VOP_MODULE_SET(vop2, wb, axi_uv_id, 0xe);
....@@ -3178,10 +3830,10 @@
31783830 }
31793831
31803832 /*
3181
- * This is unused and error init value for rk3528 vp1, if less of this config,
3833
+ * This is unused and error init value for rk3528/rk3562 vp1, if less of this config,
31823834 * vp1 can't display normally.
31833835 */
3184
- if (vop2->version == VOP_VERSION_RK3528)
3836
+ if (vop2->version == VOP_VERSION_RK3528 || vop2->version == VOP_VERSION_RK3562)
31853837 vop2_mask_write(vop2, 0x700, 0x3, 4, 0, 0, true);
31863838
31873839 VOP_CTRL_SET(vop2, cfg_done_en, 1);
....@@ -3192,6 +3844,7 @@
31923844 VOP_CTRL_SET(vop2, auto_gating_en, 0);
31933845
31943846 VOP_CTRL_SET(vop2, aclk_pre_auto_gating_en, 0);
3847
+
31953848 /*
31963849 * Register OVERLAY_LAYER_SEL and OVERLAY_PORT_SEL should take effect immediately,
31973850 * than windows configuration(CLUSTER/ESMART/SMART) can take effect according the
....@@ -3204,9 +3857,17 @@
32043857 */
32053858 VOP_CTRL_SET(vop2, if_ctrl_cfg_done_imd, 1);
32063859
3860
+ /* Close dynamic turn on/off rk3588 PD_ESMART and keep esmart pd on when enable */
3861
+ if (vop2->version == VOP_VERSION_RK3588) {
3862
+ struct vop2_power_domain *esmart_pd = vop2_find_pd_by_id(vop2, VOP2_PD_ESMART);
3863
+
3864
+ if (vop2_power_domain_status(esmart_pd))
3865
+ esmart_pd->on = true;
3866
+ else
3867
+ vop2_power_domain_on(esmart_pd);
3868
+ }
32073869 vop2_layer_map_initial(vop2, current_vp_id);
32083870 vop2_axi_irqs_enable(vop2);
3209
-
32103871 vop2->is_enabled = true;
32113872 }
32123873
....@@ -3220,6 +3881,93 @@
32203881 vp->id, ret);
32213882 }
32223883
3884
+/*
3885
+ * The internal PD of VOP2 on rk3588 take effect immediately
3886
+ * for power up and take effect by vsync for power down.
3887
+ *
3888
+ * And the PD_CLUSTER0 is a parent PD of PD_CLUSTER1/2/3,
3889
+ * we may have this use case:
3890
+ * Cluster0 is attached to VP0 for HDMI output,
3891
+ * Cluster1 is attached to VP1 for MIPI DSI,
3892
+
3893
+ * When we enable Cluster1 on VP1, we should enable PD_CLUSTER0 as
3894
+ * it is the parent PD, event though HDMI is plugout, VP1 is disabled,
3895
+ * the PD of Cluster0 should keep power on.
3896
+
3897
+ * When system go to suspend:
3898
+ * (1) Power down PD of Cluster1 before VP1 standby(the power down is take
3899
+ * effect by vsync)
3900
+ * (2) Power down PD of Cluster0
3901
+ *
3902
+ * But we have problem at step (2), Cluster0 is attached to VP0. but VP0
3903
+ * is in standby mode, as it is never used or hdmi plugout. So there is
3904
+ * no vsync, the power down will never take effect.
3905
+
3906
+ * According to IC designer: We must power down all internal PD of VOP
3907
+ * before we power down the global PD_VOP.
3908
+
3909
+ * So we get this workaround:
3910
+ * If we found a VP is in standby mode when we want power down a PD is
3911
+ * attached to it, we release the VP from standby mode, than it will
3912
+ * run a default timing and generate vsync. Than we can power down the
3913
+ * PD by this vsync. After all this is done, we standby the VP at last.
3914
+ */
3915
+static void vop2_power_domain_off_by_disabled_vp(struct vop2_power_domain *pd)
3916
+{
3917
+ struct vop2_video_port *vp = NULL;
3918
+ struct vop2 *vop2 = pd->vop2;
3919
+ struct vop2_win *win;
3920
+ struct drm_crtc *crtc;
3921
+ uint32_t vp_id;
3922
+ uint8_t phys_id;
3923
+ int ret;
3924
+
3925
+ if (pd->data->id == VOP2_PD_CLUSTER0 || pd->data->id == VOP2_PD_CLUSTER1 ||
3926
+ pd->data->id == VOP2_PD_CLUSTER2 || pd->data->id == VOP2_PD_CLUSTER3 ||
3927
+ pd->data->id == VOP2_PD_ESMART) {
3928
+ phys_id = ffs(pd->data->module_id_mask) - 1;
3929
+ win = vop2_find_win_by_phys_id(vop2, phys_id);
3930
+ vp_id = ffs(win->vp_mask) - 1;
3931
+ vp = &vop2->vps[vp_id];
3932
+ } else {
3933
+ DRM_DEV_ERROR(vop2->dev, "unexpected power on pd%d\n", ffs(pd->data->id) - 1);
3934
+ }
3935
+
3936
+ if (vp) {
3937
+ ret = clk_prepare_enable(vp->dclk);
3938
+ if (ret < 0)
3939
+ DRM_DEV_ERROR(vop2->dev, "failed to enable dclk for video port%d - %d\n",
3940
+ vp->id, ret);
3941
+ crtc = &vp->rockchip_crtc.crtc;
3942
+ VOP_MODULE_SET(vop2, vp, standby, 0);
3943
+ vop2_power_domain_off(pd);
3944
+ vop2_cfg_done(crtc);
3945
+ vop2_wait_power_domain_off(pd);
3946
+
3947
+ reinit_completion(&vp->dsp_hold_completion);
3948
+ vop2_dsp_hold_valid_irq_enable(crtc);
3949
+ VOP_MODULE_SET(vop2, vp, standby, 1);
3950
+ ret = wait_for_completion_timeout(&vp->dsp_hold_completion, msecs_to_jiffies(50));
3951
+ if (!ret)
3952
+ DRM_DEV_INFO(vop2->dev, "wait for vp%d dsp_hold timeout\n", vp->id);
3953
+
3954
+ vop2_dsp_hold_valid_irq_disable(crtc);
3955
+ clk_disable_unprepare(vp->dclk);
3956
+ }
3957
+}
3958
+
3959
+static void vop2_power_off_all_pd(struct vop2 *vop2)
3960
+{
3961
+ struct vop2_power_domain *pd, *n;
3962
+
3963
+ list_for_each_entry_safe_reverse(pd, n, &vop2->pd_list_head, list) {
3964
+ if (vop2_power_domain_status(pd))
3965
+ vop2_power_domain_off_by_disabled_vp(pd);
3966
+ pd->on = false;
3967
+ pd->vp_mask = 0;
3968
+ }
3969
+}
3970
+
32233971 static void vop2_disable(struct drm_crtc *crtc)
32243972 {
32253973 struct vop2_video_port *vp = to_vop2_video_port(crtc);
....@@ -3230,7 +3978,6 @@
32303978 if (--vop2->enable_count > 0)
32313979 return;
32323980
3233
- vop2->is_enabled = false;
32343981 if (vop2->is_iommu_enabled) {
32353982 /*
32363983 * vop2 standby complete, so iommu detach is safe.
....@@ -3239,25 +3986,358 @@
32393986 rockchip_drm_dma_detach_device(vop2->drm_dev, vop2->dev);
32403987 vop2->is_iommu_enabled = false;
32413988 }
3989
+ if (vop2->version == VOP_VERSION_RK3588)
3990
+ vop2_power_off_all_pd(vop2);
32423991
3992
+ vop2->is_enabled = false;
32433993 pm_runtime_put_sync(vop2->dev);
32443994
3995
+ clk_disable_unprepare(vop2->pclk);
32453996 clk_disable_unprepare(vop2->aclk);
32463997 clk_disable_unprepare(vop2->hclk);
3998
+}
3999
+
4000
+static void vop2_crtc_disable_dsc(struct vop2 *vop2, u8 dsc_id)
4001
+{
4002
+ struct vop2_dsc *dsc = &vop2->dscs[dsc_id];
4003
+
4004
+ VOP_MODULE_SET(vop2, dsc, dsc_mer, 1);
4005
+ VOP_MODULE_SET(vop2, dsc, dsc_interface_mode, 0);
4006
+ VOP_MODULE_SET(vop2, dsc, dsc_en, 0);
4007
+ VOP_MODULE_SET(vop2, dsc, rst_deassert, 0);
4008
+}
4009
+
4010
+static struct vop2_clk *vop2_clk_get(struct vop2 *vop2, const char *name)
4011
+{
4012
+ struct vop2_clk *clk, *n;
4013
+
4014
+ if (!name)
4015
+ return NULL;
4016
+
4017
+ list_for_each_entry_safe(clk, n, &vop2->clk_list_head, list) {
4018
+ if (!strcmp(clk_hw_get_name(&clk->hw), name))
4019
+ return clk;
4020
+ }
4021
+
4022
+ return NULL;
4023
+}
4024
+
4025
+static void vop2_clk_set_parent(struct clk *clk, struct clk *parent)
4026
+{
4027
+ int ret = 0;
4028
+
4029
+ if (parent)
4030
+ ret = clk_set_parent(clk, parent);
4031
+ if (ret < 0)
4032
+ DRM_WARN("failed to set %s as parent for %s\n",
4033
+ __clk_get_name(parent), __clk_get_name(clk));
4034
+}
4035
+
4036
+static int vop2_extend_clk_init(struct vop2 *vop2)
4037
+{
4038
+ const char * const extend_clk_name[] = {
4039
+ "hdmi0_phy_pll", "hdmi1_phy_pll"};
4040
+ struct drm_device *drm_dev = vop2->drm_dev;
4041
+ struct clk *clk;
4042
+ struct vop2_extend_pll *extend_pll;
4043
+ int i;
4044
+
4045
+ INIT_LIST_HEAD(&vop2->extend_clk_list_head);
4046
+
4047
+ if (vop2->version != VOP_VERSION_RK3588)
4048
+ return 0;
4049
+
4050
+ for (i = 0; i < ARRAY_SIZE(extend_clk_name); i++) {
4051
+ clk = devm_clk_get_optional(drm_dev->dev, extend_clk_name[i]);
4052
+ if (IS_ERR(clk)) {
4053
+ dev_warn(drm_dev->dev, "failed to get %s: %ld\n",
4054
+ extend_clk_name[i], PTR_ERR(clk));
4055
+ continue;
4056
+ }
4057
+
4058
+ if (!clk)
4059
+ continue;
4060
+
4061
+ extend_pll = devm_kzalloc(drm_dev->dev, sizeof(*extend_pll), GFP_KERNEL);
4062
+ if (!extend_pll)
4063
+ return -ENOMEM;
4064
+
4065
+ extend_pll->clk = clk;
4066
+ extend_pll->vp_mask = 0;
4067
+ strncpy(extend_pll->clk_name, extend_clk_name[i], sizeof(extend_pll->clk_name));
4068
+ list_add_tail(&extend_pll->list, &vop2->extend_clk_list_head);
4069
+ }
4070
+
4071
+ return 0;
4072
+}
4073
+
4074
+static struct vop2_extend_pll *vop2_extend_clk_find_by_name(struct vop2 *vop2, char *clk_name)
4075
+{
4076
+ struct vop2_extend_pll *extend_pll;
4077
+
4078
+ list_for_each_entry(extend_pll, &vop2->extend_clk_list_head, list) {
4079
+ if (!strcmp(extend_pll->clk_name, clk_name))
4080
+ return extend_pll;
4081
+ }
4082
+
4083
+ return NULL;
4084
+}
4085
+
4086
+static int vop2_extend_clk_switch_pll(struct vop2 *vop2, struct vop2_extend_pll *src,
4087
+ struct vop2_extend_pll *dst)
4088
+{
4089
+ struct vop2_clk *dclk;
4090
+ u32 vp_mask;
4091
+ int i = 0;
4092
+ char clk_name[32];
4093
+
4094
+ if (!src->vp_mask)
4095
+ return -EINVAL;
4096
+
4097
+ if (dst->vp_mask)
4098
+ return -EBUSY;
4099
+
4100
+ vp_mask = src->vp_mask;
4101
+
4102
+ while (vp_mask) {
4103
+ if ((BIT(i) & src->vp_mask)) {
4104
+ snprintf(clk_name, sizeof(clk_name), "dclk%d", i);
4105
+ dclk = vop2_clk_get(vop2, clk_name);
4106
+ clk_set_rate(dst->clk, dclk->rate);
4107
+ vop2_clk_set_parent(vop2->vps[i].dclk, dst->clk);
4108
+ src->vp_mask &= ~BIT(i);
4109
+ dst->vp_mask |= BIT(i);
4110
+ }
4111
+ i++;
4112
+ vp_mask = vp_mask >> 1;
4113
+ }
4114
+
4115
+ return 0;
4116
+}
4117
+
4118
+static inline int vop2_extend_clk_get_vp_id(struct vop2_extend_pll *ext_pll)
4119
+{
4120
+ return ffs(ext_pll->vp_mask) - 1;
4121
+}
4122
+
4123
+/*
4124
+ * Here are 2 hdmi phy pll can use for video port dclk. The strategies of how to use hdmi phy pll
4125
+ * as follow:
4126
+ *
4127
+ * 1. hdmi phy pll can be used for video port0/1/2 when output format under 4K@60Hz;
4128
+ *
4129
+ * 2. When a video port connect both hdmi0 and hdmi1(may also connect other output interface),
4130
+ * it must hold the hdmi0 and hdmi1 phy pll, and other video port can't use it. if request dclk
4131
+ * is under 4K@60Hz, set the video port dlk parent as hdmi0 phy pll.if hdmi0 or hdmi1 phy pll
4132
+ * is used by other video port, report a error.
4133
+ *
4134
+ * 3. When a video port(A) connect hdmi0(may also connect other output interface but not hdmi1),
4135
+ * it must hold the hdmi0 phy pll, and other video port can't use it. If both hdmi0 and hdmi1
4136
+ * phy pll is used by other video port, report a error. If hdmi0 phy pll is used by another
4137
+ * video port(B) and hdmi1 phy pll is free, set hdmi1 phy pll as video port(B) dclk parent and
4138
+ * video port(A) hold hdmi0 phy pll. If hdmi0 phy pll is free, video port(A) hold hdmi0 pll.If
4139
+ * video port(A) hold hdmi0 phy pll and request dclk is under 4k@60Hz, set hdmi0 phy pll as
4140
+ * video port(A) dclk parent.
4141
+ *
4142
+ * 4. When a video port(A) connect hdmi1(may also connect other output interface but not hdmi0),
4143
+ * it must hold the hdmi1 phy pll, and other video port can't use it. If both hdmi0 and hdmi1
4144
+ * phy pll is used by other video port, report a error. If hdmi1 phy pll is used by another
4145
+ * video port(B) and hdmi0 phy pll is free, set hdmi0 phy pll as video port(B) dclk parent and
4146
+ * video port(A) hold hdmi1 phy pll. If hdmi1 phy pll is free, video port(A) hold hdmi1 pll. If
4147
+ * video port(A) hold hdmi1 phy pll and request dclk is under 4k@60Hz, set hdmi1 phy pll as
4148
+ * video port(A) dclk parent.
4149
+ *
4150
+ * 5. When a video port connect dp(0, 1, or both, may also connect other output type but not hdmi0
4151
+ * and hdmi1). If the request dclk is higher than 4K@60Hz or video port id is 2, do nothing.
4152
+ * Otherwise get a free hdmi phy pll as video port dclk parent. If no free hdmi phy pll can be
4153
+ * get, report a error.
4154
+ */
4155
+
4156
+static int vop2_clk_set_parent_extend(struct vop2_video_port *vp,
4157
+ struct rockchip_crtc_state *vcstate, bool enable)
4158
+{
4159
+ struct vop2 *vop2 = vp->vop2;
4160
+ struct vop2_extend_pll *hdmi0_phy_pll, *hdmi1_phy_pll;
4161
+ struct drm_crtc *crtc = &vp->rockchip_crtc.crtc;
4162
+ struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
4163
+
4164
+ hdmi0_phy_pll = vop2_extend_clk_find_by_name(vop2, "hdmi0_phy_pll");
4165
+ hdmi1_phy_pll = vop2_extend_clk_find_by_name(vop2, "hdmi1_phy_pll");
4166
+
4167
+ if (hdmi0_phy_pll)
4168
+ clk_get_rate(hdmi0_phy_pll->clk);
4169
+ if (hdmi1_phy_pll)
4170
+ clk_get_rate(hdmi1_phy_pll->clk);
4171
+
4172
+ if ((!hdmi0_phy_pll && !hdmi1_phy_pll) ||
4173
+ ((vcstate->output_if & VOP_OUTPUT_IF_HDMI0) && !hdmi0_phy_pll) ||
4174
+ ((vcstate->output_if & VOP_OUTPUT_IF_HDMI1) && !hdmi1_phy_pll))
4175
+ return 0;
4176
+
4177
+ if (enable) {
4178
+ if ((vcstate->output_if & VOP_OUTPUT_IF_HDMI0) &&
4179
+ (vcstate->output_if & VOP_OUTPUT_IF_HDMI1)) {
4180
+ if (hdmi0_phy_pll->vp_mask) {
4181
+ DRM_ERROR("hdmi0 phy pll is used by vp%d\n",
4182
+ vop2_extend_clk_get_vp_id(hdmi0_phy_pll));
4183
+ return -EBUSY;
4184
+ }
4185
+
4186
+ if (hdmi1_phy_pll->vp_mask) {
4187
+ DRM_ERROR("hdmi1 phy pll is used by vp%d\n",
4188
+ vop2_extend_clk_get_vp_id(hdmi1_phy_pll));
4189
+ return -EBUSY;
4190
+ }
4191
+
4192
+ if (adjusted_mode->crtc_clock > VOP2_MAX_DCLK_RATE)
4193
+ vop2_clk_set_parent(vp->dclk, vp->dclk_parent);
4194
+ else
4195
+ vop2_clk_set_parent(vp->dclk, hdmi0_phy_pll->clk);
4196
+
4197
+ hdmi0_phy_pll->vp_mask |= BIT(vp->id);
4198
+ hdmi1_phy_pll->vp_mask |= BIT(vp->id);
4199
+ } else if ((vcstate->output_if & VOP_OUTPUT_IF_HDMI0) &&
4200
+ !(vcstate->output_if & VOP_OUTPUT_IF_HDMI1)) {
4201
+ if (hdmi0_phy_pll->vp_mask) {
4202
+ if (hdmi1_phy_pll) {
4203
+ if (hdmi1_phy_pll->vp_mask) {
4204
+ DRM_ERROR("hdmi0: phy pll is used by vp%d:vp%d\n",
4205
+ vop2_extend_clk_get_vp_id(hdmi0_phy_pll),
4206
+ vop2_extend_clk_get_vp_id(hdmi1_phy_pll));
4207
+ return -EBUSY;
4208
+ }
4209
+
4210
+ vop2_extend_clk_switch_pll(vop2, hdmi0_phy_pll,
4211
+ hdmi1_phy_pll);
4212
+ } else {
4213
+ DRM_ERROR("hdmi0: phy pll is used by vp%d\n",
4214
+ vop2_extend_clk_get_vp_id(hdmi0_phy_pll));
4215
+ return -EBUSY;
4216
+ }
4217
+ }
4218
+
4219
+ if (adjusted_mode->crtc_clock > VOP2_MAX_DCLK_RATE)
4220
+ vop2_clk_set_parent(vp->dclk, vp->dclk_parent);
4221
+ else
4222
+ vop2_clk_set_parent(vp->dclk, hdmi0_phy_pll->clk);
4223
+
4224
+ hdmi0_phy_pll->vp_mask |= BIT(vp->id);
4225
+ } else if (!(vcstate->output_if & VOP_OUTPUT_IF_HDMI0) &&
4226
+ (vcstate->output_if & VOP_OUTPUT_IF_HDMI1)) {
4227
+ if (hdmi1_phy_pll->vp_mask) {
4228
+ if (hdmi0_phy_pll) {
4229
+ if (hdmi0_phy_pll->vp_mask) {
4230
+ DRM_ERROR("hdmi1: phy pll is used by vp%d:vp%d\n",
4231
+ vop2_extend_clk_get_vp_id(hdmi0_phy_pll),
4232
+ vop2_extend_clk_get_vp_id(hdmi1_phy_pll));
4233
+ return -EBUSY;
4234
+ }
4235
+
4236
+ vop2_extend_clk_switch_pll(vop2, hdmi1_phy_pll,
4237
+ hdmi0_phy_pll);
4238
+ } else {
4239
+ DRM_ERROR("hdmi1: phy pll is used by vp%d\n",
4240
+ vop2_extend_clk_get_vp_id(hdmi1_phy_pll));
4241
+ return -EBUSY;
4242
+ }
4243
+ }
4244
+
4245
+ if (adjusted_mode->crtc_clock > VOP2_MAX_DCLK_RATE)
4246
+ vop2_clk_set_parent(vp->dclk, vp->dclk_parent);
4247
+ else
4248
+ vop2_clk_set_parent(vp->dclk, hdmi1_phy_pll->clk);
4249
+
4250
+ hdmi1_phy_pll->vp_mask |= BIT(vp->id);
4251
+ } else if (output_if_is_dp(vcstate->output_if)) {
4252
+ if (vp->id == 2) {
4253
+ vop2_clk_set_parent(vp->dclk, vp->dclk_parent);
4254
+ return 0;
4255
+ }
4256
+
4257
+ if (hdmi0_phy_pll && !hdmi0_phy_pll->vp_mask) {
4258
+ vop2_clk_set_parent(vp->dclk, hdmi0_phy_pll->clk);
4259
+ hdmi0_phy_pll->vp_mask |= BIT(vp->id);
4260
+ } else if (hdmi1_phy_pll && !hdmi1_phy_pll->vp_mask) {
4261
+ vop2_clk_set_parent(vp->dclk, hdmi1_phy_pll->clk);
4262
+ hdmi1_phy_pll->vp_mask |= BIT(vp->id);
4263
+ } else {
4264
+ vop2_clk_set_parent(vp->dclk, vp->dclk_parent);
4265
+ DRM_INFO("No free hdmi phy pll for DP, use default parent\n");
4266
+ }
4267
+ }
4268
+ } else {
4269
+ if (hdmi0_phy_pll && (BIT(vp->id) & hdmi0_phy_pll->vp_mask))
4270
+ hdmi0_phy_pll->vp_mask &= ~BIT(vp->id);
4271
+
4272
+ if (hdmi1_phy_pll && (BIT(vp->id) & hdmi1_phy_pll->vp_mask))
4273
+ hdmi1_phy_pll->vp_mask &= ~BIT(vp->id);
4274
+ }
4275
+
4276
+ return 0;
4277
+}
4278
+
4279
+static void vop2_crtc_atomic_disable_for_psr(struct drm_crtc *crtc,
4280
+ struct drm_crtc_state *old_state)
4281
+{
4282
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
4283
+ struct vop2 *vop2 = vp->vop2;
4284
+
4285
+ vop2_disable_all_planes_for_crtc(crtc);
4286
+ drm_crtc_vblank_off(crtc);
4287
+ if (hweight8(vop2->active_vp_mask) == 1) {
4288
+ u32 adjust_aclk_rate = 0;
4289
+ u32 htotal = (VOP_MODULE_GET(vop2, vp, htotal_pw) >> 16) & 0xffff;
4290
+ u32 pre_scan_dly = VOP_MODULE_GET(vop2, vp, pre_scan_htiming);
4291
+ u32 pre_scan_hblank = pre_scan_dly & 0x1fff;
4292
+ u32 pre_scan_hactive = (pre_scan_dly >> 16) & 0x1fff;
4293
+ u32 dclk_rate = crtc->state->adjusted_mode.crtc_clock / 1000;
4294
+ /**
4295
+ * (pre_scan_hblank + pre_scan_hactive) x aclk_margin / adjust_aclk_rate = hotal / dclk_rate
4296
+ * aclk_margin = 1.2, so
4297
+ * adjust_aclk_rate = (pre_scan_hblank + pre_scan_hactive) x 1.2 * aclk_margin / htotal
4298
+ */
4299
+
4300
+ adjust_aclk_rate = (pre_scan_hblank + pre_scan_hactive) * dclk_rate * 12 / 10 / htotal;
4301
+
4302
+ vop2->aclk_rate = clk_get_rate(vop2->aclk);
4303
+ clk_set_rate(vop2->aclk, adjust_aclk_rate * 1000000L);
4304
+ vop2->aclk_rate_reset = true;
4305
+ }
32474306 }
32484307
32494308 static void vop2_crtc_atomic_disable(struct drm_crtc *crtc,
32504309 struct drm_crtc_state *old_state)
32514310 {
32524311 struct vop2_video_port *vp = to_vop2_video_port(crtc);
4312
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
32534313 struct vop2 *vop2 = vp->vop2;
32544314 const struct vop2_video_port_data *vp_data = &vop2->data->vp[vp->id];
4315
+ struct vop2_video_port *splice_vp = &vop2->vps[vp_data->splice_vp_id];
4316
+ bool dual_channel = !!(vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE);
32554317 int ret;
32564318
32574319 WARN_ON(vp->event);
4320
+
4321
+ if (crtc->state->self_refresh_active) {
4322
+ vop2_crtc_atomic_disable_for_psr(crtc, old_state);
4323
+ goto out;
4324
+ }
4325
+
32584326 vop2_lock(vop2);
32594327 DRM_DEV_INFO(vop2->dev, "Crtc atomic disable vp%d\n", vp->id);
4328
+ VOP_MODULE_SET(vop2, vp, almost_full_or_en, 0);
4329
+ VOP_MODULE_SET(vop2, vp, line_flag_or_en, 0);
32604330 drm_crtc_vblank_off(crtc);
4331
+ if (vop2->dscs[vcstate->dsc_id].enabled &&
4332
+ vop2->dscs[vcstate->dsc_id].attach_vp_id == vp->id &&
4333
+ vop2->data->nr_dscs) {
4334
+ if (dual_channel) {
4335
+ vop2_crtc_disable_dsc(vop2, 0);
4336
+ vop2_crtc_disable_dsc(vop2, 1);
4337
+ } else {
4338
+ vop2_crtc_disable_dsc(vop2, vcstate->dsc_id);
4339
+ }
4340
+ }
32614341
32624342 if (vp->cubic_lut) {
32634343 VOP_MODULE_SET(vop2, vp, cubic_lut_update_en, 0);
....@@ -3268,6 +4348,47 @@
32684348 VOP_MODULE_SET(vop2, vp, hdr_lut_update_en, 0);
32694349 vop2_disable_all_planes_for_crtc(crtc);
32704350
4351
+ if (vop2->dscs[vcstate->dsc_id].enabled &&
4352
+ vop2->dscs[vcstate->dsc_id].attach_vp_id == vp->id &&
4353
+ vop2->data->nr_dscs && vop2->dscs[vcstate->dsc_id].pd) {
4354
+ if (dual_channel) {
4355
+ vop2_power_domain_put(vop2->dscs[0].pd);
4356
+ vop2_power_domain_put(vop2->dscs[1].pd);
4357
+ vop2->dscs[0].pd->vp_mask = 0;
4358
+ vop2->dscs[1].pd->vp_mask = 0;
4359
+ vop2->dscs[0].attach_vp_id = -1;
4360
+ vop2->dscs[1].attach_vp_id = -1;
4361
+ } else {
4362
+ vop2_power_domain_put(vop2->dscs[vcstate->dsc_id].pd);
4363
+ vop2->dscs[vcstate->dsc_id].pd->vp_mask = 0;
4364
+ vop2->dscs[vcstate->dsc_id].attach_vp_id = -1;
4365
+ }
4366
+ vop2->dscs[vcstate->dsc_id].enabled = false;
4367
+ vcstate->dsc_enable = false;
4368
+ }
4369
+
4370
+ if (vp->output_if & VOP_OUTPUT_IF_eDP0)
4371
+ VOP_GRF_SET(vop2, grf, grf_edp0_en, 0);
4372
+
4373
+ if (vp->output_if & VOP_OUTPUT_IF_eDP1)
4374
+ VOP_GRF_SET(vop2, grf, grf_edp1_en, 0);
4375
+
4376
+ if (vp->output_if & VOP_OUTPUT_IF_HDMI0) {
4377
+ VOP_GRF_SET(vop2, grf, grf_hdmi0_dsc_en, 0);
4378
+ VOP_GRF_SET(vop2, grf, grf_hdmi0_en, 0);
4379
+ }
4380
+
4381
+ if (vp->output_if & VOP_OUTPUT_IF_HDMI1) {
4382
+ VOP_GRF_SET(vop2, grf, grf_hdmi1_dsc_en, 0);
4383
+ VOP_GRF_SET(vop2, grf, grf_hdmi1_en, 0);
4384
+ }
4385
+
4386
+ VOP_MODULE_SET(vop2, vp, dual_channel_en, 0);
4387
+ VOP_MODULE_SET(vop2, vp, dual_channel_swap, 0);
4388
+
4389
+ vp->output_if = 0;
4390
+
4391
+ vop2_clk_set_parent_extend(vp, vcstate, false);
32714392 /*
32724393 * Vop standby will take effect at end of current frame,
32734394 * if dsp hold valid irq happen, it means standby complete.
....@@ -3280,6 +4401,8 @@
32804401
32814402 spin_lock(&vop2->reg_lock);
32824403
4404
+ VOP_MODULE_SET(vop2, vp, splice_en, 0);
4405
+
32834406 VOP_MODULE_SET(vop2, vp, standby, 1);
32844407
32854408 spin_unlock(&vop2->reg_lock);
....@@ -3291,12 +4414,21 @@
32914414 vop2_dsp_hold_valid_irq_disable(crtc);
32924415
32934416 vop2_disable(crtc);
4417
+
4418
+ vop2->active_vp_mask &= ~BIT(vp->id);
4419
+ if (vcstate->splice_mode)
4420
+ vop2->active_vp_mask &= ~BIT(splice_vp->id);
4421
+ vcstate->splice_mode = false;
4422
+ vcstate->output_flags = 0;
4423
+ vp->splice_mode_right = false;
4424
+ vp->loader_protect = false;
4425
+ splice_vp->splice_mode_right = false;
32944426 memset(&vp->active_tv_state, 0, sizeof(vp->active_tv_state));
32954427 vop2_unlock(vop2);
32964428
3297
- vop2->active_vp_mask &= ~BIT(vp->id);
32984429 vop2_set_system_status(vop2);
32994430
4431
+out:
33004432 if (crtc->state->event && !crtc->state->active) {
33014433 spin_lock_irq(&crtc->dev->event_lock);
33024434 drm_crtc_send_vblank_event(crtc, crtc->state->event);
....@@ -3306,23 +4438,140 @@
33064438 }
33074439 }
33084440
4441
+static int vop2_cluster_two_win_mode_check(struct drm_plane_state *pstate)
4442
+{
4443
+ struct drm_atomic_state *state = pstate->state;
4444
+ struct drm_plane *plane = pstate->plane;
4445
+ struct vop2_win *win = to_vop2_win(plane);
4446
+ struct vop2 *vop2 = win->vop2;
4447
+ struct vop2_win *main_win = vop2_find_win_by_phys_id(vop2, win->phys_id);
4448
+ struct drm_plane_state *main_pstate;
4449
+ int actual_w = drm_rect_width(&pstate->src) >> 16;
4450
+ int xoffset;
4451
+
4452
+ if (pstate->fb->modifier == DRM_FORMAT_MOD_LINEAR)
4453
+ xoffset = 0;
4454
+ else
4455
+ xoffset = pstate->src.x1 >> 16;
4456
+
4457
+ if ((actual_w + xoffset % 16) > 2048) {
4458
+ DRM_ERROR("%s act_w(%d) + xoffset(%d) / 16 << 2048 in two win mode\n",
4459
+ win->name, actual_w, xoffset);
4460
+ return -EINVAL;
4461
+ }
4462
+
4463
+ main_pstate = drm_atomic_get_new_plane_state(state, &main_win->base);
4464
+
4465
+ if (pstate->fb->modifier != main_pstate->fb->modifier) {
4466
+ DRM_ERROR("%s(fb->modifier: 0x%llx) must use same data layout as %s(fb->modifier: 0x%llx)\n",
4467
+ win->name, pstate->fb->modifier, main_win->name, main_pstate->fb->modifier);
4468
+ return -EINVAL;
4469
+ }
4470
+
4471
+ if (main_pstate->fb->modifier == DRM_FORMAT_MOD_LINEAR)
4472
+ xoffset = 0;
4473
+ else
4474
+ xoffset = main_pstate->src.x1 >> 16;
4475
+ actual_w = drm_rect_width(&main_pstate->src) >> 16;
4476
+
4477
+ if ((actual_w + xoffset % 16) > 2048) {
4478
+ DRM_ERROR("%s act_w(%d) + xoffset(%d) / 16 << 2048 in two win mode\n",
4479
+ main_win->name, actual_w, xoffset);
4480
+ return -EINVAL;
4481
+ }
4482
+
4483
+ return 0;
4484
+}
4485
+
4486
+static int vop2_cluter_splice_scale_check(struct vop2_win *win, struct drm_plane_state *pstate,
4487
+ u16 hdisplay)
4488
+{
4489
+ struct drm_rect src = drm_plane_state_src(pstate);
4490
+ struct drm_rect dst = drm_plane_state_dest(pstate);
4491
+ u16 half_hdisplay = hdisplay >> 1;
4492
+
4493
+ /* scale up is ok */
4494
+ if ((drm_rect_width(&src) >> 16) <= drm_rect_width(&dst))
4495
+ return 0;
4496
+
4497
+ if ((drm_rect_width(&src) >> 16) <= VOP2_MAX_VP_OUTPUT_WIDTH)
4498
+ return 0;
4499
+ /*
4500
+ * Cluster scale down limitation in splice mode:
4501
+ * If scale down, must display at horizontal center
4502
+ */
4503
+ if ((dst.x1 < half_hdisplay) && (dst.x2 > half_hdisplay)) {
4504
+ if ((dst.x2 + dst.x1) != hdisplay) {
4505
+ DRM_ERROR("%s src_w: %d dst_w %d dst(%d %d) must scale down at center in splice mode\n",
4506
+ win->name, drm_rect_width(&src) >> 16,
4507
+ drm_rect_width(&dst), dst.x1, dst.x2);
4508
+ return -EINVAL;
4509
+ }
4510
+
4511
+ if (drm_rect_calc_hscale(&src, &dst, 1, FRAC_16_16(6, 5)) < 0) {
4512
+ DRM_ERROR("%s %d --> %d scale down factor should < 1.2 in splice mode\n",
4513
+ win->name, drm_rect_width(&src) >> 16, drm_rect_width(&dst));
4514
+ return -EINVAL;
4515
+ }
4516
+ }
4517
+
4518
+ return 0;
4519
+}
4520
+
4521
+static int vop2_plane_splice_check(struct drm_plane *plane, struct drm_plane_state *pstate,
4522
+ struct drm_display_mode *mode)
4523
+{
4524
+ struct vop2_win *win = to_vop2_win(plane);
4525
+ int ret = 0;
4526
+
4527
+ if (!(win->feature & WIN_FEATURE_SPLICE_LEFT)) {
4528
+ DRM_ERROR("%s can't be left win in splice mode\n", win->name);
4529
+ return -EINVAL;
4530
+ }
4531
+
4532
+ if (win->feature & WIN_FEATURE_CLUSTER_SUB) {
4533
+ DRM_ERROR("%s can't use two win mode in splice mode\n", win->name);
4534
+ return -EINVAL;
4535
+ }
4536
+
4537
+ if ((pstate->rotation & DRM_MODE_ROTATE_270) ||
4538
+ (pstate->rotation & DRM_MODE_ROTATE_90) ||
4539
+ (pstate->rotation & DRM_MODE_REFLECT_X)) {
4540
+ DRM_ERROR("%s can't rotate 270/90 and xmirror in splice mode\n", win->name);
4541
+ return -EINVAL;
4542
+ }
4543
+
4544
+ /* check for cluster splice scale down */
4545
+ if (win->feature & WIN_FEATURE_CLUSTER_MAIN)
4546
+ ret = vop2_cluter_splice_scale_check(win, pstate, mode->hdisplay);
4547
+
4548
+ return ret;
4549
+}
4550
+
33094551 static int vop2_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
33104552 {
33114553 struct vop2_plane_state *vpstate = to_vop2_plane_state(state);
33124554 struct vop2_win *win = to_vop2_win(plane);
4555
+ struct vop2_win *splice_win;
4556
+ struct vop2 *vop2 = win->vop2;
33134557 struct drm_framebuffer *fb = state->fb;
4558
+ struct drm_display_mode *mode;
33144559 struct drm_crtc *crtc = state->crtc;
33154560 struct drm_crtc_state *cstate;
4561
+ struct rockchip_crtc_state *vcstate;
33164562 struct vop2_video_port *vp;
33174563 const struct vop2_data *vop2_data;
33184564 struct drm_rect *dest = &vpstate->dest;
33194565 struct drm_rect *src = &vpstate->src;
4566
+ struct drm_gem_object *obj, *uv_obj;
4567
+ struct rockchip_gem_object *rk_obj, *rk_uv_obj;
33204568 int min_scale = win->regs->scl ? FRAC_16_16(1, 8) : DRM_PLANE_HELPER_NO_SCALING;
33214569 int max_scale = win->regs->scl ? FRAC_16_16(8, 1) : DRM_PLANE_HELPER_NO_SCALING;
33224570 uint32_t tile_size = 1;
4571
+ int max_input_w;
4572
+ int max_input_h;
33234573 unsigned long offset;
33244574 dma_addr_t dma_addr;
3325
- void *kvaddr;
33264575 int ret;
33274576
33284577 crtc = crtc ? crtc : plane->state->crtc;
....@@ -3338,6 +4587,26 @@
33384587 if (WARN_ON(!cstate))
33394588 return -EINVAL;
33404589
4590
+ mode = &cstate->mode;
4591
+ vcstate = to_rockchip_crtc_state(cstate);
4592
+
4593
+ max_input_w = vop2_data->max_input.width;
4594
+ max_input_h = vop2_data->max_input.height;
4595
+
4596
+ if (vop2_has_feature(win->vop2, VOP_FEATURE_SPLICE)) {
4597
+ if (mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) {
4598
+ vcstate->splice_mode = true;
4599
+ ret = vop2_plane_splice_check(plane, state, mode);
4600
+ if (ret < 0)
4601
+ return ret;
4602
+ splice_win = vop2_find_win_by_phys_id(vop2, win->splice_win_id);
4603
+ splice_win->splice_mode_right = true;
4604
+ splice_win->left_win = win;
4605
+ win->splice_win = splice_win;
4606
+ max_input_w <<= 1;
4607
+ }
4608
+ }
4609
+
33414610 vpstate->xmirror_en = (state->rotation & DRM_MODE_REFLECT_X) ? 1 : 0;
33424611 vpstate->ymirror_en = (state->rotation & DRM_MODE_REFLECT_Y) ? 1 : 0;
33434612 vpstate->rotate_270_en = (state->rotation & DRM_MODE_ROTATE_270) ? 1 : 0;
....@@ -3347,7 +4616,6 @@
33474616 DRM_ERROR("Can't rotate 90 and 270 at the same time\n");
33484617 return -EINVAL;
33494618 }
3350
-
33514619
33524620 ret = drm_atomic_helper_check_plane_state(state, cstate,
33534621 min_scale, max_scale,
....@@ -3388,13 +4656,13 @@
33884656 return 0;
33894657 }
33904658
3391
- if (drm_rect_width(src) >> 16 > vop2_data->max_input.width ||
3392
- drm_rect_height(src) >> 16 > vop2_data->max_input.height) {
4659
+ if (drm_rect_width(src) >> 16 > max_input_w ||
4660
+ drm_rect_height(src) >> 16 > max_input_h) {
33934661 DRM_ERROR("Invalid source: %dx%d. max input: %dx%d\n",
33944662 drm_rect_width(src) >> 16,
33954663 drm_rect_height(src) >> 16,
3396
- vop2_data->max_input.width,
3397
- vop2_data->max_input.height);
4664
+ max_input_w,
4665
+ max_input_h);
33984666 return -EINVAL;
33994667 }
34004668
....@@ -3417,11 +4685,31 @@
34174685 * This is special feature at rk356x, the cluster layer only can support
34184686 * afbc format and can't support linear format;
34194687 */
3420
- if (VOP_MAJOR(vop2_data->version) == 0x40 && VOP_MINOR(vop2_data->version) == 0x15) {
4688
+ if (vp->vop2->version == VOP_VERSION_RK3568) {
34214689 if (vop2_cluster_window(win) && !vpstate->afbc_en) {
34224690 DRM_ERROR("Unsupported linear format at %s\n", win->name);
34234691 return -EINVAL;
34244692 }
4693
+ }
4694
+
4695
+ if (vp->vop2->version > VOP_VERSION_RK3568) {
4696
+ if (vop2_cluster_window(win) && !vpstate->afbc_en && fb->format->is_yuv && !is_vop3(vop2)) {
4697
+ DRM_ERROR("Unsupported linear yuv format at %s\n", win->name);
4698
+ return -EINVAL;
4699
+ }
4700
+
4701
+ if (vop2_cluster_window(win) && !vpstate->afbc_en &&
4702
+ (win->supported_rotations & state->rotation)) {
4703
+ DRM_ERROR("Unsupported linear rotation(%d) format at %s\n",
4704
+ state->rotation, win->name);
4705
+ return -EINVAL;
4706
+ }
4707
+ }
4708
+
4709
+ if (win->feature & WIN_FEATURE_CLUSTER_SUB) {
4710
+ ret = vop2_cluster_two_win_mode_check(state);
4711
+ if (ret < 0)
4712
+ return ret;
34254713 }
34264714
34274715 /*
....@@ -3433,7 +4721,10 @@
34334721 return -EINVAL;
34344722 }
34354723
3436
- offset = ALIGN_DOWN(src->x1 >> 16, tile_size) * fb->format->bpp[0] / 8 * tile_size;
4724
+ if (fb->format->char_per_block[0] == 0)
4725
+ offset = ALIGN_DOWN(src->x1 >> 16, tile_size) * fb->format->cpp[0] * tile_size;
4726
+ else
4727
+ offset = drm_format_info_min_pitch(fb->format, 0, ALIGN_DOWN(src->x1 >> 16, tile_size)) * tile_size;
34374728 vpstate->offset = offset + fb->offsets[0];
34384729
34394730 /*
....@@ -3446,30 +4737,33 @@
34464737 else
34474738 offset += ALIGN_DOWN(src->y1 >> 16, tile_size) * fb->pitches[0];
34484739
3449
- dma_addr = rockchip_fb_get_dma_addr(fb, 0);
3450
- kvaddr = rockchip_fb_get_kvaddr(fb, 0);
4740
+ obj = fb->obj[0];
4741
+ rk_obj = to_rockchip_obj(obj);
34514742
3452
- vpstate->yrgb_mst = dma_addr + offset + fb->offsets[0];
3453
- vpstate->yrgb_kvaddr = kvaddr + offset + fb->offsets[0];
3454
- if (fb->format->is_yuv) {
3455
- int hsub = drm_format_horz_chroma_subsampling(fb->format->format);
3456
- int vsub = drm_format_vert_chroma_subsampling(fb->format->format);
4743
+ vpstate->yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
4744
+ if (fb->format->is_yuv && fb->format->num_planes > 1) {
4745
+ int hsub = fb->format->hsub;
4746
+ int vsub = fb->format->vsub;
34574747
3458
- offset = ALIGN_DOWN(src->x1 >> 16, tile_size) * fb->format->bpp[1] / hsub / 8 * tile_size;
4748
+ if (fb->format->char_per_block[0] == 0)
4749
+ offset = ALIGN_DOWN(src->x1 >> 16, tile_size) * fb->format->cpp[1] / hsub * tile_size;
4750
+ else
4751
+ offset = drm_format_info_min_pitch(fb->format, 1, ALIGN_DOWN(src->x1 >> 16, tile_size)) * tile_size / hsub;
4752
+
34594753 if (vpstate->tiled_en)
34604754 offset /= vsub;
34614755 offset += ALIGN_DOWN(src->y1 >> 16, tile_size) * fb->pitches[1] / vsub;
4756
+
4757
+ uv_obj = fb->obj[1];
4758
+ rk_uv_obj = to_rockchip_obj(uv_obj);
4759
+
34624760 if (vpstate->ymirror_en && !vpstate->afbc_en)
34634761 offset += fb->pitches[1] * ((state->src_h >> 16) - 2) / vsub;
3464
- dma_addr = rockchip_fb_get_dma_addr(fb, 1);
3465
- dma_addr += offset + fb->offsets[1];
4762
+ dma_addr = rk_uv_obj->dma_addr + offset + fb->offsets[1];
34664763 vpstate->uv_mst = dma_addr;
3467
-
34684764 /* tile 4x4 m0 format, y and uv is packed together */
3469
- if (vpstate->tiled_en == ROCKCHIP_TILED_BLOCK_SIZE_4x4_MODE0) {
4765
+ if (vpstate->tiled_en == ROCKCHIP_TILED_BLOCK_SIZE_4x4_MODE0)
34704766 vpstate->yrgb_mst += offset;
3471
- vpstate->yrgb_kvaddr += offset;
3472
- }
34734767 }
34744768
34754769 return 0;
....@@ -3483,15 +4777,17 @@
34834777 struct vop2_plane_state *vpstate = to_vop2_plane_state(plane->state);
34844778 #endif
34854779
3486
- DRM_DEV_DEBUG(vop2->dev, "%s disable\n", win->name);
4780
+ rockchip_drm_dbg(vop2->dev, VOP_DEBUG_PLANE, "%s disable %s\n",
4781
+ win->name, current->comm);
34874782
34884783 if (!old_state->crtc)
34894784 return;
34904785
34914786 spin_lock(&vop2->reg_lock);
34924787
3493
- vop2_win_disable(win);
3494
- VOP_WIN_SET(vop2, win, yuv_clip, 0);
4788
+ vop2_win_disable(win, false);
4789
+ if (win->splice_win)
4790
+ vop2_win_disable(win->splice_win, false);
34954791
34964792 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
34974793 kfree(vpstate->planlist);
....@@ -3555,6 +4851,64 @@
35554851 VOP_WIN_SET(vop2, win, color_key, color_key);
35564852 }
35574853
4854
+static void vop2_calc_drm_rect_for_splice(struct vop2_plane_state *vpstate,
4855
+ struct drm_rect *left_src, struct drm_rect *left_dst,
4856
+ struct drm_rect *right_src, struct drm_rect *right_dst)
4857
+{
4858
+ struct drm_crtc *crtc = vpstate->base.crtc;
4859
+ struct drm_display_mode *mode = &crtc->state->adjusted_mode;
4860
+ struct drm_rect *dst = &vpstate->dest;
4861
+ struct drm_rect *src = &vpstate->src;
4862
+ u16 half_hdisplay = mode->crtc_hdisplay >> 1;
4863
+ int hscale = drm_rect_calc_hscale(src, dst, 0, INT_MAX);
4864
+ int dst_w = drm_rect_width(dst);
4865
+ int src_w = drm_rect_width(src) >> 16;
4866
+ int left_src_w, left_dst_w, right_dst_w;
4867
+ struct drm_plane_state *pstate = &vpstate->base;
4868
+ struct drm_framebuffer *fb = pstate->fb;
4869
+
4870
+ left_dst_w = min_t(u16, half_hdisplay, dst->x2) - dst->x1;
4871
+ if (left_dst_w < 0)
4872
+ left_dst_w = 0;
4873
+ right_dst_w = dst_w - left_dst_w;
4874
+
4875
+ if (!right_dst_w)
4876
+ left_src_w = src_w;
4877
+ else
4878
+ left_src_w = (left_dst_w * hscale) >> 16;
4879
+
4880
+ /*
4881
+ * Make sure the yrgb/uv mst of right win are byte aligned
4882
+ * with full pixel.
4883
+ */
4884
+ if (right_dst_w) {
4885
+ if (fb->format->format == DRM_FORMAT_NV15)
4886
+ left_src_w &= ~0x7;
4887
+ else if (fb->format->format == DRM_FORMAT_NV12)
4888
+ left_src_w &= ~0x1;
4889
+ }
4890
+ left_src->x1 = src->x1;
4891
+ left_src->x2 = src->x1 + (left_src_w << 16);
4892
+ left_dst->x1 = dst->x1;
4893
+ left_dst->x2 = dst->x1 + left_dst_w;
4894
+ right_src->x1 = left_src->x2;
4895
+ right_src->x2 = src->x2;
4896
+ right_dst->x1 = dst->x1 + left_dst_w - half_hdisplay;
4897
+ if (right_dst->x1 < 0)
4898
+ right_dst->x1 = 0;
4899
+
4900
+ right_dst->x2 = right_dst->x1 + right_dst_w;
4901
+
4902
+ left_src->y1 = src->y1;
4903
+ left_src->y2 = src->y2;
4904
+ left_dst->y1 = dst->y1;
4905
+ left_dst->y2 = dst->y2;
4906
+ right_src->y1 = src->y1;
4907
+ right_src->y2 = src->y2;
4908
+ right_dst->y1 = dst->y1;
4909
+ right_dst->y2 = dst->y2;
4910
+}
4911
+
35584912 static void rk3588_vop2_win_cfg_axi(struct vop2_win *win)
35594913 {
35604914 struct vop2 *vop2 = win->vop2;
....@@ -3589,49 +4943,301 @@
35894943 }
35904944 }
35914945
4946
+static void vop2_win_atomic_update(struct vop2_win *win, struct drm_rect *src, struct drm_rect *dst,
4947
+ struct drm_plane_state *pstate)
4948
+{
4949
+ struct drm_crtc *crtc = pstate->crtc;
4950
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
4951
+ struct vop2_plane_state *vpstate = to_vop2_plane_state(pstate);
4952
+ struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
4953
+ struct vop2 *vop2 = win->vop2;
4954
+ struct drm_framebuffer *fb = pstate->fb;
4955
+ struct drm_rect *left_src = &vpstate->src;
4956
+ uint32_t bpp = rockchip_drm_get_bpp(fb->format);
4957
+ uint32_t actual_w, actual_h, dsp_w, dsp_h;
4958
+ uint32_t dsp_stx, dsp_sty;
4959
+ uint32_t act_info, dsp_info, dsp_st;
4960
+ uint32_t format;
4961
+ uint32_t afbc_format;
4962
+ uint32_t rb_swap;
4963
+ uint32_t uv_swap;
4964
+ uint32_t afbc_half_block_en;
4965
+ uint32_t afbc_tile_num;
4966
+ uint32_t lb_mode;
4967
+ uint32_t stride, uv_stride = 0;
4968
+ uint32_t transform_offset;
4969
+ /* offset of the right window in splice mode */
4970
+ uint32_t splice_pixel_offset = 0;
4971
+ uint32_t splice_yrgb_offset = 0;
4972
+ uint32_t splice_uv_offset = 0;
4973
+ uint32_t afbc_xoffset;
4974
+ uint32_t hsub;
4975
+ dma_addr_t yrgb_mst;
4976
+ dma_addr_t uv_mst;
4977
+
4978
+ struct drm_format_name_buf format_name;
4979
+ bool dither_up;
4980
+ bool tile_4x4_m0 = vpstate->tiled_en == ROCKCHIP_TILED_BLOCK_SIZE_4x4_MODE0 ? true : false;
4981
+
4982
+ actual_w = drm_rect_width(src) >> 16;
4983
+ actual_h = drm_rect_height(src) >> 16;
4984
+
4985
+ if (!actual_w || !actual_h) {
4986
+ vop2_win_disable(win, true);
4987
+ return;
4988
+ }
4989
+
4990
+ dsp_w = drm_rect_width(dst);
4991
+ /*
4992
+ * This win is for the right part of the plane,
4993
+ * we need calculate the fb offset for it.
4994
+ */
4995
+ if (win->splice_mode_right) {
4996
+ splice_pixel_offset = (src->x1 - left_src->x1) >> 16;
4997
+ splice_yrgb_offset = drm_format_info_min_pitch(fb->format, 0, splice_pixel_offset);
4998
+ if (fb->format->is_yuv && fb->format->num_planes > 1) {
4999
+ hsub = fb->format->hsub;
5000
+ splice_uv_offset = drm_format_info_min_pitch(fb->format, 1, splice_pixel_offset / hsub);
5001
+ }
5002
+ }
5003
+
5004
+ if (dst->x1 + dsp_w > adjusted_mode->crtc_hdisplay) {
5005
+ DRM_ERROR("vp%d %s dest->x1[%d] + dsp_w[%d] exceed mode hdisplay[%d]\n",
5006
+ vp->id, win->name, dst->x1, dsp_w, adjusted_mode->crtc_hdisplay);
5007
+ dsp_w = adjusted_mode->crtc_hdisplay - dst->x1;
5008
+ if (dsp_w < 4)
5009
+ dsp_w = 4;
5010
+ actual_w = dsp_w * actual_w / drm_rect_width(dst);
5011
+ }
5012
+ dsp_h = drm_rect_height(dst);
5013
+ if (dst->y1 + dsp_h > adjusted_mode->crtc_vdisplay) {
5014
+ DRM_ERROR("vp%d %s dest->y1[%d] + dsp_h[%d] exceed mode vdisplay[%d]\n",
5015
+ vp->id, win->name, dst->y1, dsp_h, adjusted_mode->crtc_vdisplay);
5016
+ dsp_h = adjusted_mode->crtc_vdisplay - dst->y1;
5017
+ if (dsp_h < 4)
5018
+ dsp_h = 4;
5019
+ actual_h = dsp_h * actual_h / drm_rect_height(dst);
5020
+ }
5021
+
5022
+ /*
5023
+ * Workaround only for rk3568 vop
5024
+ */
5025
+ if (vop2->version == VOP_VERSION_RK3568) {
5026
+ /*
5027
+ * This is workaround solution for IC design:
5028
+ * esmart can't support scale down when actual_w % 16 == 1.
5029
+ */
5030
+ if (!(win->feature & WIN_FEATURE_AFBDC)) {
5031
+ 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);
5033
+ actual_w -= 1;
5034
+ }
5035
+ }
5036
+
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);
5040
+ actual_w = ALIGN_DOWN(actual_w, 4);
5041
+ }
5042
+ }
5043
+
5044
+ act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff);
5045
+ dsp_info = (dsp_h - 1) << 16 | ((dsp_w - 1) & 0xffff);
5046
+ stride = DIV_ROUND_UP(fb->pitches[0], 4);
5047
+ dsp_stx = dst->x1;
5048
+ dsp_sty = dst->y1;
5049
+ dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
5050
+
5051
+ if (vpstate->tiled_en) {
5052
+ if (is_vop3(vop2))
5053
+ format = vop3_convert_tiled_format(fb->format->format, vpstate->tiled_en);
5054
+ else
5055
+ format = vop2_convert_tiled_format(fb->format->format);
5056
+ } else {
5057
+ format = vop2_convert_format(fb->format->format);
5058
+ }
5059
+
5060
+ vop2_setup_csc_mode(vp, vpstate);
5061
+
5062
+ afbc_half_block_en = vop2_afbc_half_block_enable(vpstate);
5063
+
5064
+ vop2_win_enable(win);
5065
+ spin_lock(&vop2->reg_lock);
5066
+ rockchip_drm_dbg(vop2->dev, VOP_DEBUG_PLANE,
5067
+ "vp%d update %s[%dx%d->%dx%d@(%d, %d)] fmt[%.4s%s] addr[%pad] by %s\n",
5068
+ vp->id, win->name, actual_w, actual_h, dsp_w, dsp_h,
5069
+ dsp_stx, dsp_sty,
5070
+ drm_get_format_name(fb->format->format, &format_name),
5071
+ modifier_to_string(fb->modifier), &vpstate->yrgb_mst, current->comm);
5072
+
5073
+ if (vop2->version != VOP_VERSION_RK3568)
5074
+ rk3588_vop2_win_cfg_axi(win);
5075
+
5076
+ if (!win->parent && !vop2_cluster_window(win) && is_vop3(vop2))
5077
+ VOP_WIN_SET(vop2, win, scale_engine_num, win->scale_engine_num);
5078
+
5079
+ if (vpstate->afbc_en) {
5080
+ /* the afbc superblock is 16 x 16 */
5081
+ afbc_format = vop2_convert_afbc_format(fb->format->format);
5082
+ /* Enable color transform for YTR */
5083
+ if (fb->modifier & AFBC_FORMAT_MOD_YTR)
5084
+ afbc_format |= (1 << 4);
5085
+ afbc_tile_num = ALIGN(actual_w, 16) >> 4;
5086
+
5087
+ /* The right win should have a src offset in splice mode */
5088
+ afbc_xoffset = (src->x1 >> 16);
5089
+ /* AFBC pic_vir_width is count by pixel, this is different
5090
+ * with WIN_VIR_STRIDE.
5091
+ */
5092
+ if (!bpp) {
5093
+ WARN(1, "bpp is zero\n");
5094
+ bpp = 1;
5095
+ }
5096
+ stride = (fb->pitches[0] << 3) / bpp;
5097
+ if ((stride & 0x3f) &&
5098
+ (vpstate->xmirror_en || vpstate->rotate_90_en || vpstate->rotate_270_en))
5099
+ DRM_ERROR("vp%d %s stride[%d] must align as 64 pixel when enable xmirror/rotate_90/rotate_270[0x%x]\n",
5100
+ vp->id, win->name, stride, pstate->rotation);
5101
+
5102
+ rb_swap = vop2_afbc_rb_swap(fb->format->format);
5103
+ uv_swap = vop2_afbc_uv_swap(fb->format->format);
5104
+ vpstate->afbc_half_block_en = afbc_half_block_en;
5105
+
5106
+ transform_offset = vop2_afbc_transform_offset(vpstate, splice_pixel_offset);
5107
+ VOP_CLUSTER_SET(vop2, win, afbc_enable, 1);
5108
+ VOP_AFBC_SET(vop2, win, format, afbc_format);
5109
+ VOP_AFBC_SET(vop2, win, rb_swap, rb_swap);
5110
+ VOP_AFBC_SET(vop2, win, uv_swap, uv_swap);
5111
+
5112
+ if (vop2->version == VOP_VERSION_RK3568)
5113
+ VOP_AFBC_SET(vop2, win, auto_gating_en, 0);
5114
+ else
5115
+ VOP_AFBC_SET(vop2, win, auto_gating_en, 1);
5116
+ VOP_AFBC_SET(vop2, win, block_split_en, 0);
5117
+ VOP_AFBC_SET(vop2, win, hdr_ptr, vpstate->yrgb_mst);
5118
+ VOP_AFBC_SET(vop2, win, pic_size, act_info);
5119
+ VOP_AFBC_SET(vop2, win, transform_offset, transform_offset);
5120
+ VOP_AFBC_SET(vop2, win, pic_offset, (afbc_xoffset | src->y1));
5121
+ VOP_AFBC_SET(vop2, win, dsp_offset, (dst->x1 | (dst->y1 << 16)));
5122
+ VOP_AFBC_SET(vop2, win, pic_vir_width, stride);
5123
+ VOP_AFBC_SET(vop2, win, tile_num, afbc_tile_num);
5124
+ VOP_AFBC_SET(vop2, win, xmirror, vpstate->xmirror_en);
5125
+ VOP_AFBC_SET(vop2, win, ymirror, vpstate->ymirror_en);
5126
+ VOP_AFBC_SET(vop2, win, rotate_270, vpstate->rotate_270_en);
5127
+ VOP_AFBC_SET(vop2, win, rotate_90, vpstate->rotate_90_en);
5128
+ } else {
5129
+ VOP_CLUSTER_SET(vop2, win, afbc_enable, 0);
5130
+ transform_offset = vop2_tile_transform_offset(vpstate, vpstate->tiled_en);
5131
+ VOP_AFBC_SET(vop2, win, transform_offset, transform_offset);
5132
+ VOP_WIN_SET(vop2, win, ymirror, vpstate->ymirror_en);
5133
+ VOP_WIN_SET(vop2, win, xmirror, vpstate->xmirror_en);
5134
+ }
5135
+
5136
+ if (vpstate->rotate_90_en || vpstate->rotate_270_en) {
5137
+ act_info = swahw32(act_info);
5138
+ actual_w = drm_rect_height(src) >> 16;
5139
+ actual_h = drm_rect_width(src) >> 16;
5140
+ }
5141
+
5142
+ yrgb_mst = vpstate->yrgb_mst + splice_yrgb_offset;
5143
+ uv_mst = vpstate->uv_mst + splice_uv_offset;
5144
+ /* rk3588 should set half_blocK_en to 1 in line and tile mode */
5145
+ VOP_AFBC_SET(vop2, win, half_block_en, afbc_half_block_en);
5146
+
5147
+ VOP_WIN_SET(vop2, win, format, format);
5148
+ VOP_WIN_SET(vop2, win, yrgb_mst, yrgb_mst);
5149
+
5150
+ rb_swap = vop2_win_rb_swap(fb->format->format);
5151
+ uv_swap = vop2_win_uv_swap(fb->format->format);
5152
+ if (vpstate->tiled_en) {
5153
+ uv_swap = 1;
5154
+ if (vpstate->tiled_en == ROCKCHIP_TILED_BLOCK_SIZE_8x8)
5155
+ stride <<= 3;
5156
+ else
5157
+ stride <<= 2;
5158
+ }
5159
+ VOP_WIN_SET(vop2, win, rb_swap, rb_swap);
5160
+ VOP_WIN_SET(vop2, win, uv_swap, uv_swap);
5161
+
5162
+ if (fb->format->is_yuv) {
5163
+ uv_stride = DIV_ROUND_UP(fb->pitches[1], 4);
5164
+ if (vpstate->tiled_en) {
5165
+ int vsub = fb->format->vsub;
5166
+
5167
+ if (vpstate->tiled_en == ROCKCHIP_TILED_BLOCK_SIZE_8x8)
5168
+ uv_stride = uv_stride * 8 / vsub;
5169
+ else
5170
+ uv_stride = uv_stride * 4 / vsub;
5171
+ VOP_WIN_SET(vop2, win, tile_mode, tile_4x4_m0);
5172
+ }
5173
+
5174
+ VOP_WIN_SET(vop2, win, uv_vir, uv_stride);
5175
+ VOP_WIN_SET(vop2, win, uv_mst, uv_mst);
5176
+ }
5177
+
5178
+ /* tile 4x4 m0 format, y and uv is packed together */
5179
+ if (tile_4x4_m0)
5180
+ VOP_WIN_SET(vop2, win, yrgb_vir, stride + uv_stride);
5181
+ else
5182
+ VOP_WIN_SET(vop2, win, yrgb_vir, stride);
5183
+
5184
+ vop2_setup_scale(vop2, win, actual_w, actual_h, dsp_w, dsp_h, pstate);
5185
+ vop2_plane_setup_color_key(&win->base);
5186
+ VOP_WIN_SET(vop2, win, act_info, act_info);
5187
+ VOP_WIN_SET(vop2, win, dsp_info, dsp_info);
5188
+ VOP_WIN_SET(vop2, win, dsp_st, dsp_st);
5189
+
5190
+ VOP_WIN_SET(vop2, win, y2r_en, vpstate->y2r_en);
5191
+ VOP_WIN_SET(vop2, win, r2y_en, vpstate->r2y_en);
5192
+ VOP_WIN_SET(vop2, win, csc_mode, vpstate->csc_mode);
5193
+
5194
+ if (win->feature & WIN_FEATURE_Y2R_13BIT_DEPTH && !vop2_cluster_window(win))
5195
+ VOP_WIN_SET(vop2, win, csc_13bit_en, !!(vpstate->csc_mode & CSC_BT709L_13BIT));
5196
+
5197
+ dither_up = vop2_win_dither_up(fb->format->format);
5198
+ VOP_WIN_SET(vop2, win, dither_up, dither_up);
5199
+
5200
+ VOP_WIN_SET(vop2, win, enable, 1);
5201
+ if (vop2_cluster_window(win)) {
5202
+ lb_mode = vop2_get_cluster_lb_mode(win, vpstate);
5203
+ VOP_CLUSTER_SET(vop2, win, lb_mode, lb_mode);
5204
+ VOP_CLUSTER_SET(vop2, win, scl_lb_mode, lb_mode == 1 ? 3 : 0);
5205
+ VOP_CLUSTER_SET(vop2, win, enable, 1);
5206
+ VOP_CLUSTER_SET(vop2, win, frm_reset_en, 1);
5207
+ }
5208
+ spin_unlock(&vop2->reg_lock);
5209
+}
5210
+
35925211 static void vop2_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *old_state)
35935212 {
35945213 struct drm_plane_state *pstate = plane->state;
35955214 struct drm_crtc *crtc = pstate->crtc;
35965215 struct vop2_win *win = to_vop2_win(plane);
5216
+ struct vop2_win *splice_win;
35975217 struct vop2_video_port *vp = to_vop2_video_port(crtc);
35985218 struct vop2_plane_state *vpstate = to_vop2_plane_state(pstate);
3599
- struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
36005219 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
3601
- struct vop2 *vop2 = win->vop2;
36025220 struct drm_framebuffer *fb = pstate->fb;
3603
- uint32_t bpp = fb->format->bpp[0];
3604
- uint32_t actual_w, actual_h, dsp_w, dsp_h;
3605
- uint32_t dsp_stx, dsp_sty;
3606
- uint32_t act_info, dsp_info, dsp_st;
3607
- uint32_t format, check_size;
3608
- uint32_t afbc_format;
3609
- uint32_t rb_swap;
3610
- uint32_t uv_swap;
3611
- struct drm_rect *src = &vpstate->src;
3612
- struct drm_rect *dest = &vpstate->dest;
3613
- uint32_t afbc_tile_num;
3614
- uint32_t afbc_half_block_en;
3615
- uint32_t lb_mode;
3616
- uint32_t stride, uv_stride = 0;
3617
- uint32_t transform_offset;
36185221 struct drm_format_name_buf format_name;
3619
- bool dither_up;
3620
- bool tile_4x4_m0 = vpstate->tiled_en == ROCKCHIP_TILED_BLOCK_SIZE_4x4_MODE0 ? true : false;
5222
+ struct vop2 *vop2 = win->vop2;
5223
+ struct drm_rect wsrc;
5224
+ struct drm_rect wdst;
5225
+ /* right part in splice mode */
5226
+ struct drm_rect right_wsrc;
5227
+ struct drm_rect right_wdst;
36215228
36225229 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
5230
+ struct drm_rect *psrc = &vpstate->src;
36235231 bool AFBC_flag = false;
36245232 struct vop_dump_list *planlist;
36255233 unsigned long num_pages;
36265234 struct page **pages;
3627
- struct rockchip_drm_fb *rk_fb;
36285235 struct drm_gem_object *obj;
36295236 struct rockchip_gem_object *rk_obj;
36305237
36315238 num_pages = 0;
36325239 pages = NULL;
3633
- rk_fb = to_rockchip_fb(fb);
3634
- obj = rk_fb->obj[0];
5240
+ obj = fb->obj[0];
36355241 rk_obj = to_rockchip_obj(obj);
36365242 if (rk_obj) {
36375243 num_pages = rk_obj->num_pages;
....@@ -3670,219 +5276,24 @@
36705276 vp->skip_vsync = false;
36715277 }
36725278
3673
- actual_w = drm_rect_width(src) >> 16;
3674
- actual_h = drm_rect_height(src) >> 16;
3675
- dsp_w = drm_rect_width(dest);
3676
- if (dest->x1 + dsp_w > adjusted_mode->crtc_hdisplay) {
3677
- DRM_ERROR("vp%d %s dest->x1[%d] + dsp_w[%d] exceed mode hdisplay[%d]\n",
3678
- vp->id, win->name, dest->x1, dsp_w, adjusted_mode->crtc_hdisplay);
3679
- dsp_w = adjusted_mode->hdisplay - dest->x1;
3680
- if (dsp_w < 4)
3681
- dsp_w = 4;
3682
- actual_w = dsp_w * actual_w / drm_rect_width(dest);
3683
- }
3684
- dsp_h = drm_rect_height(dest);
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) {
3687
- DRM_ERROR("vp%d %s dest->y1[%d] + dsp_h[%d] exceed mode vdisplay[%d]\n",
3688
- vp->id, win->name, dest->y1, dsp_h, adjusted_mode->crtc_vdisplay);
3689
- dsp_h = adjusted_mode->vdisplay - dest->y1;
3690
- if (dsp_h < 4)
3691
- dsp_h = 4;
3692
- actual_h = dsp_h * actual_h / drm_rect_height(dest);
3693
- }
5279
+ if (vcstate->splice_mode) {
5280
+ DRM_DEV_DEBUG(vop2->dev, "vp%d update %s[%dx%d->%dx%d@(%d,%d)] fmt[%.4s%s] addr[%pad]\n",
5281
+ vp->id, win->name, drm_rect_width(&vpstate->src) >> 16,
5282
+ drm_rect_height(&vpstate->src) >> 16,
5283
+ drm_rect_width(&vpstate->dest), drm_rect_height(&vpstate->dest),
5284
+ vpstate->dest.x1, vpstate->dest.y1,
5285
+ drm_get_format_name(fb->format->format, &format_name),
5286
+ modifier_to_string(fb->modifier), &vpstate->yrgb_mst);
36945287
3695
- /*
3696
- * Workaround only for rk3568 vop
3697
- */
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
- }
3708
- }
3709
-
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
- }
3715
- }
3716
-
3717
- act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff);
3718
- dsp_info = (dsp_h - 1) << 16 | ((dsp_w - 1) & 0xffff);
3719
- stride = DIV_ROUND_UP(fb->pitches[0], 4);
3720
- dsp_stx = dest->x1;
3721
- dsp_sty = dest->y1;
3722
- dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
3723
-
3724
- if (vpstate->tiled_en) {
3725
- if (is_vop3(vop2))
3726
- format = vop3_convert_tiled_format(fb->format->format, vpstate->tiled_en);
3727
- else
3728
- format = vop2_convert_tiled_format(fb->format->format);
5288
+ vop2_calc_drm_rect_for_splice(vpstate, &wsrc, &wdst, &right_wsrc, &right_wdst);
5289
+ splice_win = win->splice_win;
5290
+ vop2_win_atomic_update(splice_win, &right_wsrc, &right_wdst, pstate);
37295291 } else {
3730
- format = vop2_convert_format(fb->format->format);
5292
+ memcpy(&wsrc, &vpstate->src, sizeof(struct drm_rect));
5293
+ memcpy(&wdst, &vpstate->dest, sizeof(struct drm_rect));
37315294 }
37325295
3733
- vop2_setup_csc_mode(vp, vpstate);
3734
- afbc_half_block_en = vop2_afbc_half_block_enable(vpstate);
3735
-
3736
- spin_lock(&vop2->reg_lock);
3737
- DRM_DEV_DEBUG(vop2->dev, "vp%d update %s[%dx%d->%dx%d@%dx%d] fmt[%.4s%s] addr[%pad] zpos[%d]\n",
3738
- vp->id, win->name, actual_w, actual_h, dsp_w, dsp_h,
3739
- dsp_stx, dsp_sty,
3740
- drm_get_format_name(fb->format->format, &format_name),
3741
- modifier_to_string(fb->modifier), &vpstate->yrgb_mst, vpstate->zpos);
3742
-
3743
- if (vop2->version != VOP_VERSION_RK3568)
3744
- rk3588_vop2_win_cfg_axi(win);
3745
-
3746
- if (is_vop3(vop2) && !vop2_cluster_window(win) && !win->parent)
3747
- VOP_WIN_SET(vop2, win, scale_engine_num, win->scale_engine_num);
3748
-
3749
- if (vpstate->afbc_en) {
3750
- /* the afbc superblock is 16 x 16 */
3751
- afbc_format = vop2_convert_afbc_format(fb->format->format);
3752
- /* Enable color transform for YTR */
3753
- if (fb->modifier & AFBC_FORMAT_MOD_YTR)
3754
- afbc_format |= (1 << 4);
3755
- afbc_tile_num = ALIGN(actual_w, 16) >> 4;
3756
- /* AFBC pic_vir_width is count by pixel, this is different
3757
- * with WIN_VIR_STRIDE.
3758
- */
3759
- if (!bpp) {
3760
- WARN(1, "bpp is zero\n");
3761
- bpp = 1;
3762
- }
3763
- stride = (fb->pitches[0] << 3) / bpp;
3764
- if ((stride & 0x3f) &&
3765
- (vpstate->xmirror_en || vpstate->rotate_90_en || vpstate->rotate_270_en))
3766
- DRM_ERROR("vp%d %s stride[%d] must align as 64 pixel when enable xmirror/rotate_90/rotate_270[0x%x]\n",
3767
- vp->id, win->name, stride, pstate->rotation);
3768
-
3769
- rb_swap = vop2_afbc_rb_swap(fb->format->format);
3770
- uv_swap = vop2_afbc_uv_swap(fb->format->format);
3771
- /*
3772
- * This is a workaround for crazy IC design, Cluster
3773
- * and Esmart/Smart use different format configuration map:
3774
- * YUV420_10BIT: 0x10 for Cluster, 0x14 for Esmart/Smart.
3775
- *
3776
- * This is one thing we can make the convert simple:
3777
- * AFBCD decode all the YUV data to YUV444. So we just
3778
- * set all the yuv 10 bit to YUV444_10.
3779
- */
3780
- if (fb->format->is_yuv && (bpp == 10) && (vop2->version == VOP_VERSION_RK3568))
3781
- format = VOP2_CLUSTER_YUV444_10;
3782
-
3783
- vpstate->afbc_half_block_en = afbc_half_block_en;
3784
- transform_offset = vop2_afbc_transform_offset(vpstate);
3785
- VOP_CLUSTER_SET(vop2, win, afbc_enable, 1);
3786
- VOP_AFBC_SET(vop2, win, format, afbc_format);
3787
- VOP_AFBC_SET(vop2, win, rb_swap, rb_swap);
3788
- VOP_AFBC_SET(vop2, win, uv_swap, uv_swap);
3789
- if (vop2->version == VOP_VERSION_RK3568)
3790
- VOP_AFBC_SET(vop2, win, auto_gating_en, 0);
3791
- else
3792
- VOP_AFBC_SET(vop2, win, auto_gating_en, 1);
3793
- VOP_AFBC_SET(vop2, win, block_split_en, 0);
3794
- VOP_AFBC_SET(vop2, win, hdr_ptr, vpstate->yrgb_mst);
3795
- VOP_AFBC_SET(vop2, win, pic_size, act_info);
3796
- VOP_AFBC_SET(vop2, win, transform_offset, transform_offset);
3797
- VOP_AFBC_SET(vop2, win, pic_offset, ((src->x1 >> 16) | src->y1));
3798
- VOP_AFBC_SET(vop2, win, dsp_offset, (dest->x1 | (dest->y1 << 16)));
3799
- VOP_AFBC_SET(vop2, win, pic_vir_width, stride);
3800
- VOP_AFBC_SET(vop2, win, tile_num, afbc_tile_num);
3801
- VOP_AFBC_SET(vop2, win, xmirror, vpstate->xmirror_en);
3802
- VOP_AFBC_SET(vop2, win, ymirror, vpstate->ymirror_en);
3803
- VOP_AFBC_SET(vop2, win, rotate_270, vpstate->rotate_270_en);
3804
- VOP_AFBC_SET(vop2, win, rotate_90, vpstate->rotate_90_en);
3805
- } else {
3806
- VOP_AFBC_SET(vop2, win, enable, 0);
3807
- VOP_CLUSTER_SET(vop2, win, afbc_enable, 0);
3808
- transform_offset = vop2_tile_transform_offset(vpstate, vpstate->tiled_en);
3809
- VOP_AFBC_SET(vop2, win, transform_offset, transform_offset);
3810
- VOP_WIN_SET(vop2, win, ymirror, vpstate->ymirror_en);
3811
- VOP_WIN_SET(vop2, win, xmirror, vpstate->xmirror_en);
3812
- }
3813
-
3814
- if (vpstate->rotate_90_en || vpstate->rotate_270_en) {
3815
- act_info = swahw32(act_info);
3816
- actual_w = drm_rect_height(src) >> 16;
3817
- actual_h = drm_rect_width(src) >> 16;
3818
- }
3819
- VOP_AFBC_SET(vop2, win, half_block_en, afbc_half_block_en);
3820
-
3821
- VOP_WIN_SET(vop2, win, format, format);
3822
- VOP_WIN_SET(vop2, win, yrgb_mst, vpstate->yrgb_mst);
3823
-
3824
- rb_swap = vop2_win_rb_swap(fb->format->format);
3825
- uv_swap = vop2_win_uv_swap(fb->format->format);
3826
- if (vpstate->tiled_en) {
3827
- uv_swap = 1;
3828
- if (vpstate->tiled_en == ROCKCHIP_TILED_BLOCK_SIZE_8x8)
3829
- stride <<= 3;
3830
- else
3831
- stride <<= 2;
3832
- }
3833
- VOP_WIN_SET(vop2, win, rb_swap, rb_swap);
3834
- VOP_WIN_SET(vop2, win, uv_swap, uv_swap);
3835
-
3836
- if (fb->format->is_yuv) {
3837
- uv_stride = DIV_ROUND_UP(fb->pitches[1], 4);
3838
- if (vpstate->tiled_en) {
3839
- int vsub = drm_format_vert_chroma_subsampling(fb->format->format);
3840
-
3841
- if (vpstate->tiled_en == ROCKCHIP_TILED_BLOCK_SIZE_8x8)
3842
- uv_stride = uv_stride * 8 / vsub;
3843
- else
3844
- uv_stride = uv_stride * 4 / vsub;
3845
- VOP_WIN_SET(vop2, win, tile_mode, tile_4x4_m0);
3846
- }
3847
-
3848
- VOP_WIN_SET(vop2, win, uv_vir, uv_stride);
3849
- VOP_WIN_SET(vop2, win, uv_mst, vpstate->uv_mst);
3850
- }
3851
-
3852
- /* tile 4x4 m0 format, y and uv is packed together */
3853
- if (tile_4x4_m0)
3854
- VOP_WIN_SET(vop2, win, yrgb_vir, stride + uv_stride);
3855
- else
3856
- VOP_WIN_SET(vop2, win, yrgb_vir, stride);
3857
-
3858
- vop2_setup_scale(vop2, win, actual_w, actual_h, dsp_w, dsp_h, pstate);
3859
- vop2_plane_setup_color_key(plane);
3860
- VOP_WIN_SET(vop2, win, act_info, act_info);
3861
- VOP_WIN_SET(vop2, win, dsp_info, dsp_info);
3862
- VOP_WIN_SET(vop2, win, dsp_st, dsp_st);
3863
-
3864
- VOP_WIN_SET(vop2, win, y2r_en, vpstate->y2r_en);
3865
- VOP_WIN_SET(vop2, win, r2y_en, vpstate->r2y_en);
3866
- VOP_WIN_SET(vop2, win, csc_mode, vpstate->csc_mode);
3867
-
3868
- if (win->feature & WIN_FEATURE_Y2R_13BIT_DEPTH && !vop2_cluster_window(win))
3869
- VOP_WIN_SET(vop2, win, csc_13bit_en, !!(vpstate->csc_mode & CSC_BT709L_13BIT));
3870
-
3871
- dither_up = vop2_win_dither_up(fb->format->format);
3872
- VOP_WIN_SET(vop2, win, dither_up, dither_up);
3873
-
3874
- VOP_WIN_SET(vop2, win, enable, 1);
3875
- if (vop2_cluster_window(win)) {
3876
- lb_mode = vop2_get_cluster_lb_mode(win, vpstate);
3877
- VOP_CLUSTER_SET(vop2, win, lb_mode, lb_mode);
3878
- VOP_CLUSTER_SET(vop2, win, scl_lb_mode, lb_mode == 1 ? 3 : 0);
3879
- VOP_CLUSTER_SET(vop2, win, enable, 1);
3880
- VOP_CLUSTER_SET(vop2, win, frm_reset_en, 1);
3881
- }
3882
- if (vcstate->output_if & VOP_OUTPUT_IF_BT1120 ||
3883
- vcstate->output_if & VOP_OUTPUT_IF_BT656)
3884
- VOP_WIN_SET(vop2, win, yuv_clip, 1);
3885
- spin_unlock(&vop2->reg_lock);
5296
+ vop2_win_atomic_update(win, &wsrc, &wdst, pstate);
38865297
38875298 vop2->is_iommu_needed = true;
38885299 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
....@@ -3899,18 +5310,18 @@
38995310 planlist->dump_info.pages = pages;
39005311 planlist->dump_info.offset = vpstate->offset;
39015312 planlist->dump_info.pitches = fb->pitches[0];
3902
- planlist->dump_info.height = actual_h;
3903
- planlist->dump_info.pixel_format = fb->format->format;
3904
- list_add_tail(&planlist->entry, &crtc->vop_dump_list_head);
5313
+ planlist->dump_info.height = drm_rect_height(psrc) >> 16;
5314
+ planlist->dump_info.format = fb->format;
5315
+ list_add_tail(&planlist->entry, &vp->rockchip_crtc.vop_dump_list_head);
39055316 vpstate->planlist = planlist;
39065317 } else {
39075318 DRM_ERROR("can't alloc a node of planlist %p\n", planlist);
39085319 return;
39095320 }
3910
- if (crtc->vop_dump_status == DUMP_KEEP ||
3911
- crtc->vop_dump_times > 0) {
3912
- vop_plane_dump(&planlist->dump_info, crtc->frame_count);
3913
- crtc->vop_dump_times--;
5321
+ if (vp->rockchip_crtc.vop_dump_status == DUMP_KEEP ||
5322
+ vp->rockchip_crtc.vop_dump_times > 0) {
5323
+ rockchip_drm_dump_plane_buffer(&planlist->dump_info, vp->rockchip_crtc.frame_count);
5324
+ vp->rockchip_crtc.vop_dump_times--;
39145325 }
39155326 #endif
39165327 }
....@@ -4056,11 +5467,8 @@
40565467 if (!vpstate)
40575468 return;
40585469
4059
- plane->state = &vpstate->base;
4060
- plane->state->plane = plane;
4061
- plane->state->zpos = win->zpos;
4062
- plane->state->alpha = DRM_BLEND_ALPHA_OPAQUE;
4063
- plane->state->rotation = DRM_MODE_ROTATE_0;
5470
+ __drm_atomic_helper_plane_reset(plane, &vpstate->base);
5471
+ vpstate->base.zpos = win->zpos;
40645472 }
40655473
40665474 static struct drm_plane_state *vop2_atomic_plane_duplicate_state(struct drm_plane *plane)
....@@ -4248,6 +5656,192 @@
42485656 spin_unlock_irqrestore(&drm->event_lock, flags);
42495657 }
42505658
5659
+static bool vop2_crtc_line_flag_irq_is_enabled(struct vop2_video_port *vp)
5660
+{
5661
+ struct vop2 *vop2 = vp->vop2;
5662
+ const struct vop2_data *vop2_data = vop2->data;
5663
+ const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
5664
+ const struct vop_intr *intr = vp_data->intr;
5665
+ uint32_t line_flag_irq;
5666
+ unsigned long flags;
5667
+
5668
+ spin_lock_irqsave(&vop2->irq_lock, flags);
5669
+ line_flag_irq = VOP_INTR_GET_TYPE(vop2, intr, enable, LINE_FLAG_INTR);
5670
+ spin_unlock_irqrestore(&vop2->irq_lock, flags);
5671
+
5672
+ return !!line_flag_irq;
5673
+}
5674
+
5675
+static void vop2_crtc_line_flag_irq_enable(struct vop2_video_port *vp)
5676
+{
5677
+ struct vop2 *vop2 = vp->vop2;
5678
+ const struct vop2_data *vop2_data = vop2->data;
5679
+ const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
5680
+ const struct vop_intr *intr = vp_data->intr;
5681
+ unsigned long flags;
5682
+
5683
+ if (!vop2->is_enabled)
5684
+ return;
5685
+
5686
+ spin_lock_irqsave(&vop2->irq_lock, flags);
5687
+ VOP_INTR_SET_TYPE(vop2, intr, clear, LINE_FLAG_INTR, 1);
5688
+ VOP_INTR_SET_TYPE(vop2, intr, enable, LINE_FLAG_INTR, 1);
5689
+ spin_unlock_irqrestore(&vop2->irq_lock, flags);
5690
+}
5691
+
5692
+static void vop2_crtc_line_flag_irq_disable(struct vop2_video_port *vp)
5693
+{
5694
+ struct vop2 *vop2 = vp->vop2;
5695
+ const struct vop2_data *vop2_data = vop2->data;
5696
+ const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
5697
+ const struct vop_intr *intr = vp_data->intr;
5698
+ unsigned long flags;
5699
+
5700
+ if (!vop2->is_enabled)
5701
+ return;
5702
+
5703
+ spin_lock_irqsave(&vop2->irq_lock, flags);
5704
+ VOP_INTR_SET_TYPE(vop2, intr, enable, LINE_FLAG_INTR, 0);
5705
+ spin_unlock_irqrestore(&vop2->irq_lock, flags);
5706
+}
5707
+
5708
+static void vop3_mcu_mode_setup(struct drm_crtc *crtc)
5709
+{
5710
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
5711
+ struct vop2 *vop2 = vp->vop2;
5712
+
5713
+ VOP_MODULE_SET(vop2, vp, mcu_type, 1);
5714
+ VOP_MODULE_SET(vop2, vp, mcu_hold_mode, 1);
5715
+ VOP_MODULE_SET(vop2, vp, mcu_pix_total, vp->mcu_timing.mcu_pix_total);
5716
+ VOP_MODULE_SET(vop2, vp, mcu_cs_pst, vp->mcu_timing.mcu_cs_pst);
5717
+ VOP_MODULE_SET(vop2, vp, mcu_cs_pend, vp->mcu_timing.mcu_cs_pend);
5718
+ VOP_MODULE_SET(vop2, vp, mcu_rw_pst, vp->mcu_timing.mcu_rw_pst);
5719
+ VOP_MODULE_SET(vop2, vp, mcu_rw_pend, vp->mcu_timing.mcu_rw_pend);
5720
+}
5721
+
5722
+static void vop3_mcu_bypass_mode_setup(struct drm_crtc *crtc)
5723
+{
5724
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
5725
+ struct vop2 *vop2 = vp->vop2;
5726
+
5727
+ VOP_MODULE_SET(vop2, vp, mcu_type, 1);
5728
+ VOP_MODULE_SET(vop2, vp, mcu_hold_mode, 1);
5729
+ VOP_MODULE_SET(vop2, vp, mcu_pix_total, 53);
5730
+ VOP_MODULE_SET(vop2, vp, mcu_cs_pst, 6);
5731
+ VOP_MODULE_SET(vop2, vp, mcu_cs_pend, 48);
5732
+ VOP_MODULE_SET(vop2, vp, mcu_rw_pst, 12);
5733
+ VOP_MODULE_SET(vop2, vp, mcu_rw_pend, 30);
5734
+}
5735
+
5736
+static u32 vop3_mode_done(struct vop2_video_port *vp)
5737
+{
5738
+ return VOP_MODULE_GET(vp->vop2, vp, out_mode);
5739
+}
5740
+
5741
+static void vop3_set_out_mode(struct drm_crtc *crtc, u32 out_mode)
5742
+{
5743
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
5744
+ struct vop2 *vop2 = vp->vop2;
5745
+ int ret;
5746
+ u32 val;
5747
+
5748
+ VOP_MODULE_SET(vop2, vp, out_mode, out_mode);
5749
+ vop2_cfg_done(crtc);
5750
+ ret = readx_poll_timeout(vop3_mode_done, vp, val, val == out_mode,
5751
+ 1000, 500 * 1000);
5752
+ if (ret)
5753
+ dev_err(vop2->dev, "wait mode 0x%x timeout\n", out_mode);
5754
+}
5755
+
5756
+static void vop3_crtc_send_mcu_cmd(struct drm_crtc *crtc, u32 type, u32 value)
5757
+{
5758
+ struct drm_crtc_state *crtc_state;
5759
+ struct drm_display_mode *adjusted_mode;
5760
+ struct vop2_video_port *vp;
5761
+ struct vop2 *vop2;
5762
+
5763
+ if (!crtc)
5764
+ return;
5765
+
5766
+ crtc_state = crtc->state;
5767
+ adjusted_mode = &crtc_state->adjusted_mode;
5768
+ vp = to_vop2_video_port(crtc);
5769
+ vop2 = vp->vop2;
5770
+
5771
+ /*
5772
+ * 1.set mcu bypass mode timing.
5773
+ * 2.set dclk rate to 150M.
5774
+ */
5775
+ if ((type == MCU_SETBYPASS) && value) {
5776
+ vop3_mcu_bypass_mode_setup(crtc);
5777
+ clk_set_rate(vp->dclk, 150000000);
5778
+ }
5779
+
5780
+ mutex_lock(&vop2->vop2_lock);
5781
+ if (vop2 && vop2->is_enabled) {
5782
+ switch (type) {
5783
+ case MCU_WRCMD:
5784
+ VOP_MODULE_SET(vop2, vp, mcu_rs, 0);
5785
+ VOP_MODULE_SET(vop2, vp, mcu_rw_bypass_port, value);
5786
+ VOP_MODULE_SET(vop2, vp, mcu_rs, 1);
5787
+ break;
5788
+ case MCU_WRDATA:
5789
+ VOP_MODULE_SET(vop2, vp, mcu_rs, 1);
5790
+ VOP_MODULE_SET(vop2, vp, mcu_rw_bypass_port, value);
5791
+ break;
5792
+ case MCU_SETBYPASS:
5793
+ VOP_MODULE_SET(vop2, vp, mcu_bypass, value ? 1 : 0);
5794
+ break;
5795
+ default:
5796
+ break;
5797
+ }
5798
+ }
5799
+ mutex_unlock(&vop2->vop2_lock);
5800
+
5801
+ /*
5802
+ * 1.restore mcu data mode timing.
5803
+ * 2.restore dclk rate to crtc_clock.
5804
+ */
5805
+ if ((type == MCU_SETBYPASS) && !value) {
5806
+ vop3_mcu_mode_setup(crtc);
5807
+ clk_set_rate(vp->dclk, adjusted_mode->crtc_clock * 1000);
5808
+ }
5809
+}
5810
+
5811
+static int vop2_crtc_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout)
5812
+{
5813
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
5814
+ struct vop2 *vop2 = vp->vop2;
5815
+ unsigned long jiffies_left;
5816
+ int ret = 0;
5817
+
5818
+ if (!vop2->is_enabled)
5819
+ return -ENODEV;
5820
+
5821
+ mutex_lock(&vop2->vop2_lock);
5822
+
5823
+ if (vop2_crtc_line_flag_irq_is_enabled(vp)) {
5824
+ ret = -EBUSY;
5825
+ goto out;
5826
+ }
5827
+
5828
+ reinit_completion(&vp->line_flag_completion);
5829
+ vop2_crtc_line_flag_irq_enable(vp);
5830
+ jiffies_left = wait_for_completion_timeout(&vp->line_flag_completion,
5831
+ msecs_to_jiffies(mstimeout));
5832
+ vop2_crtc_line_flag_irq_disable(vp);
5833
+
5834
+ if (jiffies_left == 0) {
5835
+ DRM_DEV_ERROR(vop2->dev, "timeout waiting for lineflag IRQ\n");
5836
+ ret = -ETIMEDOUT;
5837
+ goto out;
5838
+ }
5839
+
5840
+out:
5841
+ mutex_unlock(&vop2->vop2_lock);
5842
+ return ret;
5843
+}
5844
+
42515845 static int vop2_crtc_enable_line_flag_event(struct drm_crtc *crtc, uint32_t line)
42525846 {
42535847 struct vop2_video_port *vp = to_vop2_video_port(crtc);
....@@ -4291,20 +5885,69 @@
42915885 spin_unlock_irqrestore(&vop2->irq_lock, flags);
42925886 }
42935887
4294
-
42955888 static int vop2_crtc_loader_protect(struct drm_crtc *crtc, bool on)
42965889 {
42975890 struct vop2_video_port *vp = to_vop2_video_port(crtc);
5891
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
42985892 struct vop2 *vop2 = vp->vop2;
42995893 struct rockchip_drm_private *private = crtc->dev->dev_private;
5894
+ const struct vop2_video_port_data *vp_data = &vop2->data->vp[vp->id];
5895
+ struct vop2_video_port *splice_vp = &vop2->vps[vp_data->splice_vp_id];
5896
+ struct drm_crtc_state *crtc_state;
5897
+ struct drm_display_mode *mode;
5898
+ struct vop2_win *win, *splice_win;
5899
+ struct vop2_extend_pll *ext_pll;
5900
+ struct clk *parent_clk;
5901
+ const char *clk_name;
43005902
43015903 if (on == vp->loader_protect)
43025904 return 0;
43035905
43045906 if (on) {
5907
+ vp->loader_protect = true;
43055908 vop2->active_vp_mask |= BIT(vp->id);
43065909 vop2_set_system_status(vop2);
43075910 vop2_initial(crtc);
5911
+ if (crtc->primary) {
5912
+ win = to_vop2_win(crtc->primary);
5913
+ if (VOP_WIN_GET(vop2, win, enable)) {
5914
+ if (win->pd) {
5915
+ win->pd->ref_count++;
5916
+ win->pd->vp_mask |= BIT(vp->id);
5917
+ }
5918
+
5919
+ crtc_state = drm_atomic_get_crtc_state(crtc->state->state, crtc);
5920
+ mode = &crtc_state->adjusted_mode;
5921
+ if (mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) {
5922
+ vcstate->splice_mode = true;
5923
+ splice_win = vop2_find_win_by_phys_id(vop2,
5924
+ win->splice_win_id);
5925
+ splice_win->splice_mode_right = true;
5926
+ splice_win->left_win = win;
5927
+ win->splice_win = splice_win;
5928
+ splice_vp->win_mask |= BIT(splice_win->phys_id);
5929
+ splice_win->vp_mask = BIT(splice_vp->id);
5930
+ vop2->active_vp_mask |= BIT(splice_vp->id);
5931
+
5932
+ if (splice_win->pd &&
5933
+ VOP_WIN_GET(vop2, splice_win, enable)) {
5934
+ splice_win->pd->ref_count++;
5935
+ splice_win->pd->vp_mask |= BIT(splice_vp->id);
5936
+ }
5937
+ }
5938
+ }
5939
+ }
5940
+ parent_clk = clk_get_parent(vp->dclk);
5941
+ clk_name = __clk_get_name(parent_clk);
5942
+ if (!strcmp(clk_name, "clk_hdmiphy_pixel0")) {
5943
+ ext_pll = vop2_extend_clk_find_by_name(vop2, "hdmi0_phy_pll");
5944
+ if (ext_pll)
5945
+ ext_pll->vp_mask |= BIT(vp->id);
5946
+ } else if (!strcmp(clk_name, "clk_hdmiphy_pixel1")) {
5947
+ ext_pll = vop2_extend_clk_find_by_name(vop2, "hdmi1_phy_pll");
5948
+ if (ext_pll)
5949
+ ext_pll->vp_mask |= BIT(vp->id);
5950
+ }
43085951 drm_crtc_vblank_on(crtc);
43095952 if (private->cubic_lut[vp->id].enable) {
43105953 dma_addr_t cubic_lut_mst;
....@@ -4313,10 +5956,8 @@
43135956 cubic_lut_mst = cubic_lut->offset + private->cubic_lut_dma_addr;
43145957 VOP_MODULE_SET(vop2, vp, cubic_lut_mst, cubic_lut_mst);
43155958 }
4316
- vp->loader_protect = true;
43175959 } else {
43185960 vop2_crtc_atomic_disable(crtc, NULL);
4319
- vp->loader_protect = false;
43205961 }
43215962
43225963 return 0;
....@@ -4338,6 +5979,10 @@
43385979 struct drm_rect *src, *dest;
43395980 struct drm_framebuffer *fb = pstate->fb;
43405981 struct drm_format_name_buf format_name;
5982
+ struct drm_gem_object *obj;
5983
+ struct rockchip_gem_object *rk_obj;
5984
+ dma_addr_t fb_addr;
5985
+
43415986 int i;
43425987
43435988 DEBUG_PRINT(" %s: %s\n", win->name, pstate->crtc ? "ACTIVE" : "DISABLED");
....@@ -4368,8 +6013,10 @@
43686013 DEBUG_PRINT("\tdst: pos[%d, %d] rect[%d x %d]\n", dest->x1, dest->y1,
43696014 drm_rect_width(dest), drm_rect_height(dest));
43706015
4371
- for (i = 0; i < drm_format_num_planes(fb->format->format); i++) {
4372
- dma_addr_t fb_addr = rockchip_fb_get_dma_addr(fb, i);
6016
+ for (i = 0; i < fb->format->num_planes; i++) {
6017
+ obj = fb->obj[0];
6018
+ rk_obj = to_rockchip_obj(obj);
6019
+ fb_addr = rk_obj->dma_addr + fb->offsets[0];
43736020
43746021 DEBUG_PRINT("\tbuf[%d]: addr: %pad pitch: %d offset: %d\n",
43756022 i, &fb_addr, fb->pitches[i], fb->offsets[i]);
....@@ -4449,8 +6096,8 @@
44496096
44506097 /* only need to dump once at first active crtc for vop2 */
44516098 for (i = 0; i < vop2_data->nr_vps; i++) {
4452
- if (vop2->vps[i].crtc.state->active) {
4453
- first_active_crtc = &vop2->vps[i].crtc;
6099
+ if (vop2->vps[i].rockchip_crtc.crtc.state->active) {
6100
+ first_active_crtc = &vop2->vps[i].rockchip_crtc.crtc;
44546101 break;
44556102 }
44566103 }
....@@ -4492,8 +6139,8 @@
44926139
44936140 /* only need to dump once at first active crtc for vop2 */
44946141 for (i = 0; i < vop2_data->nr_vps; i++) {
4495
- if (vop2->vps[i].crtc.state->active) {
4496
- first_active_crtc = &vop2->vps[i].crtc;
6142
+ if (vop2->vps[i].rockchip_crtc.crtc.state->active) {
6143
+ first_active_crtc = &vop2->vps[i].rockchip_crtc.crtc;
44976144 break;
44986145 }
44996146 }
....@@ -4529,7 +6176,7 @@
45296176 struct vop2_video_port *vp = &vop2->vps[i];
45306177
45316178 if (!vp->lut || !vp->gamma_lut_active ||
4532
- !vop2->lut_regs || !vp->crtc.state->enable) {
6179
+ !vop2->lut_regs || !vp->rockchip_crtc.crtc.state->enable) {
45336180 DEBUG_PRINT("Video port%d gamma disabled\n", vp->id);
45346181 continue;
45356182 }
....@@ -4556,7 +6203,7 @@
45566203 struct vop2_video_port *vp = &vop2->vps[i];
45576204
45586205 if ((!vp->cubic_lut_gem_obj && !private->cubic_lut[vp->id].enable) ||
4559
- !vp->cubic_lut || !vp->crtc.state->enable) {
6206
+ !vp->cubic_lut || !vp->rockchip_crtc.crtc.state->enable) {
45606207 DEBUG_PRINT("Video port%d cubic lut disabled\n", vp->id);
45616208 continue;
45626209 }
....@@ -4599,24 +6246,17 @@
45996246 goto remove;
46006247 }
46016248 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
4602
- drm_debugfs_vop_add(crtc, vop2->debugfs);
6249
+ rockchip_drm_add_dump_buffer(crtc, vop2->debugfs);
6250
+ rockchip_drm_debugfs_add_color_bar(crtc, vop2->debugfs);
46036251 #endif
46046252 for (i = 0; i < ARRAY_SIZE(vop2_debugfs_files); i++)
46056253 vop2->debugfs_files[i].data = vop2;
46066254
4607
- ret = drm_debugfs_create_files(vop2->debugfs_files,
4608
- ARRAY_SIZE(vop2_debugfs_files),
4609
- vop2->debugfs,
4610
- minor);
4611
- if (ret) {
4612
- dev_err(vop2->dev, "could not install rockchip_debugfs_list\n");
4613
- goto free;
4614
- }
4615
-
6255
+ drm_debugfs_create_files(vop2->debugfs_files,
6256
+ ARRAY_SIZE(vop2_debugfs_files),
6257
+ vop2->debugfs,
6258
+ minor);
46166259 return 0;
4617
-free:
4618
- kfree(vop2->debugfs_files);
4619
- vop2->debugfs_files = NULL;
46206260 remove:
46216261 debugfs_remove(vop2->debugfs);
46226262 vop2->debugfs = NULL;
....@@ -4624,29 +6264,59 @@
46246264 }
46256265
46266266 static enum drm_mode_status
4627
-vop2_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode,
4628
- int output_type)
6267
+vop2_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
46296268 {
6269
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
46306270 struct vop2_video_port *vp = to_vop2_video_port(crtc);
46316271 struct vop2 *vop2 = vp->vop2;
46326272 const struct vop2_data *vop2_data = vop2->data;
46336273 const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
46346274 int request_clock = mode->clock;
46356275 int clock;
6276
+ unsigned long aclk_rate;
6277
+ uint8_t active_vp_mask = vop2->active_vp_mask;
6278
+
6279
+ /*
6280
+ * For RK3588, VP0 and VP1 will be both used in splice mode. All display
6281
+ * modes of the right VP should be set as invalid when vop2 is working in
6282
+ * splice mode.
6283
+ */
6284
+ if (vp->splice_mode_right)
6285
+ return MODE_BAD;
6286
+
6287
+ if ((active_vp_mask & BIT(ROCKCHIP_VOP_VP1)) && !vcstate->splice_mode &&
6288
+ mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) {
6289
+ DRM_DEV_DEBUG(vop2->dev, "can not support resolution %dx%d, vp1 is busy\n",
6290
+ mode->hdisplay, mode->vdisplay);
6291
+ return MODE_BAD;
6292
+ }
46366293
46376294 if (mode->hdisplay > vp_data->max_output.width)
46386295 return MODE_BAD_HVALUE;
46396296
4640
- if (mode->flags & DRM_MODE_FLAG_DBLCLK)
6297
+ if (mode->flags & DRM_MODE_FLAG_DBLCLK || vcstate->output_if & VOP_OUTPUT_IF_BT656)
46416298 request_clock *= 2;
46426299
4643
- clock = clk_round_rate(vp->dclk, request_clock * 1000) / 1000;
6300
+ aclk_rate = clk_get_rate(vop2->aclk) / 1000;
6301
+
6302
+ if (request_clock > VOP2_MAX_DCLK_RATE && aclk_rate <= VOP2_COMMON_ACLK_RATE)
6303
+ return MODE_BAD;
6304
+
6305
+ if ((request_clock <= VOP2_MAX_DCLK_RATE) &&
6306
+ (vop2_extend_clk_find_by_name(vop2, "hdmi0_phy_pll") ||
6307
+ vop2_extend_clk_find_by_name(vop2, "hdmi1_phy_pll"))) {
6308
+ clock = request_clock;
6309
+ } else {
6310
+ if (request_clock > VOP2_MAX_DCLK_RATE)
6311
+ request_clock = request_clock >> 2;
6312
+ clock = clk_round_rate(vp->dclk, request_clock * 1000) / 1000;
6313
+ }
46446314
46456315 /*
46466316 * Hdmi or DisplayPort request a Accurate clock.
46476317 */
4648
- if (output_type == DRM_MODE_CONNECTOR_HDMIA ||
4649
- output_type == DRM_MODE_CONNECTOR_DisplayPort)
6318
+ if (vcstate->output_type == DRM_MODE_CONNECTOR_HDMIA ||
6319
+ vcstate->output_type == DRM_MODE_CONNECTOR_DisplayPort)
46506320 if (clock != request_clock)
46516321 return MODE_CLOCK_RANGE;
46526322
....@@ -4673,7 +6343,7 @@
46736343 struct drm_framebuffer *fb = pstate->fb;
46746344 struct drm_rect *dst = &vpstate->dest;
46756345 struct drm_rect *src = &vpstate->src;
4676
- int bpp = fb->format->bpp[0];
6346
+ int bpp = rockchip_drm_get_bpp(fb->format);
46776347 int src_width = drm_rect_width(src) >> 16;
46786348 int src_height = drm_rect_height(src) >> 16;
46796349 int dst_width = drm_rect_width(dst);
....@@ -4721,10 +6391,9 @@
47216391
47226392 static size_t vop2_crtc_bandwidth(struct drm_crtc *crtc,
47236393 struct drm_crtc_state *crtc_state,
4724
- size_t *frame_bw_mbyte,
4725
- unsigned int *plane_num_total)
6394
+ struct dmcfreq_vop_info *vop_bw_info)
47266395 {
4727
- struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
6396
+ struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
47286397 uint16_t htotal = adjusted_mode->crtc_htotal;
47296398 uint16_t vdisplay = adjusted_mode->crtc_vdisplay;
47306399 int clock = adjusted_mode->crtc_clock;
....@@ -4733,44 +6402,49 @@
47336402 struct drm_plane_state *pstate;
47346403 struct vop2_bandwidth *pbandwidth;
47356404 struct drm_plane *plane;
4736
- uint64_t line_bandwidth;
6405
+ u64 line_bw_mbyte = 0;
47376406 int8_t cnt = 0, plane_num = 0;
6407
+ int i = 0;
47386408 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
47396409 struct vop_dump_list *pos, *n;
6410
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
47406411 #endif
47416412
47426413 if (!htotal || !vdisplay)
47436414 return 0;
47446415
47456416 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
4746
- if (!crtc->vop_dump_list_init_flag) {
4747
- INIT_LIST_HEAD(&crtc->vop_dump_list_head);
4748
- crtc->vop_dump_list_init_flag = true;
6417
+ if (!vp->rockchip_crtc.vop_dump_list_init_flag) {
6418
+ INIT_LIST_HEAD(&vp->rockchip_crtc.vop_dump_list_head);
6419
+ vp->rockchip_crtc.vop_dump_list_init_flag = true;
47496420 }
4750
- list_for_each_entry_safe(pos, n, &crtc->vop_dump_list_head, entry) {
6421
+ list_for_each_entry_safe(pos, n, &vp->rockchip_crtc.vop_dump_list_head, entry) {
47516422 list_del(&pos->entry);
47526423 }
4753
- if (crtc->vop_dump_status == DUMP_KEEP ||
4754
- crtc->vop_dump_times > 0) {
4755
- crtc->frame_count++;
6424
+ if (vp->rockchip_crtc.vop_dump_status == DUMP_KEEP ||
6425
+ vp->rockchip_crtc.vop_dump_times > 0) {
6426
+ vp->rockchip_crtc.frame_count++;
47566427 }
47576428 #endif
47586429
4759
- drm_atomic_crtc_state_for_each_plane(plane, crtc_state)
4760
- plane_num++;
6430
+ for_each_new_plane_in_state(state, plane, pstate, i) {
6431
+ if (pstate->crtc == crtc)
6432
+ plane_num++;
6433
+ }
47616434
4762
- if (plane_num_total)
4763
- *plane_num_total += plane_num;
6435
+ vop_bw_info->plane_num += plane_num;
47646436 pbandwidth = kmalloc_array(plane_num, sizeof(*pbandwidth),
47656437 GFP_KERNEL);
47666438 if (!pbandwidth)
47676439 return -ENOMEM;
4768
- drm_atomic_crtc_state_for_each_plane(plane, crtc_state) {
4769
- int act_w, act_h, bpp, afbc_fac;
47706440
4771
- pstate = drm_atomic_get_new_plane_state(state, plane);
6441
+ for_each_new_plane_in_state(state, plane, pstate, i) {
6442
+ int act_w, act_h, bpp, afbc_fac;
6443
+ int fps = drm_mode_vrefresh(adjusted_mode);
6444
+
47726445 if (!pstate || pstate->crtc != crtc || !pstate->fb)
47736446 continue;
6447
+
47746448 /* This is an empirical value, if it's afbc format, the frame buffer size div 2 */
47756449 afbc_fac = rockchip_afbc(plane, pstate->fb->modifier) ? 2 : 1;
47766450
....@@ -4781,24 +6455,25 @@
47816455
47826456 act_w = drm_rect_width(&pstate->src) >> 16;
47836457 act_h = drm_rect_height(&pstate->src) >> 16;
4784
- bpp = pstate->fb->format->bpp[0];
6458
+ bpp = rockchip_drm_get_bpp(pstate->fb->format);
47856459
4786
- *frame_bw_mbyte += act_w * act_h / 1000 * bpp / 8 * adjusted_mode->vrefresh / afbc_fac / 1000;
6460
+ vop_bw_info->frame_bw_mbyte += act_w * act_h / 1000 * bpp / 8 * fps / 1000;
47876461 }
47886462
47896463 sort(pbandwidth, cnt, sizeof(pbandwidth[0]), vop2_bandwidth_cmp, NULL);
47906464
4791
- line_bandwidth = vop2_calc_max_bandwidth(pbandwidth, 0, cnt, vdisplay);
6465
+ line_bw_mbyte = vop2_calc_max_bandwidth(pbandwidth, 0, cnt, vdisplay);
47926466 kfree(pbandwidth);
47936467 /*
47946468 * line_bandwidth(MB/s)
4795
- * = line_bandwidth(Byte) / line_time(s)
6469
+ * = line_bandwidth / line_time
47966470 * = line_bandwidth(Byte) * clock(KHZ) / 1000 / htotal
47976471 */
4798
- line_bandwidth *= clock;
4799
- do_div(line_bandwidth, htotal * 1000);
6472
+ line_bw_mbyte *= clock;
6473
+ do_div(line_bw_mbyte, htotal * 1000);
6474
+ vop_bw_info->line_bw_mbyte = line_bw_mbyte;
48006475
4801
- return line_bandwidth;
6476
+ return 0;
48026477 }
48036478
48046479 static void vop2_crtc_close(struct drm_crtc *crtc)
....@@ -4830,6 +6505,44 @@
48306505 VOP_MODULE_SET(vop2, vp, edpi_wms_fs, 1);
48316506 }
48326507
6508
+static int vop2_crtc_set_color_bar(struct drm_crtc *crtc, enum rockchip_color_bar_mode mode)
6509
+{
6510
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
6511
+ struct vop2 *vop2 = vp->vop2;
6512
+ int ret = 0;
6513
+
6514
+ if (!crtc->state->active) {
6515
+ DRM_INFO("Video port%d disabled\n", vp->id);
6516
+ return -EINVAL;
6517
+ }
6518
+
6519
+ switch (mode) {
6520
+ case ROCKCHIP_COLOR_BAR_OFF:
6521
+ DRM_INFO("disable color bar in VP%d\n", vp->id);
6522
+ VOP_MODULE_SET(vop2, vp, color_bar_en, 0);
6523
+ vop2_cfg_done(crtc);
6524
+ break;
6525
+ case ROCKCHIP_COLOR_BAR_HORIZONTAL:
6526
+ DRM_INFO("enable horizontal color bar in VP%d\n", vp->id);
6527
+ VOP_MODULE_SET(vop2, vp, color_bar_mode, 0);
6528
+ VOP_MODULE_SET(vop2, vp, color_bar_en, 1);
6529
+ vop2_cfg_done(crtc);
6530
+ break;
6531
+ case ROCKCHIP_COLOR_BAR_VERTICAL:
6532
+ DRM_INFO("enable vertical color bar in VP%d\n", vp->id);
6533
+ VOP_MODULE_SET(vop2, vp, color_bar_mode, 1);
6534
+ VOP_MODULE_SET(vop2, vp, color_bar_en, 1);
6535
+ vop2_cfg_done(crtc);
6536
+ break;
6537
+ default:
6538
+ DRM_INFO("Unsupported color bar mode\n");
6539
+ ret = -EINVAL;
6540
+ break;
6541
+ }
6542
+
6543
+ return ret;
6544
+}
6545
+
48336546 static const struct rockchip_crtc_funcs private_crtc_funcs = {
48346547 .loader_protect = vop2_crtc_loader_protect,
48356548 .cancel_pending_vblank = vop2_crtc_cancel_pending_vblank,
....@@ -4837,10 +6550,13 @@
48376550 .debugfs_dump = vop2_crtc_debugfs_dump,
48386551 .regs_dump = vop2_crtc_regs_dump,
48396552 .active_regs_dump = vop2_crtc_active_regs_dump,
4840
- .mode_valid = vop2_crtc_mode_valid,
48416553 .bandwidth = vop2_crtc_bandwidth,
48426554 .crtc_close = vop2_crtc_close,
48436555 .te_handler = vop2_crtc_te_handler,
6556
+ .crtc_send_mcu_cmd = vop3_crtc_send_mcu_cmd,
6557
+ .wait_vact_end = vop2_crtc_wait_vact_end,
6558
+ .crtc_standby = vop2_crtc_standby,
6559
+ .crtc_set_color_bar = vop2_crtc_set_color_bar,
48446560 };
48456561
48466562 static bool vop2_crtc_mode_fixup(struct drm_crtc *crtc,
....@@ -4849,6 +6565,10 @@
48496565 {
48506566 struct vop2_video_port *vp = to_vop2_video_port(crtc);
48516567 struct vop2 *vop2 = vp->vop2;
6568
+ struct drm_connector *connector;
6569
+ struct drm_connector_list_iter conn_iter;
6570
+ struct drm_crtc_state *new_crtc_state = container_of(mode, struct drm_crtc_state, mode);
6571
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(new_crtc_state);
48526572
48536573 /*
48546574 * For RK3568 and RK3588, the hactive of video timing must
....@@ -4872,12 +6592,30 @@
48726592
48736593 drm_mode_set_crtcinfo(adj_mode, CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE);
48746594
4875
- if (mode->flags & DRM_MODE_FLAG_DBLCLK)
6595
+ if (mode->flags & DRM_MODE_FLAG_DBLCLK || vcstate->output_if & VOP_OUTPUT_IF_BT656)
48766596 adj_mode->crtc_clock *= 2;
48776597
4878
- adj_mode->crtc_clock = DIV_ROUND_UP(clk_round_rate(vp->dclk,
4879
- adj_mode->crtc_clock * 1000), 1000);
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
+ }
48806604
6605
+ drm_connector_list_iter_begin(crtc->dev, &conn_iter);
6606
+ drm_for_each_connector_iter(connector, &conn_iter) {
6607
+ if ((new_crtc_state->connector_mask & drm_connector_mask(connector)) &&
6608
+ ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
6609
+ (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA))) {
6610
+ drm_connector_list_iter_end(&conn_iter);
6611
+ return true;
6612
+ }
6613
+ }
6614
+ drm_connector_list_iter_end(&conn_iter);
6615
+
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);
48816619 return true;
48826620 }
48836621
....@@ -4896,24 +6634,25 @@
48966634 case MEDIA_BUS_FMT_RGB666_1X18:
48976635 case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
48986636 case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
4899
- case MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA:
49006637 VOP_MODULE_SET(vop2, vp, dither_down_en, 1);
49016638 VOP_MODULE_SET(vop2, vp, dither_down_mode, RGB888_TO_RGB666);
49026639 VOP_MODULE_SET(vop2, vp, pre_dither_down_en, 1);
49036640 break;
6641
+ case MEDIA_BUS_FMT_YUYV8_1X16:
49046642 case MEDIA_BUS_FMT_YUV8_1X24:
49056643 case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
49066644 VOP_MODULE_SET(vop2, vp, dither_down_en, 0);
49076645 VOP_MODULE_SET(vop2, vp, pre_dither_down_en, 1);
49086646 break;
6647
+ case MEDIA_BUS_FMT_YUYV10_1X20:
49096648 case MEDIA_BUS_FMT_YUV10_1X30:
49106649 case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
49116650 case MEDIA_BUS_FMT_RGB101010_1X30:
49126651 VOP_MODULE_SET(vop2, vp, dither_down_en, 0);
49136652 VOP_MODULE_SET(vop2, vp, pre_dither_down_en, 0);
49146653 break;
4915
- case MEDIA_BUS_FMT_SRGB888_3X8:
4916
- case MEDIA_BUS_FMT_SRGB888_DUMMY_4X8:
6654
+ case MEDIA_BUS_FMT_RGB888_3X8:
6655
+ case MEDIA_BUS_FMT_RGB888_DUMMY_4X8:
49176656 case MEDIA_BUS_FMT_RGB888_1X24:
49186657 case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
49196658 case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
....@@ -5009,18 +6748,598 @@
50096748 u16 vact_end = vact_st + vdisplay;
50106749 u32 htotal_sync = htotal << 16 | hsync_len;
50116750 u32 hactive_st_end = hact_st << 16 | hact_end;
5012
- u32 vtotal_sync = vtotal << 16 | vsync_len;
50136751 u32 vactive_st_end = vact_st << 16 | vact_end;
50146752 u32 crtc_clock = adjusted_mode->crtc_clock * 100;
50156753
50166754 if (htotal_sync != VOP_MODULE_GET(vop2, vp, htotal_pw) ||
50176755 hactive_st_end != VOP_MODULE_GET(vop2, vp, hact_st_end) ||
5018
- vtotal_sync != VOP_MODULE_GET(vop2, vp, vtotal_pw) ||
6756
+ vtotal != VOP_MODULE_GET(vop2, vp, dsp_vtotal) ||
6757
+ vsync_len != VOP_MODULE_GET(vop2, vp, dsp_vs_end) ||
50196758 vactive_st_end != VOP_MODULE_GET(vop2, vp, vact_st_end) ||
50206759 crtc_clock != clk_get_rate(vp->dclk))
50216760 return true;
50226761
50236762 return false;
6763
+}
6764
+
6765
+static int vop2_cru_set_rate(struct vop2_clk *if_pixclk, struct vop2_clk *if_dclk)
6766
+{
6767
+ int ret = 0;
6768
+
6769
+ if (if_pixclk) {
6770
+ ret = clk_set_rate(if_pixclk->hw.clk, if_pixclk->rate);
6771
+ if (ret < 0) {
6772
+ DRM_DEV_ERROR(if_pixclk->vop2->dev, "set %s to %ld failed: %d\n",
6773
+ clk_hw_get_name(&if_pixclk->hw), if_pixclk->rate, ret);
6774
+ return ret;
6775
+ }
6776
+ }
6777
+
6778
+ if (if_dclk) {
6779
+ ret = clk_set_rate(if_dclk->hw.clk, if_dclk->rate);
6780
+ if (ret < 0)
6781
+ DRM_DEV_ERROR(if_dclk->vop2->dev, "set %s to %ld failed %d\n",
6782
+ clk_hw_get_name(&if_dclk->hw), if_dclk->rate, ret);
6783
+ }
6784
+
6785
+ return ret;
6786
+}
6787
+
6788
+static int vop2_set_dsc_clk(struct drm_crtc *crtc, u8 dsc_id)
6789
+{
6790
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
6791
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
6792
+ struct vop2 *vop2 = vp->vop2;
6793
+ const struct vop2_data *vop2_data = vop2->data;
6794
+ const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id];
6795
+ struct vop2_clk *dsc_txp_clk, *dsc_pxl_clk, *dsc_cds_clk, *dsc_txp_clk_parent;
6796
+ char clk_name[32];
6797
+ int ret = 0;
6798
+
6799
+ /* set clk parent */
6800
+ snprintf(clk_name, sizeof(clk_name), "dclk%d", vp->id);
6801
+ dsc_txp_clk = vop2_clk_get(vop2, dsc_data->dsc_txp_clk_src_name);
6802
+ dsc_txp_clk_parent = vop2_clk_get(vop2, clk_name);
6803
+ if (!dsc_txp_clk || !dsc_txp_clk_parent) {
6804
+ DRM_DEV_ERROR(vop2->dev, "failed to get dsc clk\n");
6805
+ return -ENODEV;
6806
+ }
6807
+ ret = clk_set_parent(dsc_txp_clk->hw.clk, dsc_txp_clk_parent->hw.clk);
6808
+ if (ret < 0) {
6809
+ DRM_DEV_ERROR(vop2->dev, "failed to set parent(%s) for %s: %d\n",
6810
+ __clk_get_name(dsc_txp_clk_parent->hw.clk),
6811
+ __clk_get_name(dsc_txp_clk->hw.clk), ret);
6812
+ return ret;
6813
+ }
6814
+
6815
+ /* set dsc txp clk rate */
6816
+ clk_set_rate(dsc_txp_clk->hw.clk, vcstate->dsc_txp_clk_rate);
6817
+
6818
+ /* set dsc pxl clk rate */
6819
+ dsc_pxl_clk = vop2_clk_get(vop2, dsc_data->dsc_pxl_clk_name);
6820
+ if (!dsc_pxl_clk) {
6821
+ DRM_DEV_ERROR(vop2->dev, "failed to get dsc_pxl_clk\n");
6822
+ return -ENODEV;
6823
+ }
6824
+ clk_set_rate(dsc_pxl_clk->hw.clk, vcstate->dsc_pxl_clk_rate);
6825
+
6826
+ /* set dsc cds clk rate */
6827
+ dsc_cds_clk = vop2_clk_get(vop2, dsc_data->dsc_cds_clk_name);
6828
+ if (!dsc_cds_clk) {
6829
+ DRM_DEV_ERROR(vop2->dev, "failed to get dsc_cds_clk\n");
6830
+ return -ENODEV;
6831
+ }
6832
+ clk_set_rate(dsc_cds_clk->hw.clk, vcstate->dsc_cds_clk_rate);
6833
+
6834
+ return 0;
6835
+}
6836
+
6837
+static int vop2_calc_if_clk(struct drm_crtc *crtc, const struct vop2_connector_if_data *if_data,
6838
+ struct vop2_clk *if_pixclk, struct vop2_clk *if_dclk, int conn_id)
6839
+{
6840
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
6841
+ struct vop2 *vop2 = vp->vop2;
6842
+ struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
6843
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
6844
+ u64 v_pixclk = adjusted_mode->crtc_clock * 1000LL; /* video timing pixclk */
6845
+ unsigned long dclk_core_rate, dclk_out_rate = 0;
6846
+ /*conn_dclk = conn_pixclk or conn_dclk = conn_pixclk / 2 */
6847
+ u64 hdmi_edp_pixclk, hdmi_edp_dclk, mipi_pixclk;
6848
+ char dclk_core_div_shift = 2;
6849
+ char K = 1;
6850
+ char clk_name[32];
6851
+ struct vop2_clk *dclk_core, *dclk_out, *dclk;
6852
+ int ret;
6853
+ bool dsc_txp_clk_is_biggest = false;
6854
+ u8 dsc_id = conn_id & (VOP_OUTPUT_IF_MIPI0 | VOP_OUTPUT_IF_HDMI0) ? 0 : 1;
6855
+
6856
+ dclk_core_div_shift = if_data->post_proc_div_shift;
6857
+ dclk_core_rate = v_pixclk >> dclk_core_div_shift;
6858
+
6859
+ if (!if_dclk && (output_if_is_hdmi(conn_id) || output_if_is_edp(conn_id)))
6860
+ return -EINVAL;
6861
+ if ((vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) &&
6862
+ (vcstate->output_mode == ROCKCHIP_OUT_MODE_YUV420)) {
6863
+ DRM_DEV_ERROR(vop2->dev, "Dual channel and YUV420 can't work together\n");
6864
+ return -EINVAL;
6865
+ }
6866
+
6867
+ if ((vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) ||
6868
+ (vcstate->output_mode == ROCKCHIP_OUT_MODE_YUV420))
6869
+ K = 2;
6870
+
6871
+ if (output_if_is_hdmi(conn_id)) {
6872
+ if (vcstate->dsc_enable) {
6873
+ hdmi_edp_pixclk = vcstate->dsc_cds_clk_rate << 1;
6874
+ hdmi_edp_dclk = vcstate->dsc_cds_clk_rate;
6875
+ } else {
6876
+ hdmi_edp_pixclk = (dclk_core_rate << 1) / K;
6877
+ hdmi_edp_dclk = dclk_core_rate / K;
6878
+ }
6879
+
6880
+ if_pixclk->rate = hdmi_edp_pixclk;
6881
+ if_dclk->rate = hdmi_edp_dclk;
6882
+ } else if (output_if_is_edp(conn_id)) {
6883
+ hdmi_edp_pixclk = v_pixclk;
6884
+ do_div(hdmi_edp_pixclk, K);
6885
+ hdmi_edp_dclk = hdmi_edp_pixclk;
6886
+
6887
+ if_pixclk->rate = hdmi_edp_pixclk;
6888
+ if_dclk->rate = hdmi_edp_dclk;
6889
+ } else if (output_if_is_dp(conn_id)) {
6890
+ dclk_out_rate = v_pixclk >> 2;
6891
+ dclk_out_rate = dclk_out_rate / K;
6892
+ if_pixclk->rate = dclk_out_rate;
6893
+ } else if (output_if_is_mipi(conn_id)) {
6894
+ if (vcstate->dsc_enable)
6895
+ /* dsc output is 96bit, dsi input is 192 bit */
6896
+ mipi_pixclk = vcstate->dsc_cds_clk_rate >> 1;
6897
+ else
6898
+ mipi_pixclk = dclk_core_rate / K;
6899
+
6900
+ dclk_out_rate = dclk_core_rate / K;
6901
+ if_pixclk->rate = mipi_pixclk;
6902
+ } else if (output_if_is_dpi(conn_id)) {
6903
+ if_pixclk->rate = v_pixclk;
6904
+ }
6905
+
6906
+ /*
6907
+ * RGB/eDP/HDMI: if_pixclk >= dclk_core
6908
+ * DP: dp_pixclk = dclk_out <= dclk_core
6909
+ * DSI: mipi_pixclk <= dclk_out <= dclk_core
6910
+ *
6911
+ */
6912
+ snprintf(clk_name, sizeof(clk_name), "dclk_core%d", vp->id);
6913
+ dclk_core = vop2_clk_get(vop2, clk_name);
6914
+
6915
+ snprintf(clk_name, sizeof(clk_name), "dclk_out%d", vp->id);
6916
+ dclk_out = vop2_clk_get(vop2, clk_name);
6917
+
6918
+ /*
6919
+ * HDMI use 1:1 dclk for rgb/yuv444, 1:2 for yuv420 when
6920
+ * pixclk <= 600
6921
+ * We want use HDMI PHY clk as dclk source for DP/HDMI.
6922
+ * The max freq of HDMI PHY CLK is 600 MHZ.
6923
+ * When used for HDMI, the input freq and v_pixclk must
6924
+ * keep 1:1 for rgb/yuv444, 1:2 for yuv420
6925
+ */
6926
+ if (output_if_is_hdmi(conn_id) || output_if_is_dp(conn_id) || output_if_is_mipi(conn_id)) {
6927
+ snprintf(clk_name, sizeof(clk_name), "dclk%d", vp->id);
6928
+ dclk = vop2_clk_get(vop2, clk_name);
6929
+ if (v_pixclk <= (VOP2_MAX_DCLK_RATE * 1000)) {
6930
+ if (vcstate->output_mode == ROCKCHIP_OUT_MODE_YUV420 ||
6931
+ (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE))
6932
+ v_pixclk = v_pixclk >> 1;
6933
+ } else {
6934
+ v_pixclk = v_pixclk >> 2;
6935
+ }
6936
+ clk_set_rate(dclk->hw.clk, v_pixclk);
6937
+ }
6938
+
6939
+ if (vcstate->dsc_enable) {
6940
+ if ((vcstate->dsc_txp_clk_rate >= dclk_core_rate) &&
6941
+ (vcstate->dsc_txp_clk_rate >= if_pixclk->rate)) {
6942
+ dsc_txp_clk_is_biggest = true;
6943
+ if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
6944
+ vop2_set_dsc_clk(crtc, 0);
6945
+ vop2_set_dsc_clk(crtc, 1);
6946
+ } else {
6947
+ vop2_set_dsc_clk(crtc, dsc_id);
6948
+ }
6949
+ }
6950
+ }
6951
+
6952
+ if (dclk_core_rate > if_pixclk->rate) {
6953
+ clk_set_rate(dclk_core->hw.clk, dclk_core_rate);
6954
+ if (output_if_is_mipi(conn_id))
6955
+ clk_set_rate(dclk_out->hw.clk, dclk_out_rate);
6956
+ ret = vop2_cru_set_rate(if_pixclk, if_dclk);
6957
+ } else {
6958
+ if (output_if_is_mipi(conn_id))
6959
+ clk_set_rate(dclk_out->hw.clk, dclk_out_rate);
6960
+ ret = vop2_cru_set_rate(if_pixclk, if_dclk);
6961
+ clk_set_rate(dclk_core->hw.clk, dclk_core_rate);
6962
+ }
6963
+
6964
+ if (!dsc_txp_clk_is_biggest && vcstate->dsc_enable) {
6965
+ if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
6966
+ vop2_set_dsc_clk(crtc, 0);
6967
+ vop2_set_dsc_clk(crtc, 1);
6968
+ } else {
6969
+ vop2_set_dsc_clk(crtc, dsc_id);
6970
+ }
6971
+ }
6972
+
6973
+ return ret;
6974
+}
6975
+
6976
+static int vop2_calc_dsc_clk(struct drm_crtc *crtc)
6977
+{
6978
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
6979
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
6980
+ struct vop2 *vop2 = vp->vop2;
6981
+ struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
6982
+ u64 v_pixclk = adjusted_mode->crtc_clock * 1000LL; /* video timing pixclk */
6983
+ u8 k = 1;
6984
+
6985
+ if (!vop2->data->nr_dscs) {
6986
+ DRM_WARN("Unsupported DSC\n");
6987
+
6988
+ return 0;
6989
+ }
6990
+
6991
+ if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
6992
+ k = 2;
6993
+
6994
+ vcstate->dsc_txp_clk_rate = v_pixclk;
6995
+ do_div(vcstate->dsc_txp_clk_rate, (vcstate->dsc_pixel_num * k));
6996
+
6997
+ vcstate->dsc_pxl_clk_rate = v_pixclk;
6998
+ do_div(vcstate->dsc_pxl_clk_rate, (vcstate->dsc_slice_num * k));
6999
+
7000
+ /* dsc_cds = crtc_clock / (cds_dat_width / bits_per_pixel)
7001
+ * cds_dat_width = 96;
7002
+ * bits_per_pixel = [8-12];
7003
+ * As cds clk is div from txp clk and only support 1/2/4 div,
7004
+ * so when txp_clk is equal to v_pixclk, we set dsc_cds = crtc_clock / 4,
7005
+ * otherwise dsc_cds = crtc_clock / 8;
7006
+ */
7007
+ vcstate->dsc_cds_clk_rate = v_pixclk / (vcstate->dsc_txp_clk_rate == v_pixclk ? 4 : 8);
7008
+
7009
+ return 0;
7010
+}
7011
+
7012
+static int vop2_calc_cru_cfg(struct drm_crtc *crtc, int conn_id,
7013
+ struct vop2_clk **if_pixclk, struct vop2_clk **if_dclk)
7014
+{
7015
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
7016
+ struct vop2 *vop2 = vp->vop2;
7017
+ const struct vop2_connector_if_data *if_data;
7018
+ struct vop2_clk *if_clk_src, *if_clk_parent;
7019
+ char clk_name[32];
7020
+ int ret;
7021
+
7022
+ if (vop2->version != VOP_VERSION_RK3588)
7023
+ return 0;
7024
+
7025
+ if_data = vop2_find_connector_if_data(vop2, conn_id);
7026
+ if_clk_src = vop2_clk_get(vop2, if_data->clk_src_name);
7027
+ snprintf(clk_name, sizeof(clk_name), "%s%d", if_data->clk_parent_name, vp->id);
7028
+ if_clk_parent = vop2_clk_get(vop2, clk_name);
7029
+ *if_pixclk = vop2_clk_get(vop2, if_data->pixclk_name);
7030
+ *if_dclk = vop2_clk_get(vop2, if_data->dclk_name);
7031
+ if (!(*if_pixclk) || !if_clk_parent) {
7032
+ DRM_DEV_ERROR(vop2->dev, "failed to get connector interface clk\n");
7033
+ return -ENODEV;
7034
+ }
7035
+
7036
+ ret = clk_set_parent(if_clk_src->hw.clk, if_clk_parent->hw.clk);
7037
+ if (ret < 0) {
7038
+ DRM_DEV_ERROR(vop2->dev, "failed to set parent(%s) for %s: %d\n",
7039
+ __clk_get_name(if_clk_parent->hw.clk),
7040
+ __clk_get_name(if_clk_src->hw.clk), ret);
7041
+ return ret;
7042
+ }
7043
+
7044
+ /* HDMI and eDP use independent if_pixclk and if_dclk, and others if_pixclk = if_dclk */
7045
+ if (output_if_is_hdmi(conn_id) || output_if_is_edp(conn_id))
7046
+ ret = vop2_calc_if_clk(crtc, if_data, *if_pixclk, *if_dclk, conn_id);
7047
+ else
7048
+ ret = vop2_calc_if_clk(crtc, if_data, *if_pixclk, NULL, conn_id);
7049
+
7050
+ return ret;
7051
+}
7052
+
7053
+static void vop2_crtc_load_pps(struct drm_crtc *crtc, u8 dsc_id)
7054
+{
7055
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
7056
+ struct vop2 *vop2 = vp->vop2;
7057
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
7058
+
7059
+ struct drm_dsc_picture_parameter_set *pps = &vcstate->pps;
7060
+ struct drm_dsc_picture_parameter_set config_pps;
7061
+ int i = 0;
7062
+ u32 *pps_val = (u32 *)&config_pps;
7063
+ u32 offset;
7064
+ struct vop2_dsc *dsc;
7065
+
7066
+ dsc = &vop2->dscs[dsc_id];
7067
+ offset = dsc->regs->dsc_pps0_3.offset;
7068
+
7069
+ memcpy(&config_pps, pps, sizeof(config_pps));
7070
+
7071
+ if ((config_pps.pps_3 & 0xf) > dsc->max_linebuf_depth) {
7072
+ config_pps.pps_3 &= 0xf0;
7073
+ config_pps.pps_3 |= dsc->max_linebuf_depth;
7074
+ DRM_WARN("DSC%d max_linebuf_depth is: %d, current set value is: %d\n",
7075
+ dsc_id, dsc->max_linebuf_depth, config_pps.pps_3 & 0xf);
7076
+ }
7077
+
7078
+ for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
7079
+ config_pps.rc_range_parameters[i] =
7080
+ (pps->rc_range_parameters[i] >> 3 & 0x1f) |
7081
+ ((pps->rc_range_parameters[i] >> 14 & 0x3) << 5) |
7082
+ ((pps->rc_range_parameters[i] >> 0 & 0x7) << 7) |
7083
+ ((pps->rc_range_parameters[i] >> 8 & 0x3f) << 10);
7084
+ }
7085
+
7086
+ for (i = 0; i < ROCKCHIP_DSC_PPS_SIZE_BYTE / 4; i++)
7087
+ vop2_writel(vop2, offset + i * 4, *pps_val++);
7088
+}
7089
+
7090
+static void vop2_crtc_enable_dsc(struct drm_crtc *crtc, struct drm_crtc_state *old_state, u8 dsc_id)
7091
+{
7092
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
7093
+ struct vop2 *vop2 = vp->vop2;
7094
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
7095
+ struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
7096
+ struct rockchip_dsc_sink_cap *dsc_sink_cap = &vcstate->dsc_sink_cap;
7097
+ u16 hsync_len = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
7098
+ u16 hdisplay = adjusted_mode->crtc_hdisplay;
7099
+ u16 htotal = adjusted_mode->crtc_htotal;
7100
+ u16 hact_st = adjusted_mode->crtc_htotal - adjusted_mode->crtc_hsync_start;
7101
+ u16 vdisplay = adjusted_mode->crtc_vdisplay;
7102
+ u16 vtotal = adjusted_mode->crtc_vtotal;
7103
+ u16 vsync_len = adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start;
7104
+ u16 vact_st = adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vsync_start;
7105
+ u16 vact_end = vact_st + vdisplay;
7106
+ u8 dsc_interface_mode = 0;
7107
+ struct vop2_dsc *dsc;
7108
+ struct vop2_clk *dsc_cds_clk, *dsc_pxl_clk, *dsc_txp_clk;
7109
+ const struct vop2_data *vop2_data = vop2->data;
7110
+ const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id];
7111
+ bool mipi_ds_mode = false;
7112
+ uint32_t *reg_base = vop2->regs;
7113
+ u32 offset = 0;
7114
+
7115
+ if (!vop2->data->nr_dscs) {
7116
+ DRM_WARN("Unsupported DSC\n");
7117
+
7118
+ return;
7119
+ }
7120
+
7121
+ if (vcstate->dsc_slice_num > dsc_data->max_slice_num)
7122
+ DRM_ERROR("DSC%d supported max slice is: %d, current is: %d\n",
7123
+ dsc_data->id, dsc_data->max_slice_num, vcstate->dsc_slice_num);
7124
+
7125
+ dsc = &vop2->dscs[dsc_id];
7126
+ if (dsc->pd) {
7127
+ dsc->pd->vp_mask = BIT(vp->id);
7128
+ vop2_power_domain_get(dsc->pd);
7129
+ }
7130
+
7131
+ VOP_MODULE_SET(vop2, dsc, scan_timing_para_imd_en, 1);
7132
+ VOP_MODULE_SET(vop2, dsc, dsc_port_sel, vp->id);
7133
+ if (vcstate->output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) {
7134
+ dsc_interface_mode = VOP_DSC_IF_HDMI;
7135
+ } else {
7136
+ mipi_ds_mode = !!(vcstate->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE);
7137
+ if (mipi_ds_mode)
7138
+ dsc_interface_mode = VOP_DSC_IF_MIPI_DS_MODE;
7139
+ else
7140
+ dsc_interface_mode = VOP_DSC_IF_MIPI_VIDEO_MODE;
7141
+ }
7142
+
7143
+ if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
7144
+ VOP_MODULE_SET(vop2, dsc, dsc_man_mode, 0);
7145
+ else
7146
+ VOP_MODULE_SET(vop2, dsc, dsc_man_mode, 1);
7147
+ dsc_cds_clk = vop2_clk_get(vop2, dsc_data->dsc_cds_clk_name);
7148
+ dsc_pxl_clk = vop2_clk_get(vop2, dsc_data->dsc_pxl_clk_name);
7149
+ dsc_txp_clk = vop2_clk_get(vop2, dsc_data->dsc_txp_clk_name);
7150
+
7151
+ VOP_MODULE_SET(vop2, dsc, dsc_interface_mode, dsc_interface_mode);
7152
+ VOP_MODULE_SET(vop2, dsc, dsc_pixel_num, vcstate->dsc_pixel_num >> 1);
7153
+ VOP_MODULE_SET(vop2, dsc, dsc_txp_clk_div, dsc_txp_clk->div_val);
7154
+ VOP_MODULE_SET(vop2, dsc, dsc_pxl_clk_div, dsc_pxl_clk->div_val);
7155
+ VOP_MODULE_SET(vop2, dsc, dsc_cds_clk_div, dsc_cds_clk->div_val);
7156
+ VOP_MODULE_SET(vop2, dsc, dsc_scan_en, !mipi_ds_mode);
7157
+ VOP_MODULE_SET(vop2, dsc, dsc_halt_en, mipi_ds_mode);
7158
+
7159
+ if (!mipi_ds_mode) {
7160
+ u16 dsc_hsync, dsc_htotal, dsc_hact_st, dsc_hact_end;
7161
+ u32 target_bpp = dsc_sink_cap->target_bits_per_pixel_x16;
7162
+ u64 dsc_cds_rate = vcstate->dsc_cds_clk_rate;
7163
+ u32 v_pixclk_mhz = adjusted_mode->crtc_clock / 1000; /* video timing pixclk */
7164
+ u32 dly_num, dsc_cds_rate_mhz, val = 0;
7165
+ struct vop2_clk *dclk_core;
7166
+ char clk_name[32];
7167
+ int k = 1;
7168
+
7169
+ if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
7170
+ k = 2;
7171
+
7172
+ snprintf(clk_name, sizeof(clk_name), "dclk_core%d", vp->id);
7173
+ dclk_core = vop2_clk_get(vop2, clk_name);
7174
+
7175
+ if (target_bpp >> 4 < dsc->min_bits_per_pixel)
7176
+ DRM_ERROR("Unsupported bpp less than: %d\n", dsc->min_bits_per_pixel);
7177
+
7178
+ /*
7179
+ * dly_num = delay_line_num * T(one-line) / T (dsc_cds)
7180
+ * T (one-line) = 1/v_pixclk_mhz * htotal = htotal/v_pixclk_mhz
7181
+ * T (dsc_cds) = 1 / dsc_cds_rate_mhz
7182
+ *
7183
+ * HDMI:
7184
+ * delay_line_num: according the pps initial_xmit_delay to adjust vop dsc delay
7185
+ * delay_line_num = 4 - BPP / 8
7186
+ * = (64 - target_bpp / 8) / 16
7187
+ * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16;
7188
+ *
7189
+ * MIPI DSI[4320 and 9216 is buffer size for DSC]:
7190
+ * DSC0:delay_line_num = 4320 * 8 / slince_num / chunk_size;
7191
+ * delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
7192
+ * DSC1:delay_line_num = 9216 * 2 / slince_num / chunk_size;
7193
+ * delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
7194
+ * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num
7195
+ */
7196
+ do_div(dsc_cds_rate, 1000000); /* hz to Mhz */
7197
+ dsc_cds_rate_mhz = dsc_cds_rate;
7198
+ dsc_hsync = hsync_len / 2;
7199
+ if (dsc_interface_mode == VOP_DSC_IF_HDMI) {
7200
+ dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16;
7201
+ } else {
7202
+ int dsc_buf_size = dsc->id == 0 ? 4320 * 8 : 9216 * 2;
7203
+ int delay_line_num = dsc_buf_size / vcstate->dsc_slice_num / be16_to_cpu(vcstate->pps.chunk_size);
7204
+
7205
+ delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
7206
+ dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num;
7207
+
7208
+ /* The dsc mipi video mode dsc_hsync minimum size is 8 pixels */
7209
+ if (dsc_hsync < 8)
7210
+ dsc_hsync = 8;
7211
+ }
7212
+ VOP_MODULE_SET(vop2, dsc, dsc_init_dly_mode, 0);
7213
+ VOP_MODULE_SET(vop2, dsc, dsc_init_dly_num, dly_num);
7214
+ /*
7215
+ * htotal / dclk_core = dsc_htotal /cds_clk
7216
+ *
7217
+ * dclk_core = DCLK / (1 << dclk_core->div_val)
7218
+ * cds_clk = txp_clk / (1 << dsc_cds_clk->div_val)
7219
+ * txp_clk = DCLK / (1 << dsc_txp_clk->div_val)
7220
+ *
7221
+ * dsc_htotal = htotal * (1 << dclk_core->div_val) /
7222
+ ((1 << dsc_txp_clk->div_val) * (1 << dsc_cds_clk->div_val))
7223
+ */
7224
+ dsc_htotal = htotal * (1 << dclk_core->div_val) /
7225
+ ((1 << dsc_txp_clk->div_val) * (1 << dsc_cds_clk->div_val));
7226
+ val = dsc_htotal << 16 | dsc_hsync;
7227
+ VOP_MODULE_SET(vop2, dsc, dsc_htotal_pw, val);
7228
+
7229
+ dsc_hact_st = hact_st / 2;
7230
+ dsc_hact_end = (hdisplay / k * target_bpp >> 4) / 24 + dsc_hact_st;
7231
+ val = dsc_hact_end << 16 | dsc_hact_st;
7232
+ VOP_MODULE_SET(vop2, dsc, dsc_hact_st_end, val);
7233
+
7234
+ VOP_MODULE_SET(vop2, dsc, dsc_vtotal, vtotal);
7235
+ VOP_MODULE_SET(vop2, dsc, dsc_vs_end, vsync_len);
7236
+ VOP_MODULE_SET(vop2, dsc, dsc_vact_st_end, vact_end << 16 | vact_st);
7237
+ }
7238
+
7239
+ VOP_MODULE_SET(vop2, dsc, rst_deassert, 1);
7240
+ udelay(10);
7241
+ /* read current dsc core register and backup to regsbak */
7242
+ offset = dsc->regs->dsc_en.offset;
7243
+ vop2->regsbak[offset >> 2] = reg_base[offset >> 2];
7244
+
7245
+ VOP_MODULE_SET(vop2, dsc, dsc_en, 1);
7246
+ vop2_crtc_load_pps(crtc, dsc_id);
7247
+
7248
+ VOP_MODULE_SET(vop2, dsc, dsc_rbit, 1);
7249
+ VOP_MODULE_SET(vop2, dsc, dsc_rbyt, 0);
7250
+ VOP_MODULE_SET(vop2, dsc, dsc_flal, 1);
7251
+ VOP_MODULE_SET(vop2, dsc, dsc_mer, 1);
7252
+ VOP_MODULE_SET(vop2, dsc, dsc_epb, 0);
7253
+ VOP_MODULE_SET(vop2, dsc, dsc_epl, 1);
7254
+ VOP_MODULE_SET(vop2, dsc, dsc_nslc, ilog2(vcstate->dsc_slice_num));
7255
+ VOP_MODULE_SET(vop2, dsc, dsc_sbo, 1);
7256
+ VOP_MODULE_SET(vop2, dsc, dsc_ifep, dsc_sink_cap->version_minor == 2 ? 1 : 0);
7257
+ VOP_MODULE_SET(vop2, dsc, dsc_pps_upd, 1);
7258
+
7259
+ DRM_DEV_INFO(vop2->dev, "DSC%d: txp:%lld div:%d, pxl:%lld div:%d, dsc:%lld div:%d\n",
7260
+ dsc->id,
7261
+ vcstate->dsc_txp_clk_rate, dsc_txp_clk->div_val,
7262
+ vcstate->dsc_pxl_clk_rate, dsc_pxl_clk->div_val,
7263
+ vcstate->dsc_cds_clk_rate, dsc_cds_clk->div_val);
7264
+
7265
+ dsc->attach_vp_id = vp->id;
7266
+ dsc->enabled = true;
7267
+}
7268
+
7269
+static void vop2_setup_dual_channel_if(struct drm_crtc *crtc)
7270
+{
7271
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
7272
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
7273
+ struct vop2 *vop2 = vp->vop2;
7274
+
7275
+ VOP_MODULE_SET(vop2, vp, dual_channel_en, 1);
7276
+ if (vcstate->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
7277
+ VOP_MODULE_SET(vop2, vp, dual_channel_swap, 1);
7278
+
7279
+ if (vcstate->output_if & VOP_OUTPUT_IF_DP1)
7280
+ VOP_CTRL_SET(vop2, dp_dual_en, 1);
7281
+ else if (vcstate->output_if & VOP_OUTPUT_IF_eDP1)
7282
+ VOP_CTRL_SET(vop2, edp_dual_en, 1);
7283
+ else if (vcstate->output_if & VOP_OUTPUT_IF_HDMI1)
7284
+ VOP_CTRL_SET(vop2, hdmi_dual_en, 1);
7285
+ else if (vcstate->output_if & VOP_OUTPUT_IF_MIPI1)
7286
+ VOP_CTRL_SET(vop2, mipi_dual_en, 1);
7287
+}
7288
+
7289
+/*
7290
+ * MIPI port mux on rk3588:
7291
+ * 0: Video Port2
7292
+ * 1: Video Port3
7293
+ * 3: Video Port 1(MIPI1 only)
7294
+ */
7295
+static int vop2_get_mipi_port_mux(struct vop2 *vop2, int vp_id)
7296
+{
7297
+ if (vop2->version == VOP_VERSION_RK3588) {
7298
+ if (vp_id == 1)
7299
+ return 3;
7300
+ else if (vp_id == 3)
7301
+ return 1;
7302
+ else
7303
+ return 0;
7304
+ } else {
7305
+ return vp_id;
7306
+ }
7307
+}
7308
+
7309
+static u32 vop2_get_hdmi_pol(struct vop2 *vop2, u32 flags)
7310
+{
7311
+ u32 val;
7312
+
7313
+ if (vop2->version == VOP_VERSION_RK3588) {
7314
+ val = (flags & DRM_MODE_FLAG_NHSYNC) ? BIT(HSYNC_POSITIVE) : 0;
7315
+ val |= (flags & DRM_MODE_FLAG_NVSYNC) ? BIT(VSYNC_POSITIVE) : 0;
7316
+ } else {
7317
+ val = (flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
7318
+ val |= (flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
7319
+ }
7320
+
7321
+ return val;
7322
+}
7323
+
7324
+static void vop2_post_color_swap(struct drm_crtc *crtc)
7325
+{
7326
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
7327
+ struct vop2 *vop2 = vp->vop2;
7328
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
7329
+ u32 output_if = vcstate->output_if;
7330
+ u32 data_swap = 0;
7331
+
7332
+ if (vop2_output_uv_swap(vcstate->bus_format, vcstate->output_mode) ||
7333
+ vop3_output_rb_swap(vcstate->bus_format, vcstate->output_mode))
7334
+ data_swap = DSP_RB_SWAP;
7335
+
7336
+ if (vop2->version == VOP_VERSION_RK3588 &&
7337
+ (output_if_is_hdmi(output_if) || output_if_is_dp(output_if)) &&
7338
+ (vcstate->bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
7339
+ vcstate->bus_format == MEDIA_BUS_FMT_YUV10_1X30))
7340
+ data_swap |= DSP_RG_SWAP;
7341
+
7342
+ VOP_MODULE_SET(vop2, vp, dsp_data_swap, data_swap);
50247343 }
50257344
50267345 /*
....@@ -5048,7 +7367,7 @@
50487367 static void vop3_setup_pipe_dly(struct vop2_video_port *vp, const struct vop2_zpos *vop2_zpos)
50497368 {
50507369 struct vop2 *vop2 = vp->vop2;
5051
- struct drm_crtc *crtc = &vp->crtc;
7370
+ struct drm_crtc *crtc = &vp->rockchip_crtc.crtc;
50527371 const struct vop2_zpos *zpos;
50537372 struct drm_plane *plane;
50547373 struct vop2_plane_state *vpstate;
....@@ -5124,15 +7443,25 @@
51247443 }
51257444 }
51267445
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
+
51277454 static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
51287455 {
51297456 struct vop2_video_port *vp = to_vop2_video_port(crtc);
7457
+ struct vop2_video_port *splice_vp;
51307458 struct vop2 *vop2 = vp->vop2;
51317459 const struct vop2_data *vop2_data = vop2->data;
51327460 const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
51337461 const struct vop_intr *intr = vp_data->intr;
51347462 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
51357463 struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
7464
+ struct rockchip_dsc_sink_cap *dsc_sink_cap = &vcstate->dsc_sink_cap;
51367465 u16 hsync_len = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
51377466 u16 hdisplay = adjusted_mode->crtc_hdisplay;
51387467 u16 htotal = adjusted_mode->crtc_htotal;
....@@ -5147,14 +7476,57 @@
51477476 bool dclk_inv, yc_swap = false;
51487477 int act_end;
51497478 uint32_t val;
7479
+ char clk_name[32];
7480
+ struct vop2_clk *if_pixclk = NULL;
7481
+ struct vop2_clk *if_dclk = NULL;
7482
+ struct vop2_clk *dclk, *dclk_out, *dclk_core;
7483
+ int splice_en = 0;
7484
+ int port_mux;
7485
+ int ret;
7486
+
7487
+ 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;
7492
+
7493
+ return;
7494
+ }
51507495
51517496 vop2->active_vp_mask |= BIT(vp->id);
51527497 vop2_set_system_status(vop2);
51537498
51547499 vop2_lock(vop2);
5155
- DRM_DEV_INFO(vop2->dev, "Update mode to %dx%d%s%d, type: %d for vp%d\n",
5156
- hdisplay, vdisplay, interlaced ? "i" : "p",
5157
- adjusted_mode->vrefresh, vcstate->output_type, vp->id);
7500
+ DRM_DEV_INFO(vop2->dev, "Update mode to %dx%d%s%d, type: %d(if:%x) for vp%d dclk: %d\n",
7501
+ 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);
7504
+
7505
+ if (adjusted_mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) {
7506
+ vcstate->splice_mode = true;
7507
+ splice_vp = &vop2->vps[vp_data->splice_vp_id];
7508
+ splice_vp->splice_mode_right = true;
7509
+ splice_vp->left_vp = vp;
7510
+ splice_en = 1;
7511
+ vop2->active_vp_mask |= BIT(splice_vp->id);
7512
+ }
7513
+
7514
+ if (vcstate->dsc_enable) {
7515
+ int k = 1;
7516
+
7517
+ if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
7518
+ k = 2;
7519
+
7520
+ vcstate->dsc_id = vcstate->output_if & (VOP_OUTPUT_IF_MIPI0 | VOP_OUTPUT_IF_HDMI0) ? 0 : 1;
7521
+ vcstate->dsc_slice_num = hdisplay / dsc_sink_cap->slice_width / k;
7522
+ vcstate->dsc_pixel_num = vcstate->dsc_slice_num > 4 ? 4 : vcstate->dsc_slice_num;
7523
+
7524
+ vop2_calc_dsc_clk(crtc);
7525
+ DRM_DEV_INFO(vop2->dev, "Enable DSC%d slice:%dx%d, slice num:%d\n",
7526
+ vcstate->dsc_id, dsc_sink_cap->slice_width,
7527
+ dsc_sink_cap->slice_height, vcstate->dsc_slice_num);
7528
+ }
7529
+
51587530 vop2_initial(crtc);
51597531 vcstate->vdisplay = vdisplay;
51607532 vcstate->mode_update = vop2_crtc_mode_update(crtc);
....@@ -5165,26 +7537,51 @@
51657537 val = (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
51667538 val |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
51677539
7540
+ vp->output_if = vcstate->output_if;
7541
+
51687542 if (vcstate->output_if & VOP_OUTPUT_IF_RGB) {
7543
+ ret = vop2_calc_cru_cfg(crtc, VOP_OUTPUT_IF_RGB, &if_pixclk, &if_dclk);
7544
+ if (ret < 0)
7545
+ goto out;
7546
+
51697547 VOP_CTRL_SET(vop2, rgb_en, 1);
51707548 VOP_CTRL_SET(vop2, rgb_mux, vp_data->id);
51717549 VOP_CTRL_SET(vop2, rgb_pin_pol, val);
5172
- VOP_GRF_SET(vop2, grf_dclk_inv, dclk_inv);
7550
+ VOP_GRF_SET(vop2, sys_grf, grf_dclk_inv, dclk_inv);
51737551 }
51747552
51757553 if (vcstate->output_if & VOP_OUTPUT_IF_BT1120) {
5176
- VOP_CTRL_SET(vop2, rgb_en, 1);
5177
- VOP_CTRL_SET(vop2, bt1120_en, 1);
7554
+ ret = vop2_calc_cru_cfg(crtc, VOP_OUTPUT_IF_RGB, &if_pixclk, &if_dclk);
7555
+ if (ret < 0)
7556
+ goto out;
7557
+
7558
+ if (vop2->version == VOP_VERSION_RK3588) {
7559
+ VOP_CTRL_SET(vop2, bt1120_en, 3);
7560
+ } else {
7561
+ VOP_CTRL_SET(vop2, rgb_en, 1);
7562
+ VOP_CTRL_SET(vop2, bt1120_en, 1);
7563
+ }
51787564 VOP_CTRL_SET(vop2, rgb_mux, vp_data->id);
5179
- VOP_GRF_SET(vop2, grf_bt1120_clk_inv, !dclk_inv);
7565
+ VOP_GRF_SET(vop2, sys_grf, grf_bt1120_clk_inv, !dclk_inv);
7566
+ VOP_CTRL_SET(vop2, bt1120_dclk_pol, !dclk_inv);
51807567 yc_swap = vop2_output_yc_swap(vcstate->bus_format);
51817568 VOP_CTRL_SET(vop2, bt1120_yc_swap, yc_swap);
51827569 }
51837570
51847571 if (vcstate->output_if & VOP_OUTPUT_IF_BT656) {
5185
- VOP_CTRL_SET(vop2, bt656_en, 1);
7572
+ ret = vop2_calc_cru_cfg(crtc, VOP_OUTPUT_IF_RGB, &if_pixclk, &if_dclk);
7573
+ if (ret < 0)
7574
+ goto out;
7575
+
7576
+ if (vop2->version == VOP_VERSION_RK3588) {
7577
+ VOP_CTRL_SET(vop2, bt656_en, 1);
7578
+ } else {
7579
+ VOP_CTRL_SET(vop2, rgb_en, 1);
7580
+ VOP_CTRL_SET(vop2, bt656_en, 1);
7581
+ }
51867582 VOP_CTRL_SET(vop2, rgb_mux, vp_data->id);
5187
- VOP_GRF_SET(vop2, grf_bt656_clk_inv, !dclk_inv);
7583
+ VOP_GRF_SET(vop2, sys_grf, grf_bt656_clk_inv, !dclk_inv);
7584
+ VOP_CTRL_SET(vop2, bt656_dclk_pol, !dclk_inv);
51887585 yc_swap = vop2_output_yc_swap(vcstate->bus_format);
51897586 VOP_CTRL_SET(vop2, bt656_yc_swap, yc_swap);
51907587 }
....@@ -5213,8 +7610,18 @@
52137610 }
52147611
52157612 if (vcstate->output_if & VOP_OUTPUT_IF_MIPI0) {
7613
+ ret = vop2_calc_cru_cfg(crtc, VOP_OUTPUT_IF_MIPI0, &if_pixclk, &if_dclk);
7614
+ if (ret < 0)
7615
+ goto out;
7616
+ if (if_pixclk)
7617
+ VOP_CTRL_SET(vop2, mipi0_pixclk_div, if_pixclk->div_val);
7618
+
7619
+ if (vcstate->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
7620
+ VOP_CTRL_SET(vop2, mipi0_ds_mode, 1);
7621
+
7622
+ port_mux = vop2_get_mipi_port_mux(vop2, vp_data->id);
52167623 VOP_CTRL_SET(vop2, mipi0_en, 1);
5217
- VOP_CTRL_SET(vop2, mipi0_mux, vp_data->id);
7624
+ VOP_CTRL_SET(vop2, mipi0_mux, port_mux);
52187625 VOP_CTRL_SET(vop2, mipi_pin_pol, val);
52197626 VOP_CTRL_SET(vop2, mipi_dclk_pol, dclk_inv);
52207627 if (vcstate->hold_mode) {
....@@ -5224,8 +7631,19 @@
52247631 }
52257632
52267633 if (vcstate->output_if & VOP_OUTPUT_IF_MIPI1) {
7634
+ ret = vop2_calc_cru_cfg(crtc, VOP_OUTPUT_IF_MIPI1, &if_pixclk, &if_dclk);
7635
+ if (ret < 0)
7636
+ goto out;
7637
+ if (if_pixclk)
7638
+ VOP_CTRL_SET(vop2, mipi1_pixclk_div, if_pixclk->div_val);
7639
+
7640
+ if (vcstate->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
7641
+ VOP_CTRL_SET(vop2, mipi1_ds_mode, 1);
7642
+
7643
+ port_mux = vop2_get_mipi_port_mux(vop2, vp_data->id);
7644
+
52277645 VOP_CTRL_SET(vop2, mipi1_en, 1);
5228
- VOP_CTRL_SET(vop2, mipi1_mux, vp_data->id);
7646
+ VOP_CTRL_SET(vop2, mipi1_mux, port_mux);
52297647 VOP_CTRL_SET(vop2, mipi_pin_pol, val);
52307648 VOP_CTRL_SET(vop2, mipi_dclk_pol, dclk_inv);
52317649 if (vcstate->hold_mode) {
....@@ -5234,41 +7652,78 @@
52347652 }
52357653 }
52367654
5237
- if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
5238
- VOP_MODULE_SET(vop2, vp, mipi_dual_en, 1);
5239
- if (vcstate->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
5240
- VOP_MODULE_SET(vop2, vp, mipi_dual_channel_swap, 1);
5241
- }
7655
+ if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
7656
+ vop2_setup_dual_channel_if(crtc);
52427657
52437658 if (vcstate->output_if & VOP_OUTPUT_IF_eDP0) {
7659
+ ret = vop2_calc_cru_cfg(crtc, VOP_OUTPUT_IF_eDP0, &if_pixclk, &if_dclk);
7660
+ if (ret < 0)
7661
+ goto out;
7662
+ if (if_pixclk && if_dclk) {
7663
+ VOP_CTRL_SET(vop2, edp0_pixclk_div, if_pixclk->div_val);
7664
+ VOP_CTRL_SET(vop2, edp0_dclk_div, if_dclk->div_val);
7665
+ }
7666
+
52447667 VOP_CTRL_SET(vop2, edp0_en, 1);
52457668 VOP_CTRL_SET(vop2, edp0_mux, vp_data->id);
52467669 VOP_CTRL_SET(vop2, edp_pin_pol, val);
52477670 VOP_CTRL_SET(vop2, edp_dclk_pol, dclk_inv);
7671
+ VOP_GRF_SET(vop2, grf, grf_edp0_en, 1);
52487672 }
52497673
52507674 if (vcstate->output_if & VOP_OUTPUT_IF_eDP1) {
7675
+ ret = vop2_calc_cru_cfg(crtc, VOP_OUTPUT_IF_eDP1, &if_pixclk, &if_dclk);
7676
+ if (ret < 0)
7677
+ goto out;
7678
+ if (if_pixclk && if_dclk) {
7679
+ VOP_CTRL_SET(vop2, edp1_pixclk_div, if_pixclk->div_val);
7680
+ VOP_CTRL_SET(vop2, edp1_dclk_div, if_dclk->div_val);
7681
+ }
7682
+
52517683 VOP_CTRL_SET(vop2, edp1_en, 1);
52527684 VOP_CTRL_SET(vop2, edp1_mux, vp_data->id);
52537685 VOP_CTRL_SET(vop2, edp_pin_pol, val);
52547686 VOP_CTRL_SET(vop2, edp_dclk_pol, dclk_inv);
7687
+ VOP_GRF_SET(vop2, grf, grf_edp1_en, 1);
52557688 }
52567689
52577690 if (vcstate->output_if & VOP_OUTPUT_IF_DP0) {
7691
+ ret = vop2_calc_cru_cfg(crtc, VOP_OUTPUT_IF_DP0, &if_pixclk, &if_dclk);
7692
+ if (ret < 0)
7693
+ goto out;
52587694 VOP_CTRL_SET(vop2, dp0_en, 1);
52597695 VOP_CTRL_SET(vop2, dp0_mux, vp_data->id);
5260
- VOP_CTRL_SET(vop2, dp_dclk_pol, 0);
5261
- VOP_CTRL_SET(vop2, dp_pin_pol, val);
7696
+ VOP_CTRL_SET(vop2, dp0_dclk_pol, 0);
7697
+ VOP_CTRL_SET(vop2, dp0_pin_pol, val);
52627698 }
52637699
52647700 if (vcstate->output_if & VOP_OUTPUT_IF_DP1) {
7701
+ ret = vop2_calc_cru_cfg(crtc, VOP_OUTPUT_IF_DP0, &if_pixclk, &if_dclk);
7702
+ if (ret < 0)
7703
+ goto out;
7704
+
52657705 VOP_CTRL_SET(vop2, dp1_en, 1);
52667706 VOP_CTRL_SET(vop2, dp1_mux, vp_data->id);
5267
- VOP_CTRL_SET(vop2, dp_dclk_pol, 0);
5268
- VOP_CTRL_SET(vop2, dp_pin_pol, val);
7707
+ VOP_CTRL_SET(vop2, dp1_dclk_pol, 0);
7708
+ VOP_CTRL_SET(vop2, dp1_pin_pol, val);
52697709 }
52707710
52717711 if (vcstate->output_if & VOP_OUTPUT_IF_HDMI0) {
7712
+ ret = vop2_calc_cru_cfg(crtc, VOP_OUTPUT_IF_HDMI0, &if_pixclk, &if_dclk);
7713
+ if (ret < 0)
7714
+ goto out;
7715
+ if (if_pixclk && if_dclk) {
7716
+ VOP_CTRL_SET(vop2, hdmi0_pixclk_div, if_pixclk->div_val);
7717
+ VOP_CTRL_SET(vop2, hdmi0_dclk_div, if_dclk->div_val);
7718
+ }
7719
+
7720
+ if (vcstate->dsc_enable)
7721
+ VOP_GRF_SET(vop2, grf, grf_hdmi0_dsc_en, 1);
7722
+
7723
+ val = vop2_get_hdmi_pol(vop2, adjusted_mode->flags);
7724
+ VOP_GRF_SET(vop2, grf, grf_hdmi0_en, 1);
7725
+ VOP_GRF_SET(vop2, vo1_grf, grf_hdmi0_pin_pol, val);
7726
+
52727727 VOP_CTRL_SET(vop2, hdmi0_en, 1);
52737728 VOP_CTRL_SET(vop2, hdmi0_mux, vp_data->id);
52747729 VOP_CTRL_SET(vop2, hdmi_pin_pol, val);
....@@ -5276,11 +7731,29 @@
52767731 }
52777732
52787733 if (vcstate->output_if & VOP_OUTPUT_IF_HDMI1) {
7734
+ ret = vop2_calc_cru_cfg(crtc, VOP_OUTPUT_IF_HDMI1, &if_pixclk, &if_dclk);
7735
+ if (ret < 0)
7736
+ goto out;
7737
+
7738
+ if (if_pixclk && if_dclk) {
7739
+ VOP_CTRL_SET(vop2, hdmi1_pixclk_div, if_pixclk->div_val);
7740
+ VOP_CTRL_SET(vop2, hdmi1_dclk_div, if_dclk->div_val);
7741
+ }
7742
+
7743
+ if (vcstate->dsc_enable)
7744
+ VOP_GRF_SET(vop2, grf, grf_hdmi1_dsc_en, 1);
7745
+
7746
+ val = vop2_get_hdmi_pol(vop2, adjusted_mode->flags);
7747
+ VOP_GRF_SET(vop2, grf, grf_hdmi1_en, 1);
7748
+ VOP_GRF_SET(vop2, vo1_grf, grf_hdmi1_pin_pol, val);
7749
+
52797750 VOP_CTRL_SET(vop2, hdmi1_en, 1);
52807751 VOP_CTRL_SET(vop2, hdmi1_mux, vp_data->id);
52817752 VOP_CTRL_SET(vop2, hdmi_pin_pol, val);
52827753 VOP_CTRL_SET(vop2, hdmi_dclk_pol, 1);
52837754 }
7755
+
7756
+ VOP_MODULE_SET(vop2, vp, splice_en, splice_en);
52847757
52857758 VOP_MODULE_SET(vop2, vp, htotal_pw, (htotal << 16) | hsync_len);
52867759 val = hact_st << 16;
....@@ -5318,7 +7791,13 @@
53187791 VOP_INTR_SET(vop2, intr, line_flag_num[0], act_end);
53197792 VOP_INTR_SET(vop2, intr, line_flag_num[1], act_end);
53207793
5321
- VOP_MODULE_SET(vop2, vp, vtotal_pw, vtotal << 16 | vsync_len);
7794
+ VOP_MODULE_SET(vop2, vp, dsp_vtotal, vtotal);
7795
+ VOP_MODULE_SET(vop2, vp, dsp_vs_end, vsync_len);
7796
+ /**
7797
+ * when display interface support vrr, config vtotal valid immediately
7798
+ */
7799
+ if (vcstate->max_refresh_rate && vcstate->min_refresh_rate)
7800
+ VOP_MODULE_SET(vop2, vp, sw_dsp_vtotal_imd, 1);
53227801
53237802 if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK ||
53247803 vcstate->output_if & VOP_OUTPUT_IF_BT656)
....@@ -5334,18 +7813,68 @@
53347813 VOP_MODULE_SET(vop2, vp, dclk_div2_phase_lock, 0);
53357814 }
53367815
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.
7816
+ snprintf(clk_name, sizeof(clk_name), "dclk_out%d", vp->id);
7817
+ dclk_out = vop2_clk_get(vop2, clk_name);
7818
+ snprintf(clk_name, sizeof(clk_name), "dclk_core%d", vp->id);
7819
+ dclk_core = vop2_clk_get(vop2, clk_name);
7820
+ if (dclk_out && dclk_core) {
7821
+ DRM_DEV_INFO(vop2->dev, "%s div: %d %s div: %d\n",
7822
+ __clk_get_name(dclk_out->hw.clk), dclk_out->div_val,
7823
+ __clk_get_name(dclk_core->hw.clk), dclk_core->div_val);
7824
+ VOP_MODULE_SET(vop2, vp, dclk_src_sel, 0);
7825
+ VOP_MODULE_SET(vop2, vp, dclk_out_div, dclk_out->div_val);
7826
+ VOP_MODULE_SET(vop2, vp, dclk_core_div, dclk_core->div_val);
7827
+ }
7828
+
7829
+ snprintf(clk_name, sizeof(clk_name), "dclk%d", vp->id);
7830
+ dclk = vop2_clk_get(vop2, clk_name);
7831
+ if (dclk) {
7832
+ /*
7833
+ * use HDMI_PHY_PLL as dclk source under 4K@60 if it is available,
7834
+ * otherwise use system cru as dclk source.
7835
+ */
7836
+ ret = vop2_clk_set_parent_extend(vp, vcstate, true);
7837
+ if (ret < 0)
7838
+ goto out;
7839
+
7840
+ clk_set_rate(vp->dclk, dclk->rate);
7841
+ DRM_DEV_INFO(vop2->dev, "set %s to %ld, get %ld\n",
7842
+ __clk_get_name(vp->dclk), dclk->rate, clk_get_rate(vp->dclk));
7843
+ } 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);
7853
+ }
7854
+
7855
+ if (vp_data->feature & VOP_FEATURE_OVERSCAN)
7856
+ vop2_post_config(crtc);
7857
+
7858
+ VOP_MODULE_SET(vop2, vp, almost_full_or_en, 1);
7859
+ VOP_MODULE_SET(vop2, vp, line_flag_or_en, 1);
7860
+ if (vcstate->dsc_enable) {
7861
+ if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
7862
+ vop2_crtc_enable_dsc(crtc, old_state, 0);
7863
+ vop2_crtc_enable_dsc(crtc, old_state, 1);
7864
+ } else {
7865
+ vop2_crtc_enable_dsc(crtc, old_state, vcstate->dsc_id);
7866
+ }
7867
+ }
7868
+ /* For RK3588, the reset value of background is 0xa0080200,
7869
+ * which will enable background and output a grey image. But
7870
+ * the reset value is just valid in first frame and disable
7871
+ * in follow frames. If the panel backlight is valid before
7872
+ * follow frames. The screen may flick a grey image. To avoid
7873
+ * this phenomenon appear, setting black background after
7874
+ * reset vop
53417875 */
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);
5346
-
5347
- vop2_post_config(crtc);
5348
-
7876
+ if (vop2->version == VOP_VERSION_RK3588)
7877
+ VOP_MODULE_SET(vop2, vp, dsp_background, 0x80000000);
53497878 if (is_vop3(vop2))
53507879 vop3_setup_pipe_dly(vp, NULL);
53517880
....@@ -5368,14 +7897,22 @@
53687897 */
53697898 VOP_MODULE_SET(vop2, vp, standby, 0);
53707899
5371
- drm_crtc_vblank_on(crtc);
7900
+ if (vp->mcu_timing.mcu_pix_total) {
7901
+ vop3_set_out_mode(crtc, vcstate->output_mode);
7902
+ vop3_mcu_mode_setup(crtc);
7903
+ }
53727904
7905
+ if (!vp->loader_protect)
7906
+ vop2_clk_reset(vp->dclk_rst);
7907
+ if (vcstate->dsc_enable)
7908
+ rk3588_vop2_dsc_cfg_done(crtc);
7909
+ drm_crtc_vblank_on(crtc);
53737910 /*
53747911 * restore the lut table.
53757912 */
53767913 if (vp->gamma_lut_active)
53777914 vop2_crtc_load_lut(crtc);
5378
-
7915
+out:
53797916 vop2_unlock(vop2);
53807917 }
53817918
....@@ -5393,6 +7930,30 @@
53937930 static int vop2_crtc_atomic_check(struct drm_crtc *crtc,
53947931 struct drm_crtc_state *crtc_state)
53957932 {
7933
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
7934
+ struct vop2_video_port *splice_vp;
7935
+ struct vop2 *vop2 = vp->vop2;
7936
+ const struct vop2_data *vop2_data = vop2->data;
7937
+ const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
7938
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
7939
+ struct rockchip_crtc_state *new_vcstate = to_rockchip_crtc_state(crtc_state);
7940
+ struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
7941
+
7942
+ if (vop2_has_feature(vop2, VOP_FEATURE_SPLICE)) {
7943
+ if (adjusted_mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) {
7944
+ vcstate->splice_mode = true;
7945
+ splice_vp = &vop2->vps[vp_data->splice_vp_id];
7946
+ splice_vp->splice_mode_right = true;
7947
+ splice_vp->left_vp = vp;
7948
+ }
7949
+ }
7950
+
7951
+ if ((vcstate->request_refresh_rate != new_vcstate->request_refresh_rate) ||
7952
+ crtc_state->active_changed || crtc_state->mode_changed)
7953
+ vp->refresh_rate_change = true;
7954
+ else
7955
+ vp->refresh_rate_change = false;
7956
+
53967957 return 0;
53977958 }
53987959
....@@ -5427,12 +7988,13 @@
54277988 struct drm_plane *plane = &win->base;
54287989 struct drm_plane_state *pstate = plane->state;
54297990 struct vop2_plane_state *vpstate = to_vop2_plane_state(pstate);
5430
- struct drm_crtc_state *cstate = vp->crtc.state;
7991
+ struct drm_crtc_state *cstate = vp->rockchip_crtc.crtc.state;
54317992 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(cstate);
54327993 unsigned long win_mask = vp->win_mask;
54337994 int phys_id;
54347995 struct hdrvivid_regs *hdrvivid_data;
54357996 struct hdr_extend *hdr_data;
7997
+ struct rockchip_gem_object *lut_gem_obj;
54367998 bool have_sdr_layer = false;
54377999 uint32_t hdr_mode;
54388000 int i;
....@@ -5463,7 +8025,7 @@
54638025 if (hdr_mode == SDR2HLG_USERSPACE)
54648026 hdr_mode = SDR2HLG;
54658027
5466
- if (hdr_mode <= HDR102SDR && vpstate->eotf != SMPTE_ST2084 && vpstate->eotf != HLG) {
8028
+ if (hdr_mode <= HDR102SDR && vpstate->eotf != HDMI_EOTF_SMPTE_ST2084 && vpstate->eotf != HDMI_EOTF_BT_2100_HLG) {
54678029 DRM_ERROR("Invalid HDR mode:%d, mismatch plane eotf:%d\n", hdr_mode,
54688030 vpstate->eotf);
54698031 return;
....@@ -5493,7 +8055,8 @@
54938055 if (!vop2_plane_active(pstate))
54948056 continue;
54958057
5496
- if (vpstate->eotf != SMPTE_ST2084 && vpstate->eotf != HLG) {
8058
+ if (vpstate->eotf != HDMI_EOTF_SMPTE_ST2084 &&
8059
+ vpstate->eotf != HDMI_EOTF_BT_2100_HLG) {
54978060 have_sdr_layer = true;
54988061 break;
54998062 }
....@@ -5546,6 +8109,16 @@
55468109 vop2_writel(vop2, RK3528_HDR_CSC_COE20_21, hdrvivid_data->hdr_csc_coe20_21);
55478110 vop2_writel(vop2, RK3528_HDR_CSC_COE22, hdrvivid_data->hdr_csc_coe22);
55488111
8112
+ if (!vp->hdr_lut_gem_obj) {
8113
+ lut_gem_obj = rockchip_gem_create_object(vop2->drm_dev,
8114
+ RK_HDRVIVID_TONE_SCA_AXI_TAB_LENGTH * 4, true, 0);
8115
+ if (IS_ERR(lut_gem_obj)) {
8116
+ DRM_ERROR("create hdr lut obj failed\n");
8117
+ return;
8118
+ }
8119
+ vp->hdr_lut_gem_obj = lut_gem_obj;
8120
+ }
8121
+
55498122 tone_lut_kvaddr = (u32 *)vp->hdr_lut_gem_obj->kvaddr;
55508123 tone_lut_mst = vp->hdr_lut_gem_obj->dma_addr;
55518124
....@@ -5583,7 +8156,7 @@
55838156
55848157 static void vop3_setup_dynamic_hdr(struct vop2_video_port *vp, uint8_t win_phys_id)
55858158 {
5586
- struct drm_crtc_state *cstate = vp->crtc.state;
8159
+ struct drm_crtc_state *cstate = vp->rockchip_crtc.crtc.state;
55878160 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(cstate);
55888161 struct hdr_extend *hdr_data;
55898162 uint32_t hdr_format;
....@@ -5619,13 +8192,13 @@
56198192 struct vop2 *vop2 = vp->vop2;
56208193 struct vop2_win *win = vop2_find_win_by_phys_id(vop2, win_phys_id);
56218194 struct drm_plane *plane = &win->base;
5622
- struct drm_plane_state *pstate = plane->state;
5623
- struct vop2_plane_state *vpstate = to_vop2_plane_state(pstate);
5624
- struct drm_crtc_state *cstate = vp->crtc.state;
5625
- struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(cstate);
8195
+ struct drm_plane_state *pstate;
8196
+ struct drm_crtc_state *cstate = vp->rockchip_crtc.crtc.state;
56268197 const struct vop2_data *vop2_data = vop2->data;
56278198 const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
56288199 const struct vop_hdr_table *hdr_table = vp_data->hdr_table;
8200
+ struct rockchip_crtc_state *vcstate;
8201
+ struct vop2_plane_state *vpstate;
56298202 uint32_t lut_mode = VOP2_HDR_LUT_MODE_AHB;
56308203 uint32_t sdr2hdr_r2r_mode = 0;
56318204 bool hdr_en = 0;
....@@ -5645,14 +8218,27 @@
56458218 return;
56468219
56478220 /*
8221
+ * right vp share the same crtc/plane state in splice mode
8222
+ */
8223
+ if (vp->splice_mode_right) {
8224
+ vcstate = to_rockchip_crtc_state(vp->left_vp->rockchip_crtc.crtc.state);
8225
+ pstate = win->left_win->base.state;
8226
+ } else {
8227
+ vcstate = to_rockchip_crtc_state(cstate);
8228
+ pstate = plane->state;
8229
+ }
8230
+
8231
+ vpstate = to_vop2_plane_state(pstate);
8232
+
8233
+ /*
56488234 * HDR video plane input
56498235 */
5650
- if (vpstate->eotf == SMPTE_ST2084)
8236
+ if (vpstate->eotf == HDMI_EOTF_SMPTE_ST2084)
56518237 hdr_en = 1;
56528238
56538239 vp->hdr_en = hdr_en;
56548240 vp->hdr_in = hdr_en;
5655
- vp->hdr_out = (vcstate->eotf == SMPTE_ST2084) ? true : false;
8241
+ vp->hdr_out = (vcstate->eotf == HDMI_EOTF_SMPTE_ST2084) ? true : false;
56568242
56578243 /*
56588244 * only laryer0 support hdr2sdr
....@@ -5670,15 +8256,21 @@
56708256 */
56718257 for_each_set_bit(phys_id, &win_mask, ROCKCHIP_MAX_LAYER) {
56728258 win = vop2_find_win_by_phys_id(vop2, phys_id);
5673
- plane = &win->base;
5674
- pstate = plane->state;
5675
- vpstate = to_vop2_plane_state(pstate);
8259
+ if (vp->splice_mode_right) {
8260
+ if (win->left_win)
8261
+ pstate = win->left_win->base.state;
8262
+ else
8263
+ pstate = NULL; /* this win is not activated */
8264
+ } else {
8265
+ pstate = win->base.state;
8266
+ }
56768267
5677
- /* skip inactive plane */
8268
+ vpstate = pstate ? to_vop2_plane_state(pstate) : NULL;
8269
+
56788270 if (!vop2_plane_active(pstate))
56798271 continue;
56808272
5681
- if (vpstate->eotf != SMPTE_ST2084) {
8273
+ if (vpstate->eotf != HDMI_EOTF_SMPTE_ST2084) {
56828274 have_sdr_layer = true;
56838275 break;
56848276 }
....@@ -5825,7 +8417,15 @@
58258417
58268418 if (!sub_win) {
58278419 /* At one win mode, win0 is dst/bottom win, and win1 is a all zero src/top win */
5828
- plane = &main_win->base;
8420
+
8421
+ /*
8422
+ * right cluster share the same plane state in splice mode
8423
+ */
8424
+ if (cluster->splice_mode)
8425
+ plane = &main_win->left_win->base;
8426
+ else
8427
+ plane = &main_win->base;
8428
+
58298429 top_win_vpstate = NULL;
58308430 bottom_win_vpstate = to_vop2_plane_state(plane->state);
58318431 src_glb_alpha_val = 0;
....@@ -5884,25 +8484,35 @@
58848484 uint32_t dst_color_ctrl_offset = vop2->data->ctrl->dst_color_ctrl.offset;
58858485 uint32_t src_alpha_ctrl_offset = vop2->data->ctrl->src_alpha_ctrl.offset;
58868486 uint32_t dst_alpha_ctrl_offset = vop2->data->ctrl->dst_alpha_ctrl.offset;
8487
+ unsigned long win_mask = vp->win_mask;
58878488 const struct vop2_zpos *zpos;
5888
- struct drm_framebuffer *fb;
8489
+ struct vop2_plane_state *vpstate;
58898490 struct vop2_alpha_config alpha_config;
58908491 struct vop2_alpha alpha;
58918492 struct vop2_win *win;
5892
- struct drm_plane *plane;
5893
- struct vop2_plane_state *vpstate;
8493
+ struct drm_plane_state *pstate;
8494
+ struct drm_framebuffer *fb;
58948495 int pixel_alpha_en;
5895
- int premulti_en;
8496
+ int premulti_en = 1;
58968497 int mixer_id;
8498
+ int phys_id;
58978499 uint32_t offset;
58988500 int i;
58998501 bool bottom_layer_alpha_en = false;
59008502 u32 dst_global_alpha = 0xff;
59018503
5902
- drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
5903
- struct vop2_win *win = to_vop2_win(plane);
8504
+ for_each_set_bit(phys_id, &win_mask, ROCKCHIP_MAX_LAYER) {
8505
+ win = vop2_find_win_by_phys_id(vop2, phys_id);
8506
+ if (win->splice_mode_right)
8507
+ pstate = win->left_win->base.state;
8508
+ else
8509
+ pstate = win->base.state;
59048510
5905
- vpstate = to_vop2_plane_state(plane->state);
8511
+ vpstate = to_vop2_plane_state(pstate);
8512
+
8513
+ if (!vop2_plane_active(pstate))
8514
+ continue;
8515
+
59068516 if (vpstate->zpos == 0 && vpstate->global_alpha != 0xff &&
59078517 !vop2_cluster_window(win)) {
59088518 /*
....@@ -5912,19 +8522,33 @@
59128522 */
59138523 bottom_layer_alpha_en = true;
59148524 dst_global_alpha = vpstate->global_alpha;
8525
+ if (pstate->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI)
8526
+ premulti_en = 1;
8527
+ else
8528
+ premulti_en = 0;
8529
+
59158530 break;
59168531 }
59178532 }
59188533
59198534 mixer_id = vop2_find_start_mixer_id_for_vp(vop2, vp->id);
8535
+
8536
+ if (vop2->version == VOP_VERSION_RK3588 &&
8537
+ vp->hdr10_at_splice_mode && vp->id == 0)
8538
+ mixer_id++;/* fixed path for rk3588: layer1 -> hdr10_1 */
8539
+
59208540 alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */
59218541 for (i = 1; i < vp->nr_layers; i++) {
59228542 zpos = &vop2_zpos[i];
59238543 win = vop2_find_win_by_phys_id(vop2, zpos->win_phys_id);
5924
- plane = &win->base;
5925
- vpstate = to_vop2_plane_state(plane->state);
5926
- fb = plane->state->fb;
5927
- if (plane->state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI)
8544
+ if (win->splice_mode_right)
8545
+ pstate = win->left_win->base.state;
8546
+ else
8547
+ pstate = win->base.state;
8548
+
8549
+ vpstate = to_vop2_plane_state(pstate);
8550
+ fb = pstate->fb;
8551
+ if (pstate->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI)
59288552 premulti_en = 1;
59298553 else
59308554 premulti_en = 0;
....@@ -5954,29 +8578,27 @@
59548578 vop2_writel(vop2, dst_color_ctrl_offset + offset, alpha.dst_color_ctrl.val);
59558579 vop2_writel(vop2, src_alpha_ctrl_offset + offset, alpha.src_alpha_ctrl.val);
59568580 vop2_writel(vop2, dst_alpha_ctrl_offset + offset, alpha.dst_alpha_ctrl.val);
8581
+ }
59578582
5958
- if (i == 1) {
5959
- if (bottom_layer_alpha_en || vp->hdr_en) {
5960
- /* Transfer pixel alpha to hdr mix */
5961
- alpha_config.src_premulti_en = premulti_en;
5962
- alpha_config.dst_premulti_en = true;
5963
- alpha_config.src_pixel_alpha_en = true;
5964
- alpha_config.src_glb_alpha_value = 0xff;
5965
- alpha_config.dst_glb_alpha_value = 0xff;
5966
- vop2_parse_alpha(&alpha_config, &alpha);
8583
+ if (bottom_layer_alpha_en || vp->hdr_en) {
8584
+ /* Transfer pixel alpha to hdr mix */
8585
+ alpha_config.src_premulti_en = premulti_en;
8586
+ alpha_config.dst_premulti_en = true;
8587
+ alpha_config.src_pixel_alpha_en = true;
8588
+ alpha_config.src_glb_alpha_value = 0xff;
8589
+ alpha_config.dst_glb_alpha_value = 0xff;
8590
+ vop2_parse_alpha(&alpha_config, &alpha);
59678591
5968
- VOP_MODULE_SET(vop2, vp, hdr_src_color_ctrl,
5969
- alpha.src_color_ctrl.val);
5970
- VOP_MODULE_SET(vop2, vp, hdr_dst_color_ctrl,
5971
- alpha.dst_color_ctrl.val);
5972
- VOP_MODULE_SET(vop2, vp, hdr_src_alpha_ctrl,
5973
- alpha.src_alpha_ctrl.val);
5974
- VOP_MODULE_SET(vop2, vp, hdr_dst_alpha_ctrl,
5975
- alpha.dst_alpha_ctrl.val);
5976
- } else {
5977
- VOP_MODULE_SET(vop2, vp, hdr_src_color_ctrl, 0);
5978
- }
5979
- }
8592
+ VOP_MODULE_SET(vop2, vp, hdr_src_color_ctrl,
8593
+ alpha.src_color_ctrl.val);
8594
+ VOP_MODULE_SET(vop2, vp, hdr_dst_color_ctrl,
8595
+ alpha.dst_color_ctrl.val);
8596
+ VOP_MODULE_SET(vop2, vp, hdr_src_alpha_ctrl,
8597
+ alpha.src_alpha_ctrl.val);
8598
+ VOP_MODULE_SET(vop2, vp, hdr_dst_alpha_ctrl,
8599
+ alpha.dst_alpha_ctrl.val);
8600
+ } else {
8601
+ VOP_MODULE_SET(vop2, vp, hdr_src_color_ctrl, 0);
59808602 }
59818603
59828604 /* Transfer pixel alpha value to next mix */
....@@ -6137,21 +8759,6 @@
61378759 VOP_MODULE_SET(vop2, vp, bg_mix_ctrl, bg_alpha_ctrl.val);
61388760 }
61398761
6140
-static void vop2_setup_port_mux(struct vop2_video_port *vp, uint16_t port_mux_cfg)
6141
-{
6142
- struct vop2 *vop2 = vp->vop2;
6143
-
6144
- spin_lock(&vop2->reg_lock);
6145
- if (vop2->port_mux_cfg != port_mux_cfg) {
6146
- VOP_CTRL_SET(vop2, ovl_port_mux_cfg, port_mux_cfg);
6147
- vp->skip_vsync = true;
6148
- vop2_cfg_done(&vp->crtc);
6149
- vop2->port_mux_cfg = port_mux_cfg;
6150
- vop2_wait_for_port_mux_done(vop2);
6151
- }
6152
- spin_unlock(&vop2->reg_lock);
6153
-}
6154
-
61558762 static u32 vop2_layer_cfg_update(struct vop2_layer *layer, u32 old_layer_cfg, u8 win_layer_id)
61568763 {
61578764 const struct vop_reg *reg = &layer->regs->layer_sel;
....@@ -6174,6 +8781,12 @@
61748781 for (i = 0; i < vop2_data->nr_vps - 1; i++) {
61758782 prev_vp = &vop2->vps[i];
61768783 used_layers += hweight32(prev_vp->win_mask);
8784
+ if (vop2->version == VOP_VERSION_RK3588) {
8785
+ if (vop2->vps[0].hdr10_at_splice_mode && i == 0)
8786
+ used_layers += 1;
8787
+ if (vop2->vps[0].hdr10_at_splice_mode && i == 1)
8788
+ used_layers -= 1;
8789
+ }
61778790 /*
61788791 * when a window move from vp0 to vp1, or vp0 to vp2,
61798792 * it should flow these steps:
....@@ -6199,10 +8812,26 @@
61998812 prev_vp->bg_ovl_dly = (vop2_data->nr_mixers - port_mux) << 1;
62008813 }
62018814
6202
- if (vop2->data->nr_vps >= 1)
6203
- port_mux_cfg |= 7 << (4 * (vop2->data->nr_vps - 1));
8815
+ port_mux_cfg |= 7 << (4 * (vop2->data->nr_vps - 1));
62048816
62058817 return port_mux_cfg;
8818
+}
8819
+
8820
+static void vop2_setup_port_mux(struct vop2_video_port *vp)
8821
+{
8822
+ struct vop2 *vop2 = vp->vop2;
8823
+ u16 port_mux_cfg;
8824
+
8825
+ port_mux_cfg = vop2_calc_bg_ovl_and_port_mux(vp);
8826
+ spin_lock(&vop2->reg_lock);
8827
+ if (vop2->port_mux_cfg != port_mux_cfg) {
8828
+ VOP_CTRL_SET(vop2, ovl_port_mux_cfg, port_mux_cfg);
8829
+ vp->skip_vsync = true;
8830
+ vop2_cfg_done(&vp->rockchip_crtc.crtc);
8831
+ vop2->port_mux_cfg = port_mux_cfg;
8832
+ vop2_wait_for_port_mux_done(vop2);
8833
+ }
8834
+ spin_unlock(&vop2->reg_lock);
62068835 }
62078836
62088837 static void vop2_setup_layer_mixer_for_vp(struct vop2_video_port *vp,
....@@ -6216,15 +8845,12 @@
62168845 struct vop2_win *win;
62178846 u8 used_layers = 0;
62188847 u8 layer_id, win_phys_id;
6219
- u16 port_mux_cfg;
62208848 u32 layer_cfg_reg_offset = layer->regs->layer_sel.offset;
62218849 u8 nr_layers = vp->nr_layers;
62228850 u32 old_layer_cfg = 0;
62238851 u32 new_layer_cfg = 0;
62248852 u32 atv_layer_cfg;
62258853 int i;
6226
-
6227
- port_mux_cfg = vop2_calc_bg_ovl_and_port_mux(vp);
62288854
62298855 /*
62308856 * Win and layer must map one by one, if a win is selected
....@@ -6240,6 +8866,10 @@
62408866
62418867 old_layer_cfg = vop2->regsbak[layer_cfg_reg_offset >> 2];
62428868 new_layer_cfg = old_layer_cfg;
8869
+
8870
+ if (vp->hdr10_at_splice_mode)
8871
+ nr_layers *= 2;
8872
+
62438873 for (i = 0; i < nr_layers; i++) {
62448874 layer = &vop2->layers[used_layers + i];
62458875 zpos = &vop2_zpos[i];
....@@ -6253,21 +8883,21 @@
62538883 layer = &vop2->layers[layer_id];
62548884 win = vop2_find_win_by_phys_id(vop2, win_phys_id);
62558885 new_layer_cfg = vop2_layer_cfg_update(layer, new_layer_cfg, win->layer_sel_id[vp->id]);
6256
- win->layer_id = layer->id;
62578886 win->layer_id = layer_id;
62588887 layer->win_phys_id = win_phys_id;
62598888 }
62608889
62618890 atv_layer_cfg = vop2_read_layer_cfg(vop2);
6262
- if ((new_layer_cfg != old_layer_cfg) &&
6263
- (atv_layer_cfg != old_layer_cfg)) {
8891
+ if (new_layer_cfg != old_layer_cfg &&
8892
+ atv_layer_cfg != old_layer_cfg &&
8893
+ !vp->splice_mode_right) {
62648894 dev_dbg(vop2->dev, "wait old_layer_sel: 0x%x\n", old_layer_cfg);
62658895 vop2_wait_for_layer_cfg_done(vop2, old_layer_cfg);
62668896 }
62678897 vop2_writel(vop2, RK3568_OVL_LAYER_SEL, new_layer_cfg);
6268
- VOP_CTRL_SET(vop2, ovl_cfg_done_port, vp->id);
8898
+ if (new_layer_cfg != old_layer_cfg)
8899
+ VOP_CTRL_SET(vop2, ovl_cfg_done_port, vp->id);
62698900 VOP_CTRL_SET(vop2, ovl_port_mux_cfg_done_imd, 0);
6270
- vop2_setup_port_mux(vp, port_mux_cfg);
62718901 }
62728902
62738903 static void vop3_setup_layer_sel_for_vp(struct vop2_video_port *vp,
....@@ -6310,7 +8940,9 @@
63108940 struct vop2 *vop2 = vp->vop2;
63118941 const struct vop2_data *vop2_data = vop2->data;
63128942 const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
6313
- struct drm_crtc *crtc = &vp->crtc;
8943
+ struct vop2_video_port *left_vp = vp->left_vp;
8944
+ struct drm_crtc *crtc = &vp->rockchip_crtc.crtc;
8945
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
63148946 struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
63158947 u16 hsync_len = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
63168948 u16 hdisplay = adjusted_mode->crtc_hdisplay;
....@@ -6329,13 +8961,30 @@
63298961 }
63308962 }
63318963
6332
- if (!vp->hdr_in)
8964
+ if (!vp->hdr_in ||
8965
+ (vop2->version == VOP_VERSION_RK3588 && vp->hdr_out))
63338966 bg_dly -= vp->bg_ovl_dly;
63348967
6335
- pre_scan_dly = bg_dly + (hdisplay >> 1) - 1;
6336
- if (vop2->version >= VOP_VERSION_RK3588 && hsync_len < 8)
8968
+ /*
8969
+ * right vp share the same crtc state in splice mode
8970
+ */
8971
+ if (vp->splice_mode_right) {
8972
+ vcstate = to_rockchip_crtc_state(left_vp->rockchip_crtc.crtc.state);
8973
+ adjusted_mode = &left_vp->rockchip_crtc.crtc.state->adjusted_mode;
8974
+ hsync_len = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
8975
+ hdisplay = adjusted_mode->crtc_hdisplay;
8976
+ }
8977
+
8978
+ if (vcstate->splice_mode)
8979
+ pre_scan_dly = bg_dly + (hdisplay >> 2) - 1;
8980
+ else
8981
+ pre_scan_dly = bg_dly + (hdisplay >> 1) - 1;
8982
+
8983
+ if (vop2->version == VOP_VERSION_RK3588 && hsync_len < 8)
63378984 hsync_len = 8;
8985
+
63388986 pre_scan_dly = (pre_scan_dly << 16) | hsync_len;
8987
+
63398988 VOP_MODULE_SET(vop2, vp, bg_dly, bg_dly);
63408989 VOP_MODULE_SET(vop2, vp, pre_scan_htiming, pre_scan_dly);
63418990 }
....@@ -6353,8 +9002,17 @@
63539002 for (i = 0; i < vp->nr_layers; i++) {
63549003 zpos = &vop2_zpos[i];
63559004 win = vop2_find_win_by_phys_id(vop2, zpos->win_phys_id);
6356
- plane = &win->base;
6357
- vpstate = to_vop2_plane_state(plane->state);
9005
+ /*
9006
+ * right vp share the same plane state in splice mode
9007
+ */
9008
+ if (vp->splice_mode_right) {
9009
+ plane = &win->left_win->base;
9010
+ vpstate = to_vop2_plane_state(plane->state);
9011
+ } else {
9012
+ plane = &win->base;
9013
+ vpstate = to_vop2_plane_state(plane->state);
9014
+ }
9015
+
63589016 if (vp->hdr_in && !vp->hdr_out && !vpstate->hdr_in) {
63599017 dly = win->dly[VOP2_DLY_MODE_HISO_S];
63609018 dly += vp->bg_ovl_dly;
....@@ -6371,22 +9029,128 @@
63719029 }
63729030 }
63739031
9032
+static void rk3588_vop2_setup_hdr10_splice_layer_mixer(struct drm_crtc *crtc,
9033
+ struct vop2_zpos *vop2_zpos,
9034
+ struct vop2_zpos *vop2_zpos_splice)
9035
+{
9036
+ int zpos_id, i;
9037
+ struct vop2_zpos *vop2_zpos_splice_hdr;
9038
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
9039
+ struct vop2 *vop2 = vp->vop2;
9040
+
9041
+ vop2_zpos_splice_hdr = kmalloc_array(vop2->data->win_size, sizeof(*vop2_zpos),
9042
+ GFP_KERNEL);
9043
+ if (!vop2_zpos_splice_hdr)
9044
+ goto out;
9045
+
9046
+ zpos_id = 0;
9047
+ vop2_zpos_splice_hdr[zpos_id].zpos = zpos_id;
9048
+ vop2_zpos_splice_hdr[zpos_id].win_phys_id = vop2_zpos[0].win_phys_id;
9049
+ vop2_zpos_splice_hdr[zpos_id].plane = vop2_zpos[0].plane;
9050
+
9051
+ zpos_id++;
9052
+ vop2_zpos_splice_hdr[zpos_id].zpos = zpos_id;
9053
+ vop2_zpos_splice_hdr[zpos_id].win_phys_id = vop2_zpos_splice[0].win_phys_id;
9054
+ vop2_zpos_splice_hdr[zpos_id].plane = vop2_zpos_splice[0].plane;
9055
+
9056
+ for (i = 1; i < vp->nr_layers; i++) {
9057
+ zpos_id++;
9058
+ vop2_zpos_splice_hdr[zpos_id].zpos = zpos_id;
9059
+ vop2_zpos_splice_hdr[zpos_id].win_phys_id = vop2_zpos[i].win_phys_id;
9060
+ vop2_zpos_splice_hdr[zpos_id].plane = vop2_zpos[i].plane;
9061
+ }
9062
+
9063
+ for (i = 1; i < vp->nr_layers; i++) {
9064
+ zpos_id++;
9065
+ vop2_zpos_splice_hdr[zpos_id].zpos = zpos_id;
9066
+ vop2_zpos_splice_hdr[zpos_id].win_phys_id = vop2_zpos_splice[i].win_phys_id;
9067
+ vop2_zpos_splice_hdr[zpos_id].plane = vop2_zpos_splice[i].plane;
9068
+ }
9069
+ vop2_setup_layer_mixer_for_vp(vp, vop2_zpos_splice_hdr);
9070
+
9071
+out:
9072
+ kfree(vop2_zpos_splice_hdr);
9073
+}
9074
+
9075
+static void vop2_crtc_update_vrr(struct drm_crtc *crtc)
9076
+{
9077
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
9078
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
9079
+ struct vop2 *vop2 = vp->vop2;
9080
+ struct drm_display_mode *adjust_mode = &crtc->state->adjusted_mode;
9081
+
9082
+ unsigned int vrefresh;
9083
+ unsigned int new_vtotal, vfp, new_vfp;
9084
+
9085
+ if (!vp->refresh_rate_change)
9086
+ return;
9087
+
9088
+ if (!vcstate->min_refresh_rate || !vcstate->max_refresh_rate)
9089
+ return;
9090
+
9091
+ if (vcstate->request_refresh_rate < vcstate->min_refresh_rate ||
9092
+ vcstate->request_refresh_rate > vcstate->max_refresh_rate) {
9093
+ DRM_ERROR("invalid rate:%d\n", vcstate->request_refresh_rate);
9094
+ return;
9095
+ }
9096
+
9097
+ vrefresh = drm_mode_vrefresh(adjust_mode);
9098
+
9099
+ /* calculate new vfp for new refresh rate */
9100
+ new_vtotal = adjust_mode->vtotal * vrefresh / vcstate->request_refresh_rate;
9101
+ vfp = adjust_mode->vsync_start - adjust_mode->vdisplay;
9102
+ new_vfp = vfp + new_vtotal - adjust_mode->vtotal;
9103
+
9104
+ /* config vop2 vtotal register */
9105
+ VOP_MODULE_SET(vop2, vp, dsp_vtotal, new_vtotal);
9106
+
9107
+ /* config dsc vtotal register */
9108
+ if (vcstate->dsc_enable) {
9109
+ struct vop2_dsc *dsc;
9110
+
9111
+ dsc = &vop2->dscs[vcstate->dsc_id];
9112
+ VOP_MODULE_SET(vop2, dsc, dsc_vtotal, new_vtotal);
9113
+
9114
+ if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
9115
+ dsc = &vop2->dscs[vcstate->dsc_id ? 0 : 1];
9116
+ VOP_MODULE_SET(vop2, dsc, dsc_vtotal, new_vtotal);
9117
+ }
9118
+ }
9119
+
9120
+ /* config all connectors attach to this crtc */
9121
+ rockchip_connector_update_vfp_for_vrr(crtc, adjust_mode, new_vfp);
9122
+}
9123
+
63749124 static void vop2_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state)
63759125 {
63769126 struct vop2_video_port *vp = to_vop2_video_port(crtc);
63779127 struct vop2 *vop2 = vp->vop2;
9128
+ const struct vop2_video_port_data *vp_data = &vop2->data->vp[vp->id];
9129
+ struct vop2_video_port *splice_vp = &vop2->vps[vp_data->splice_vp_id];
63789130 struct drm_plane *plane;
63799131 struct vop2_plane_state *vpstate;
63809132 struct vop2_zpos *vop2_zpos;
9133
+ struct vop2_zpos *vop2_zpos_splice;
63819134 struct vop2_cluster cluster;
63829135 uint8_t nr_layers = 0;
9136
+ uint8_t splice_nr_layers = 0;
9137
+ bool hdr10_in = false;
9138
+ bool hdr10_at_splice_mode = false;
63839139 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];
63859140
63869141 vcstate->yuv_overlay = is_yuv_output(vcstate->bus_format);
63879142 vop2_zpos = kmalloc_array(vop2->data->win_size, sizeof(*vop2_zpos), GFP_KERNEL);
63889143 if (!vop2_zpos)
63899144 return;
9145
+ if (vcstate->splice_mode) {
9146
+ vop2_zpos_splice = kmalloc_array(vop2->data->win_size, sizeof(*vop2_zpos),
9147
+ GFP_KERNEL);
9148
+ if (!vop2_zpos_splice)
9149
+ goto out;
9150
+ }
9151
+
9152
+ if (vop2->version == VOP_VERSION_RK3588)
9153
+ vop2_crtc_update_vrr(crtc);
63909154
63919155 /* Process cluster sub windows overlay. */
63929156 drm_atomic_crtc_for_each_plane(plane, crtc) {
....@@ -6396,9 +9160,13 @@
63969160 win->two_win_mode = false;
63979161 if (!(win->feature & WIN_FEATURE_CLUSTER_SUB))
63989162 continue;
9163
+ if (vcstate->splice_mode)
9164
+ DRM_ERROR("vp%d %s not supported two win mode at splice mode\n",
9165
+ vp->id, win->name);
63999166 main_win = vop2_find_win_by_phys_id(vop2, win->phys_id);
64009167 cluster.main = main_win;
64019168 cluster.sub = win;
9169
+ cluster.splice_mode = false;
64029170 win->two_win_mode = true;
64039171 main_win->two_win_mode = true;
64049172 vop2_setup_cluster_alpha(vop2, &cluster);
....@@ -6410,6 +9178,7 @@
64109178
64119179 drm_atomic_crtc_for_each_plane(plane, crtc) {
64129180 struct vop2_win *win = to_vop2_win(plane);
9181
+ struct vop2_win *splice_win;
64139182 struct vop2_video_port *old_vp;
64149183 uint8_t old_vp_id;
64159184
....@@ -6429,35 +9198,93 @@
64299198 vop2_zpos[nr_layers].win_phys_id = win->phys_id;
64309199 vop2_zpos[nr_layers].zpos = vpstate->zpos;
64319200 vop2_zpos[nr_layers].plane = plane;
9201
+
9202
+ rockchip_drm_dbg(vop2->dev, VOP_DEBUG_OVERLAY, "%s active zpos:%d for vp%d from vp%d\n",
9203
+ win->name, vpstate->zpos, vp->id, old_vp->id);
9204
+ /* left and right win may have different number */
9205
+ if (vcstate->splice_mode) {
9206
+ splice_win = vop2_find_win_by_phys_id(vop2, win->splice_win_id);
9207
+ splice_win->splice_mode_right = true;
9208
+ splice_win->left_win = win;
9209
+ win->splice_win = splice_win;
9210
+
9211
+ old_vp_id = ffs(splice_win->vp_mask);
9212
+ old_vp_id = (old_vp_id == 0) ? 0 : old_vp_id - 1;
9213
+ old_vp = &vop2->vps[old_vp_id];
9214
+ old_vp->win_mask &= ~BIT(splice_win->phys_id);
9215
+ splice_vp->win_mask |= BIT(splice_win->phys_id);
9216
+ splice_win->vp_mask = BIT(splice_vp->id);
9217
+ hdr10_in |= vpstate->eotf == HDMI_EOTF_SMPTE_ST2084 ? true : false;
9218
+ vop2_zpos_splice[splice_nr_layers].win_phys_id = splice_win->phys_id;
9219
+ vop2_zpos_splice[splice_nr_layers].zpos = vpstate->zpos;
9220
+ vop2_zpos_splice[splice_nr_layers].plane = &splice_win->base;
9221
+ splice_nr_layers++;
9222
+ DRM_DEV_DEBUG(vop2->dev, "%s active zpos:%d for vp%d from vp%d\n",
9223
+ splice_win->name, vpstate->zpos, splice_vp->id, old_vp->id);
9224
+ }
64329225 nr_layers++;
6433
- DRM_DEV_DEBUG(vop2->dev, "%s active zpos:%d for vp%d from vp%d\n",
6434
- win->name, vpstate->zpos, vp->id, old_vp->id);
64359226 }
64369227
6437
- DRM_DEV_DEBUG(vop2->dev, "vp%d: %d windows, active layers %d\n",
6438
- vp->id, hweight32(vp->win_mask), nr_layers);
9228
+ if (vcstate->splice_mode) {
9229
+ if (hdr10_in)
9230
+ hdr10_at_splice_mode = true;
9231
+
9232
+ splice_vp->hdr10_at_splice_mode = hdr10_at_splice_mode;
9233
+ }
9234
+ vp->hdr10_at_splice_mode = hdr10_at_splice_mode;
9235
+
9236
+ rockchip_drm_dbg(vop2->dev, VOP_DEBUG_OVERLAY, "vp%d: %d windows, active layers %d\n",
9237
+ vp->id, hweight32(vp->win_mask), nr_layers);
64399238 if (nr_layers) {
64409239 vp->nr_layers = nr_layers;
64419240
64429241 sort(vop2_zpos, nr_layers, sizeof(vop2_zpos[0]), vop2_zpos_cmp, NULL);
64439242
9243
+ if (!vp->hdr10_at_splice_mode) {
9244
+ if (is_vop3(vop2)) {
9245
+ vop3_setup_layer_sel_for_vp(vp, vop2_zpos);
9246
+ } else {
9247
+ vop2_setup_port_mux(vp);
9248
+ vop2_setup_layer_mixer_for_vp(vp, vop2_zpos);
9249
+ }
9250
+ }
9251
+
64449252 if (is_vop3(vop2)) {
6445
- vop3_setup_layer_sel_for_vp(vp, vop2_zpos);
64469253 if (vp_data->feature & VOP_FEATURE_VIVID_HDR)
64479254 vop3_setup_dynamic_hdr(vp, vop2_zpos[0].win_phys_id);
64489255 vop3_setup_alpha(vp, vop2_zpos);
64499256 vop3_setup_pipe_dly(vp, vop2_zpos);
64509257 } else {
6451
- vop2_setup_layer_mixer_for_vp(vp, vop2_zpos);
64529258 vop2_setup_hdr10(vp, vop2_zpos[0].win_phys_id);
64539259 vop2_setup_alpha(vp, vop2_zpos);
64549260 vop2_setup_dly_for_vp(vp);
64559261 vop2_setup_dly_for_window(vp, vop2_zpos);
64569262 }
9263
+
9264
+ if (vcstate->splice_mode) {/* Fixme for VOP3 8K */
9265
+ splice_vp->nr_layers = splice_nr_layers;
9266
+
9267
+ sort(vop2_zpos_splice, splice_nr_layers, sizeof(vop2_zpos_splice[0]),
9268
+ vop2_zpos_cmp, NULL);
9269
+
9270
+ vop2_setup_port_mux(splice_vp);
9271
+ if (!vp->hdr10_at_splice_mode)
9272
+ vop2_setup_layer_mixer_for_vp(splice_vp, vop2_zpos_splice);
9273
+ vop2_setup_hdr10(splice_vp, vop2_zpos_splice[0].win_phys_id);
9274
+ vop2_setup_alpha(splice_vp, vop2_zpos_splice);
9275
+ vop2_setup_dly_for_vp(splice_vp);
9276
+ vop2_setup_dly_for_window(splice_vp, vop2_zpos_splice);
9277
+
9278
+ if (vop2->version == VOP_VERSION_RK3588 &&
9279
+ vp->hdr10_at_splice_mode)
9280
+ rk3588_vop2_setup_hdr10_splice_layer_mixer(crtc, vop2_zpos, vop2_zpos_splice);
9281
+ }
64579282 } else {
64589283 if (!is_vop3(vop2)) {
64599284 vop2_calc_bg_ovl_and_port_mux(vp);
64609285 vop2_setup_dly_for_vp(vp);
9286
+ if (vcstate->splice_mode)
9287
+ vop2_setup_dly_for_vp(splice_vp);
64619288 } else {
64629289 vop3_setup_pipe_dly(vp, NULL);
64639290 }
....@@ -6466,6 +9293,7 @@
64669293 /* The pre alpha overlay of Cluster still need process in one win mode. */
64679294 drm_atomic_crtc_for_each_plane(plane, crtc) {
64689295 struct vop2_win *win = to_vop2_win(plane);
9296
+ struct vop2_win *splice_win;
64699297
64709298 if (!(win->feature & WIN_FEATURE_CLUSTER_MAIN))
64719299 continue;
....@@ -6473,9 +9301,19 @@
64739301 continue;
64749302 cluster.main = win;
64759303 cluster.sub = NULL;
9304
+ cluster.splice_mode = false;
64769305 vop2_setup_cluster_alpha(vop2, &cluster);
9306
+ if (vcstate->splice_mode) {
9307
+ splice_win = win->splice_win;
9308
+ cluster.main = splice_win;
9309
+ cluster.splice_mode = true;
9310
+ vop2_setup_cluster_alpha(vop2, &cluster);
9311
+ }
64779312 }
64789313
9314
+ if (vcstate->splice_mode)
9315
+ kfree(vop2_zpos_splice);
9316
+out:
64799317 kfree(vop2_zpos);
64809318 }
64819319
....@@ -6586,6 +9424,12 @@
65869424 bcsh_state.cos_hue = cos_hue;
65879425
65889426 vop2_bcsh_reg_update(vcstate, vp, &bcsh_state);
9427
+ if (vcstate->splice_mode) {
9428
+ const struct vop2_video_port_data *vp_data = &vop2->data->vp[vp->id];
9429
+ struct vop2_video_port *splice_vp = &vop2->vps[vp_data->splice_vp_id];
9430
+
9431
+ vop2_bcsh_reg_update(vcstate, splice_vp, &bcsh_state);
9432
+ }
65899433 }
65909434
65919435 static void vop3_post_csc_config(struct drm_crtc *crtc, struct post_acm *acm, struct post_csc *csc)
....@@ -6671,25 +9515,18 @@
66719515 u32 value;
66729516 int i;
66739517
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)
9518
+ if (!acm) {
9519
+ writel(0x2, vop2->acm_regs + RK3528_ACM_CTRL);
9520
+ VOP_MODULE_SET(vop2, vp, acm_bypass_en, 1);
66789521 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
-
9522
+ }
66919523
66929524 writel(1, vop2->acm_regs + RK3528_ACM_FETCH_START);
9525
+
9526
+ value = (acm->acm_enable & 0x1) + ((adjusted_mode->hdisplay & 0xfff) << 8) +
9527
+ ((adjusted_mode->vdisplay & 0xfff) << 20);
9528
+ writel(value, vop2->acm_regs + RK3528_ACM_CTRL);
9529
+ VOP_MODULE_SET(vop2, vp, acm_bypass_en, acm->acm_enable ? 0 : 1);
66939530
66949531 value = (acm->y_gain & 0x3ff) + ((acm->h_gain << 10) & 0xffc00) +
66959532 ((acm->s_gain << 20) & 0x3ff00000);
....@@ -6728,23 +9565,14 @@
67289565 static void vop3_post_config(struct drm_crtc *crtc)
67299566 {
67309567 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
6731
- struct vop2_video_port *vp = to_vop2_video_port(crtc);
67329568 struct post_acm *acm;
67339569 struct post_csc *csc;
67349570
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
-
67409571 acm = vcstate->acm_lut_data ? (struct post_acm *)vcstate->acm_lut_data->data : NULL;
9572
+ vop3_post_acm_config(crtc, acm);
67419573
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
- }
9574
+ csc = vcstate->post_csc_data ? (struct post_csc *)vcstate->post_csc_data->data : NULL;
9575
+ vop3_post_csc_config(crtc, acm, csc);
67489576 }
67499577
67509578 static void vop2_cfg_update(struct drm_crtc *crtc,
....@@ -6755,6 +9583,7 @@
67559583 struct vop2 *vop2 = vp->vop2;
67569584 const struct vop2_data *vop2_data = vop2->data;
67579585 const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
9586
+ struct vop2_video_port *splice_vp = &vop2->vps[vp_data->splice_vp_id];
67589587 uint32_t val;
67599588 uint32_t r, g, b;
67609589 uint8_t out_mode;
....@@ -6769,10 +9598,7 @@
67699598 out_mode = vcstate->output_mode;
67709599 VOP_MODULE_SET(vop2, vp, out_mode, out_mode);
67719600
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);
9601
+ vop2_post_color_swap(crtc);
67769602
67779603 vop2_dither_setup(crtc);
67789604
....@@ -6797,15 +9623,86 @@
67979623 }
67989624
67999625 VOP_MODULE_SET(vop2, vp, dsp_background, val);
9626
+ if (vcstate->splice_mode) {
9627
+ VOP_MODULE_SET(vop2, splice_vp, overlay_mode, vcstate->yuv_overlay);
9628
+ VOP_MODULE_SET(vop2, splice_vp, dsp_background, val);
9629
+ }
68009630
68019631 vop2_tv_config_update(crtc, old_crtc_state);
68029632
6803
- vop2_post_config(crtc);
6804
-
6805
- spin_unlock(&vop2->reg_lock);
9633
+ if (vp_data->feature & VOP_FEATURE_OVERSCAN)
9634
+ vop2_post_config(crtc);
68069635
68079636 if (vp_data->feature & (VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC))
68089637 vop3_post_config(crtc);
9638
+
9639
+ spin_unlock(&vop2->reg_lock);
9640
+}
9641
+
9642
+static void vop2_sleep_scan_line_time(struct vop2_video_port *vp, int scan_line)
9643
+{
9644
+ struct vop2 *vop2 = vp->vop2;
9645
+ struct drm_display_mode *mode = &vp->rockchip_crtc.crtc.state->adjusted_mode;
9646
+
9647
+ if (scan_line <= 0)
9648
+ return;
9649
+
9650
+ if (IS_ENABLED(CONFIG_HIGH_RES_TIMERS) &&
9651
+ (!IS_ENABLED(CONFIG_NO_GKI) || (hrtimer_resolution != LOW_RES_NSEC))) {
9652
+ u16 htotal = VOP_MODULE_GET(vop2, vp, htotal_pw) >> 16;
9653
+ u32 linedur_ns = div_u64((u64) htotal * 1000000, mode->crtc_clock);
9654
+ u64 sleep_time = linedur_ns * scan_line;
9655
+
9656
+ sleep_time = div_u64((sleep_time + 1000), 1000);
9657
+ if (sleep_time > 200)
9658
+ usleep_range(sleep_time, sleep_time);
9659
+ }
9660
+}
9661
+
9662
+/*
9663
+ * return scan timing from FS to the assigned wait line
9664
+ */
9665
+static void vop2_wait_for_scan_timing_max_to_assigned_line(struct vop2_video_port *vp,
9666
+ u32 current_line,
9667
+ u32 wait_line)
9668
+
9669
+{
9670
+ struct vop2 *vop2 = vp->vop2;
9671
+ u32 vcnt;
9672
+ int ret;
9673
+ u16 vtotal = VOP_MODULE_GET(vop2, vp, dsp_vtotal);
9674
+ int delta_line = vtotal - current_line;
9675
+
9676
+ vop2_sleep_scan_line_time(vp, delta_line);
9677
+ if (vop2_read_vcnt(vp) < wait_line)
9678
+ return;
9679
+
9680
+ ret = readx_poll_timeout_atomic(vop2_read_vcnt, vp, vcnt, vcnt < wait_line, 0, 50 * 1000);
9681
+ if (ret)
9682
+ DRM_DEV_ERROR(vop2->dev, "wait scan timing from FS to the assigned wait line: %d, vcnt:%d, ret:%d\n",
9683
+ wait_line, vcnt, ret);
9684
+}
9685
+
9686
+/*
9687
+ * return scan timing from the assigned wait line
9688
+ */
9689
+static void vop2_wait_for_scan_timing_from_the_assigned_line(struct vop2_video_port *vp,
9690
+ u32 current_line,
9691
+ u32 wait_line)
9692
+{
9693
+ struct vop2 *vop2 = vp->vop2;
9694
+ u32 vcnt;
9695
+ int ret;
9696
+ int delta_line = wait_line - current_line;
9697
+
9698
+ vop2_sleep_scan_line_time(vp, delta_line);
9699
+ if (vop2_read_vcnt(vp) > wait_line)
9700
+ return;
9701
+
9702
+ ret = readx_poll_timeout_atomic(vop2_read_vcnt, vp, vcnt, vcnt > wait_line, 0, 50 * 1000);
9703
+ if (ret)
9704
+ DRM_DEV_ERROR(vop2->dev, "wait scan timing from the assigned wait line: %d, vcnt:%d, ret:%d\n",
9705
+ wait_line, vcnt, ret);
68099706 }
68109707
68119708 static void vop2_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_cstate)
....@@ -6813,11 +9710,26 @@
68139710 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
68149711 struct drm_atomic_state *old_state = old_cstate->state;
68159712 struct vop2_video_port *vp = to_vop2_video_port(crtc);
6816
- struct drm_plane_state *old_pstate;
68179713 struct vop2 *vop2 = vp->vop2;
9714
+ struct drm_plane_state *old_pstate;
68189715 struct drm_plane *plane;
68199716 unsigned long flags;
68209717 int i, ret;
9718
+ struct vop2_wb *wb = &vop2->wb;
9719
+ struct drm_writeback_connector *wb_conn = &wb->conn;
9720
+ struct drm_connector_state *conn_state = wb_conn->base.state;
9721
+
9722
+ if (conn_state && conn_state->writeback_job && conn_state->writeback_job->fb) {
9723
+ u16 vtotal = VOP_MODULE_GET(vop2, vp, dsp_vtotal);
9724
+ u32 current_line = vop2_read_vcnt(vp);
9725
+
9726
+ if (current_line > vtotal * 7 >> 3)
9727
+ vop2_wait_for_scan_timing_max_to_assigned_line(vp, current_line, vtotal * 7 >> 3);
9728
+
9729
+ current_line = vop2_read_vcnt(vp);
9730
+ if (current_line < vtotal >> 3)
9731
+ vop2_wait_for_scan_timing_from_the_assigned_line(vp, current_line, vtotal >> 3);
9732
+ }
68219733
68229734 vop2_cfg_update(crtc, old_cstate);
68239735
....@@ -6843,12 +9755,13 @@
68439755 vp->gamma_lut = crtc->state->gamma_lut->data;
68449756 vop2_crtc_atomic_gamma_set(crtc, crtc->state);
68459757 }
6846
-
9758
+#if defined(CONFIG_ROCKCHIP_DRM_CUBIC_LUT)
68479759 if (crtc->state->cubic_lut || vp->cubic_lut) {
68489760 if (crtc->state->cubic_lut)
68499761 vp->cubic_lut = crtc->state->cubic_lut->data;
68509762 vop2_crtc_atomic_cubic_lut_set(crtc, crtc->state);
68519763 }
9764
+#endif
68529765 } else {
68539766 VOP_MODULE_SET(vop2, vp, cubic_lut_update_en, 0);
68549767 }
....@@ -6861,6 +9774,9 @@
68619774 spin_lock_irqsave(&vop2->irq_lock, flags);
68629775 vop2_wb_commit(crtc);
68639776 vop2_cfg_done(crtc);
9777
+
9778
+ if (vp->mcu_timing.mcu_pix_total)
9779
+ VOP_MODULE_SET(vop2, vp, mcu_hold_mode, 0);
68649780
68659781 spin_unlock_irqrestore(&vop2->irq_lock, flags);
68669782
....@@ -6902,6 +9818,7 @@
69029818 }
69039819
69049820 static const struct drm_crtc_helper_funcs vop2_crtc_helper_funcs = {
9821
+ .mode_valid = vop2_crtc_mode_valid,
69059822 .mode_fixup = vop2_crtc_mode_fixup,
69069823 .atomic_check = vop2_crtc_atomic_check,
69079824 .atomic_begin = vop2_crtc_atomic_begin,
....@@ -6941,6 +9858,9 @@
69419858 {
69429859 struct rockchip_crtc_state *vcstate, *old_vcstate;
69439860 struct vop2_video_port *vp = to_vop2_video_port(crtc);
9861
+
9862
+ if (WARN_ON(!crtc->state))
9863
+ return NULL;
69449864
69459865 old_vcstate = to_rockchip_crtc_state(crtc->state);
69469866 vcstate = kmemdup(old_vcstate, sizeof(*old_vcstate), GFP_KERNEL);
....@@ -7068,36 +9988,51 @@
70689988 return 0;
70699989 }
70709990
7071
- if (property == private->alpha_scale_prop) {
7072
- *val = (vop2->data->feature & VOP_FEATURE_ALPHA_SCALE) ? 1 : 0;
7073
- return 0;
7074
- }
7075
-
7076
- if (property == vop2->aclk_prop) {
9991
+ if (property == private->aclk_prop) {
70779992 /* KHZ, keep align with mode->clock */
70789993 *val = clk_get_rate(vop2->aclk) / 1000;
70799994 return 0;
70809995 }
70819996
7082
-
7083
- if (property == vop2->bg_prop) {
9997
+ if (property == private->bg_prop) {
70849998 *val = vcstate->background;
70859999 return 0;
708610000 }
708710001
7088
- if (property == vop2->line_flag_prop) {
10002
+ if (property == private->line_flag_prop) {
708910003 *val = vcstate->line_flag;
709010004 return 0;
709110005 }
709210006
7093
- if (property == vp->hdr_ext_data_prop)
10007
+ if (property == vp->variable_refresh_rate_prop) {
10008
+ *val = vcstate->request_refresh_rate;
709410009 return 0;
10010
+ }
709510011
7096
- if (property == vp->acm_lut_data_prop)
10012
+ if (property == vp->max_refresh_rate_prop) {
10013
+ *val = vcstate->max_refresh_rate;
709710014 return 0;
10015
+ }
709810016
7099
- if (property == vp->post_csc_data_prop)
10017
+ if (property == vp->min_refresh_rate_prop) {
10018
+ *val = vcstate->min_refresh_rate;
710010019 return 0;
10020
+ }
10021
+
10022
+ if (property == vp->hdr_ext_data_prop) {
10023
+ *val = vcstate->hdr_ext_data ? vcstate->hdr_ext_data->base.id : 0;
10024
+ return 0;
10025
+ }
10026
+
10027
+ if (property == vp->acm_lut_data_prop) {
10028
+ *val = vcstate->acm_lut_data ? vcstate->acm_lut_data->base.id : 0;
10029
+ return 0;
10030
+ }
10031
+
10032
+ if (property == vp->post_csc_data_prop) {
10033
+ *val = vcstate->post_csc_data ? vcstate->post_csc_data->base.id : 0;
10034
+ return 0;
10035
+ }
710110036
710210037 DRM_ERROR("failed to get vop2 crtc property: %s\n", property->name);
710310038
....@@ -7144,10 +10079,10 @@
714410079 uint64_t val)
714510080 {
714610081 struct drm_device *drm_dev = crtc->dev;
10082
+ struct rockchip_drm_private *private = drm_dev->dev_private;
714710083 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(state);
714810084 struct drm_mode_config *mode_config = &drm_dev->mode_config;
714910085 struct vop2_video_port *vp = to_vop2_video_port(crtc);
7150
- struct vop2 *vop2 = vp->vop2;
715110086 bool replaced = false;
715210087 int ret;
715310088
....@@ -7172,13 +10107,28 @@
717210107 }
717310108
717410109
7175
- if (property == vop2->bg_prop) {
10110
+ if (property == private->bg_prop) {
717610111 vcstate->background = val;
717710112 return 0;
717810113 }
717910114
7180
- if (property == vop2->line_flag_prop) {
10115
+ if (property == private->line_flag_prop) {
718110116 vcstate->line_flag = val;
10117
+ return 0;
10118
+ }
10119
+
10120
+ if (property == vp->variable_refresh_rate_prop) {
10121
+ vcstate->request_refresh_rate = val;
10122
+ return 0;
10123
+ }
10124
+
10125
+ if (property == vp->max_refresh_rate_prop) {
10126
+ vcstate->max_refresh_rate = val;
10127
+ return 0;
10128
+ }
10129
+
10130
+ if (property == vp->min_refresh_rate_prop) {
10131
+ vcstate->min_refresh_rate = val;
718210132 return 0;
718310133 }
718410134
....@@ -7235,7 +10185,7 @@
723510185 struct vop2_video_port *vp = container_of(work, struct vop2_video_port, fb_unref_work);
723610186 struct drm_framebuffer *fb = val;
723710187
7238
- drm_crtc_vblank_put(&vp->crtc);
10188
+ drm_crtc_vblank_put(&vp->rockchip_crtc.crtc);
723910189 if (!vp->vop2->skip_ref_fb)
724010190 drm_framebuffer_put(fb);
724110191 }
....@@ -7306,6 +10256,7 @@
730610256 struct vop2_wb *wb = &vop2->wb;
730710257
730810258 VOP_MODULE_SET(vop2, wb, enable, 0);
10259
+ VOP_CTRL_SET(vop2, wb_dma_finish_and_en, 0);
730910260 vop2_wb_cfg_done(vp);
731010261 }
731110262
....@@ -7344,6 +10295,43 @@
734410295 }
734510296 }
734610297 spin_unlock_irqrestore(&wb->job_lock, flags);
10298
+}
10299
+
10300
+static void vop2_dsc_isr(struct vop2 *vop2)
10301
+{
10302
+ const struct vop2_data *vop2_data = vop2->data;
10303
+ struct vop2_dsc *dsc;
10304
+ const struct dsc_error_info *dsc_error_ecw = vop2_data->dsc_error_ecw;
10305
+ const struct dsc_error_info *dsc_error_buffer_flow = vop2_data->dsc_error_buffer_flow;
10306
+ u32 dsc_error_status = 0, dsc_ecw = 0;
10307
+ int i = 0, j = 0;
10308
+
10309
+ for (i = 0; i < vop2_data->nr_dscs; i++) {
10310
+ dsc = &vop2->dscs[i];
10311
+
10312
+ if (!dsc->enabled)
10313
+ continue;
10314
+
10315
+ dsc_error_status = VOP_MODULE_GET(vop2, dsc, dsc_error_status);
10316
+ if (!dsc_error_status)
10317
+ continue;
10318
+ dsc_ecw = VOP_MODULE_GET(vop2, dsc, dsc_ecw);
10319
+
10320
+ for (j = 0; j < vop2_data->nr_dsc_ecw; j++) {
10321
+ if (dsc_ecw == dsc_error_ecw[j].dsc_error_val) {
10322
+ DRM_ERROR("dsc%d %s\n", dsc->id, dsc_error_ecw[j].dsc_error_info);
10323
+ break;
10324
+ }
10325
+ }
10326
+
10327
+ if (dsc_ecw == 0x0120ffff) {
10328
+ u32 offset = dsc->regs->dsc_status.offset;
10329
+
10330
+ for (j = 0; j < vop2_data->nr_dsc_buffer_flow; j++)
10331
+ DRM_ERROR("dsc%d %s:0x%x\n", dsc->id, dsc_error_buffer_flow[j].dsc_error_info,
10332
+ vop2_readl(vop2, offset + (j << 2)));
10333
+ }
10334
+ }
734710335 }
734810336
734910337 static irqreturn_t vop2_isr(int irq, void *data)
....@@ -7400,7 +10388,7 @@
740010388
740110389 for (i = 0; i < vp_max; i++) {
740210390 vp = &vop2->vps[i];
7403
- crtc = &vp->crtc;
10391
+ crtc = &vp->rockchip_crtc.crtc;
740410392 active_irqs = vp_irqs[i];
740510393 if (active_irqs & DSP_HOLD_VALID_INTR) {
740610394 complete(&vp->dsp_hold_completion);
....@@ -7431,6 +10419,7 @@
743110419 }
743210420
743310421 if (active_irqs & FS_FIELD_INTR) {
10422
+ rockchip_drm_dbg(vop2->dev, VOP_DEBUG_VSYNC, "vsync_vp%d\n", vp->id);
743410423 vop2_wb_handler(vp);
743510424 if (likely(!vp->skip_vsync) || (vp->layer_sel_update == false)) {
743610425 drm_crtc_handle_vblank(crtc);
....@@ -7462,6 +10451,9 @@
746210451 if (active_irqs)
746310452 DRM_ERROR("Unknown axi_bus%d IRQs: %02x\n", i, active_irqs);
746410453 }
10454
+
10455
+ if (vop2->data->nr_dscs)
10456
+ vop2_dsc_isr(vop2);
746510457
746610458 vop2_core_clks_disable(vop2);
746710459 out:
....@@ -7714,7 +10706,7 @@
771410706
771510707 for (i = 0; i < vop2_data->nr_vps; i++) {
771610708 vp = &vop2->vps[i];
7717
- crtc = &vp->crtc;
10709
+ crtc = &vp->rockchip_crtc.crtc;
771810710 if (!crtc->dev)
771910711 continue;
772010712 vp_data = &vop2_data->vp[vp->id];
....@@ -7751,27 +10743,6 @@
775110743 return 0;
775210744 }
775310745
7754
-static void vop2_cubic_lut_init(struct vop2 *vop2)
7755
-{
7756
- const struct vop2_data *vop2_data = vop2->data;
7757
- const struct vop2_video_port_data *vp_data;
7758
- struct vop2_video_port *vp;
7759
- struct drm_crtc *crtc;
7760
- int i;
7761
-
7762
- for (i = 0; i < vop2_data->nr_vps; i++) {
7763
- vp = &vop2->vps[i];
7764
- crtc = &vp->crtc;
7765
- if (!crtc->dev)
7766
- continue;
7767
- vp_data = &vop2_data->vp[vp->id];
7768
- vp->cubic_lut_len = vp_data->cubic_lut_len;
7769
-
7770
- if (vp->cubic_lut_len)
7771
- drm_crtc_enable_cubic_lut(crtc, vp->cubic_lut_len);
7772
- }
7773
-}
7774
-
777510746 static int vop2_crtc_create_plane_mask_property(struct vop2 *vop2,
777610747 struct drm_crtc *crtc,
777710748 uint32_t plane_mask)
....@@ -7803,6 +10774,92 @@
780310774
780410775 vp->plane_mask_prop = prop;
780510776 drm_object_attach_property(&crtc->base, vp->plane_mask_prop, plane_mask);
10777
+
10778
+ return 0;
10779
+}
10780
+
10781
+static int vop2_crtc_create_feature_property(struct vop2 *vop2, struct drm_crtc *crtc)
10782
+{
10783
+ const struct vop2_data *vop2_data = vop2->data;
10784
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
10785
+ const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
10786
+ struct drm_property *prop;
10787
+ u64 feature = 0;
10788
+
10789
+ static const struct drm_prop_enum_list props[] = {
10790
+ { ROCKCHIP_DRM_CRTC_FEATURE_ALPHA_SCALE, "ALPHA_SCALE" },
10791
+ { ROCKCHIP_DRM_CRTC_FEATURE_HDR10, "HDR10" },
10792
+ { ROCKCHIP_DRM_CRTC_FEATURE_NEXT_HDR, "NEXT_HDR" },
10793
+ };
10794
+
10795
+ if (vp_data->feature & VOP_FEATURE_ALPHA_SCALE)
10796
+ feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_ALPHA_SCALE);
10797
+ if (vp_data->feature & VOP_FEATURE_HDR10)
10798
+ feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_HDR10);
10799
+ if (vp_data->feature & VOP_FEATURE_NEXT_HDR)
10800
+ feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_NEXT_HDR);
10801
+
10802
+ prop = drm_property_create_bitmask(vop2->drm_dev,
10803
+ DRM_MODE_PROP_IMMUTABLE, "FEATURE",
10804
+ props, ARRAY_SIZE(props),
10805
+ 0xffffffff);
10806
+ if (!prop) {
10807
+ DRM_DEV_ERROR(vop2->dev, "create FEATURE prop for vp%d failed\n", vp->id);
10808
+ return -ENOMEM;
10809
+ }
10810
+
10811
+ vp->feature_prop = prop;
10812
+ drm_object_attach_property(&crtc->base, vp->feature_prop, feature);
10813
+
10814
+ prop = drm_property_create_range(vop2->drm_dev, DRM_MODE_PROP_IMMUTABLE, "OUTPUT_WIDTH",
10815
+ 0, vop2->data->vp[vp->id].max_output.width);
10816
+ if (!prop) {
10817
+ DRM_DEV_ERROR(vop2->dev, "create OUTPUT_WIDTH prop for vp%d failed\n", vp->id);
10818
+ return -ENOMEM;
10819
+ }
10820
+ vp->output_width_prop = prop;
10821
+ drm_object_attach_property(&crtc->base, vp->output_width_prop, 0);
10822
+
10823
+ prop = drm_property_create_range(vop2->drm_dev, DRM_MODE_PROP_IMMUTABLE, "OUTPUT_DCLK",
10824
+ 0, rockchip_drm_get_dclk_by_width(vop2->data->vp[vp->id].max_output.width) * 1000);
10825
+ if (!prop) {
10826
+ DRM_DEV_ERROR(vop2->dev, "create OUTPUT_DCLK prop for vp%d failed\n", vp->id);
10827
+ return -ENOMEM;
10828
+ }
10829
+ vp->output_dclk_prop = prop;
10830
+ drm_object_attach_property(&crtc->base, vp->output_dclk_prop, 0);
10831
+
10832
+ return 0;
10833
+}
10834
+
10835
+static int vop2_crtc_create_vrr_property(struct vop2 *vop2, struct drm_crtc *crtc)
10836
+{
10837
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
10838
+ struct drm_property *prop;
10839
+
10840
+ prop = drm_property_create_range(vop2->drm_dev, 0, "variable refresh rate", 0, 144);
10841
+ if (!prop) {
10842
+ DRM_DEV_ERROR(vop2->dev, "create vrr prop for vp%d failed\n", vp->id);
10843
+ return -ENOMEM;
10844
+ }
10845
+ vp->variable_refresh_rate_prop = prop;
10846
+ drm_object_attach_property(&crtc->base, vp->variable_refresh_rate_prop, 0);
10847
+
10848
+ prop = drm_property_create_range(vop2->drm_dev, 0, "max refresh rate", 0, 144);
10849
+ if (!prop) {
10850
+ DRM_DEV_ERROR(vop2->dev, "create vrr prop for vp%d failed\n", vp->id);
10851
+ return -ENOMEM;
10852
+ }
10853
+ vp->max_refresh_rate_prop = prop;
10854
+ drm_object_attach_property(&crtc->base, vp->max_refresh_rate_prop, 0);
10855
+
10856
+ prop = drm_property_create_range(vop2->drm_dev, 0, "min refresh rate", 0, 144);
10857
+ if (!prop) {
10858
+ DRM_DEV_ERROR(vop2->dev, "create vrr prop for vp%d failed\n", vp->id);
10859
+ return -ENOMEM;
10860
+ }
10861
+ vp->min_refresh_rate_prop = prop;
10862
+ drm_object_attach_property(&crtc->base, vp->min_refresh_rate_prop, 0);
780610863
780710864 return 0;
780810865 }
....@@ -7877,12 +10934,13 @@
787710934 uint64_t soc_id;
787810935 uint32_t registered_num_crtcs = 0;
787910936 uint32_t plane_mask = 0;
7880
- char dclk_name[9];
10937
+ char clk_name[16];
788110938 int i = 0, j = 0, k = 0;
788210939 int ret = 0;
788310940 bool be_used_for_primary_plane = false;
788410941 bool find_primary_plane = false;
788510942 bool bootloader_initialized = false;
10943
+ struct rockchip_drm_private *private = drm_dev->dev_private;
788610944
788710945 /* all planes can attach to any crtc */
788810946 possible_crtcs = (1 << vop2_data->nr_vps) - 1;
....@@ -7932,14 +10990,27 @@
793210990 else
793310991 soc_id = vp_data->soc_id[0];
793410992
7935
- snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", vp->id);
7936
- vp->dclk = devm_clk_get(vop2->dev, dclk_name);
10993
+ snprintf(clk_name, sizeof(clk_name), "dclk_vp%d", vp->id);
10994
+ vp->dclk_rst = devm_reset_control_get_optional(vop2->dev, clk_name);
10995
+ if (IS_ERR(vp->dclk_rst)) {
10996
+ DRM_DEV_ERROR(vop2->dev, "failed to get dclk reset\n");
10997
+ return PTR_ERR(vp->dclk_rst);
10998
+ }
10999
+
11000
+ vp->dclk = devm_clk_get(vop2->dev, clk_name);
793711001 if (IS_ERR(vp->dclk)) {
7938
- DRM_DEV_ERROR(vop2->dev, "failed to get %s\n", dclk_name);
11002
+ DRM_DEV_ERROR(vop2->dev, "failed to get %s\n", clk_name);
793911003 return PTR_ERR(vp->dclk);
794011004 }
794111005
7942
- crtc = &vp->crtc;
11006
+ snprintf(clk_name, sizeof(clk_name), "dclk_src_vp%d", vp->id);
11007
+ vp->dclk_parent = devm_clk_get_optional(vop2->dev, clk_name);
11008
+ if (IS_ERR(vp->dclk)) {
11009
+ DRM_DEV_ERROR(vop2->dev, "failed to get %s\n", clk_name);
11010
+ return PTR_ERR(vp->dclk);
11011
+ }
11012
+
11013
+ crtc = &vp->rockchip_crtc.crtc;
794311014
794411015 port = of_graph_get_port_by_id(dev->of_node, i);
794511016 if (!port) {
....@@ -8057,31 +11128,34 @@
805711128 init_completion(&vp->line_flag_completion);
805811129 rockchip_register_crtc_funcs(crtc, &private_crtc_funcs);
805911130 soc_id = vop2_soc_id_fixup(soc_id);
8060
- drm_object_attach_property(&crtc->base, vop2->soc_id_prop, soc_id);
8061
- drm_object_attach_property(&crtc->base, vop2->vp_id_prop, vp->id);
8062
- drm_object_attach_property(&crtc->base, vop2->aclk_prop, 0);
8063
- drm_object_attach_property(&crtc->base, vop2->bg_prop, 0);
8064
- drm_object_attach_property(&crtc->base, vop2->line_flag_prop, 0);
8065
- drm_object_attach_property(&crtc->base,
8066
- drm_dev->mode_config.tv_left_margin_property, 100);
8067
- drm_object_attach_property(&crtc->base,
8068
- drm_dev->mode_config.tv_right_margin_property, 100);
8069
- drm_object_attach_property(&crtc->base,
8070
- drm_dev->mode_config.tv_top_margin_property, 100);
8071
- drm_object_attach_property(&crtc->base,
8072
- drm_dev->mode_config.tv_bottom_margin_property, 100);
11131
+ drm_object_attach_property(&crtc->base, private->soc_id_prop, soc_id);
11132
+ drm_object_attach_property(&crtc->base, private->port_id_prop, vp->id);
11133
+ drm_object_attach_property(&crtc->base, private->aclk_prop, 0);
11134
+ drm_object_attach_property(&crtc->base, private->bg_prop, 0);
11135
+ drm_object_attach_property(&crtc->base, private->line_flag_prop, 0);
11136
+ if (vp_data->feature & VOP_FEATURE_OVERSCAN) {
11137
+ drm_object_attach_property(&crtc->base,
11138
+ drm_dev->mode_config.tv_left_margin_property, 100);
11139
+ drm_object_attach_property(&crtc->base,
11140
+ drm_dev->mode_config.tv_right_margin_property, 100);
11141
+ drm_object_attach_property(&crtc->base,
11142
+ drm_dev->mode_config.tv_top_margin_property, 100);
11143
+ drm_object_attach_property(&crtc->base,
11144
+ drm_dev->mode_config.tv_bottom_margin_property, 100);
11145
+ }
807311146 if (plane_mask)
807411147 vop2_crtc_create_plane_mask_property(vop2, crtc, plane_mask);
11148
+ vop2_crtc_create_feature_property(vop2, crtc);
11149
+ vop2_crtc_create_vrr_property(vop2, crtc);
807511150
8076
- if (vp_data->feature & VOP_FEATURE_VIVID_HDR) {
11151
+ ret = drm_self_refresh_helper_init(crtc);
11152
+ if (ret)
11153
+ DRM_DEV_DEBUG_KMS(vop2->dev,
11154
+ "Failed to init %s with SR helpers %d, ignoring\n",
11155
+ crtc->name, ret);
11156
+
11157
+ if (vp_data->feature & VOP_FEATURE_VIVID_HDR)
807711158 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
- }
808511159 if (vp_data->feature & VOP_FEATURE_POST_ACM)
808611160 vop2_crtc_create_post_acm_property(vop2, crtc);
808711161 if (vp_data->feature & VOP_FEATURE_POST_CSC)
....@@ -8141,7 +11215,7 @@
814111215
814211216 ret = vop2_plane_init(vop2, win, possible_crtcs);
814311217 if (ret)
8144
- DRM_WARN("failed to init overlay plane %s, ret:%d\n", win->name, ret);
11218
+ DRM_WARN("failed to init overlay plane %s\n", win->name);
814511219 }
814611220
814711221 if (is_vop3(vop2))
....@@ -8154,6 +11228,7 @@
815411228 {
815511229 struct vop2_video_port *vp = to_vop2_video_port(crtc);
815611230
11231
+ drm_self_refresh_helper_cleanup(crtc);
815711232 if (vp->hdr_lut_gem_obj)
815811233 rockchip_gem_free_object(&vp->hdr_lut_gem_obj->base);
815911234
....@@ -8167,6 +11242,59 @@
816711242 drm_flip_work_cleanup(&vp->fb_unref_work);
816811243 }
816911244
11245
+static int vop2_pd_data_init(struct vop2 *vop2)
11246
+{
11247
+ const struct vop2_data *vop2_data = vop2->data;
11248
+ const struct vop2_power_domain_data *pd_data;
11249
+ struct vop2_power_domain *pd;
11250
+ int i;
11251
+
11252
+ INIT_LIST_HEAD(&vop2->pd_list_head);
11253
+
11254
+ for (i = 0; i < vop2_data->nr_pds; i++) {
11255
+ pd_data = &vop2_data->pd[i];
11256
+ pd = devm_kzalloc(vop2->dev, sizeof(*pd), GFP_KERNEL);
11257
+ if (!pd)
11258
+ return -ENOMEM;
11259
+ pd->vop2 = vop2;
11260
+ pd->data = pd_data;
11261
+ pd->vp_mask = 0;
11262
+ spin_lock_init(&pd->lock);
11263
+ list_add_tail(&pd->list, &vop2->pd_list_head);
11264
+ INIT_DELAYED_WORK(&pd->power_off_work, vop2_power_domain_off_work);
11265
+ if (pd_data->parent_id) {
11266
+ pd->parent = vop2_find_pd_by_id(vop2, pd_data->parent_id);
11267
+ if (!pd->parent) {
11268
+ DRM_DEV_ERROR(vop2->dev, "no parent pd find for pd%d\n", pd->data->id);
11269
+ return -EINVAL;
11270
+ }
11271
+ }
11272
+ }
11273
+
11274
+ return 0;
11275
+}
11276
+
11277
+static void vop2_dsc_data_init(struct vop2 *vop2)
11278
+{
11279
+ const struct vop2_data *vop2_data = vop2->data;
11280
+ const struct vop2_dsc_data *dsc_data;
11281
+ struct vop2_dsc *dsc;
11282
+ int i;
11283
+
11284
+ for (i = 0; i < vop2_data->nr_dscs; i++) {
11285
+ dsc = &vop2->dscs[i];
11286
+ dsc_data = &vop2_data->dsc[i];
11287
+ dsc->id = dsc_data->id;
11288
+ dsc->max_slice_num = dsc_data->max_slice_num;
11289
+ dsc->max_linebuf_depth = dsc_data->max_linebuf_depth;
11290
+ dsc->min_bits_per_pixel = dsc_data->min_bits_per_pixel;
11291
+ dsc->regs = dsc_data->regs;
11292
+ dsc->attach_vp_id = -1;
11293
+ if (dsc_data->pd_id)
11294
+ dsc->pd = vop2_find_pd_by_id(vop2, dsc_data->pd_id);
11295
+ }
11296
+}
11297
+
817011298 static int vop2_win_init(struct vop2 *vop2)
817111299 {
817211300 const struct vop2_data *vop2_data = vop2->data;
....@@ -8174,7 +11302,6 @@
817411302 struct drm_prop_enum_list *plane_name_list;
817511303 struct vop2_win *win;
817611304 struct vop2_layer *layer;
8177
- struct drm_property *prop;
817811305 char name[DRM_PROP_NAME_LEN];
817911306 unsigned int num_wins = 0;
818011307 uint8_t plane_id = 0;
....@@ -8203,6 +11330,7 @@
820311330 win->dly = win_data->dly;
820411331 win->feature = win_data->feature;
820511332 win->phys_id = win_data->phys_id;
11333
+ win->splice_win_id = win_data->splice_win_id;
820611334 win->layer_sel_id = win_data->layer_sel_id;
820711335 win->win_id = i;
820811336 win->plane_id = plane_id++;
....@@ -8213,6 +11341,9 @@
821311341 win->axi_yrgb_id = win_data->axi_yrgb_id;
821411342 win->axi_uv_id = win_data->axi_uv_id;
821511343 win->possible_crtcs = win_data->possible_crtcs;
11344
+
11345
+ if (win_data->pd_id)
11346
+ win->pd = vop2_find_pd_by_id(vop2, win_data->pd_id);
821611347
821711348 num_wins++;
821811349
....@@ -8253,6 +11384,7 @@
825311384 num_wins++;
825411385 }
825511386 }
11387
+
825611388 vop2->registered_num_wins = num_wins;
825711389
825811390 if (!is_vop3(vop2)) {
....@@ -8280,30 +11412,10 @@
828011412
828111413 vop2->plane_name_list = plane_name_list;
828211414
8283
- prop = drm_property_create_object(vop2->drm_dev,
8284
- DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_IMMUTABLE,
8285
- "SOC_ID", DRM_MODE_OBJECT_CRTC);
8286
- vop2->soc_id_prop = prop;
8287
-
8288
- prop = drm_property_create_object(vop2->drm_dev,
8289
- DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_IMMUTABLE,
8290
- "PORT_ID", DRM_MODE_OBJECT_CRTC);
8291
- vop2->vp_id_prop = prop;
8292
-
8293
- vop2->aclk_prop = drm_property_create_range(vop2->drm_dev, 0, "ACLK", 0, UINT_MAX);
8294
- vop2->bg_prop = drm_property_create_range(vop2->drm_dev, 0, "BACKGROUND", 0, UINT_MAX);
8295
-
8296
- vop2->line_flag_prop = drm_property_create_range(vop2->drm_dev, 0, "LINE_FLAG1", 0, UINT_MAX);
8297
-
8298
- if (!vop2->soc_id_prop || !vop2->vp_id_prop || !vop2->aclk_prop || !vop2->bg_prop ||
8299
- !vop2->line_flag_prop) {
8300
- DRM_DEV_ERROR(vop2->dev, "failed to create soc_id/vp_id/aclk property\n");
8301
- return -ENOMEM;
8302
- }
8303
-
830411415 return 0;
830511416 }
830611417
11418
+#include "rockchip_vop2_clk.c"
830711419 static void post_buf_empty_work_event(struct work_struct *work)
830811420 {
830911421 struct vop2 *vop2 = container_of(work, struct vop2, post_buf_empty_work);
....@@ -8323,7 +11435,7 @@
832311435 mutex_lock(&private->ovl_lock);
832411436 vop2_wait_for_fs_by_done_bit_status(vp);
832511437 VOP_MODULE_SET(vop2, vp, p2i_en, 0);
8326
- vop2_cfg_done(&vp->crtc);
11438
+ vop2_cfg_done(&vp->rockchip_crtc.crtc);
832711439 vop2_wait_for_fs_by_done_bit_status(vp);
832811440 mutex_unlock(&private->ovl_lock);
832911441
....@@ -8332,11 +11444,102 @@
833211444 mutex_lock(&private->ovl_lock);
833311445 vop2_wait_for_fs_by_done_bit_status(vp);
833411446 VOP_MODULE_SET(vop2, vp, p2i_en, 1);
8335
- vop2_cfg_done(&vp->crtc);
11447
+ vop2_cfg_done(&vp->rockchip_crtc.crtc);
833611448 vop2_wait_for_fs_by_done_bit_status(vp);
833711449 mutex_unlock(&private->ovl_lock);
833811450
833911451 vp->need_reset_p2i_flag = false;
11452
+ }
11453
+ }
11454
+}
11455
+
11456
+static bool vop2_plane_mask_check(struct vop2 *vop2)
11457
+{
11458
+ const struct vop2_data *vop2_data = vop2->data;
11459
+ u32 plane_mask = 0;
11460
+ int i;
11461
+
11462
+ /*
11463
+ * For RK3568 and RK3588, all windows need to be assigned to
11464
+ * one of all vps, and two of vps can not share the same window.
11465
+ */
11466
+ if (vop2->version != VOP_VERSION_RK3568 && vop2->version != VOP_VERSION_RK3588)
11467
+ return true;
11468
+
11469
+ for (i = 0; i < vop2_data->nr_vps; i++) {
11470
+ if (plane_mask & vop2->vps[i].plane_mask) {
11471
+ DRM_WARN("the same window can't be assigned to two vp\n");
11472
+ return false;
11473
+ }
11474
+ plane_mask |= vop2->vps[i].plane_mask;
11475
+ }
11476
+
11477
+ if (hweight32(plane_mask) != vop2_data->nr_layers ||
11478
+ plane_mask != vop2_data->plane_mask_base) {
11479
+ DRM_WARN("all windows should be assigned, full plane mask: 0x%x, current plane mask: 0x%x\n",
11480
+ vop2_data->plane_mask_base, plane_mask);
11481
+ return false;
11482
+ }
11483
+
11484
+ return true;
11485
+}
11486
+
11487
+static uint32_t vop2_vp_plane_mask_to_bitmap(const struct vop2_vp_plane_mask *vp_plane_mask)
11488
+{
11489
+ int layer_phy_id = 0;
11490
+ int plane_mask = 0;
11491
+ int i;
11492
+
11493
+ for (i = 0; i < vp_plane_mask->attached_layers_nr; i++) {
11494
+ layer_phy_id = vp_plane_mask->attached_layers[i];
11495
+ plane_mask |= BIT(layer_phy_id);
11496
+ }
11497
+
11498
+ return plane_mask;
11499
+}
11500
+
11501
+static bool vop2_get_vp_of_status(struct device_node *vp_node)
11502
+{
11503
+ struct device_node *vp_sub_node;
11504
+ struct device_node *remote_node;
11505
+ bool vp_enable = false;
11506
+
11507
+ for_each_child_of_node(vp_node, vp_sub_node) {
11508
+ remote_node = of_graph_get_remote_endpoint(vp_sub_node);
11509
+ vp_enable |= of_device_is_available(remote_node);
11510
+ }
11511
+
11512
+ return vp_enable;
11513
+}
11514
+
11515
+static void vop2_plane_mask_assign(struct vop2 *vop2, struct device_node *vop_out_node)
11516
+{
11517
+ const struct vop2_data *vop2_data = vop2->data;
11518
+ const struct vop2_vp_plane_mask *plane_mask;
11519
+ struct device_node *child;
11520
+ int active_vp_num = 0;
11521
+ int vp_id;
11522
+ int i = 0;
11523
+
11524
+ for_each_child_of_node(vop_out_node, child) {
11525
+ if (vop2_get_vp_of_status(child))
11526
+ active_vp_num++;
11527
+ }
11528
+
11529
+ if (vop2_soc_is_rk3566() && active_vp_num > 2)
11530
+ DRM_WARN("RK3566 only support 2 vps\n");
11531
+ plane_mask = vop2_data->plane_mask;
11532
+ plane_mask += (active_vp_num - 1) * ROCKCHIP_MAX_CRTC;
11533
+
11534
+ for_each_child_of_node(vop_out_node, child) {
11535
+ of_property_read_u32(child, "reg", &vp_id);
11536
+ if (vop2_get_vp_of_status(child)) {
11537
+ vop2->vps[vp_id].plane_mask = vop2_vp_plane_mask_to_bitmap(&plane_mask[i]);
11538
+ vop2->vps[vp_id].primary_plane_phy_id = plane_mask[i].primary_plane_id;
11539
+ i++;
11540
+ } else {
11541
+ vop2->vps[vp_id].plane_mask = 0;
11542
+ vop2->vps[vp_id].primary_plane_phy_id = ROCKCHIP_VOP2_PHY_ID_INVALID;
834011543 }
834111544 }
834211545 }
....@@ -8353,6 +11556,7 @@
835311556 int num_wins = 0;
835411557 int registered_num_crtcs;
835511558 struct device_node *vop_out_node;
11559
+ struct device_node *mcu_timing_node;
835611560
835711561 vop2_data = of_device_get_match_data(dev);
835811562 if (!vop2_data)
....@@ -8382,6 +11586,9 @@
838211586 vop2->disable_win_move = of_property_read_bool(dev->of_node, "disable-win-move");
838311587 vop2->skip_ref_fb = of_property_read_bool(dev->of_node, "skip-ref-fb");
838411588
11589
+ ret = vop2_pd_data_init(vop2);
11590
+ if (ret)
11591
+ return ret;
838511592 /*
838611593 * esmart lb mode default config at vop2_reg.c vop2_data.esmart_lb_mode,
838711594 * you can rewrite at dts vop node:
....@@ -8432,7 +11639,10 @@
843211639 return PTR_ERR(vop2->acm_regs);
843311640 }
843411641
8435
- vop2->grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
11642
+ vop2->sys_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
11643
+ vop2->grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,vop-grf");
11644
+ vop2->vo1_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,vo1-grf");
11645
+ vop2->sys_pmu = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pmu");
843611646
843711647 vop2->hclk = devm_clk_get(vop2->dev, "hclk_vop");
843811648 if (IS_ERR(vop2->hclk)) {
....@@ -8443,6 +11653,24 @@
844311653 if (IS_ERR(vop2->aclk)) {
844411654 DRM_DEV_ERROR(vop2->dev, "failed to get aclk source\n");
844511655 return PTR_ERR(vop2->aclk);
11656
+ }
11657
+
11658
+ vop2->pclk = devm_clk_get_optional(vop2->dev, "pclk_vop");
11659
+ if (IS_ERR(vop2->pclk)) {
11660
+ DRM_DEV_ERROR(vop2->dev, "failed to get pclk source\n");
11661
+ return PTR_ERR(vop2->pclk);
11662
+ }
11663
+
11664
+ vop2->ahb_rst = devm_reset_control_get_optional(vop2->dev, "ahb");
11665
+ if (IS_ERR(vop2->ahb_rst)) {
11666
+ DRM_DEV_ERROR(vop2->dev, "failed to get ahb reset\n");
11667
+ return PTR_ERR(vop2->ahb_rst);
11668
+ }
11669
+
11670
+ vop2->axi_rst = devm_reset_control_get_optional(vop2->dev, "axi");
11671
+ if (IS_ERR(vop2->axi_rst)) {
11672
+ DRM_DEV_ERROR(vop2->dev, "failed to get axi reset\n");
11673
+ return PTR_ERR(vop2->axi_rst);
844611674 }
844711675
844811676 vop2->irq = platform_get_irq(pdev, 0);
....@@ -8459,6 +11687,7 @@
845911687 u32 plane_mask = 0;
846011688 u32 primary_plane_phy_id = 0;
846111689 u32 vp_id = 0;
11690
+ u32 val = 0;
846211691
846311692 of_property_read_u32(child, "rockchip,plane-mask", &plane_mask);
846411693 of_property_read_u32(child, "rockchip,primary-plane", &primary_plane_phy_id);
....@@ -8472,12 +11701,42 @@
847211701
847311702 vop2->vps[vp_id].xmirror_en = of_property_read_bool(child, "xmirror-enable");
847411703
11704
+ ret = of_clk_set_defaults(child, false);
11705
+ if (ret) {
11706
+ DRM_DEV_ERROR(dev, "Failed to set clock defaults %d\n", ret);
11707
+ return ret;
11708
+ }
11709
+
11710
+ mcu_timing_node = of_get_child_by_name(child, "mcu-timing");
11711
+ if (mcu_timing_node) {
11712
+ if (!of_property_read_u32(mcu_timing_node, "mcu-pix-total", &val))
11713
+ vop2->vps[vp_id].mcu_timing.mcu_pix_total = val;
11714
+ if (!of_property_read_u32(mcu_timing_node, "mcu-cs-pst", &val))
11715
+ vop2->vps[vp_id].mcu_timing.mcu_cs_pst = val;
11716
+ if (!of_property_read_u32(mcu_timing_node, "mcu-cs-pend", &val))
11717
+ vop2->vps[vp_id].mcu_timing.mcu_cs_pend = val;
11718
+ if (!of_property_read_u32(mcu_timing_node, "mcu-rw-pst", &val))
11719
+ vop2->vps[vp_id].mcu_timing.mcu_rw_pst = val;
11720
+ if (!of_property_read_u32(mcu_timing_node, "mcu-rw-pend", &val))
11721
+ vop2->vps[vp_id].mcu_timing.mcu_rw_pend = val;
11722
+ if (!of_property_read_u32(mcu_timing_node, "mcu-hold-mode", &val))
11723
+ vop2->vps[vp_id].mcu_timing.mcu_hold_mode = val;
11724
+ }
11725
+ }
11726
+
11727
+ if (!vop2_plane_mask_check(vop2)) {
11728
+ DRM_WARN("use default plane mask\n");
11729
+ vop2_plane_mask_assign(vop2, vop_out_node);
11730
+ }
11731
+
11732
+ for (i = 0; i < vop2->data->nr_vps; i++) {
847511733 DRM_DEV_INFO(dev, "vp%d assign plane mask: 0x%x, primary plane phy id: %d\n",
8476
- vp_id, vop2->vps[vp_id].plane_mask,
8477
- vop2->vps[vp_id].primary_plane_phy_id);
11734
+ i, vop2->vps[i].plane_mask,
11735
+ vop2->vps[i].primary_plane_phy_id);
847811736 }
847911737 }
848011738
11739
+ vop2_extend_clk_init(vop2);
848111740 spin_lock_init(&vop2->reg_lock);
848211741 spin_lock_init(&vop2->irq_lock);
848311742 mutex_init(&vop2->vop2_lock);
....@@ -8492,12 +11751,16 @@
849211751 if (ret)
849311752 return ret;
849411753
11754
+ vop2_dsc_data_init(vop2);
11755
+
849511756 registered_num_crtcs = vop2_create_crtc(vop2);
849611757 if (registered_num_crtcs <= 0)
849711758 return -ENODEV;
11759
+
849811760 ret = vop2_gamma_init(vop2);
849911761 if (ret)
850011762 return ret;
11763
+ vop2_clk_init(vop2);
850111764 vop2_cubic_lut_init(vop2);
850211765 vop2_wb_connector_init(vop2, registered_num_crtcs);
850311766 pm_runtime_enable(&pdev->dev);