forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 072de836f53be56a70cecf70b43ae43b7ce17376
kernel/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
....@@ -1,59 +1,56 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
34 * Author:Mark Yao <mark.yao@rock-chips.com>
4
- *
5
- * This software is licensed under the terms of the GNU General Public
6
- * License version 2, as published by the Free Software Foundation, and
7
- * may be copied, distributed, and modified under those terms.
8
- *
9
- * This program is distributed in the hope that it will be useful,
10
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- * GNU General Public License for more details.
135 */
146
7
+#include <linux/clk.h>
8
+#include <linux/component.h>
9
+#include <linux/debugfs.h>
10
+#include <linux/delay.h>
11
+#include <linux/fixp-arith.h>
12
+#include <linux/iopoll.h>
13
+#include <linux/kernel.h>
14
+#include <linux/mfd/syscon.h>
15
+#include <linux/module.h>
16
+#include <linux/of.h>
17
+#include <linux/of_device.h>
18
+#include <linux/overflow.h>
19
+#include <linux/platform_device.h>
20
+#include <linux/pm_runtime.h>
21
+#include <linux/regmap.h>
22
+#include <linux/reset.h>
23
+#include <linux/sort.h>
24
+
1525 #include <drm/drm.h>
16
-#include <drm/drmP.h>
1726 #include <drm/drm_atomic.h>
27
+#include <drm/drm_atomic_uapi.h>
1828 #include <drm/drm_crtc.h>
1929 #include <drm/drm_crtc_helper.h>
30
+#include <drm/drm_debugfs.h>
2031 #include <drm/drm_flip_work.h>
32
+#include <drm/drm_fourcc.h>
33
+#include <drm/drm_gem_framebuffer_helper.h>
2134 #include <drm/drm_plane_helper.h>
35
+#include <drm/drm_probe_helper.h>
36
+#include <drm/drm_self_refresh_helper.h>
37
+#include <drm/drm_vblank.h>
38
+
2239 #ifdef CONFIG_DRM_ANALOGIX_DP
2340 #include <drm/bridge/analogix_dp.h>
2441 #endif
2542 #include <dt-bindings/soc/rockchip-system-status.h>
2643
27
-#include <linux/debugfs.h>
28
-#include <linux/fixp-arith.h>
29
-#include <linux/iopoll.h>
30
-#include <linux/kernel.h>
31
-#include <linux/module.h>
32
-#include <linux/platform_device.h>
33
-#include <linux/clk.h>
34
-#include <linux/iopoll.h>
35
-#include <linux/of.h>
36
-#include <linux/of_device.h>
37
-#include <linux/pm_runtime.h>
38
-#include <linux/component.h>
39
-#include <linux/overflow.h>
40
-#include <linux/regmap.h>
41
-#include <linux/mfd/syscon.h>
42
-
43
-#include <linux/reset.h>
44
-#include <linux/delay.h>
45
-#include <linux/sort.h>
4644 #include <soc/rockchip/rockchip_dmc.h>
4745 #include <soc/rockchip/rockchip-system-status.h>
4846 #include <uapi/linux/videodev2.h>
49
-
50
-#include "../drm_internal.h"
47
+#include "../drm_crtc_internal.h"
5148
5249 #include "rockchip_drm_drv.h"
5350 #include "rockchip_drm_gem.h"
5451 #include "rockchip_drm_fb.h"
55
-#include "rockchip_drm_psr.h"
5652 #include "rockchip_drm_vop.h"
53
+#include "rockchip_rgb.h"
5754
5855 #define VOP_REG_SUPPORT(vop, reg) \
5956 (reg.mask && \
....@@ -151,7 +148,6 @@
151148 } \
152149 } while (0)
153150
154
-#define to_vop(x) container_of(x, struct vop, crtc)
155151 #define to_vop_win(x) container_of(x, struct vop_win, base)
156152 #define to_vop_plane_state(x) container_of(x, struct vop_plane_state, base)
157153
....@@ -172,7 +168,6 @@
172168 struct drm_rect dest;
173169 dma_addr_t yrgb_mst;
174170 dma_addr_t uv_mst;
175
- void *yrgb_kvaddr;
176171 const uint32_t *y2r_table;
177172 const uint32_t *r2r_table;
178173 const uint32_t *r2y_table;
....@@ -181,7 +176,7 @@
181176 bool r2r_en;
182177 bool r2y_en;
183178 int color_space;
184
- int color_key;
179
+ u32 color_key;
185180 unsigned int csc_mode;
186181 int global_alpha;
187182 int blend_mode;
....@@ -191,21 +186,15 @@
191186 struct vop_dump_list *planlist;
192187 };
193188
194
-struct rockchip_mcu_timing {
195
- int mcu_pix_total;
196
- int mcu_cs_pst;
197
- int mcu_cs_pend;
198
- int mcu_rw_pst;
199
- int mcu_rw_pend;
200
- int mcu_hold_mode;
201
-};
202
-
203189 struct vop_win {
204190 struct vop_win *parent;
205191 struct drm_plane base;
206192
207193 int win_id;
208194 int area_id;
195
+ u8 plane_id; /* unique plane id */
196
+ const char *name;
197
+
209198 int zpos;
210199 uint32_t offset;
211200 enum drm_plane_type type;
....@@ -213,28 +202,45 @@
213202 const struct vop_csc *csc;
214203 const uint32_t *data_formats;
215204 uint32_t nformats;
205
+ const uint64_t *format_modifiers;
216206 u64 feature;
217207 struct vop *vop;
218208 struct vop_plane_state state;
219209
210
+ struct drm_property *input_width_prop;
211
+ struct drm_property *input_height_prop;
212
+ struct drm_property *output_width_prop;
213
+ struct drm_property *output_height_prop;
220214 struct drm_property *color_key_prop;
215
+ struct drm_property *scale_prop;
216
+ struct drm_property *name_prop;
221217 };
222218
223219 struct vop {
224
- struct drm_crtc crtc;
220
+ struct rockchip_crtc rockchip_crtc;
225221 struct device *dev;
226222 struct drm_device *drm_dev;
227223 struct dentry *debugfs;
228224 struct drm_info_list *debugfs_files;
229
- struct drm_property *plane_zpos_prop;
230225 struct drm_property *plane_feature_prop;
226
+ struct drm_property *plane_mask_prop;
231227 struct drm_property *feature_prop;
228
+
232229 bool is_iommu_enabled;
233230 bool is_iommu_needed;
234231 bool is_enabled;
235232 bool support_multi_area;
236233
234
+ bool aclk_rate_reset;
235
+ unsigned long aclk_rate;
236
+
237237 u32 version;
238
+ u32 background;
239
+ u32 line_flag;
240
+ u8 id;
241
+ u8 plane_mask;
242
+ u64 soc_id;
243
+ struct drm_prop_enum_list *plane_name_list;
238244
239245 struct drm_tv_connector_state active_tv_state;
240246 bool pre_overlay;
....@@ -308,13 +314,12 @@
308314 { MEDIA_BUS_FMT_RGB666_1X18, "RGB666_1X18" },
309315 { MEDIA_BUS_FMT_RGB666_1X24_CPADHI, "RGB666_1X24_CPADHI" },
310316 { MEDIA_BUS_FMT_RGB666_1X7X3_SPWG, "RGB666_1X7X3_SPWG" },
311
- { MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA, "RGB666_1X7X3_JEIDA" },
312317 { MEDIA_BUS_FMT_YUV8_1X24, "YUV8_1X24" },
313318 { MEDIA_BUS_FMT_UYYVYY8_0_5X24, "UYYVYY8_0_5X24" },
314319 { MEDIA_BUS_FMT_YUV10_1X30, "YUV10_1X30" },
315320 { MEDIA_BUS_FMT_UYYVYY10_0_5X30, "UYYVYY10_0_5X30" },
316
- { MEDIA_BUS_FMT_SRGB888_3X8, "SRGB888_3X8" },
317
- { MEDIA_BUS_FMT_SRGB888_DUMMY_4X8, "SRGB888_DUMMY_4X8" },
321
+ { MEDIA_BUS_FMT_RGB888_3X8, "RGB888_3X8" },
322
+ { MEDIA_BUS_FMT_RGB888_DUMMY_4X8, "RGB888_DUMMY_4X8" },
318323 { MEDIA_BUS_FMT_RGB888_1X24, "RGB888_1X24" },
319324 { MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, "RGB888_1X7X4_SPWG" },
320325 { MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, "RGB888_1X7X4_JEIDA" },
....@@ -324,6 +329,15 @@
324329 };
325330
326331 static DRM_ENUM_NAME_FN(drm_get_bus_format_name, drm_bus_format_enum_list)
332
+
333
+static inline struct vop *to_vop(struct drm_crtc *crtc)
334
+{
335
+ struct rockchip_crtc *rockchip_crtc;
336
+
337
+ rockchip_crtc = container_of(crtc, struct rockchip_crtc, crtc);
338
+
339
+ return container_of(rockchip_crtc, struct vop, rockchip_crtc);
340
+}
327341
328342 static void vop_lock(struct vop *vop)
329343 {
....@@ -583,20 +597,46 @@
583597 case DRM_FORMAT_BGR565:
584598 return VOP_FMT_RGB565;
585599 case DRM_FORMAT_NV12:
586
- case DRM_FORMAT_NV12_10:
600
+ case DRM_FORMAT_NV15:
587601 return VOP_FMT_YUV420SP;
588602 case DRM_FORMAT_NV16:
589
- case DRM_FORMAT_NV16_10:
603
+ case DRM_FORMAT_NV20:
590604 return VOP_FMT_YUV422SP;
591605 case DRM_FORMAT_NV24:
592
- case DRM_FORMAT_NV24_10:
606
+ case DRM_FORMAT_NV30:
593607 return VOP_FMT_YUV444SP;
608
+ case DRM_FORMAT_YVYU:
609
+ case DRM_FORMAT_VYUY:
594610 case DRM_FORMAT_YUYV:
611
+ case DRM_FORMAT_UYVY:
595612 return VOP_FMT_YUYV;
596613 default:
597614 DRM_ERROR("unsupported format[%08x]\n", format);
598615 return -EINVAL;
599616 }
617
+}
618
+
619
+static int vop_convert_afbc_format(uint32_t format)
620
+{
621
+ switch (format) {
622
+ case DRM_FORMAT_XRGB8888:
623
+ case DRM_FORMAT_ARGB8888:
624
+ case DRM_FORMAT_XBGR8888:
625
+ case DRM_FORMAT_ABGR8888:
626
+ return AFBDC_FMT_U8U8U8U8;
627
+ case DRM_FORMAT_RGB888:
628
+ case DRM_FORMAT_BGR888:
629
+ return AFBDC_FMT_U8U8U8;
630
+ case DRM_FORMAT_RGB565:
631
+ case DRM_FORMAT_BGR565:
632
+ return AFBDC_FMT_RGB565;
633
+ /* either of the below should not be reachable */
634
+ default:
635
+ DRM_WARN_ONCE("unsupported AFBC format[%08x]\n", format);
636
+ return -EINVAL;
637
+ }
638
+
639
+ return -EINVAL;
600640 }
601641
602642 static bool is_uv_swap(uint32_t bus_format, uint32_t output_mode)
....@@ -618,6 +658,21 @@
618658 bus_format == MEDIA_BUS_FMT_YUV10_1X30) &&
619659 (output_mode == ROCKCHIP_OUT_MODE_AAAA ||
620660 output_mode == ROCKCHIP_OUT_MODE_P888)))
661
+ return true;
662
+ else
663
+ return false;
664
+}
665
+
666
+static bool is_rb_swap(uint32_t bus_format, uint32_t output_mode)
667
+{
668
+ /*
669
+ * The default component order of serial formats
670
+ * is BGR. So it is needed to enable RB swap.
671
+ */
672
+ if (bus_format == MEDIA_BUS_FMT_RGB888_3X8 ||
673
+ bus_format == MEDIA_BUS_FMT_RGB888_DUMMY_4X8 ||
674
+ bus_format == MEDIA_BUS_FMT_RGB666_3X6 ||
675
+ bus_format == MEDIA_BUS_FMT_RGB565_2X8_LE)
621676 return true;
622677 else
623678 return false;
....@@ -661,12 +716,15 @@
661716 {
662717 switch (format) {
663718 case DRM_FORMAT_NV12:
664
- case DRM_FORMAT_NV12_10:
719
+ case DRM_FORMAT_NV15:
665720 case DRM_FORMAT_NV16:
666
- case DRM_FORMAT_NV16_10:
721
+ case DRM_FORMAT_NV20:
667722 case DRM_FORMAT_NV24:
668
- case DRM_FORMAT_NV24_10:
723
+ case DRM_FORMAT_NV30:
724
+ case DRM_FORMAT_YVYU:
725
+ case DRM_FORMAT_VYUY:
669726 case DRM_FORMAT_YUYV:
727
+ case DRM_FORMAT_UYVY:
670728 return true;
671729 default:
672730 return false;
....@@ -676,7 +734,10 @@
676734 static bool is_yuyv_format(uint32_t format)
677735 {
678736 switch (format) {
737
+ case DRM_FORMAT_YVYU:
738
+ case DRM_FORMAT_VYUY:
679739 case DRM_FORMAT_YUYV:
740
+ case DRM_FORMAT_UYVY:
680741 return true;
681742 default:
682743 return false;
....@@ -686,9 +747,9 @@
686747 static bool is_yuv_10bit(uint32_t format)
687748 {
688749 switch (format) {
689
- case DRM_FORMAT_NV12_10:
690
- case DRM_FORMAT_NV16_10:
691
- case DRM_FORMAT_NV24_10:
750
+ case DRM_FORMAT_NV15:
751
+ case DRM_FORMAT_NV20:
752
+ case DRM_FORMAT_NV30:
692753 return true;
693754 default:
694755 return false;
....@@ -704,6 +765,20 @@
704765 default:
705766 return false;
706767 }
768
+}
769
+
770
+static inline bool rockchip_afbc(struct drm_plane *plane, u64 modifier)
771
+{
772
+ int i;
773
+
774
+ if (modifier == DRM_FORMAT_MOD_LINEAR)
775
+ return false;
776
+
777
+ for (i = 0 ; i < plane->modifier_count; i++)
778
+ if (plane->modifiers[i] == modifier)
779
+ break;
780
+
781
+ return (i < plane->modifier_count) ? true : false;
707782 }
708783
709784 static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src,
....@@ -747,9 +822,9 @@
747822 uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;
748823 uint16_t cbcr_hor_scl_mode = SCALE_NONE;
749824 uint16_t cbcr_ver_scl_mode = SCALE_NONE;
750
- int hsub = drm_format_horz_chroma_subsampling(pixel_format);
751
- int vsub = drm_format_vert_chroma_subsampling(pixel_format);
752
- const struct drm_format_info *info;
825
+ const struct drm_format_info *info = drm_format_info(pixel_format);
826
+ uint8_t hsub = info->hsub;
827
+ uint8_t vsub = info->vsub;
753828 bool is_yuv = false;
754829 uint16_t cbcr_src_w = src_w / hsub;
755830 uint16_t cbcr_src_h = src_h / vsub;
....@@ -757,17 +832,27 @@
757832 uint16_t lb_mode;
758833 uint32_t val;
759834 const struct vop_data *vop_data = vop->data;
835
+ struct drm_display_mode *adjusted_mode = &vop->rockchip_crtc.crtc.state->adjusted_mode;
760836 int vskiplines;
761837
762838 if (!win->phy->scl)
763839 return;
840
+
841
+ if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) && vop->version == VOP_VERSION(2, 2)) {
842
+ VOP_SCL_SET(vop, win, scale_yrgb_x, ((src_w << 12) / dst_w));
843
+ VOP_SCL_SET(vop, win, scale_yrgb_y, ((src_h << 12) / dst_h));
844
+ if (is_yuv) {
845
+ VOP_SCL_SET(vop, win, scale_cbcr_x, ((cbcr_src_w << 12) / dst_w));
846
+ VOP_SCL_SET(vop, win, scale_cbcr_y, ((cbcr_src_h << 12) / dst_h));
847
+ }
848
+ return;
849
+ }
764850
765851 if (!(vop_data->feature & VOP_FEATURE_ALPHA_SCALE)) {
766852 if (is_alpha_support(pixel_format) &&
767853 (src_w != dst_w || src_h != dst_h))
768854 DRM_ERROR("ERROR: unsupported ppixel alpha&scale\n");
769855 }
770
- info = drm_format_info(pixel_format);
771856
772857 if (info->is_yuv)
773858 is_yuv = true;
....@@ -1193,7 +1278,7 @@
11931278 * UI(rgbx) -> yuv -> rgb ->hdr2sdr -> overlay -> output.
11941279 */
11951280 if (s->hdr.hdr2sdr_en &&
1196
- vop_plane_state->eotf == SMPTE_ST2084 &&
1281
+ vop_plane_state->eotf == HDMI_EOTF_SMPTE_ST2084 &&
11971282 !is_yuv_support(pstate->fb->format->format))
11981283 vop_plane_state->r2y_en = true;
11991284 if (win->feature & WIN_FEATURE_PRE_OVERLAY)
....@@ -1533,6 +1618,18 @@
15331618 vop_enable_debug_irq(crtc);
15341619 }
15351620
1621
+static void vop_crtc_atomic_disable_for_psr(struct drm_crtc *crtc,
1622
+ struct drm_crtc_state *old_state)
1623
+{
1624
+ struct vop *vop = to_vop(crtc);
1625
+
1626
+ vop_disable_all_planes(vop);
1627
+ drm_crtc_vblank_off(crtc);
1628
+ vop->aclk_rate = clk_get_rate(vop->aclk);
1629
+ clk_set_rate(vop->aclk, vop->aclk_rate / 3);
1630
+ vop->aclk_rate_reset = true;
1631
+}
1632
+
15361633 static void vop_crtc_atomic_disable(struct drm_crtc *crtc,
15371634 struct drm_crtc_state *old_state)
15381635 {
....@@ -1541,6 +1638,11 @@
15411638 SYS_STATUS_LCDC1 : SYS_STATUS_LCDC0;
15421639
15431640 WARN_ON(vop->event);
1641
+
1642
+ if (crtc->state->self_refresh_active) {
1643
+ vop_crtc_atomic_disable_for_psr(crtc, old_state);
1644
+ goto out;
1645
+ }
15441646
15451647 vop_lock(vop);
15461648 VOP_CTRL_SET(vop, reg_done_frm, 1);
....@@ -1589,6 +1691,7 @@
15891691
15901692 rockchip_clear_system_status(sys_status);
15911693
1694
+out:
15921695 if (crtc->state->event && !crtc->state->active) {
15931696 spin_lock_irq(&crtc->dev->event_lock);
15941697 drm_crtc_send_vblank_event(crtc, crtc->state->event);
....@@ -1614,6 +1717,21 @@
16141717 drm_framebuffer_put(old_state->fb);
16151718 }
16161719
1720
+static bool rockchip_vop_mod_supported(struct drm_plane *plane,
1721
+ u32 format, u64 modifier)
1722
+{
1723
+ if (modifier == DRM_FORMAT_MOD_LINEAR)
1724
+ return true;
1725
+
1726
+ if (!rockchip_afbc(plane, modifier)) {
1727
+ DRM_DEBUG_KMS("Unsupported format modifier 0x%llx\n", modifier);
1728
+
1729
+ return false;
1730
+ }
1731
+
1732
+ return vop_convert_afbc_format(format) >= 0;
1733
+}
1734
+
16171735 static int vop_plane_atomic_check(struct drm_plane *plane,
16181736 struct drm_plane_state *state)
16191737 {
....@@ -1627,13 +1745,14 @@
16271745 int ret;
16281746 struct drm_rect *dest = &vop_plane_state->dest;
16291747 struct drm_rect *src = &vop_plane_state->src;
1748
+ struct drm_gem_object *obj, *uv_obj;
1749
+ struct rockchip_gem_object *rk_obj, *rk_uv_obj;
16301750 int min_scale = win->phy->scl ? FRAC_16_16(1, 8) :
16311751 DRM_PLANE_HELPER_NO_SCALING;
16321752 int max_scale = win->phy->scl ? FRAC_16_16(8, 1) :
16331753 DRM_PLANE_HELPER_NO_SCALING;
16341754 unsigned long offset;
16351755 dma_addr_t dma_addr;
1636
- void *kvaddr;
16371756
16381757 crtc = crtc ? crtc : plane->state->crtc;
16391758 if (!crtc || !fb) {
....@@ -1645,14 +1764,8 @@
16451764 if (WARN_ON(!crtc_state))
16461765 return -EINVAL;
16471766
1648
- src->x1 = state->src_x;
1649
- src->y1 = state->src_y;
1650
- src->x2 = state->src_x + state->src_w;
1651
- src->y2 = state->src_y + state->src_h;
1652
- dest->x1 = state->crtc_x;
1653
- dest->y1 = state->crtc_y;
1654
- dest->x2 = state->crtc_x + state->crtc_w;
1655
- dest->y2 = state->crtc_y + state->crtc_h;
1767
+ vop_plane_state->zpos = state->zpos;
1768
+ vop_plane_state->blend_mode = state->pixel_blend_mode;
16561769
16571770 ret = drm_atomic_helper_check_plane_state(state, crtc_state,
16581771 min_scale, max_scale,
....@@ -1660,8 +1773,22 @@
16601773 if (ret)
16611774 return ret;
16621775
1663
- if (!state->visible)
1776
+ if (!state->visible) {
1777
+ DRM_ERROR("%s is invisible(src: pos[%d, %d] rect[%d x %d] dst: pos[%d, %d] rect[%d x %d]\n",
1778
+ plane->name, state->src_x >> 16, state->src_y >> 16, state->src_w >> 16,
1779
+ state->src_h >> 16, state->crtc_x, state->crtc_y, state->crtc_w,
1780
+ state->crtc_h);
16641781 return 0;
1782
+ }
1783
+
1784
+ src->x1 = state->src.x1;
1785
+ src->y1 = state->src.y1;
1786
+ src->x2 = state->src.x2;
1787
+ src->y2 = state->src.y2;
1788
+ dest->x1 = state->dst.x1;
1789
+ dest->y1 = state->dst.y1;
1790
+ dest->x2 = state->dst.x2;
1791
+ dest->y2 = state->dst.y2;
16651792
16661793 vop_plane_state->format = vop_convert_format(fb->format->format);
16671794 if (vop_plane_state->format < 0)
....@@ -1670,12 +1797,19 @@
16701797 vop = to_vop(crtc);
16711798 vop_data = vop->data;
16721799
1673
- if (state->src_w >> 16 < 4 || state->src_h >> 16 < 4 ||
1674
- state->crtc_w < 4 || state->crtc_h < 4) {
1675
- DRM_ERROR("Invalid size: %dx%d->%dx%d, min size is 4x4\n",
1676
- state->src_w >> 16, state->src_h >> 16,
1677
- state->crtc_w, state->crtc_h);
1800
+ if (VOP_MAJOR(vop->version) == 2 && is_alpha_support(fb->format->format) &&
1801
+ vop_plane_state->global_alpha != 0xff) {
1802
+ DRM_ERROR("Pixel alpha and global alpha can't be enabled at the same time\n");
16781803 return -EINVAL;
1804
+ }
1805
+
1806
+ if (drm_rect_width(src) >> 16 < 4 || drm_rect_height(src) >> 16 < 4 ||
1807
+ drm_rect_width(dest) < 4 || drm_rect_width(dest) < 4) {
1808
+ DRM_ERROR("Invalid size: %dx%d->%dx%d, min size is 4x4\n",
1809
+ drm_rect_width(src) >> 16, drm_rect_height(src) >> 16,
1810
+ drm_rect_width(dest), drm_rect_height(dest));
1811
+ state->visible = false;
1812
+ return 0;
16791813 }
16801814
16811815 if (drm_rect_width(src) >> 16 > vop_data->max_input.width ||
....@@ -1702,26 +1836,27 @@
17021836 return -EINVAL;
17031837 }
17041838
1705
- offset = (src->x1 >> 16) * fb->format->bpp[0] / 8;
1839
+ offset = (src->x1 >> 16) * fb->format->cpp[0];
17061840 vop_plane_state->offset = offset + fb->offsets[0];
17071841 if (state->rotation & DRM_MODE_REFLECT_Y)
17081842 offset += ((src->y2 >> 16) - 1) * fb->pitches[0];
17091843 else
17101844 offset += (src->y1 >> 16) * fb->pitches[0];
17111845
1712
- dma_addr = rockchip_fb_get_dma_addr(fb, 0);
1713
- kvaddr = rockchip_fb_get_kvaddr(fb, 0);
1714
- vop_plane_state->yrgb_mst = dma_addr + offset + fb->offsets[0];
1715
- vop_plane_state->yrgb_kvaddr = kvaddr + offset + fb->offsets[0];
1846
+ obj = fb->obj[0];
1847
+ rk_obj = to_rockchip_obj(obj);
1848
+ vop_plane_state->yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
17161849 if (fb->format->is_yuv) {
1717
- int hsub = drm_format_horz_chroma_subsampling(fb->format->format);
1718
- int vsub = drm_format_vert_chroma_subsampling(fb->format->format);
1850
+ int hsub = fb->format->hsub;
1851
+ int vsub = fb->format->vsub;
17191852
1720
- offset = (src->x1 >> 16) * fb->format->bpp[1] / hsub / 8;
1853
+ offset = (src->x1 >> 16) * fb->format->cpp[1] / hsub;
17211854 offset += (src->y1 >> 16) * fb->pitches[1] / vsub;
17221855
1723
- dma_addr = rockchip_fb_get_dma_addr(fb, 1);
1724
- dma_addr += offset + fb->offsets[1];
1856
+ uv_obj = fb->obj[1];
1857
+ rk_uv_obj = to_rockchip_obj(uv_obj);
1858
+
1859
+ dma_addr = rk_uv_obj->dma_addr + offset + fb->offsets[1];
17251860 vop_plane_state->uv_mst = dma_addr;
17261861 }
17271862
....@@ -1737,6 +1872,9 @@
17371872 struct vop_plane_state *vop_plane_state =
17381873 to_vop_plane_state(plane->state);
17391874 #endif
1875
+
1876
+ rockchip_drm_dbg(vop->dev, VOP_DEBUG_PLANE, "disable win%d-area%d by %s\n",
1877
+ win->win_id, win->area_id, current->comm);
17401878
17411879 if (!old_state->crtc)
17421880 return;
....@@ -1847,20 +1985,19 @@
18471985 uint32_t val;
18481986 bool rb_swap, global_alpha_en;
18491987 int is_yuv = fb->format->is_yuv;
1988
+ struct drm_format_name_buf format_name;
18501989
18511990 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
18521991 bool AFBC_flag = false;
18531992 struct vop_dump_list *planlist;
18541993 unsigned long num_pages;
18551994 struct page **pages;
1856
- struct rockchip_drm_fb *rk_fb;
18571995 struct drm_gem_object *obj;
18581996 struct rockchip_gem_object *rk_obj;
18591997
18601998 num_pages = 0;
18611999 pages = NULL;
1862
- rk_fb = to_rockchip_fb(fb);
1863
- obj = rk_fb->obj[0];
2000
+ obj = fb->obj[0];
18642001 rk_obj = to_rockchip_obj(obj);
18652002 if (rk_obj) {
18662003 num_pages = rk_obj->num_pages;
....@@ -1908,6 +2045,8 @@
19082045 dsp_h = 4;
19092046 actual_h = dsp_h * actual_h / drm_rect_height(dest);
19102047 }
2048
+ if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) && vop->version == VOP_VERSION(2, 2))
2049
+ dsp_h = dsp_h / 2;
19112050
19122051 act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff);
19132052
....@@ -1916,12 +2055,18 @@
19162055
19172056 dsp_stx = dest->x1 + mode->crtc_htotal - mode->crtc_hsync_start;
19182057 dsp_sty = dest->y1 + mode->crtc_vtotal - mode->crtc_vsync_start;
2058
+ if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) && vop->version == VOP_VERSION(2, 2))
2059
+ dsp_sty = dest->y1 / 2 + mode->crtc_vtotal - mode->crtc_vsync_start;
19192060 dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
19202061
19212062 s = to_rockchip_crtc_state(crtc->state);
19222063 spin_lock(&vop->reg_lock);
19232064
19242065 VOP_WIN_SET(vop, win, format, vop_plane_state->format);
2066
+
2067
+ VOP_WIN_SET(vop, win, interlace_read,
2068
+ (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
2069
+
19252070 VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4));
19262071 VOP_WIN_SET(vop, win, yrgb_mst, vop_plane_state->yrgb_mst);
19272072
....@@ -1939,7 +2084,7 @@
19392084
19402085 if (win->phy->scl)
19412086 scl_vop_cal_scl_fac(vop, win, actual_w, actual_h,
1942
- drm_rect_width(dest), drm_rect_height(dest),
2087
+ drm_rect_width(dest), dsp_h,
19432088 fb->format->format);
19442089
19452090 if (VOP_WIN_SUPPORT(vop, win, color_key))
....@@ -1970,7 +2115,6 @@
19702115 src_blend_m0 = ALPHA_PER_PIX;
19712116 else
19722117 src_blend_m0 = ALPHA_GLOBAL;
1973
-
19742118
19752119 if (vop_plane_state->blend_mode == 0 || src_blend_m0 == ALPHA_GLOBAL)
19762120 pre_multi_alpha = ALPHA_SRC_NO_PRE_MUL;
....@@ -2006,6 +2150,13 @@
20062150 VOP_WIN_SET(vop, win, enable, 1);
20072151 VOP_WIN_SET(vop, win, gate, 1);
20082152 spin_unlock(&vop->reg_lock);
2153
+
2154
+ drm_get_format_name(fb->format->format, &format_name);
2155
+ rockchip_drm_dbg(vop->dev, VOP_DEBUG_PLANE,
2156
+ "update win%d-area%d [%dx%d->%dx%d@(%d, %d)] zpos:%d fmt[%s%s] addr[%pad] by %s\n",
2157
+ win->win_id, win->area_id, actual_w, actual_h,
2158
+ dsp_w, dsp_h, dsp_stx, dsp_sty, vop_plane_state->zpos, format_name.str,
2159
+ fb->modifier ? "[AFBC]" : "", &vop_plane_state->yrgb_mst, current->comm);
20092160 /*
20102161 * spi interface(vop_plane_state->yrgb_kvaddr, fb->pixel_format,
20112162 * actual_w, actual_h)
....@@ -2027,17 +2178,17 @@
20272178 planlist->dump_info.offset = vop_plane_state->offset;
20282179 planlist->dump_info.pitches = fb->pitches[0];
20292180 planlist->dump_info.height = actual_h;
2030
- planlist->dump_info.pixel_format = fb->format->format;
2031
- list_add_tail(&planlist->entry, &crtc->vop_dump_list_head);
2181
+ planlist->dump_info.format = fb->format;
2182
+ list_add_tail(&planlist->entry, &vop->rockchip_crtc.vop_dump_list_head);
20322183 vop_plane_state->planlist = planlist;
20332184 } else {
20342185 DRM_ERROR("can't alloc a node of planlist %p\n", planlist);
20352186 return;
20362187 }
2037
- if (crtc->vop_dump_status == DUMP_KEEP ||
2038
- crtc->vop_dump_times > 0) {
2039
- vop_plane_dump(&planlist->dump_info, crtc->frame_count);
2040
- crtc->vop_dump_times--;
2188
+ if (vop->rockchip_crtc.vop_dump_status == DUMP_KEEP ||
2189
+ vop->rockchip_crtc.vop_dump_times > 0) {
2190
+ rockchip_drm_dump_plane_buffer(&planlist->dump_info, vop->rockchip_crtc.frame_count);
2191
+ vop->rockchip_crtc.vop_dump_times--;
20412192 }
20422193 #endif
20432194 }
....@@ -2186,10 +2337,9 @@
21862337 if (!vop_plane_state)
21872338 return;
21882339
2189
- win->state.zpos = win->zpos;
2340
+ __drm_atomic_helper_plane_reset(plane, &vop_plane_state->base);
2341
+ vop_plane_state->base.zpos = win->zpos;
21902342 vop_plane_state->global_alpha = 0xff;
2191
- plane->state = &vop_plane_state->base;
2192
- plane->state->plane = plane;
21932343 }
21942344
21952345 static struct drm_plane_state *
....@@ -2232,11 +2382,6 @@
22322382 struct vop_win *win = to_vop_win(plane);
22332383 struct vop_plane_state *plane_state = to_vop_plane_state(state);
22342384
2235
- if (property == win->vop->plane_zpos_prop) {
2236
- plane_state->zpos = val;
2237
- return 0;
2238
- }
2239
-
22402385 if (property == private->eotf_prop) {
22412386 plane_state->eotf = val;
22422387 return 0;
....@@ -2244,16 +2389,6 @@
22442389
22452390 if (property == private->color_space_prop) {
22462391 plane_state->color_space = val;
2247
- return 0;
2248
- }
2249
-
2250
- if (property == private->global_alpha_prop) {
2251
- plane_state->global_alpha = val;
2252
- return 0;
2253
- }
2254
-
2255
- if (property == private->blend_mode_prop) {
2256
- plane_state->blend_mode = val;
22572392 return 0;
22582393 }
22592394
....@@ -2282,11 +2417,6 @@
22822417 struct vop_win *win = to_vop_win(plane);
22832418 struct rockchip_drm_private *private = plane->dev->dev_private;
22842419
2285
- if (property == win->vop->plane_zpos_prop) {
2286
- *val = plane_state->zpos;
2287
- return 0;
2288
- }
2289
-
22902420 if (property == private->eotf_prop) {
22912421 *val = plane_state->eotf;
22922422 return 0;
....@@ -2294,16 +2424,6 @@
22942424
22952425 if (property == private->color_space_prop) {
22962426 *val = plane_state->color_space;
2297
- return 0;
2298
- }
2299
-
2300
- if (property == private->global_alpha_prop) {
2301
- *val = plane_state->global_alpha;
2302
- return 0;
2303
- }
2304
-
2305
- if (property == private->blend_mode_prop) {
2306
- *val = plane_state->blend_mode;
23072427 return 0;
23082428 }
23092429
....@@ -2344,6 +2464,7 @@
23442464 .atomic_destroy_state = vop_atomic_plane_destroy_state,
23452465 .atomic_set_property = vop_atomic_plane_set_property,
23462466 .atomic_get_property = vop_atomic_plane_get_property,
2467
+ .format_mod_supported = rockchip_vop_mod_supported,
23472468 };
23482469
23492470 static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
....@@ -2400,13 +2521,13 @@
24002521 if (e && e->base.file_priv == file_priv) {
24012522 vop->event = NULL;
24022523
2403
- //e->base.destroy(&e->base);//todo
2524
+ /* e->base.destroy(&e->base);//todo */
24042525 file_priv->event_space += sizeof(e->event);
24052526 }
24062527 spin_unlock_irqrestore(&drm->event_lock, flags);
24072528 }
24082529
2409
-static int vop_crtc_loader_protect(struct drm_crtc *crtc, bool on)
2530
+static int vop_crtc_loader_protect(struct drm_crtc *crtc, bool on, void *data)
24102531 {
24112532 struct rockchip_drm_private *private = crtc->dev->dev_private;
24122533 struct vop *vop = to_vop(crtc);
....@@ -2465,6 +2586,9 @@
24652586 struct drm_framebuffer *fb = state->fb;
24662587 struct drm_format_name_buf format_name;
24672588 int i;
2589
+ struct drm_gem_object *obj;
2590
+ struct rockchip_gem_object *rk_obj;
2591
+ dma_addr_t fb_addr;
24682592 u64 afbdc_format =
24692593 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16);
24702594
....@@ -2492,14 +2616,30 @@
24922616 DEBUG_PRINT("\tdst: pos[%dx%d] rect[%dx%d]\n", dest->x1, dest->y1,
24932617 drm_rect_width(dest), drm_rect_height(dest));
24942618
2495
- for (i = 0; i < drm_format_num_planes(fb->format->format); i++) {
2496
- dma_addr_t fb_addr = rockchip_fb_get_dma_addr(fb, i);
2619
+ for (i = 0; i < fb->format->num_planes; i++) {
2620
+ obj = fb->obj[0];
2621
+ rk_obj = to_rockchip_obj(obj);
2622
+ fb_addr = rk_obj->dma_addr + fb->offsets[0];
24972623
24982624 DEBUG_PRINT("\tbuf[%d]: addr: %pad pitch: %d offset: %d\n",
24992625 i, &fb_addr, fb->pitches[i], fb->offsets[i]);
25002626 }
25012627
25022628 return 0;
2629
+}
2630
+
2631
+static void vop_dump_connector_on_crtc(struct drm_crtc *crtc, struct seq_file *s)
2632
+{
2633
+ struct drm_connector_list_iter conn_iter;
2634
+ struct drm_connector *connector;
2635
+
2636
+ drm_connector_list_iter_begin(crtc->dev, &conn_iter);
2637
+ drm_for_each_connector_iter(connector, &conn_iter) {
2638
+ if (crtc->state->connector_mask & drm_connector_mask(connector))
2639
+ DEBUG_PRINT(" Connector: %s\n", connector->name);
2640
+
2641
+ }
2642
+ drm_connector_list_iter_end(&conn_iter);
25032643 }
25042644
25052645 static int vop_crtc_debugfs_dump(struct drm_crtc *crtc, struct seq_file *s)
....@@ -2518,8 +2658,7 @@
25182658 if (!crtc_state->active)
25192659 return 0;
25202660
2521
- DEBUG_PRINT(" Connector: %s\n",
2522
- drm_get_connector_name(state->output_type));
2661
+ vop_dump_connector_on_crtc(crtc, s);
25232662 DEBUG_PRINT("\tbus_format[%x]: %s\n", state->bus_format,
25242663 drm_get_bus_format_name(state->bus_format));
25252664 DEBUG_PRINT("\toverlay_mode[%d] output_mode[%x]",
....@@ -2613,24 +2752,15 @@
26132752 goto remove;
26142753 }
26152754 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
2616
- drm_debugfs_vop_add(crtc, vop->debugfs);
2755
+ rockchip_drm_add_dump_buffer(crtc, vop->debugfs);
26172756 #endif
26182757 for (i = 0; i < ARRAY_SIZE(vop_debugfs_files); i++)
26192758 vop->debugfs_files[i].data = vop;
26202759
2621
- ret = drm_debugfs_create_files(vop->debugfs_files,
2622
- ARRAY_SIZE(vop_debugfs_files),
2623
- vop->debugfs,
2624
- minor);
2625
- if (ret) {
2626
- dev_err(vop->dev, "could not install rockchip_debugfs_list\n");
2627
- goto free;
2628
- }
2760
+ drm_debugfs_create_files(vop->debugfs_files, ARRAY_SIZE(vop_debugfs_files),
2761
+ vop->debugfs, minor);
26292762
26302763 return 0;
2631
-free:
2632
- kfree(vop->debugfs_files);
2633
- vop->debugfs_files = NULL;
26342764 remove:
26352765 debugfs_remove(vop->debugfs);
26362766 vop->debugfs = NULL;
....@@ -2638,10 +2768,10 @@
26382768 }
26392769
26402770 static enum drm_mode_status
2641
-vop_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode,
2642
- int output_type)
2771
+vop_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
26432772 {
26442773 struct vop *vop = to_vop(crtc);
2774
+ struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
26452775 const struct vop_data *vop_data = vop->data;
26462776 int request_clock = mode->clock;
26472777 int clock;
....@@ -2654,15 +2784,20 @@
26542784 VOP_MINOR(vop->version) <= 2)
26552785 return MODE_BAD;
26562786
2657
- if (mode->flags & DRM_MODE_FLAG_DBLCLK)
2787
+ /*
2788
+ * Dclk need to be double if BT656 interface and vop version >= 2.12.
2789
+ */
2790
+ if (mode->flags & DRM_MODE_FLAG_DBLCLK ||
2791
+ (VOP_MAJOR(vop->version) == 2 && VOP_MINOR(vop->version) >= 12 &&
2792
+ s->output_if & VOP_OUTPUT_IF_BT656))
26582793 request_clock *= 2;
26592794 clock = clk_round_rate(vop->dclk, request_clock * 1000) / 1000;
26602795
26612796 /*
26622797 * Hdmi or DisplayPort request a Accurate clock.
26632798 */
2664
- if (output_type == DRM_MODE_CONNECTOR_HDMIA ||
2665
- output_type == DRM_MODE_CONNECTOR_DisplayPort)
2799
+ if (s->output_type == DRM_MODE_CONNECTOR_HDMIA ||
2800
+ s->output_type == DRM_MODE_CONNECTOR_DisplayPort)
26662801 if (clock != request_clock)
26672802 return MODE_CLOCK_RANGE;
26682803
....@@ -2692,7 +2827,7 @@
26922827 struct drm_framebuffer *fb = pstate->fb;
26932828 struct drm_rect *dest = &vop_plane_state->dest;
26942829 struct drm_rect *src = &vop_plane_state->src;
2695
- int bpp = fb->format->bpp[0];
2830
+ int bpp = fb->format->cpp[0] << 3;
26962831 int src_width = drm_rect_width(src) >> 16;
26972832 int src_height = drm_rect_height(src) >> 16;
26982833 int dest_width = drm_rect_width(dest);
....@@ -2741,8 +2876,7 @@
27412876
27422877 static size_t vop_crtc_bandwidth(struct drm_crtc *crtc,
27432878 struct drm_crtc_state *crtc_state,
2744
- size_t *frame_bw_mbyte,
2745
- unsigned int *plane_num_total)
2879
+ struct dmcfreq_vop_info *vop_bw_info)
27462880 {
27472881 struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
27482882 u16 htotal = adjusted_mode->crtc_htotal;
....@@ -2752,64 +2886,77 @@
27522886 struct drm_plane_state *pstate;
27532887 struct vop_bandwidth *pbandwidth;
27542888 struct drm_plane *plane;
2755
- u64 bandwidth;
2889
+ u64 line_bw_mbyte = 0;
27562890 int cnt = 0, plane_num = 0;
27572891 struct drm_atomic_state *state = crtc_state->state;
27582892 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
27592893 struct vop_dump_list *pos, *n;
2894
+ struct vop *vop = to_vop(crtc);
27602895 #endif
27612896
27622897 if (!htotal || !vdisplay)
27632898 return 0;
27642899
27652900 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
2766
- if (!crtc->vop_dump_list_init_flag) {
2767
- INIT_LIST_HEAD(&crtc->vop_dump_list_head);
2768
- crtc->vop_dump_list_init_flag = true;
2901
+ if (!vop->rockchip_crtc.vop_dump_list_init_flag) {
2902
+ INIT_LIST_HEAD(&vop->rockchip_crtc.vop_dump_list_head);
2903
+ vop->rockchip_crtc.vop_dump_list_init_flag = true;
27692904 }
2770
- list_for_each_entry_safe(pos, n, &crtc->vop_dump_list_head, entry) {
2905
+ list_for_each_entry_safe(pos, n, &vop->rockchip_crtc.vop_dump_list_head, entry) {
27712906 list_del(&pos->entry);
27722907 }
2773
- if (crtc->vop_dump_status == DUMP_KEEP ||
2774
- crtc->vop_dump_times > 0) {
2775
- crtc->frame_count++;
2908
+ if (vop->rockchip_crtc.vop_dump_status == DUMP_KEEP ||
2909
+ vop->rockchip_crtc.vop_dump_times > 0) {
2910
+ vop->rockchip_crtc.frame_count++;
27762911 }
27772912 #endif
27782913
27792914 drm_atomic_crtc_state_for_each_plane(plane, crtc_state)
27802915 plane_num++;
27812916
2782
- if (plane_num_total)
2783
- *plane_num_total += plane_num;
2917
+ vop_bw_info->plane_num += plane_num;
27842918 pbandwidth = kmalloc_array(plane_num, sizeof(*pbandwidth),
27852919 GFP_KERNEL);
27862920 if (!pbandwidth)
27872921 return -ENOMEM;
27882922
27892923 drm_atomic_crtc_state_for_each_plane(plane, crtc_state) {
2924
+ int act_w, act_h, cpp, afbc_fac;
2925
+
27902926 pstate = drm_atomic_get_existing_plane_state(state, plane);
27912927 if (pstate->crtc != crtc || !pstate->fb)
27922928 continue;
27932929
2930
+ /* This is an empirical value, if it's afbc format, the frame buffer size div 2 */
2931
+ afbc_fac = rockchip_afbc(plane, pstate->fb->modifier) ? 2 : 1;
2932
+
27942933 vop_plane_state = to_vop_plane_state(pstate);
27952934 pbandwidth[cnt].y1 = vop_plane_state->dest.y1;
27962935 pbandwidth[cnt].y2 = vop_plane_state->dest.y2;
2797
- pbandwidth[cnt++].bandwidth = vop_plane_line_bandwidth(pstate);
2936
+ pbandwidth[cnt++].bandwidth = vop_plane_line_bandwidth(pstate) / afbc_fac;
2937
+
2938
+ act_w = drm_rect_width(&pstate->src) >> 16;
2939
+ act_h = drm_rect_height(&pstate->src) >> 16;
2940
+ cpp = pstate->fb->format->cpp[0];
2941
+
2942
+ vop_bw_info->frame_bw_mbyte += act_w * act_h / 1000 * cpp * drm_mode_vrefresh(adjusted_mode) / 1000;
2943
+
27982944 }
27992945
28002946 sort(pbandwidth, cnt, sizeof(pbandwidth[0]), vop_bandwidth_cmp, NULL);
28012947
2802
- bandwidth = vop_calc_max_bandwidth(pbandwidth, 0, cnt, vdisplay);
2948
+ vop_bw_info->line_bw_mbyte = vop_calc_max_bandwidth(pbandwidth, 0, cnt, vdisplay);
28032949 kfree(pbandwidth);
28042950 /*
2805
- * bandwidth(MB/s)
2951
+ * line_bandwidth(MB/s)
28062952 * = line_bandwidth / line_time
28072953 * = line_bandwidth(Byte) * clock(KHZ) / 1000 / htotal
28082954 */
2809
- bandwidth *= clock;
2810
- do_div(bandwidth, htotal * 1000);
2955
+ line_bw_mbyte *= clock;
2956
+ do_div(line_bw_mbyte, htotal * 1000);
2957
+ vop_bw_info->line_bw_mbyte = line_bw_mbyte;
28112958
2812
- return bandwidth;
2959
+ return vop_bw_info->line_bw_mbyte;
28132960 }
28142961
28152962 static void vop_crtc_close(struct drm_crtc *crtc)
....@@ -2892,16 +3039,50 @@
28923039 vop_set_out_mode(vop, state->output_mode);
28933040 }
28943041
3042
+static int vop_crtc_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout)
3043
+{
3044
+ struct vop *vop = to_vop(crtc);
3045
+ unsigned long jiffies_left;
3046
+ int ret = 0;
3047
+
3048
+ if (!vop->is_enabled)
3049
+ return -ENODEV;
3050
+
3051
+ mutex_lock(&vop->vop_lock);
3052
+
3053
+ if (vop_line_flag_irq_is_enabled(vop)) {
3054
+ ret = -EBUSY;
3055
+ goto out;
3056
+ }
3057
+
3058
+ reinit_completion(&vop->line_flag_completion);
3059
+ vop_line_flag_irq_enable(vop);
3060
+
3061
+ jiffies_left = wait_for_completion_timeout(&vop->line_flag_completion,
3062
+ msecs_to_jiffies(mstimeout));
3063
+ vop_line_flag_irq_disable(vop);
3064
+
3065
+ if (jiffies_left == 0) {
3066
+ DRM_DEV_ERROR(vop->dev, "timeout waiting for lineflag IRQ\n");
3067
+ ret = -ETIMEDOUT;
3068
+ goto out;
3069
+ }
3070
+
3071
+out:
3072
+ mutex_unlock(&vop->vop_lock);
3073
+ return ret;
3074
+}
3075
+
28953076 static const struct rockchip_crtc_funcs private_crtc_funcs = {
28963077 .loader_protect = vop_crtc_loader_protect,
28973078 .cancel_pending_vblank = vop_crtc_cancel_pending_vblank,
28983079 .debugfs_init = vop_crtc_debugfs_init,
28993080 .debugfs_dump = vop_crtc_debugfs_dump,
29003081 .regs_dump = vop_crtc_regs_dump,
2901
- .mode_valid = vop_crtc_mode_valid,
29023082 .bandwidth = vop_crtc_bandwidth,
29033083 .crtc_close = vop_crtc_close,
29043084 .crtc_send_mcu_cmd = vop_crtc_send_mcu_cmd,
3085
+ .wait_vact_end = vop_crtc_wait_vact_end,
29053086 };
29063087
29073088 static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
....@@ -2910,6 +3091,8 @@
29103091 {
29113092 struct vop *vop = to_vop(crtc);
29123093 const struct vop_data *vop_data = vop->data;
3094
+ struct drm_crtc_state *new_crtc_state = container_of(mode, struct drm_crtc_state, mode);
3095
+ struct rockchip_crtc_state *s = to_rockchip_crtc_state(new_crtc_state);
29133096
29143097 if (mode->hdisplay > vop_data->max_output.width)
29153098 return false;
....@@ -2917,8 +3100,17 @@
29173100 drm_mode_set_crtcinfo(adj_mode,
29183101 CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE);
29193102
2920
- if (mode->flags & DRM_MODE_FLAG_DBLCLK)
3103
+ /*
3104
+ * Dclk need to be double if BT656 interface and vop version >= 2.12.
3105
+ */
3106
+ if (mode->flags & DRM_MODE_FLAG_DBLCLK ||
3107
+ (VOP_MAJOR(vop->version) == 2 && VOP_MINOR(vop->version) >= 12 &&
3108
+ s->output_if & VOP_OUTPUT_IF_BT656))
29213109 adj_mode->crtc_clock *= 2;
3110
+
3111
+ if (vop->mcu_timing.mcu_pix_total)
3112
+ adj_mode->crtc_clock *= rockchip_drm_get_cycles_per_pixel(s->bus_format) *
3113
+ (vop->mcu_timing.mcu_pix_total + 1);
29223114
29233115 adj_mode->crtc_clock =
29243116 DIV_ROUND_UP(clk_round_rate(vop->dclk, adj_mode->crtc_clock * 1000),
....@@ -2943,13 +3135,14 @@
29433135
29443136 switch (s->bus_format) {
29453137 case MEDIA_BUS_FMT_RGB565_1X16:
3138
+ case MEDIA_BUS_FMT_RGB565_2X8_LE:
29463139 VOP_CTRL_SET(vop, dither_down_en, 1);
29473140 VOP_CTRL_SET(vop, dither_down_mode, RGB888_TO_RGB565);
29483141 break;
29493142 case MEDIA_BUS_FMT_RGB666_1X18:
29503143 case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
29513144 case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
2952
- case MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA:
3145
+ case MEDIA_BUS_FMT_RGB666_3X6:
29533146 VOP_CTRL_SET(vop, dither_down_en, 1);
29543147 VOP_CTRL_SET(vop, dither_down_mode, RGB888_TO_RGB666);
29553148 break;
....@@ -2963,8 +3156,8 @@
29633156 VOP_CTRL_SET(vop, dither_down_en, 0);
29643157 VOP_CTRL_SET(vop, pre_dither_down_en, 0);
29653158 break;
2966
- case MEDIA_BUS_FMT_SRGB888_3X8:
2967
- case MEDIA_BUS_FMT_SRGB888_DUMMY_4X8:
3159
+ case MEDIA_BUS_FMT_RGB888_3X8:
3160
+ case MEDIA_BUS_FMT_RGB888_DUMMY_4X8:
29683161 case MEDIA_BUS_FMT_RGB888_1X24:
29693162 case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
29703163 case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
....@@ -2986,12 +3179,15 @@
29863179 struct vop *vop = to_vop(crtc);
29873180 u32 val;
29883181
2989
- if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
2990
- !(vop->data->feature & VOP_FEATURE_OUTPUT_10BIT))
3182
+ if ((s->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
3183
+ !(vop->data->feature & VOP_FEATURE_OUTPUT_10BIT)) ||
3184
+ (VOP_MAJOR(vop->version) == 2 && VOP_MINOR(vop->version) >= 12 &&
3185
+ s->output_if & VOP_OUTPUT_IF_BT656))
29913186 s->output_mode = ROCKCHIP_OUT_MODE_P888;
29923187
2993
- if (is_uv_swap(s->bus_format, s->output_mode))
2994
- VOP_CTRL_SET(vop, dsp_data_swap, DSP_RB_SWAP);
3188
+ if (is_uv_swap(s->bus_format, s->output_mode) ||
3189
+ is_rb_swap(s->bus_format, s->output_mode))
3190
+ VOP_CTRL_SET(vop, dsp_rb_swap, 1);
29953191 else
29963192 VOP_CTRL_SET(vop, dsp_data_swap, 0);
29973193
....@@ -3097,11 +3293,20 @@
30973293 int for_ddr_freq = 0;
30983294 bool dclk_inv, yc_swap = false;
30993295
3296
+ if (old_state && old_state->self_refresh_active) {
3297
+ drm_crtc_vblank_on(crtc);
3298
+ if (vop->aclk_rate_reset)
3299
+ clk_set_rate(vop->aclk, vop->aclk_rate);
3300
+ vop->aclk_rate_reset = false;
3301
+
3302
+ return;
3303
+ }
3304
+
31003305 rockchip_set_system_status(sys_status);
31013306 vop_lock(vop);
31023307 DRM_DEV_INFO(vop->dev, "Update mode to %dx%d%s%d, type: %d\n",
31033308 hdisplay, vdisplay, interlaced ? "i" : "p",
3104
- adjusted_mode->vrefresh, s->output_type);
3309
+ drm_mode_vrefresh(adjusted_mode), s->output_type);
31053310 vop_initial(crtc);
31063311 vop_disable_allwin(vop);
31073312 VOP_CTRL_SET(vop, standby, 0);
....@@ -3118,6 +3323,9 @@
31183323 vop_mcu_mode(crtc);
31193324
31203325 dclk_inv = (s->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
3326
+ /* For improving signal quality, dclk need to be inverted by default on rv1106. */
3327
+ if ((VOP_MAJOR(vop->version) == 2 && VOP_MINOR(vop->version) == 12))
3328
+ dclk_inv = !dclk_inv;
31213329
31223330 VOP_CTRL_SET(vop, dclk_pol, dclk_inv);
31233331 val = (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ?
....@@ -3147,6 +3355,10 @@
31473355 yc_swap = is_yc_swap(s->bus_format);
31483356 VOP_CTRL_SET(vop, bt1120_yc_swap, yc_swap);
31493357 VOP_CTRL_SET(vop, yuv_clip, 1);
3358
+ } else if (s->output_if & VOP_OUTPUT_IF_BT656) {
3359
+ VOP_CTRL_SET(vop, bt656_en, 1);
3360
+ yc_swap = is_yc_swap(s->bus_format);
3361
+ VOP_CTRL_SET(vop, bt1120_yc_swap, yc_swap);
31503362 }
31513363 break;
31523364 case DRM_MODE_CONNECTOR_eDP:
....@@ -3233,7 +3445,8 @@
32333445 VOP_CTRL_SET(vop, vtotal_pw, vtotal << 16 | vsync_len);
32343446
32353447 VOP_CTRL_SET(vop, core_dclk_div,
3236
- !!(adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK));
3448
+ !!(adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) ||
3449
+ s->output_if & VOP_OUTPUT_IF_BT656);
32373450
32383451 VOP_CTRL_SET(vop, win_csc_mode_sel, 1);
32393452
....@@ -3258,7 +3471,6 @@
32583471 struct drm_crtc_state *crtc_state)
32593472 {
32603473 struct vop *vop = to_vop(crtc);
3261
- const struct vop_data *vop_data = vop->data;
32623474 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
32633475 struct drm_atomic_state *state = crtc_state->state;
32643476 struct drm_plane *plane;
....@@ -3288,8 +3500,8 @@
32883500 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16))
32893501 continue;
32903502
3291
- if (!(vop_data->feature & VOP_FEATURE_AFBDC)) {
3292
- DRM_ERROR("not support afbdc\n");
3503
+ if (!VOP_CTRL_SUPPORT(vop, afbdc_en)) {
3504
+ DRM_INFO("not support afbdc\n");
32933505 return -EINVAL;
32943506 }
32953507
....@@ -3329,10 +3541,17 @@
33293541
33303542 if (VOP_CTRL_SUPPORT(vop, afbdc_pic_vir_width)) {
33313543 u32 align_x1, align_x2, align_y1, align_y2, align_val;
3544
+ struct drm_gem_object *obj;
3545
+ struct rockchip_gem_object *rk_obj;
3546
+ dma_addr_t fb_addr;
3547
+
3548
+ obj = fb->obj[0];
3549
+ rk_obj = to_rockchip_obj(obj);
3550
+ fb_addr = rk_obj->dma_addr + fb->offsets[0];
33323551
33333552 s->afbdc_win_format = afbdc_format;
33343553 s->afbdc_win_id = win->win_id;
3335
- s->afbdc_win_ptr = rockchip_fb_get_dma_addr(fb, 0);
3554
+ s->afbdc_win_ptr = fb_addr;
33363555 s->afbdc_win_vir_width = fb->width;
33373556 s->afbdc_win_xoffset = (src->x1 >> 16);
33383557 s->afbdc_win_yoffset = (src->y1 >> 16);
....@@ -3716,6 +3935,7 @@
37163935 struct rockchip_crtc_state *s =
37173936 to_rockchip_crtc_state(crtc->state);
37183937 struct vop *vop = to_vop(crtc);
3938
+ const struct vop_data *vop_data = vop->data;
37193939
37203940 spin_lock(&vop->reg_lock);
37213941
....@@ -3743,7 +3963,8 @@
37433963 VOP_CTRL_SET(vop, afbdc_en, s->afbdc_en);
37443964
37453965 VOP_CTRL_SET(vop, dsp_layer_sel, s->dsp_layer_sel);
3746
- vop_post_config(crtc);
3966
+ if (vop_data->feature & VOP_FEATURE_OVERSCAN)
3967
+ vop_post_config(crtc);
37473968
37483969 spin_unlock(&vop->reg_lock);
37493970 }
....@@ -3821,6 +4042,7 @@
38214042 spin_lock_irqsave(&vop->irq_lock, flags);
38224043 vop->pre_overlay = s->hdr.pre_overlay;
38234044 vop_cfg_done(vop);
4045
+ rockchip_drm_dbg(vop->dev, VOP_DEBUG_CFG_DONE, "cfg_done\n\n");
38244046 /*
38254047 * rk322x and rk332x odd-even field will mistake when in interlace mode.
38264048 * we must switch to frame effect before switch screen and switch to
....@@ -3854,21 +4076,6 @@
38544076 crtc->state->event = NULL;
38554077 }
38564078 spin_unlock_irq(&crtc->dev->event_lock);
3857
-
3858
-#if 0
3859
- for_each_plane_in_state(old_state, plane, old_plane_state, i) {
3860
- if (!old_plane_state->fb)
3861
- continue;
3862
-
3863
- if (old_plane_state->fb == plane->state->fb)
3864
- continue;
3865
-
3866
- drm_framebuffer_get(old_plane_state->fb);
3867
- WARN_ON(drm_crtc_vblank_get(crtc) != 0);
3868
- drm_flip_work_queue(&vop->fb_unref_work, old_plane_state->fb);
3869
- set_bit(VOP_PENDING_FB_UNREF, &vop->pending);
3870
- }
3871
-#else
38724079 for_each_old_plane_in_state(old_state, plane, old_plane_state, i) {
38734080 if (!old_plane_state->fb)
38744081 continue;
....@@ -3881,11 +4088,11 @@
38814088 drm_flip_work_queue(&vop->fb_unref_work, old_plane_state->fb);
38824089 set_bit(VOP_PENDING_FB_UNREF, &vop->pending);
38834090 }
3884
-#endif
38854091 }
38864092
38874093 static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = {
38884094 .mode_fixup = vop_crtc_mode_fixup,
4095
+ .mode_valid = vop_crtc_mode_valid,
38894096 .atomic_check = vop_crtc_atomic_check,
38904097 .atomic_flush = vop_crtc_atomic_flush,
38914098 .atomic_enable = vop_crtc_atomic_enable,
....@@ -3921,6 +4128,9 @@
39214128 static struct drm_crtc_state *vop_crtc_duplicate_state(struct drm_crtc *crtc)
39224129 {
39234130 struct rockchip_crtc_state *rockchip_state, *old_state;
4131
+
4132
+ if (WARN_ON(!crtc->state))
4133
+ return NULL;
39244134
39254135 old_state = to_rockchip_crtc_state(crtc->state);
39264136 rockchip_state = kmemdup(old_state, sizeof(*old_state), GFP_KERNEL);
....@@ -4036,8 +4246,19 @@
40364246 return 0;
40374247 }
40384248
4039
- if (property == private->alpha_scale_prop) {
4040
- *val = (vop->data->feature & VOP_FEATURE_ALPHA_SCALE) ? 1 : 0;
4249
+ if (property == private->aclk_prop) {
4250
+ /* KHZ, keep align with mode->clock */
4251
+ *val = clk_get_rate(vop->aclk) / 1000;
4252
+ return 0;
4253
+ }
4254
+
4255
+ if (property == private->bg_prop) {
4256
+ *val = vop->background;
4257
+ return 0;
4258
+ }
4259
+
4260
+ if (property == private->line_flag_prop) {
4261
+ *val = vop->line_flag;
40414262 return 0;
40424263 }
40434264
....@@ -4051,9 +4272,10 @@
40514272 uint64_t val)
40524273 {
40534274 struct drm_device *drm_dev = crtc->dev;
4275
+ struct rockchip_drm_private *private = drm_dev->dev_private;
40544276 struct drm_mode_config *mode_config = &drm_dev->mode_config;
40554277 struct rockchip_crtc_state *s = to_rockchip_crtc_state(state);
4056
- //struct vop *vop = to_vop(crtc);
4278
+ struct vop *vop = to_vop(crtc);
40574279
40584280 if (property == mode_config->tv_left_margin_property) {
40594281 s->left_margin = val;
....@@ -4072,6 +4294,16 @@
40724294
40734295 if (property == mode_config->tv_bottom_margin_property) {
40744296 s->bottom_margin = val;
4297
+ return 0;
4298
+ }
4299
+
4300
+ if (property == private->bg_prop) {
4301
+ vop->background = val;
4302
+ return 0;
4303
+ }
4304
+
4305
+ if (property == private->line_flag_prop) {
4306
+ vop->line_flag = val;
40754307 return 0;
40764308 }
40774309
....@@ -4100,14 +4332,14 @@
41004332 struct vop *vop = container_of(work, struct vop, fb_unref_work);
41014333 struct drm_framebuffer *fb = val;
41024334
4103
- drm_crtc_vblank_put(&vop->crtc);
4335
+ drm_crtc_vblank_put(&vop->rockchip_crtc.crtc);
41044336 drm_framebuffer_put(fb);
41054337 }
41064338
41074339 static void vop_handle_vblank(struct vop *vop)
41084340 {
41094341 struct drm_device *drm = vop->drm_dev;
4110
- struct drm_crtc *crtc = &vop->crtc;
4342
+ struct drm_crtc *crtc = &vop->rockchip_crtc.crtc;
41114343 unsigned long flags;
41124344
41134345 spin_lock_irqsave(&drm->event_lock, flags);
....@@ -4125,7 +4357,7 @@
41254357 static irqreturn_t vop_isr(int irq, void *data)
41264358 {
41274359 struct vop *vop = data;
4128
- struct drm_crtc *crtc = &vop->crtc;
4360
+ struct drm_crtc *crtc = &vop->rockchip_crtc.crtc;
41294361 uint32_t active_irqs;
41304362 unsigned long flags;
41314363 int ret = IRQ_NONE;
....@@ -4176,6 +4408,7 @@
41764408 * frame effective, but actually it's effective immediately, so
41774409 * we config this register at frame start.
41784410 */
4411
+ rockchip_drm_dbg(vop->dev, VOP_DEBUG_VSYNC, "vsync\n");
41794412 spin_lock_irqsave(&vop->irq_lock, flags);
41804413 VOP_CTRL_SET(vop, level2_overlay_en, vop->pre_overlay);
41814414 VOP_CTRL_SET(vop, alpha_hard_calc, vop->pre_overlay);
....@@ -4222,27 +4455,49 @@
42224455
42234456 flags |= (VOP_WIN_SUPPORT(vop, win, xmirror)) ? DRM_MODE_REFLECT_X : 0;
42244457 flags |= (VOP_WIN_SUPPORT(vop, win, ymirror)) ? DRM_MODE_REFLECT_Y : 0;
4458
+
42254459 if (flags)
42264460 drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
42274461 DRM_MODE_ROTATE_0 | flags);
4462
+}
4463
+
4464
+static int vop_plane_create_name_property(struct vop *vop, struct vop_win *win)
4465
+{
4466
+ struct drm_prop_enum_list *props = vop->plane_name_list;
4467
+ struct drm_property *prop;
4468
+ uint64_t bits = BIT_ULL(win->plane_id);
4469
+
4470
+ prop = drm_property_create_bitmask(vop->drm_dev,
4471
+ DRM_MODE_PROP_IMMUTABLE, "NAME",
4472
+ props, vop->num_wins, bits);
4473
+ if (!prop) {
4474
+ DRM_DEV_ERROR(vop->dev, "create Name prop for %s failed\n", win->name);
4475
+ return -ENOMEM;
4476
+ }
4477
+ win->name_prop = prop;
4478
+ drm_object_attach_property(&win->base.base, win->name_prop, bits);
4479
+
4480
+ return 0;
42284481 }
42294482
42304483 static int vop_plane_init(struct vop *vop, struct vop_win *win,
42314484 unsigned long possible_crtcs)
42324485 {
42334486 struct rockchip_drm_private *private = vop->drm_dev->dev_private;
4487
+ unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) | BIT(DRM_MODE_BLEND_PREMULTI) |
4488
+ BIT(DRM_MODE_BLEND_COVERAGE);
4489
+ const struct vop_data *vop_data = vop->data;
42344490 uint64_t feature = 0;
42354491 int ret;
42364492
42374493 ret = drm_universal_plane_init(vop->drm_dev, &win->base, possible_crtcs, &vop_plane_funcs,
4238
- win->data_formats, win->nformats, NULL, win->type, NULL);
4494
+ win->data_formats, win->nformats, win->format_modifiers,
4495
+ win->type, win->name);
42394496 if (ret) {
42404497 DRM_ERROR("failed to initialize plane %d\n", ret);
42414498 return ret;
42424499 }
42434500 drm_plane_helper_add(&win->base, &plane_helper_funcs);
4244
- drm_object_attach_property(&win->base.base,
4245
- vop->plane_zpos_prop, win->win_id);
42464501
42474502 if (win->phy->scl)
42484503 feature |= BIT(ROCKCHIP_DRM_PLANE_FEATURE_SCALE);
....@@ -4262,15 +4517,9 @@
42624517 drm_object_attach_property(&win->base.base,
42634518 private->color_space_prop, 0);
42644519 if (VOP_WIN_SUPPORT(vop, win, global_alpha_val))
4265
- drm_object_attach_property(&win->base.base,
4266
- private->global_alpha_prop, 0xff);
4267
- drm_object_attach_property(&win->base.base,
4268
- private->blend_mode_prop, 0);
4520
+ drm_plane_create_alpha_property(&win->base);
42694521 drm_object_attach_property(&win->base.base,
42704522 private->async_commit_prop, 0);
4271
- if (VOP_WIN_SUPPORT(vop, win, color_key))
4272
- drm_object_attach_property(&win->base.base,
4273
- win->color_key_prop, 0);
42744523
42754524 if (win->parent)
42764525 drm_object_attach_property(&win->base.base, private->share_id_prop,
....@@ -4278,6 +4527,45 @@
42784527 else
42794528 drm_object_attach_property(&win->base.base, private->share_id_prop,
42804529 win->base.base.id);
4530
+
4531
+ drm_plane_create_blend_mode_property(&win->base, blend_caps);
4532
+ drm_plane_create_zpos_property(&win->base, win->win_id, 0, vop->num_wins - 1);
4533
+ vop_plane_create_name_property(vop, win);
4534
+
4535
+
4536
+ win->input_width_prop = drm_property_create_range(vop->drm_dev, DRM_MODE_PROP_IMMUTABLE,
4537
+ "INPUT_WIDTH", 0, vop_data->max_input.width);
4538
+ win->input_height_prop = drm_property_create_range(vop->drm_dev, DRM_MODE_PROP_IMMUTABLE,
4539
+ "INPUT_HEIGHT", 0, vop_data->max_input.height);
4540
+
4541
+ win->output_width_prop = drm_property_create_range(vop->drm_dev, DRM_MODE_PROP_IMMUTABLE,
4542
+ "OUTPUT_WIDTH", 0, vop_data->max_input.width);
4543
+ win->output_height_prop = drm_property_create_range(vop->drm_dev, DRM_MODE_PROP_IMMUTABLE,
4544
+ "OUTPUT_HEIGHT", 0, vop_data->max_input.height);
4545
+
4546
+ win->scale_prop = drm_property_create_range(vop->drm_dev, DRM_MODE_PROP_IMMUTABLE,
4547
+ "SCALE_RATE", 8, 8);
4548
+ /*
4549
+ * Support 24 bit(RGB888) or 16 bit(rgb565) color key.
4550
+ * Bit 31 is used as a flag to disable (0) or enable
4551
+ * color keying (1).
4552
+ */
4553
+ if (VOP_WIN_SUPPORT(vop, win, color_key))
4554
+ win->color_key_prop = drm_property_create_range(vop->drm_dev, 0,
4555
+ "colorkey", 0, 0x80ffffff);
4556
+ if (!win->input_width_prop || !win->input_height_prop ||
4557
+ !win->scale_prop) {
4558
+ DRM_ERROR("failed to create property\n");
4559
+ return -ENOMEM;
4560
+ }
4561
+
4562
+ drm_object_attach_property(&win->base.base, win->input_width_prop, 0);
4563
+ drm_object_attach_property(&win->base.base, win->input_height_prop, 0);
4564
+ drm_object_attach_property(&win->base.base, win->output_width_prop, 0);
4565
+ drm_object_attach_property(&win->base.base, win->output_height_prop, 0);
4566
+ drm_object_attach_property(&win->base.base, win->scale_prop, 0);
4567
+ if (VOP_WIN_SUPPORT(vop, win, color_key))
4568
+ drm_object_attach_property(&win->base.base, win->color_key_prop, 0);
42814569
42824570 return 0;
42834571 }
....@@ -4339,16 +4627,75 @@
43394627 return 0;
43404628 }
43414629
4630
+static int vop_crtc_create_plane_mask_property(struct vop *vop, struct drm_crtc *crtc)
4631
+{
4632
+ struct drm_property *prop;
4633
+
4634
+ static const struct drm_prop_enum_list props[] = {
4635
+ { ROCKCHIP_VOP_WIN0, "Win0" },
4636
+ { ROCKCHIP_VOP_WIN1, "Win1" },
4637
+ { ROCKCHIP_VOP_WIN2, "Win2" },
4638
+ { ROCKCHIP_VOP_WIN3, "Win3" },
4639
+ };
4640
+
4641
+ prop = drm_property_create_bitmask(vop->drm_dev,
4642
+ DRM_MODE_PROP_IMMUTABLE, "PLANE_MASK",
4643
+ props, ARRAY_SIZE(props),
4644
+ 0xffffffff);
4645
+ if (!prop) {
4646
+ DRM_DEV_ERROR(vop->dev, "create plane_mask prop for vp%d failed\n", vop->id);
4647
+ return -ENOMEM;
4648
+ }
4649
+
4650
+ vop->plane_mask_prop = prop;
4651
+ drm_object_attach_property(&crtc->base, vop->plane_mask_prop, vop->plane_mask);
4652
+
4653
+ return 0;
4654
+}
4655
+
4656
+static int vop_crtc_create_feature_property(struct vop *vop, struct drm_crtc *crtc)
4657
+{
4658
+ const struct vop_data *vop_data = vop->data;
4659
+
4660
+ struct drm_property *prop;
4661
+ u64 feature = 0;
4662
+
4663
+ static const struct drm_prop_enum_list props[] = {
4664
+ { ROCKCHIP_DRM_CRTC_FEATURE_ALPHA_SCALE, "ALPHA_SCALE" },
4665
+ { ROCKCHIP_DRM_CRTC_FEATURE_HDR10, "HDR10" },
4666
+ { ROCKCHIP_DRM_CRTC_FEATURE_NEXT_HDR, "NEXT_HDR" },
4667
+ };
4668
+
4669
+ if (vop_data->feature & VOP_FEATURE_ALPHA_SCALE)
4670
+ feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_ALPHA_SCALE);
4671
+ if (vop_data->feature & VOP_FEATURE_HDR10)
4672
+ feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_HDR10);
4673
+ if (vop_data->feature & VOP_FEATURE_NEXT_HDR)
4674
+ feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_NEXT_HDR);
4675
+
4676
+ prop = drm_property_create_bitmask(vop->drm_dev,
4677
+ DRM_MODE_PROP_IMMUTABLE, "FEATURE",
4678
+ props, ARRAY_SIZE(props),
4679
+ 0xffffffff);
4680
+ if (!prop) {
4681
+ DRM_DEV_ERROR(vop->dev, "create FEATURE prop for vop%d failed\n", vop->id);
4682
+ return -ENOMEM;
4683
+ }
4684
+
4685
+ vop->feature_prop = prop;
4686
+ drm_object_attach_property(&crtc->base, vop->feature_prop, feature);
4687
+
4688
+ return 0;
4689
+}
4690
+
43424691 static int vop_create_crtc(struct vop *vop)
43434692 {
43444693 struct device *dev = vop->dev;
4345
- const struct vop_data *vop_data = vop->data;
43464694 struct drm_device *drm_dev = vop->drm_dev;
43474695 struct rockchip_drm_private *private = drm_dev->dev_private;
43484696 struct drm_plane *primary = NULL, *cursor = NULL, *plane, *tmp;
4349
- struct drm_crtc *crtc = &vop->crtc;
4697
+ struct drm_crtc *crtc = &vop->rockchip_crtc.crtc;
43504698 struct device_node *port;
4351
- uint64_t feature = 0;
43524699 int ret = 0;
43534700 int i;
43544701
....@@ -4364,7 +4711,8 @@
43644711 win->type != DRM_PLANE_TYPE_CURSOR)
43654712 continue;
43664713
4367
- if (vop_plane_init(vop, win, 0)) {
4714
+ ret = vop_plane_init(vop, win, 0);
4715
+ if (ret) {
43684716 DRM_DEV_ERROR(vop->dev, "failed to init plane\n");
43694717 goto err_cleanup_planes;
43704718 }
....@@ -4394,7 +4742,8 @@
43944742 if (win->type != DRM_PLANE_TYPE_OVERLAY)
43954743 continue;
43964744
4397
- if (vop_plane_init(vop, win, possible_crtcs)) {
4745
+ ret = vop_plane_init(vop, win, possible_crtcs);
4746
+ if (ret) {
43984747 DRM_DEV_ERROR(vop->dev, "failed to init overlay\n");
43994748 goto err_cleanup_crtc;
44004749 }
....@@ -4417,6 +4766,12 @@
44174766 crtc->port = port;
44184767 rockchip_register_crtc_funcs(crtc, &private_crtc_funcs);
44194768
4769
+ drm_object_attach_property(&crtc->base, private->soc_id_prop, vop->soc_id);
4770
+ drm_object_attach_property(&crtc->base, private->port_id_prop, vop->id);
4771
+ drm_object_attach_property(&crtc->base, private->aclk_prop, 0);
4772
+ drm_object_attach_property(&crtc->base, private->bg_prop, 0);
4773
+ drm_object_attach_property(&crtc->base, private->line_flag_prop, 0);
4774
+
44204775 #define VOP_ATTACH_MODE_CONFIG_PROP(prop, v) \
44214776 drm_object_attach_property(&crtc->base, drm_dev->mode_config.prop, v)
44224777
....@@ -4424,13 +4779,15 @@
44244779 VOP_ATTACH_MODE_CONFIG_PROP(tv_right_margin_property, 100);
44254780 VOP_ATTACH_MODE_CONFIG_PROP(tv_top_margin_property, 100);
44264781 VOP_ATTACH_MODE_CONFIG_PROP(tv_bottom_margin_property, 100);
4427
-
44284782 #undef VOP_ATTACH_MODE_CONFIG_PROP
4429
- drm_object_attach_property(&crtc->base, private->alpha_scale_prop, 0);
4430
- if (vop_data->feature & VOP_FEATURE_AFBDC)
4431
- feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_AFBDC);
4432
- drm_object_attach_property(&crtc->base, vop->feature_prop,
4433
- feature);
4783
+ vop_crtc_create_plane_mask_property(vop, crtc);
4784
+ vop_crtc_create_feature_property(vop, crtc);
4785
+ ret = drm_self_refresh_helper_init(crtc);
4786
+ if (ret)
4787
+ DRM_DEV_DEBUG_KMS(vop->dev,
4788
+ "Failed to init %s with SR helpers %d, ignoring\n",
4789
+ crtc->name, ret);
4790
+
44344791 if (vop->lut_regs) {
44354792 u16 *r_base, *g_base, *b_base;
44364793 u32 lut_len = vop->lut_len;
....@@ -4477,9 +4834,11 @@
44774834
44784835 static void vop_destroy_crtc(struct vop *vop)
44794836 {
4480
- struct drm_crtc *crtc = &vop->crtc;
4837
+ struct drm_crtc *crtc = &vop->rockchip_crtc.crtc;
44814838 struct drm_device *drm_dev = vop->drm_dev;
44824839 struct drm_plane *plane, *tmp;
4840
+
4841
+ drm_self_refresh_helper_cleanup(crtc);
44834842
44844843 of_node_put(crtc->port);
44854844
....@@ -4531,16 +4890,15 @@
45314890 const struct vop_data *vop_data = vop->data;
45324891 unsigned int i, j;
45334892 unsigned int num_wins = 0;
4534
- struct drm_property *prop;
4893
+ char name[DRM_PROP_NAME_LEN];
4894
+ uint8_t plane_id = 0;
4895
+ struct drm_prop_enum_list *plane_name_list;
45354896 static const struct drm_prop_enum_list props[] = {
45364897 { ROCKCHIP_DRM_PLANE_FEATURE_SCALE, "scale" },
45374898 { ROCKCHIP_DRM_PLANE_FEATURE_ALPHA, "alpha" },
45384899 { ROCKCHIP_DRM_PLANE_FEATURE_HDR2SDR, "hdr2sdr" },
45394900 { ROCKCHIP_DRM_PLANE_FEATURE_SDR2HDR, "sdr2hdr" },
45404901 { ROCKCHIP_DRM_PLANE_FEATURE_AFBDC, "afbdc" },
4541
- };
4542
- static const struct drm_prop_enum_list crtc_props[] = {
4543
- { ROCKCHIP_DRM_CRTC_FEATURE_AFBDC, "afbdc" },
45444902 };
45454903
45464904 for (i = 0; i < vop_data->win_size; i++) {
....@@ -4556,16 +4914,16 @@
45564914 vop_win->type = win_data->type;
45574915 vop_win->data_formats = win_data->phy->data_formats;
45584916 vop_win->nformats = win_data->phy->nformats;
4917
+ vop_win->format_modifiers = win_data->format_modifiers;
45594918 vop_win->feature = win_data->feature;
45604919 vop_win->vop = vop;
45614920 vop_win->win_id = i;
45624921 vop_win->area_id = 0;
4922
+ vop_win->plane_id = plane_id++;
4923
+ snprintf(name, sizeof(name), "VOP%d-win%d-%d", vop->id, vop_win->win_id, vop_win->area_id);
4924
+ vop_win->name = devm_kstrdup(vop->dev, name, GFP_KERNEL);
45634925 vop_win->zpos = vop_plane_get_zpos(win_data->type,
45644926 vop_data->win_size);
4565
- if (VOP_WIN_SUPPORT(vop, vop_win, color_key))
4566
- vop_win->color_key_prop = drm_property_create_range(vop->drm_dev, 0,
4567
- "colorkey", 0,
4568
- 0x80ffffff);
45694927
45704928 num_wins++;
45714929
....@@ -4582,22 +4940,19 @@
45824940 vop_area->type = DRM_PLANE_TYPE_OVERLAY;
45834941 vop_area->data_formats = vop_win->data_formats;
45844942 vop_area->nformats = vop_win->nformats;
4943
+ vop_area->format_modifiers = win_data->format_modifiers;
45854944 vop_area->vop = vop;
45864945 vop_area->win_id = i;
45874946 vop_area->area_id = j + 1;
4947
+ vop_area->plane_id = plane_id++;
4948
+ snprintf(name, sizeof(name), "VOP%d-win%d-%d", vop->id, vop_area->win_id, vop_area->area_id);
4949
+ vop_area->name = devm_kstrdup(vop->dev, name, GFP_KERNEL);
45884950 num_wins++;
45894951 }
4952
+ vop->plane_mask |= BIT(vop_win->win_id);
45904953 }
45914954
45924955 vop->num_wins = num_wins;
4593
-
4594
- prop = drm_property_create_range(vop->drm_dev, DRM_MODE_PROP_ATOMIC,
4595
- "ZPOS", 0, vop->data->win_size - 1);
4596
- if (!prop) {
4597
- DRM_ERROR("failed to create zpos property\n");
4598
- return -EINVAL;
4599
- }
4600
- vop->plane_zpos_prop = prop;
46014956
46024957 vop->plane_feature_prop = drm_property_create_bitmask(vop->drm_dev,
46034958 DRM_MODE_PROP_IMMUTABLE, "FEATURE",
....@@ -4612,66 +4967,25 @@
46124967 return -EINVAL;
46134968 }
46144969
4615
- vop->feature_prop = drm_property_create_bitmask(vop->drm_dev,
4616
- DRM_MODE_PROP_IMMUTABLE, "FEATURE",
4617
- crtc_props, ARRAY_SIZE(crtc_props),
4618
- BIT(ROCKCHIP_DRM_CRTC_FEATURE_AFBDC));
4619
- if (!vop->feature_prop) {
4620
- DRM_ERROR("failed to create vop feature property\n");
4621
- return -EINVAL;
4970
+ plane_name_list = devm_kzalloc(vop->dev,
4971
+ vop->num_wins * sizeof(*plane_name_list),
4972
+ GFP_KERNEL);
4973
+ if (!plane_name_list) {
4974
+ DRM_DEV_ERROR(vop->dev, "failed to alloc memory for plane_name_list\n");
4975
+ return -ENOMEM;
46224976 }
4977
+
4978
+ for (i = 0; i < vop->num_wins; i++) {
4979
+ struct vop_win *vop_win = &vop->win[i];
4980
+
4981
+ plane_name_list[i].type = vop_win->plane_id;
4982
+ plane_name_list[i].name = vop_win->name;
4983
+ }
4984
+
4985
+ vop->plane_name_list = plane_name_list;
46234986
46244987 return 0;
46254988 }
4626
-
4627
-/**
4628
- * rockchip_drm_wait_vact_end
4629
- * @crtc: CRTC to enable line flag
4630
- * @mstimeout: millisecond for timeout
4631
- *
4632
- * Wait for vact_end line flag irq or timeout.
4633
- *
4634
- * Returns:
4635
- * Zero on success, negative errno on failure.
4636
- */
4637
-int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout)
4638
-{
4639
- struct vop *vop = to_vop(crtc);
4640
- unsigned long jiffies_left;
4641
- int ret = 0;
4642
-
4643
- if (!crtc || !vop->is_enabled)
4644
- return -ENODEV;
4645
-
4646
- mutex_lock(&vop->vop_lock);
4647
- if (mstimeout <= 0) {
4648
- ret = -EINVAL;
4649
- goto out;
4650
- }
4651
-
4652
- if (vop_line_flag_irq_is_enabled(vop)) {
4653
- ret = -EBUSY;
4654
- goto out;
4655
- }
4656
-
4657
- reinit_completion(&vop->line_flag_completion);
4658
- vop_line_flag_irq_enable(vop);
4659
-
4660
- jiffies_left = wait_for_completion_timeout(&vop->line_flag_completion,
4661
- msecs_to_jiffies(mstimeout));
4662
- vop_line_flag_irq_disable(vop);
4663
-
4664
- if (jiffies_left == 0) {
4665
- DRM_DEV_ERROR(vop->dev, "Timeout waiting for IRQ\n");
4666
- ret = -ETIMEDOUT;
4667
- goto out;
4668
- }
4669
-
4670
-out:
4671
- mutex_unlock(&vop->vop_lock);
4672
- return ret;
4673
-}
4674
-EXPORT_SYMBOL(rockchip_drm_wait_vact_end);
46754989
46764990 static int vop_bind(struct device *dev, struct device *master, void *data)
46774991 {
....@@ -4707,6 +5021,8 @@
47075021 vop->drm_dev = drm_dev;
47085022 vop->num_wins = num_wins;
47095023 vop->version = vop_data->version;
5024
+ vop->soc_id = vop_data->soc_id;
5025
+ vop->id = vop_data->vop_id;
47105026 dev_set_drvdata(dev, vop);
47115027 vop->support_multi_area = of_property_read_bool(dev->of_node, "support-multi-area");
47125028