hc
2024-05-10 9999e48639b3cecb08ffb37358bcba3b48161b29
kernel/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
....@@ -1,59 +1,55 @@
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
15
-#include <drm/drm.h>
16
-#include <drm/drmP.h>
17
-#include <drm/drm_atomic.h>
18
-#include <drm/drm_crtc.h>
19
-#include <drm/drm_crtc_helper.h>
20
-#include <drm/drm_flip_work.h>
21
-#include <drm/drm_plane_helper.h>
22
-#ifdef CONFIG_DRM_ANALOGIX_DP
23
-#include <drm/bridge/analogix_dp.h>
24
-#endif
25
-#include <dt-bindings/soc/rockchip-system-status.h>
26
-
7
+#include <linux/clk.h>
8
+#include <linux/component.h>
279 #include <linux/debugfs.h>
10
+#include <linux/delay.h>
2811 #include <linux/fixp-arith.h>
2912 #include <linux/iopoll.h>
3013 #include <linux/kernel.h>
14
+#include <linux/mfd/syscon.h>
3115 #include <linux/module.h>
32
-#include <linux/platform_device.h>
33
-#include <linux/clk.h>
34
-#include <linux/iopoll.h>
3516 #include <linux/of.h>
3617 #include <linux/of_device.h>
37
-#include <linux/pm_runtime.h>
38
-#include <linux/component.h>
3918 #include <linux/overflow.h>
19
+#include <linux/platform_device.h>
20
+#include <linux/pm_runtime.h>
4021 #include <linux/regmap.h>
41
-#include <linux/mfd/syscon.h>
42
-
4322 #include <linux/reset.h>
44
-#include <linux/delay.h>
4523 #include <linux/sort.h>
24
+
25
+#include <drm/drm.h>
26
+#include <drm/drm_atomic.h>
27
+#include <drm/drm_atomic_uapi.h>
28
+#include <drm/drm_crtc.h>
29
+#include <drm/drm_crtc_helper.h>
30
+#include <drm/drm_debugfs.h>
31
+#include <drm/drm_flip_work.h>
32
+#include <drm/drm_fourcc.h>
33
+#include <drm/drm_gem_framebuffer_helper.h>
34
+#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
+
39
+#ifdef CONFIG_DRM_ANALOGIX_DP
40
+#include <drm/bridge/analogix_dp.h>
41
+#endif
42
+
4643 #include <soc/rockchip/rockchip_dmc.h>
4744 #include <soc/rockchip/rockchip-system-status.h>
4845 #include <uapi/linux/videodev2.h>
49
-
50
-#include "../drm_internal.h"
46
+#include "../drm_crtc_internal.h"
5147
5248 #include "rockchip_drm_drv.h"
5349 #include "rockchip_drm_gem.h"
5450 #include "rockchip_drm_fb.h"
55
-#include "rockchip_drm_psr.h"
5651 #include "rockchip_drm_vop.h"
52
+#include "rockchip_rgb.h"
5753
5854 #define VOP_REG_SUPPORT(vop, reg) \
5955 (reg.mask && \
....@@ -151,7 +147,6 @@
151147 } \
152148 } while (0)
153149
154
-#define to_vop(x) container_of(x, struct vop, crtc)
155150 #define to_vop_win(x) container_of(x, struct vop_win, base)
156151 #define to_vop_plane_state(x) container_of(x, struct vop_plane_state, base)
157152
....@@ -172,7 +167,6 @@
172167 struct drm_rect dest;
173168 dma_addr_t yrgb_mst;
174169 dma_addr_t uv_mst;
175
- void *yrgb_kvaddr;
176170 const uint32_t *y2r_table;
177171 const uint32_t *r2r_table;
178172 const uint32_t *r2y_table;
....@@ -181,7 +175,7 @@
181175 bool r2r_en;
182176 bool r2y_en;
183177 int color_space;
184
- int color_key;
178
+ u32 color_key;
185179 unsigned int csc_mode;
186180 int global_alpha;
187181 int blend_mode;
....@@ -191,21 +185,15 @@
191185 struct vop_dump_list *planlist;
192186 };
193187
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
-
203188 struct vop_win {
204189 struct vop_win *parent;
205190 struct drm_plane base;
206191
207192 int win_id;
208193 int area_id;
194
+ u8 plane_id; /* unique plane id */
195
+ const char *name;
196
+
209197 int zpos;
210198 uint32_t offset;
211199 enum drm_plane_type type;
....@@ -213,28 +201,43 @@
213201 const struct vop_csc *csc;
214202 const uint32_t *data_formats;
215203 uint32_t nformats;
204
+ const uint64_t *format_modifiers;
216205 u64 feature;
217206 struct vop *vop;
218207 struct vop_plane_state state;
219208
209
+ struct drm_property *input_width_prop;
210
+ struct drm_property *input_height_prop;
211
+ struct drm_property *output_width_prop;
212
+ struct drm_property *output_height_prop;
220213 struct drm_property *color_key_prop;
214
+ struct drm_property *scale_prop;
215
+ struct drm_property *name_prop;
221216 };
222217
223218 struct vop {
224
- struct drm_crtc crtc;
219
+ struct rockchip_crtc rockchip_crtc;
225220 struct device *dev;
226221 struct drm_device *drm_dev;
227222 struct dentry *debugfs;
228223 struct drm_info_list *debugfs_files;
229
- struct drm_property *plane_zpos_prop;
230224 struct drm_property *plane_feature_prop;
231225 struct drm_property *feature_prop;
226
+
232227 bool is_iommu_enabled;
233228 bool is_iommu_needed;
234229 bool is_enabled;
235230 bool support_multi_area;
236231
232
+ bool aclk_rate_reset;
233
+ unsigned long aclk_rate;
234
+
237235 u32 version;
236
+ u32 background;
237
+ u32 line_flag;
238
+ u8 id;
239
+ u64 soc_id;
240
+ struct drm_prop_enum_list *plane_name_list;
238241
239242 struct drm_tv_connector_state active_tv_state;
240243 bool pre_overlay;
....@@ -308,13 +311,14 @@
308311 { MEDIA_BUS_FMT_RGB666_1X18, "RGB666_1X18" },
309312 { MEDIA_BUS_FMT_RGB666_1X24_CPADHI, "RGB666_1X24_CPADHI" },
310313 { MEDIA_BUS_FMT_RGB666_1X7X3_SPWG, "RGB666_1X7X3_SPWG" },
311
- { MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA, "RGB666_1X7X3_JEIDA" },
312314 { MEDIA_BUS_FMT_YUV8_1X24, "YUV8_1X24" },
313315 { MEDIA_BUS_FMT_UYYVYY8_0_5X24, "UYYVYY8_0_5X24" },
314316 { MEDIA_BUS_FMT_YUV10_1X30, "YUV10_1X30" },
315317 { 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" },
318
+ { MEDIA_BUS_FMT_RGB565_2X8_LE, "RGB565_2X8_LE" },
319
+ { MEDIA_BUS_FMT_RGB666_3X6, "RGB666_3X6" },
320
+ { MEDIA_BUS_FMT_RGB888_3X8, "RGB888_3X8" },
321
+ { MEDIA_BUS_FMT_RGB888_DUMMY_4X8, "RGB888_DUMMY_4X8" },
318322 { MEDIA_BUS_FMT_RGB888_1X24, "RGB888_1X24" },
319323 { MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, "RGB888_1X7X4_SPWG" },
320324 { MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, "RGB888_1X7X4_JEIDA" },
....@@ -324,6 +328,15 @@
324328 };
325329
326330 static DRM_ENUM_NAME_FN(drm_get_bus_format_name, drm_bus_format_enum_list)
331
+
332
+static inline struct vop *to_vop(struct drm_crtc *crtc)
333
+{
334
+ struct rockchip_crtc *rockchip_crtc;
335
+
336
+ rockchip_crtc = container_of(crtc, struct rockchip_crtc, crtc);
337
+
338
+ return container_of(rockchip_crtc, struct vop, rockchip_crtc);
339
+}
327340
328341 static void vop_lock(struct vop *vop)
329342 {
....@@ -449,6 +462,11 @@
449462 const struct vop_hdr_table *table = vop->data->hdr_table;
450463 uint32_t sdr2hdr_eotf_oetf_yn[65];
451464 uint32_t sdr2hdr_oetf_dx_dxpow[64];
465
+
466
+ if (cmd != SDR2HDR_FOR_BT2020 && cmd != SDR2HDR_FOR_HDR && cmd != SDR2HDR_FOR_HLG_HDR) {
467
+ DRM_WARN("unknown sdr2hdr oetf: %d\n", cmd);
468
+ return;
469
+ }
452470
453471 for (i = 0; i < 65; i++) {
454472 if (cmd == SDR2HDR_FOR_BT2020)
....@@ -583,20 +601,46 @@
583601 case DRM_FORMAT_BGR565:
584602 return VOP_FMT_RGB565;
585603 case DRM_FORMAT_NV12:
586
- case DRM_FORMAT_NV12_10:
604
+ case DRM_FORMAT_NV15:
587605 return VOP_FMT_YUV420SP;
588606 case DRM_FORMAT_NV16:
589
- case DRM_FORMAT_NV16_10:
607
+ case DRM_FORMAT_NV20:
590608 return VOP_FMT_YUV422SP;
591609 case DRM_FORMAT_NV24:
592
- case DRM_FORMAT_NV24_10:
610
+ case DRM_FORMAT_NV30:
593611 return VOP_FMT_YUV444SP;
612
+ case DRM_FORMAT_YVYU:
613
+ case DRM_FORMAT_VYUY:
594614 case DRM_FORMAT_YUYV:
615
+ case DRM_FORMAT_UYVY:
595616 return VOP_FMT_YUYV;
596617 default:
597618 DRM_ERROR("unsupported format[%08x]\n", format);
598619 return -EINVAL;
599620 }
621
+}
622
+
623
+static int vop_convert_afbc_format(uint32_t format)
624
+{
625
+ switch (format) {
626
+ case DRM_FORMAT_XRGB8888:
627
+ case DRM_FORMAT_ARGB8888:
628
+ case DRM_FORMAT_XBGR8888:
629
+ case DRM_FORMAT_ABGR8888:
630
+ return AFBDC_FMT_U8U8U8U8;
631
+ case DRM_FORMAT_RGB888:
632
+ case DRM_FORMAT_BGR888:
633
+ return AFBDC_FMT_U8U8U8;
634
+ case DRM_FORMAT_RGB565:
635
+ case DRM_FORMAT_BGR565:
636
+ return AFBDC_FMT_RGB565;
637
+ /* either of the below should not be reachable */
638
+ default:
639
+ DRM_WARN_ONCE("unsupported AFBC format[%08x]\n", format);
640
+ return -EINVAL;
641
+ }
642
+
643
+ return -EINVAL;
600644 }
601645
602646 static bool is_uv_swap(uint32_t bus_format, uint32_t output_mode)
....@@ -618,6 +662,21 @@
618662 bus_format == MEDIA_BUS_FMT_YUV10_1X30) &&
619663 (output_mode == ROCKCHIP_OUT_MODE_AAAA ||
620664 output_mode == ROCKCHIP_OUT_MODE_P888)))
665
+ return true;
666
+ else
667
+ return false;
668
+}
669
+
670
+static bool is_rb_swap(uint32_t bus_format, uint32_t output_mode)
671
+{
672
+ /*
673
+ * The default component order of serial formats
674
+ * is BGR. So it is needed to enable RB swap.
675
+ */
676
+ if (bus_format == MEDIA_BUS_FMT_RGB888_3X8 ||
677
+ bus_format == MEDIA_BUS_FMT_RGB888_DUMMY_4X8 ||
678
+ bus_format == MEDIA_BUS_FMT_RGB666_3X6 ||
679
+ bus_format == MEDIA_BUS_FMT_RGB565_2X8_LE)
621680 return true;
622681 else
623682 return false;
....@@ -661,12 +720,15 @@
661720 {
662721 switch (format) {
663722 case DRM_FORMAT_NV12:
664
- case DRM_FORMAT_NV12_10:
723
+ case DRM_FORMAT_NV15:
665724 case DRM_FORMAT_NV16:
666
- case DRM_FORMAT_NV16_10:
725
+ case DRM_FORMAT_NV20:
667726 case DRM_FORMAT_NV24:
668
- case DRM_FORMAT_NV24_10:
727
+ case DRM_FORMAT_NV30:
728
+ case DRM_FORMAT_YVYU:
729
+ case DRM_FORMAT_VYUY:
669730 case DRM_FORMAT_YUYV:
731
+ case DRM_FORMAT_UYVY:
670732 return true;
671733 default:
672734 return false;
....@@ -676,7 +738,10 @@
676738 static bool is_yuyv_format(uint32_t format)
677739 {
678740 switch (format) {
741
+ case DRM_FORMAT_YVYU:
742
+ case DRM_FORMAT_VYUY:
679743 case DRM_FORMAT_YUYV:
744
+ case DRM_FORMAT_UYVY:
680745 return true;
681746 default:
682747 return false;
....@@ -686,9 +751,9 @@
686751 static bool is_yuv_10bit(uint32_t format)
687752 {
688753 switch (format) {
689
- case DRM_FORMAT_NV12_10:
690
- case DRM_FORMAT_NV16_10:
691
- case DRM_FORMAT_NV24_10:
754
+ case DRM_FORMAT_NV15:
755
+ case DRM_FORMAT_NV20:
756
+ case DRM_FORMAT_NV30:
692757 return true;
693758 default:
694759 return false;
....@@ -704,6 +769,20 @@
704769 default:
705770 return false;
706771 }
772
+}
773
+
774
+static inline bool rockchip_afbc(struct drm_plane *plane, u64 modifier)
775
+{
776
+ int i;
777
+
778
+ if (modifier == DRM_FORMAT_MOD_LINEAR)
779
+ return false;
780
+
781
+ for (i = 0 ; i < plane->modifier_count; i++)
782
+ if (plane->modifiers[i] == modifier)
783
+ break;
784
+
785
+ return (i < plane->modifier_count) ? true : false;
707786 }
708787
709788 static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src,
....@@ -747,9 +826,9 @@
747826 uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;
748827 uint16_t cbcr_hor_scl_mode = SCALE_NONE;
749828 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;
829
+ const struct drm_format_info *info = drm_format_info(pixel_format);
830
+ uint8_t hsub = info->hsub;
831
+ uint8_t vsub = info->vsub;
753832 bool is_yuv = false;
754833 uint16_t cbcr_src_w = src_w / hsub;
755834 uint16_t cbcr_src_h = src_h / vsub;
....@@ -757,17 +836,27 @@
757836 uint16_t lb_mode;
758837 uint32_t val;
759838 const struct vop_data *vop_data = vop->data;
839
+ struct drm_display_mode *adjusted_mode = &vop->rockchip_crtc.crtc.state->adjusted_mode;
760840 int vskiplines;
761841
762842 if (!win->phy->scl)
763843 return;
844
+
845
+ if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) && vop->version == VOP_VERSION(2, 2)) {
846
+ VOP_SCL_SET(vop, win, scale_yrgb_x, ((src_w << 12) / dst_w));
847
+ VOP_SCL_SET(vop, win, scale_yrgb_y, ((src_h << 12) / dst_h));
848
+ if (is_yuv) {
849
+ VOP_SCL_SET(vop, win, scale_cbcr_x, ((cbcr_src_w << 12) / dst_w));
850
+ VOP_SCL_SET(vop, win, scale_cbcr_y, ((cbcr_src_h << 12) / dst_h));
851
+ }
852
+ return;
853
+ }
764854
765855 if (!(vop_data->feature & VOP_FEATURE_ALPHA_SCALE)) {
766856 if (is_alpha_support(pixel_format) &&
767857 (src_w != dst_w || src_h != dst_h))
768858 DRM_ERROR("ERROR: unsupported ppixel alpha&scale\n");
769859 }
770
- info = drm_format_info(pixel_format);
771860
772861 if (info->is_yuv)
773862 is_yuv = true;
....@@ -1193,7 +1282,7 @@
11931282 * UI(rgbx) -> yuv -> rgb ->hdr2sdr -> overlay -> output.
11941283 */
11951284 if (s->hdr.hdr2sdr_en &&
1196
- vop_plane_state->eotf == SMPTE_ST2084 &&
1285
+ vop_plane_state->eotf == HDMI_EOTF_SMPTE_ST2084 &&
11971286 !is_yuv_support(pstate->fb->format->format))
11981287 vop_plane_state->r2y_en = true;
11991288 if (win->feature & WIN_FEATURE_PRE_OVERLAY)
....@@ -1533,6 +1622,18 @@
15331622 vop_enable_debug_irq(crtc);
15341623 }
15351624
1625
+static void vop_crtc_atomic_disable_for_psr(struct drm_crtc *crtc,
1626
+ struct drm_crtc_state *old_state)
1627
+{
1628
+ struct vop *vop = to_vop(crtc);
1629
+
1630
+ vop_disable_all_planes(vop);
1631
+ drm_crtc_vblank_off(crtc);
1632
+ vop->aclk_rate = clk_get_rate(vop->aclk);
1633
+ clk_set_rate(vop->aclk, vop->aclk_rate / 3);
1634
+ vop->aclk_rate_reset = true;
1635
+}
1636
+
15361637 static void vop_crtc_atomic_disable(struct drm_crtc *crtc,
15371638 struct drm_crtc_state *old_state)
15381639 {
....@@ -1541,6 +1642,11 @@
15411642 SYS_STATUS_LCDC1 : SYS_STATUS_LCDC0;
15421643
15431644 WARN_ON(vop->event);
1645
+
1646
+ if (crtc->state->self_refresh_active) {
1647
+ vop_crtc_atomic_disable_for_psr(crtc, old_state);
1648
+ goto out;
1649
+ }
15441650
15451651 vop_lock(vop);
15461652 VOP_CTRL_SET(vop, reg_done_frm, 1);
....@@ -1589,6 +1695,7 @@
15891695
15901696 rockchip_clear_system_status(sys_status);
15911697
1698
+out:
15921699 if (crtc->state->event && !crtc->state->active) {
15931700 spin_lock_irq(&crtc->dev->event_lock);
15941701 drm_crtc_send_vblank_event(crtc, crtc->state->event);
....@@ -1614,6 +1721,21 @@
16141721 drm_framebuffer_put(old_state->fb);
16151722 }
16161723
1724
+static bool rockchip_vop_mod_supported(struct drm_plane *plane,
1725
+ u32 format, u64 modifier)
1726
+{
1727
+ if (modifier == DRM_FORMAT_MOD_LINEAR)
1728
+ return true;
1729
+
1730
+ if (!rockchip_afbc(plane, modifier)) {
1731
+ DRM_DEBUG_KMS("Unsupported format modifier 0x%llx\n", modifier);
1732
+
1733
+ return false;
1734
+ }
1735
+
1736
+ return vop_convert_afbc_format(format) >= 0;
1737
+}
1738
+
16171739 static int vop_plane_atomic_check(struct drm_plane *plane,
16181740 struct drm_plane_state *state)
16191741 {
....@@ -1627,13 +1749,14 @@
16271749 int ret;
16281750 struct drm_rect *dest = &vop_plane_state->dest;
16291751 struct drm_rect *src = &vop_plane_state->src;
1752
+ struct drm_gem_object *obj, *uv_obj;
1753
+ struct rockchip_gem_object *rk_obj, *rk_uv_obj;
16301754 int min_scale = win->phy->scl ? FRAC_16_16(1, 8) :
16311755 DRM_PLANE_HELPER_NO_SCALING;
16321756 int max_scale = win->phy->scl ? FRAC_16_16(8, 1) :
16331757 DRM_PLANE_HELPER_NO_SCALING;
16341758 unsigned long offset;
16351759 dma_addr_t dma_addr;
1636
- void *kvaddr;
16371760
16381761 crtc = crtc ? crtc : plane->state->crtc;
16391762 if (!crtc || !fb) {
....@@ -1645,14 +1768,8 @@
16451768 if (WARN_ON(!crtc_state))
16461769 return -EINVAL;
16471770
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;
1771
+ vop_plane_state->zpos = state->zpos;
1772
+ vop_plane_state->blend_mode = state->pixel_blend_mode;
16561773
16571774 ret = drm_atomic_helper_check_plane_state(state, crtc_state,
16581775 min_scale, max_scale,
....@@ -1660,8 +1777,22 @@
16601777 if (ret)
16611778 return ret;
16621779
1663
- if (!state->visible)
1780
+ if (!state->visible) {
1781
+ DRM_ERROR("%s is invisible(src: pos[%d, %d] rect[%d x %d] dst: pos[%d, %d] rect[%d x %d]\n",
1782
+ plane->name, state->src_x >> 16, state->src_y >> 16, state->src_w >> 16,
1783
+ state->src_h >> 16, state->crtc_x, state->crtc_y, state->crtc_w,
1784
+ state->crtc_h);
16641785 return 0;
1786
+ }
1787
+
1788
+ src->x1 = state->src.x1;
1789
+ src->y1 = state->src.y1;
1790
+ src->x2 = state->src.x2;
1791
+ src->y2 = state->src.y2;
1792
+ dest->x1 = state->dst.x1;
1793
+ dest->y1 = state->dst.y1;
1794
+ dest->x2 = state->dst.x2;
1795
+ dest->y2 = state->dst.y2;
16651796
16661797 vop_plane_state->format = vop_convert_format(fb->format->format);
16671798 if (vop_plane_state->format < 0)
....@@ -1676,12 +1807,13 @@
16761807 return -EINVAL;
16771808 }
16781809
1679
- if (state->src_w >> 16 < 4 || state->src_h >> 16 < 4 ||
1680
- state->crtc_w < 4 || state->crtc_h < 4) {
1810
+ if (drm_rect_width(src) >> 16 < 4 || drm_rect_height(src) >> 16 < 4 ||
1811
+ drm_rect_width(dest) < 4 || drm_rect_width(dest) < 4) {
16811812 DRM_ERROR("Invalid size: %dx%d->%dx%d, min size is 4x4\n",
1682
- state->src_w >> 16, state->src_h >> 16,
1683
- state->crtc_w, state->crtc_h);
1684
- return -EINVAL;
1813
+ drm_rect_width(src) >> 16, drm_rect_height(src) >> 16,
1814
+ drm_rect_width(dest), drm_rect_height(dest));
1815
+ state->visible = false;
1816
+ return 0;
16851817 }
16861818
16871819 if (drm_rect_width(src) >> 16 > vop_data->max_input.width ||
....@@ -1708,26 +1840,27 @@
17081840 return -EINVAL;
17091841 }
17101842
1711
- offset = (src->x1 >> 16) * fb->format->bpp[0] / 8;
1843
+ offset = (src->x1 >> 16) * fb->format->cpp[0];
17121844 vop_plane_state->offset = offset + fb->offsets[0];
17131845 if (state->rotation & DRM_MODE_REFLECT_Y)
17141846 offset += ((src->y2 >> 16) - 1) * fb->pitches[0];
17151847 else
17161848 offset += (src->y1 >> 16) * fb->pitches[0];
17171849
1718
- dma_addr = rockchip_fb_get_dma_addr(fb, 0);
1719
- kvaddr = rockchip_fb_get_kvaddr(fb, 0);
1720
- vop_plane_state->yrgb_mst = dma_addr + offset + fb->offsets[0];
1721
- vop_plane_state->yrgb_kvaddr = kvaddr + offset + fb->offsets[0];
1850
+ obj = fb->obj[0];
1851
+ rk_obj = to_rockchip_obj(obj);
1852
+ vop_plane_state->yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
17221853 if (fb->format->is_yuv) {
1723
- int hsub = drm_format_horz_chroma_subsampling(fb->format->format);
1724
- int vsub = drm_format_vert_chroma_subsampling(fb->format->format);
1854
+ int hsub = fb->format->hsub;
1855
+ int vsub = fb->format->vsub;
17251856
1726
- offset = (src->x1 >> 16) * fb->format->bpp[1] / hsub / 8;
1857
+ offset = (src->x1 >> 16) * fb->format->cpp[1] / hsub;
17271858 offset += (src->y1 >> 16) * fb->pitches[1] / vsub;
17281859
1729
- dma_addr = rockchip_fb_get_dma_addr(fb, 1);
1730
- dma_addr += offset + fb->offsets[1];
1860
+ uv_obj = fb->obj[1];
1861
+ rk_uv_obj = to_rockchip_obj(uv_obj);
1862
+
1863
+ dma_addr = rk_uv_obj->dma_addr + offset + fb->offsets[1];
17311864 vop_plane_state->uv_mst = dma_addr;
17321865 }
17331866
....@@ -1746,6 +1879,9 @@
17461879
17471880 if (!old_state->crtc)
17481881 return;
1882
+
1883
+ rockchip_drm_dbg(vop->dev, VOP_DEBUG_PLANE, "disable win%d-area%d by %s\n",
1884
+ win->win_id, win->area_id, current->comm);
17491885
17501886 spin_lock(&vop->reg_lock);
17511887
....@@ -1853,20 +1989,19 @@
18531989 uint32_t val;
18541990 bool rb_swap, global_alpha_en;
18551991 int is_yuv = fb->format->is_yuv;
1992
+ struct drm_format_name_buf format_name;
18561993
18571994 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
18581995 bool AFBC_flag = false;
18591996 struct vop_dump_list *planlist;
18601997 unsigned long num_pages;
18611998 struct page **pages;
1862
- struct rockchip_drm_fb *rk_fb;
18631999 struct drm_gem_object *obj;
18642000 struct rockchip_gem_object *rk_obj;
18652001
18662002 num_pages = 0;
18672003 pages = NULL;
1868
- rk_fb = to_rockchip_fb(fb);
1869
- obj = rk_fb->obj[0];
2004
+ obj = fb->obj[0];
18702005 rk_obj = to_rockchip_obj(obj);
18712006 if (rk_obj) {
18722007 num_pages = rk_obj->num_pages;
....@@ -1914,6 +2049,8 @@
19142049 dsp_h = 4;
19152050 actual_h = dsp_h * actual_h / drm_rect_height(dest);
19162051 }
2052
+ if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) && vop->version == VOP_VERSION(2, 2))
2053
+ dsp_h = dsp_h / 2;
19172054
19182055 act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff);
19192056
....@@ -1922,12 +2059,18 @@
19222059
19232060 dsp_stx = dest->x1 + mode->crtc_htotal - mode->crtc_hsync_start;
19242061 dsp_sty = dest->y1 + mode->crtc_vtotal - mode->crtc_vsync_start;
2062
+ if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) && vop->version == VOP_VERSION(2, 2))
2063
+ dsp_sty = dest->y1 / 2 + mode->crtc_vtotal - mode->crtc_vsync_start;
19252064 dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
19262065
19272066 s = to_rockchip_crtc_state(crtc->state);
19282067 spin_lock(&vop->reg_lock);
19292068
19302069 VOP_WIN_SET(vop, win, format, vop_plane_state->format);
2070
+
2071
+ VOP_WIN_SET(vop, win, interlace_read,
2072
+ (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
2073
+
19312074 VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4));
19322075 VOP_WIN_SET(vop, win, yrgb_mst, vop_plane_state->yrgb_mst);
19332076
....@@ -1945,7 +2088,7 @@
19452088
19462089 if (win->phy->scl)
19472090 scl_vop_cal_scl_fac(vop, win, actual_w, actual_h,
1948
- drm_rect_width(dest), drm_rect_height(dest),
2091
+ drm_rect_width(dest), dsp_h,
19492092 fb->format->format);
19502093
19512094 if (VOP_WIN_SUPPORT(vop, win, color_key))
....@@ -1976,7 +2119,6 @@
19762119 src_blend_m0 = ALPHA_PER_PIX;
19772120 else
19782121 src_blend_m0 = ALPHA_GLOBAL;
1979
-
19802122
19812123 if (vop_plane_state->blend_mode == 0 || src_blend_m0 == ALPHA_GLOBAL)
19822124 pre_multi_alpha = ALPHA_SRC_NO_PRE_MUL;
....@@ -2012,6 +2154,13 @@
20122154 VOP_WIN_SET(vop, win, enable, 1);
20132155 VOP_WIN_SET(vop, win, gate, 1);
20142156 spin_unlock(&vop->reg_lock);
2157
+
2158
+ drm_get_format_name(fb->format->format, &format_name);
2159
+ rockchip_drm_dbg(vop->dev, VOP_DEBUG_PLANE,
2160
+ "update win%d-area%d [%dx%d->%dx%d@(%d, %d)] zpos:%d fmt[%s%s] addr[%pad] by %s\n",
2161
+ win->win_id, win->area_id, actual_w, actual_h,
2162
+ dsp_w, dsp_h, dsp_stx, dsp_sty, vop_plane_state->zpos, format_name.str,
2163
+ fb->modifier ? "[AFBC]" : "", &vop_plane_state->yrgb_mst, current->comm);
20152164 /*
20162165 * spi interface(vop_plane_state->yrgb_kvaddr, fb->pixel_format,
20172166 * actual_w, actual_h)
....@@ -2033,17 +2182,17 @@
20332182 planlist->dump_info.offset = vop_plane_state->offset;
20342183 planlist->dump_info.pitches = fb->pitches[0];
20352184 planlist->dump_info.height = actual_h;
2036
- planlist->dump_info.pixel_format = fb->format->format;
2037
- list_add_tail(&planlist->entry, &crtc->vop_dump_list_head);
2185
+ planlist->dump_info.format = fb->format;
2186
+ list_add_tail(&planlist->entry, &vop->rockchip_crtc.vop_dump_list_head);
20382187 vop_plane_state->planlist = planlist;
20392188 } else {
20402189 DRM_ERROR("can't alloc a node of planlist %p\n", planlist);
20412190 return;
20422191 }
2043
- if (crtc->vop_dump_status == DUMP_KEEP ||
2044
- crtc->vop_dump_times > 0) {
2045
- vop_plane_dump(&planlist->dump_info, crtc->frame_count);
2046
- crtc->vop_dump_times--;
2192
+ if (vop->rockchip_crtc.vop_dump_status == DUMP_KEEP ||
2193
+ vop->rockchip_crtc.vop_dump_times > 0) {
2194
+ rockchip_drm_dump_plane_buffer(&planlist->dump_info, vop->rockchip_crtc.frame_count);
2195
+ vop->rockchip_crtc.vop_dump_times--;
20472196 }
20482197 #endif
20492198 }
....@@ -2192,10 +2341,9 @@
21922341 if (!vop_plane_state)
21932342 return;
21942343
2195
- win->state.zpos = win->zpos;
2344
+ __drm_atomic_helper_plane_reset(plane, &vop_plane_state->base);
2345
+ vop_plane_state->base.zpos = win->zpos;
21962346 vop_plane_state->global_alpha = 0xff;
2197
- plane->state = &vop_plane_state->base;
2198
- plane->state->plane = plane;
21992347 }
22002348
22012349 static struct drm_plane_state *
....@@ -2238,11 +2386,6 @@
22382386 struct vop_win *win = to_vop_win(plane);
22392387 struct vop_plane_state *plane_state = to_vop_plane_state(state);
22402388
2241
- if (property == win->vop->plane_zpos_prop) {
2242
- plane_state->zpos = val;
2243
- return 0;
2244
- }
2245
-
22462389 if (property == private->eotf_prop) {
22472390 plane_state->eotf = val;
22482391 return 0;
....@@ -2250,16 +2393,6 @@
22502393
22512394 if (property == private->color_space_prop) {
22522395 plane_state->color_space = val;
2253
- return 0;
2254
- }
2255
-
2256
- if (property == private->global_alpha_prop) {
2257
- plane_state->global_alpha = val;
2258
- return 0;
2259
- }
2260
-
2261
- if (property == private->blend_mode_prop) {
2262
- plane_state->blend_mode = val;
22632396 return 0;
22642397 }
22652398
....@@ -2288,11 +2421,6 @@
22882421 struct vop_win *win = to_vop_win(plane);
22892422 struct rockchip_drm_private *private = plane->dev->dev_private;
22902423
2291
- if (property == win->vop->plane_zpos_prop) {
2292
- *val = plane_state->zpos;
2293
- return 0;
2294
- }
2295
-
22962424 if (property == private->eotf_prop) {
22972425 *val = plane_state->eotf;
22982426 return 0;
....@@ -2300,16 +2428,6 @@
23002428
23012429 if (property == private->color_space_prop) {
23022430 *val = plane_state->color_space;
2303
- return 0;
2304
- }
2305
-
2306
- if (property == private->global_alpha_prop) {
2307
- *val = plane_state->global_alpha;
2308
- return 0;
2309
- }
2310
-
2311
- if (property == private->blend_mode_prop) {
2312
- *val = plane_state->blend_mode;
23132431 return 0;
23142432 }
23152433
....@@ -2350,6 +2468,7 @@
23502468 .atomic_destroy_state = vop_atomic_plane_destroy_state,
23512469 .atomic_set_property = vop_atomic_plane_set_property,
23522470 .atomic_get_property = vop_atomic_plane_get_property,
2471
+ .format_mod_supported = rockchip_vop_mod_supported,
23532472 };
23542473
23552474 static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
....@@ -2406,13 +2525,13 @@
24062525 if (e && e->base.file_priv == file_priv) {
24072526 vop->event = NULL;
24082527
2409
- //e->base.destroy(&e->base);//todo
2528
+ /* e->base.destroy(&e->base);//todo */
24102529 file_priv->event_space += sizeof(e->event);
24112530 }
24122531 spin_unlock_irqrestore(&drm->event_lock, flags);
24132532 }
24142533
2415
-static int vop_crtc_loader_protect(struct drm_crtc *crtc, bool on)
2534
+static int vop_crtc_loader_protect(struct drm_crtc *crtc, bool on, void *data)
24162535 {
24172536 struct rockchip_drm_private *private = crtc->dev->dev_private;
24182537 struct vop *vop = to_vop(crtc);
....@@ -2471,6 +2590,9 @@
24712590 struct drm_framebuffer *fb = state->fb;
24722591 struct drm_format_name_buf format_name;
24732592 int i;
2593
+ struct drm_gem_object *obj;
2594
+ struct rockchip_gem_object *rk_obj;
2595
+ dma_addr_t fb_addr;
24742596 u64 afbdc_format =
24752597 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16);
24762598
....@@ -2498,14 +2620,30 @@
24982620 DEBUG_PRINT("\tdst: pos[%dx%d] rect[%dx%d]\n", dest->x1, dest->y1,
24992621 drm_rect_width(dest), drm_rect_height(dest));
25002622
2501
- for (i = 0; i < drm_format_num_planes(fb->format->format); i++) {
2502
- dma_addr_t fb_addr = rockchip_fb_get_dma_addr(fb, i);
2623
+ for (i = 0; i < fb->format->num_planes; i++) {
2624
+ obj = fb->obj[0];
2625
+ rk_obj = to_rockchip_obj(obj);
2626
+ fb_addr = rk_obj->dma_addr + fb->offsets[0];
25032627
25042628 DEBUG_PRINT("\tbuf[%d]: addr: %pad pitch: %d offset: %d\n",
25052629 i, &fb_addr, fb->pitches[i], fb->offsets[i]);
25062630 }
25072631
25082632 return 0;
2633
+}
2634
+
2635
+static void vop_dump_connector_on_crtc(struct drm_crtc *crtc, struct seq_file *s)
2636
+{
2637
+ struct drm_connector_list_iter conn_iter;
2638
+ struct drm_connector *connector;
2639
+
2640
+ drm_connector_list_iter_begin(crtc->dev, &conn_iter);
2641
+ drm_for_each_connector_iter(connector, &conn_iter) {
2642
+ if (crtc->state->connector_mask & drm_connector_mask(connector))
2643
+ DEBUG_PRINT(" Connector: %s\n", connector->name);
2644
+
2645
+ }
2646
+ drm_connector_list_iter_end(&conn_iter);
25092647 }
25102648
25112649 static int vop_crtc_debugfs_dump(struct drm_crtc *crtc, struct seq_file *s)
....@@ -2524,8 +2662,7 @@
25242662 if (!crtc_state->active)
25252663 return 0;
25262664
2527
- DEBUG_PRINT(" Connector: %s\n",
2528
- drm_get_connector_name(state->output_type));
2665
+ vop_dump_connector_on_crtc(crtc, s);
25292666 DEBUG_PRINT("\tbus_format[%x]: %s\n", state->bus_format,
25302667 drm_get_bus_format_name(state->bus_format));
25312668 DEBUG_PRINT("\toverlay_mode[%d] output_mode[%x]",
....@@ -2619,24 +2756,15 @@
26192756 goto remove;
26202757 }
26212758 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
2622
- drm_debugfs_vop_add(crtc, vop->debugfs);
2759
+ rockchip_drm_add_dump_buffer(crtc, vop->debugfs);
26232760 #endif
26242761 for (i = 0; i < ARRAY_SIZE(vop_debugfs_files); i++)
26252762 vop->debugfs_files[i].data = vop;
26262763
2627
- ret = drm_debugfs_create_files(vop->debugfs_files,
2628
- ARRAY_SIZE(vop_debugfs_files),
2629
- vop->debugfs,
2630
- minor);
2631
- if (ret) {
2632
- dev_err(vop->dev, "could not install rockchip_debugfs_list\n");
2633
- goto free;
2634
- }
2764
+ drm_debugfs_create_files(vop->debugfs_files, ARRAY_SIZE(vop_debugfs_files),
2765
+ vop->debugfs, minor);
26352766
26362767 return 0;
2637
-free:
2638
- kfree(vop->debugfs_files);
2639
- vop->debugfs_files = NULL;
26402768 remove:
26412769 debugfs_remove(vop->debugfs);
26422770 vop->debugfs = NULL;
....@@ -2644,10 +2772,10 @@
26442772 }
26452773
26462774 static enum drm_mode_status
2647
-vop_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode,
2648
- int output_type)
2775
+vop_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
26492776 {
26502777 struct vop *vop = to_vop(crtc);
2778
+ struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
26512779 const struct vop_data *vop_data = vop->data;
26522780 int request_clock = mode->clock;
26532781 int clock;
....@@ -2660,15 +2788,20 @@
26602788 VOP_MINOR(vop->version) <= 2)
26612789 return MODE_BAD;
26622790
2663
- if (mode->flags & DRM_MODE_FLAG_DBLCLK)
2791
+ /*
2792
+ * Dclk need to be double if BT656 interface and vop version >= 2.12.
2793
+ */
2794
+ if (mode->flags & DRM_MODE_FLAG_DBLCLK ||
2795
+ (VOP_MAJOR(vop->version) == 2 && VOP_MINOR(vop->version) >= 12 &&
2796
+ s->output_if & VOP_OUTPUT_IF_BT656))
26642797 request_clock *= 2;
26652798 clock = clk_round_rate(vop->dclk, request_clock * 1000) / 1000;
26662799
26672800 /*
26682801 * Hdmi or DisplayPort request a Accurate clock.
26692802 */
2670
- if (output_type == DRM_MODE_CONNECTOR_HDMIA ||
2671
- output_type == DRM_MODE_CONNECTOR_DisplayPort)
2803
+ if (s->output_type == DRM_MODE_CONNECTOR_HDMIA ||
2804
+ s->output_type == DRM_MODE_CONNECTOR_DisplayPort)
26722805 if (clock != request_clock)
26732806 return MODE_CLOCK_RANGE;
26742807
....@@ -2698,7 +2831,7 @@
26982831 struct drm_framebuffer *fb = pstate->fb;
26992832 struct drm_rect *dest = &vop_plane_state->dest;
27002833 struct drm_rect *src = &vop_plane_state->src;
2701
- int bpp = fb->format->bpp[0];
2834
+ int bpp = fb->format->cpp[0] << 3;
27022835 int src_width = drm_rect_width(src) >> 16;
27032836 int src_height = drm_rect_height(src) >> 16;
27042837 int dest_width = drm_rect_width(dest);
....@@ -2747,8 +2880,7 @@
27472880
27482881 static size_t vop_crtc_bandwidth(struct drm_crtc *crtc,
27492882 struct drm_crtc_state *crtc_state,
2750
- size_t *frame_bw_mbyte,
2751
- unsigned int *plane_num_total)
2883
+ struct dmcfreq_vop_info *vop_bw_info)
27522884 {
27532885 struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
27542886 u16 htotal = adjusted_mode->crtc_htotal;
....@@ -2758,64 +2890,77 @@
27582890 struct drm_plane_state *pstate;
27592891 struct vop_bandwidth *pbandwidth;
27602892 struct drm_plane *plane;
2761
- u64 bandwidth;
2893
+ u64 line_bw_mbyte = 0;
27622894 int cnt = 0, plane_num = 0;
27632895 struct drm_atomic_state *state = crtc_state->state;
27642896 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
27652897 struct vop_dump_list *pos, *n;
2898
+ struct vop *vop = to_vop(crtc);
27662899 #endif
27672900
27682901 if (!htotal || !vdisplay)
27692902 return 0;
27702903
27712904 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
2772
- if (!crtc->vop_dump_list_init_flag) {
2773
- INIT_LIST_HEAD(&crtc->vop_dump_list_head);
2774
- crtc->vop_dump_list_init_flag = true;
2905
+ if (!vop->rockchip_crtc.vop_dump_list_init_flag) {
2906
+ INIT_LIST_HEAD(&vop->rockchip_crtc.vop_dump_list_head);
2907
+ vop->rockchip_crtc.vop_dump_list_init_flag = true;
27752908 }
2776
- list_for_each_entry_safe(pos, n, &crtc->vop_dump_list_head, entry) {
2909
+ list_for_each_entry_safe(pos, n, &vop->rockchip_crtc.vop_dump_list_head, entry) {
27772910 list_del(&pos->entry);
27782911 }
2779
- if (crtc->vop_dump_status == DUMP_KEEP ||
2780
- crtc->vop_dump_times > 0) {
2781
- crtc->frame_count++;
2912
+ if (vop->rockchip_crtc.vop_dump_status == DUMP_KEEP ||
2913
+ vop->rockchip_crtc.vop_dump_times > 0) {
2914
+ vop->rockchip_crtc.frame_count++;
27822915 }
27832916 #endif
27842917
27852918 drm_atomic_crtc_state_for_each_plane(plane, crtc_state)
27862919 plane_num++;
27872920
2788
- if (plane_num_total)
2789
- *plane_num_total += plane_num;
2921
+ vop_bw_info->plane_num += plane_num;
27902922 pbandwidth = kmalloc_array(plane_num, sizeof(*pbandwidth),
27912923 GFP_KERNEL);
27922924 if (!pbandwidth)
27932925 return -ENOMEM;
27942926
27952927 drm_atomic_crtc_state_for_each_plane(plane, crtc_state) {
2928
+ int act_w, act_h, cpp, afbc_fac;
2929
+
27962930 pstate = drm_atomic_get_existing_plane_state(state, plane);
27972931 if (pstate->crtc != crtc || !pstate->fb)
27982932 continue;
27992933
2934
+ /* This is an empirical value, if it's afbc format, the frame buffer size div 2 */
2935
+ afbc_fac = rockchip_afbc(plane, pstate->fb->modifier) ? 2 : 1;
2936
+
28002937 vop_plane_state = to_vop_plane_state(pstate);
28012938 pbandwidth[cnt].y1 = vop_plane_state->dest.y1;
28022939 pbandwidth[cnt].y2 = vop_plane_state->dest.y2;
2803
- pbandwidth[cnt++].bandwidth = vop_plane_line_bandwidth(pstate);
2940
+ pbandwidth[cnt++].bandwidth = vop_plane_line_bandwidth(pstate) / afbc_fac;
2941
+
2942
+ act_w = drm_rect_width(&pstate->src) >> 16;
2943
+ act_h = drm_rect_height(&pstate->src) >> 16;
2944
+ cpp = pstate->fb->format->cpp[0];
2945
+
2946
+ vop_bw_info->frame_bw_mbyte += act_w * act_h / 1000 * cpp * drm_mode_vrefresh(adjusted_mode) / 1000;
2947
+
28042948 }
28052949
28062950 sort(pbandwidth, cnt, sizeof(pbandwidth[0]), vop_bandwidth_cmp, NULL);
28072951
2808
- bandwidth = vop_calc_max_bandwidth(pbandwidth, 0, cnt, vdisplay);
2952
+ vop_bw_info->line_bw_mbyte = vop_calc_max_bandwidth(pbandwidth, 0, cnt, vdisplay);
28092953 kfree(pbandwidth);
28102954 /*
2811
- * bandwidth(MB/s)
2955
+ * line_bandwidth(MB/s)
28122956 * = line_bandwidth / line_time
28132957 * = line_bandwidth(Byte) * clock(KHZ) / 1000 / htotal
28142958 */
2815
- bandwidth *= clock;
2816
- do_div(bandwidth, htotal * 1000);
2959
+ line_bw_mbyte *= clock;
2960
+ do_div(line_bw_mbyte, htotal * 1000);
2961
+ vop_bw_info->line_bw_mbyte = line_bw_mbyte;
28172962
2818
- return bandwidth;
2963
+ return vop_bw_info->line_bw_mbyte;
28192964 }
28202965
28212966 static void vop_crtc_close(struct drm_crtc *crtc)
....@@ -2898,16 +3043,50 @@
28983043 vop_set_out_mode(vop, state->output_mode);
28993044 }
29003045
3046
+static int vop_crtc_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout)
3047
+{
3048
+ struct vop *vop = to_vop(crtc);
3049
+ unsigned long jiffies_left;
3050
+ int ret = 0;
3051
+
3052
+ if (!vop->is_enabled)
3053
+ return -ENODEV;
3054
+
3055
+ mutex_lock(&vop->vop_lock);
3056
+
3057
+ if (vop_line_flag_irq_is_enabled(vop)) {
3058
+ ret = -EBUSY;
3059
+ goto out;
3060
+ }
3061
+
3062
+ reinit_completion(&vop->line_flag_completion);
3063
+ vop_line_flag_irq_enable(vop);
3064
+
3065
+ jiffies_left = wait_for_completion_timeout(&vop->line_flag_completion,
3066
+ msecs_to_jiffies(mstimeout));
3067
+ vop_line_flag_irq_disable(vop);
3068
+
3069
+ if (jiffies_left == 0) {
3070
+ DRM_DEV_ERROR(vop->dev, "timeout waiting for lineflag IRQ\n");
3071
+ ret = -ETIMEDOUT;
3072
+ goto out;
3073
+ }
3074
+
3075
+out:
3076
+ mutex_unlock(&vop->vop_lock);
3077
+ return ret;
3078
+}
3079
+
29013080 static const struct rockchip_crtc_funcs private_crtc_funcs = {
29023081 .loader_protect = vop_crtc_loader_protect,
29033082 .cancel_pending_vblank = vop_crtc_cancel_pending_vblank,
29043083 .debugfs_init = vop_crtc_debugfs_init,
29053084 .debugfs_dump = vop_crtc_debugfs_dump,
29063085 .regs_dump = vop_crtc_regs_dump,
2907
- .mode_valid = vop_crtc_mode_valid,
29083086 .bandwidth = vop_crtc_bandwidth,
29093087 .crtc_close = vop_crtc_close,
29103088 .crtc_send_mcu_cmd = vop_crtc_send_mcu_cmd,
3089
+ .wait_vact_end = vop_crtc_wait_vact_end,
29113090 };
29123091
29133092 static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
....@@ -2916,6 +3095,8 @@
29163095 {
29173096 struct vop *vop = to_vop(crtc);
29183097 const struct vop_data *vop_data = vop->data;
3098
+ struct drm_crtc_state *new_crtc_state = container_of(mode, struct drm_crtc_state, mode);
3099
+ struct rockchip_crtc_state *s = to_rockchip_crtc_state(new_crtc_state);
29193100
29203101 if (mode->hdisplay > vop_data->max_output.width)
29213102 return false;
....@@ -2923,8 +3104,17 @@
29233104 drm_mode_set_crtcinfo(adj_mode,
29243105 CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE);
29253106
2926
- if (mode->flags & DRM_MODE_FLAG_DBLCLK)
3107
+ /*
3108
+ * Dclk need to be double if BT656 interface and vop version >= 2.12.
3109
+ */
3110
+ if (mode->flags & DRM_MODE_FLAG_DBLCLK ||
3111
+ (VOP_MAJOR(vop->version) == 2 && VOP_MINOR(vop->version) >= 12 &&
3112
+ s->output_if & VOP_OUTPUT_IF_BT656))
29273113 adj_mode->crtc_clock *= 2;
3114
+
3115
+ if (vop->mcu_timing.mcu_pix_total)
3116
+ adj_mode->crtc_clock *= rockchip_drm_get_cycles_per_pixel(s->bus_format) *
3117
+ (vop->mcu_timing.mcu_pix_total + 1);
29283118
29293119 adj_mode->crtc_clock =
29303120 DIV_ROUND_UP(clk_round_rate(vop->dclk, adj_mode->crtc_clock * 1000),
....@@ -2949,13 +3139,14 @@
29493139
29503140 switch (s->bus_format) {
29513141 case MEDIA_BUS_FMT_RGB565_1X16:
3142
+ case MEDIA_BUS_FMT_RGB565_2X8_LE:
29523143 VOP_CTRL_SET(vop, dither_down_en, 1);
29533144 VOP_CTRL_SET(vop, dither_down_mode, RGB888_TO_RGB565);
29543145 break;
29553146 case MEDIA_BUS_FMT_RGB666_1X18:
29563147 case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
29573148 case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
2958
- case MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA:
3149
+ case MEDIA_BUS_FMT_RGB666_3X6:
29593150 VOP_CTRL_SET(vop, dither_down_en, 1);
29603151 VOP_CTRL_SET(vop, dither_down_mode, RGB888_TO_RGB666);
29613152 break;
....@@ -2969,8 +3160,8 @@
29693160 VOP_CTRL_SET(vop, dither_down_en, 0);
29703161 VOP_CTRL_SET(vop, pre_dither_down_en, 0);
29713162 break;
2972
- case MEDIA_BUS_FMT_SRGB888_3X8:
2973
- case MEDIA_BUS_FMT_SRGB888_DUMMY_4X8:
3163
+ case MEDIA_BUS_FMT_RGB888_3X8:
3164
+ case MEDIA_BUS_FMT_RGB888_DUMMY_4X8:
29743165 case MEDIA_BUS_FMT_RGB888_1X24:
29753166 case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
29763167 case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
....@@ -2992,12 +3183,15 @@
29923183 struct vop *vop = to_vop(crtc);
29933184 u32 val;
29943185
2995
- if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
2996
- !(vop->data->feature & VOP_FEATURE_OUTPUT_10BIT))
3186
+ if ((s->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
3187
+ !(vop->data->feature & VOP_FEATURE_OUTPUT_10BIT)) ||
3188
+ (VOP_MAJOR(vop->version) == 2 && VOP_MINOR(vop->version) >= 12 &&
3189
+ s->output_if & VOP_OUTPUT_IF_BT656))
29973190 s->output_mode = ROCKCHIP_OUT_MODE_P888;
29983191
2999
- if (is_uv_swap(s->bus_format, s->output_mode))
3000
- VOP_CTRL_SET(vop, dsp_data_swap, DSP_RB_SWAP);
3192
+ if (is_uv_swap(s->bus_format, s->output_mode) ||
3193
+ is_rb_swap(s->bus_format, s->output_mode))
3194
+ VOP_CTRL_SET(vop, dsp_rb_swap, 1);
30013195 else
30023196 VOP_CTRL_SET(vop, dsp_data_swap, 0);
30033197
....@@ -3068,6 +3262,12 @@
30683262 {
30693263 struct vop *vop = to_vop(crtc);
30703264
3265
+ /*
3266
+ * If mcu_hold_mode is 1, set 1 to mcu_frame_st will
3267
+ * refresh one frame from ddr. So mcu_frame_st is needed
3268
+ * to be initialized as 0.
3269
+ */
3270
+ VOP_CTRL_SET(vop, mcu_frame_st, 0);
30713271 VOP_CTRL_SET(vop, mcu_clk_sel, 1);
30723272 VOP_CTRL_SET(vop, mcu_type, 1);
30733273
....@@ -3103,11 +3303,20 @@
31033303 int for_ddr_freq = 0;
31043304 bool dclk_inv, yc_swap = false;
31053305
3306
+ if (old_state && old_state->self_refresh_active) {
3307
+ drm_crtc_vblank_on(crtc);
3308
+ if (vop->aclk_rate_reset)
3309
+ clk_set_rate(vop->aclk, vop->aclk_rate);
3310
+ vop->aclk_rate_reset = false;
3311
+
3312
+ return;
3313
+ }
3314
+
31063315 rockchip_set_system_status(sys_status);
31073316 vop_lock(vop);
31083317 DRM_DEV_INFO(vop->dev, "Update mode to %dx%d%s%d, type: %d\n",
31093318 hdisplay, vdisplay, interlaced ? "i" : "p",
3110
- adjusted_mode->vrefresh, s->output_type);
3319
+ drm_mode_vrefresh(adjusted_mode), s->output_type);
31113320 vop_initial(crtc);
31123321 vop_disable_allwin(vop);
31133322 VOP_CTRL_SET(vop, standby, 0);
....@@ -3124,6 +3333,9 @@
31243333 vop_mcu_mode(crtc);
31253334
31263335 dclk_inv = (s->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
3336
+ /* For improving signal quality, dclk need to be inverted by default on rv1106. */
3337
+ if ((VOP_MAJOR(vop->version) == 2 && VOP_MINOR(vop->version) == 12))
3338
+ dclk_inv = !dclk_inv;
31273339
31283340 VOP_CTRL_SET(vop, dclk_pol, dclk_inv);
31293341 val = (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ?
....@@ -3153,6 +3365,10 @@
31533365 yc_swap = is_yc_swap(s->bus_format);
31543366 VOP_CTRL_SET(vop, bt1120_yc_swap, yc_swap);
31553367 VOP_CTRL_SET(vop, yuv_clip, 1);
3368
+ } else if (s->output_if & VOP_OUTPUT_IF_BT656) {
3369
+ VOP_CTRL_SET(vop, bt656_en, 1);
3370
+ yc_swap = is_yc_swap(s->bus_format);
3371
+ VOP_CTRL_SET(vop, bt1120_yc_swap, yc_swap);
31563372 }
31573373 break;
31583374 case DRM_MODE_CONNECTOR_eDP:
....@@ -3239,7 +3455,8 @@
32393455 VOP_CTRL_SET(vop, vtotal_pw, vtotal << 16 | vsync_len);
32403456
32413457 VOP_CTRL_SET(vop, core_dclk_div,
3242
- !!(adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK));
3458
+ !!(adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) ||
3459
+ s->output_if & VOP_OUTPUT_IF_BT656);
32433460
32443461 VOP_CTRL_SET(vop, win_csc_mode_sel, 1);
32453462
....@@ -3264,7 +3481,6 @@
32643481 struct drm_crtc_state *crtc_state)
32653482 {
32663483 struct vop *vop = to_vop(crtc);
3267
- const struct vop_data *vop_data = vop->data;
32683484 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
32693485 struct drm_atomic_state *state = crtc_state->state;
32703486 struct drm_plane *plane;
....@@ -3294,8 +3510,8 @@
32943510 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16))
32953511 continue;
32963512
3297
- if (!(vop_data->feature & VOP_FEATURE_AFBDC)) {
3298
- DRM_ERROR("not support afbdc\n");
3513
+ if (!VOP_CTRL_SUPPORT(vop, afbdc_en)) {
3514
+ DRM_INFO("not support afbdc\n");
32993515 return -EINVAL;
33003516 }
33013517
....@@ -3335,10 +3551,17 @@
33353551
33363552 if (VOP_CTRL_SUPPORT(vop, afbdc_pic_vir_width)) {
33373553 u32 align_x1, align_x2, align_y1, align_y2, align_val;
3554
+ struct drm_gem_object *obj;
3555
+ struct rockchip_gem_object *rk_obj;
3556
+ dma_addr_t fb_addr;
3557
+
3558
+ obj = fb->obj[0];
3559
+ rk_obj = to_rockchip_obj(obj);
3560
+ fb_addr = rk_obj->dma_addr + fb->offsets[0];
33383561
33393562 s->afbdc_win_format = afbdc_format;
33403563 s->afbdc_win_id = win->win_id;
3341
- s->afbdc_win_ptr = rockchip_fb_get_dma_addr(fb, 0);
3564
+ s->afbdc_win_ptr = fb_addr;
33423565 s->afbdc_win_vir_width = fb->width;
33433566 s->afbdc_win_xoffset = (src->x1 >> 16);
33443567 s->afbdc_win_yoffset = (src->y1 >> 16);
....@@ -3722,6 +3945,7 @@
37223945 struct rockchip_crtc_state *s =
37233946 to_rockchip_crtc_state(crtc->state);
37243947 struct vop *vop = to_vop(crtc);
3948
+ const struct vop_data *vop_data = vop->data;
37253949
37263950 spin_lock(&vop->reg_lock);
37273951
....@@ -3749,7 +3973,8 @@
37493973 VOP_CTRL_SET(vop, afbdc_en, s->afbdc_en);
37503974
37513975 VOP_CTRL_SET(vop, dsp_layer_sel, s->dsp_layer_sel);
3752
- vop_post_config(crtc);
3976
+ if (vop_data->feature & VOP_FEATURE_OVERSCAN)
3977
+ vop_post_config(crtc);
37533978
37543979 spin_unlock(&vop->reg_lock);
37553980 }
....@@ -3827,6 +4052,7 @@
38274052 spin_lock_irqsave(&vop->irq_lock, flags);
38284053 vop->pre_overlay = s->hdr.pre_overlay;
38294054 vop_cfg_done(vop);
4055
+ rockchip_drm_dbg(vop->dev, VOP_DEBUG_CFG_DONE, "cfg_done\n\n");
38304056 /*
38314057 * rk322x and rk332x odd-even field will mistake when in interlace mode.
38324058 * we must switch to frame effect before switch screen and switch to
....@@ -3860,21 +4086,6 @@
38604086 crtc->state->event = NULL;
38614087 }
38624088 spin_unlock_irq(&crtc->dev->event_lock);
3863
-
3864
-#if 0
3865
- for_each_plane_in_state(old_state, plane, old_plane_state, i) {
3866
- if (!old_plane_state->fb)
3867
- continue;
3868
-
3869
- if (old_plane_state->fb == plane->state->fb)
3870
- continue;
3871
-
3872
- drm_framebuffer_get(old_plane_state->fb);
3873
- WARN_ON(drm_crtc_vblank_get(crtc) != 0);
3874
- drm_flip_work_queue(&vop->fb_unref_work, old_plane_state->fb);
3875
- set_bit(VOP_PENDING_FB_UNREF, &vop->pending);
3876
- }
3877
-#else
38784089 for_each_old_plane_in_state(old_state, plane, old_plane_state, i) {
38794090 if (!old_plane_state->fb)
38804091 continue;
....@@ -3887,11 +4098,11 @@
38874098 drm_flip_work_queue(&vop->fb_unref_work, old_plane_state->fb);
38884099 set_bit(VOP_PENDING_FB_UNREF, &vop->pending);
38894100 }
3890
-#endif
38914101 }
38924102
38934103 static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = {
38944104 .mode_fixup = vop_crtc_mode_fixup,
4105
+ .mode_valid = vop_crtc_mode_valid,
38954106 .atomic_check = vop_crtc_atomic_check,
38964107 .atomic_flush = vop_crtc_atomic_flush,
38974108 .atomic_enable = vop_crtc_atomic_enable,
....@@ -3927,6 +4138,9 @@
39274138 static struct drm_crtc_state *vop_crtc_duplicate_state(struct drm_crtc *crtc)
39284139 {
39294140 struct rockchip_crtc_state *rockchip_state, *old_state;
4141
+
4142
+ if (WARN_ON(!crtc->state))
4143
+ return NULL;
39304144
39314145 old_state = to_rockchip_crtc_state(crtc->state);
39324146 rockchip_state = kmemdup(old_state, sizeof(*old_state), GFP_KERNEL);
....@@ -4042,8 +4256,19 @@
40424256 return 0;
40434257 }
40444258
4045
- if (property == private->alpha_scale_prop) {
4046
- *val = (vop->data->feature & VOP_FEATURE_ALPHA_SCALE) ? 1 : 0;
4259
+ if (property == private->aclk_prop) {
4260
+ /* KHZ, keep align with mode->clock */
4261
+ *val = clk_get_rate(vop->aclk) / 1000;
4262
+ return 0;
4263
+ }
4264
+
4265
+ if (property == private->bg_prop) {
4266
+ *val = vop->background;
4267
+ return 0;
4268
+ }
4269
+
4270
+ if (property == private->line_flag_prop) {
4271
+ *val = vop->line_flag;
40474272 return 0;
40484273 }
40494274
....@@ -4057,9 +4282,10 @@
40574282 uint64_t val)
40584283 {
40594284 struct drm_device *drm_dev = crtc->dev;
4285
+ struct rockchip_drm_private *private = drm_dev->dev_private;
40604286 struct drm_mode_config *mode_config = &drm_dev->mode_config;
40614287 struct rockchip_crtc_state *s = to_rockchip_crtc_state(state);
4062
- //struct vop *vop = to_vop(crtc);
4288
+ struct vop *vop = to_vop(crtc);
40634289
40644290 if (property == mode_config->tv_left_margin_property) {
40654291 s->left_margin = val;
....@@ -4078,6 +4304,16 @@
40784304
40794305 if (property == mode_config->tv_bottom_margin_property) {
40804306 s->bottom_margin = val;
4307
+ return 0;
4308
+ }
4309
+
4310
+ if (property == private->bg_prop) {
4311
+ vop->background = val;
4312
+ return 0;
4313
+ }
4314
+
4315
+ if (property == private->line_flag_prop) {
4316
+ vop->line_flag = val;
40814317 return 0;
40824318 }
40834319
....@@ -4106,14 +4342,14 @@
41064342 struct vop *vop = container_of(work, struct vop, fb_unref_work);
41074343 struct drm_framebuffer *fb = val;
41084344
4109
- drm_crtc_vblank_put(&vop->crtc);
4345
+ drm_crtc_vblank_put(&vop->rockchip_crtc.crtc);
41104346 drm_framebuffer_put(fb);
41114347 }
41124348
41134349 static void vop_handle_vblank(struct vop *vop)
41144350 {
41154351 struct drm_device *drm = vop->drm_dev;
4116
- struct drm_crtc *crtc = &vop->crtc;
4352
+ struct drm_crtc *crtc = &vop->rockchip_crtc.crtc;
41174353 unsigned long flags;
41184354
41194355 spin_lock_irqsave(&drm->event_lock, flags);
....@@ -4131,7 +4367,7 @@
41314367 static irqreturn_t vop_isr(int irq, void *data)
41324368 {
41334369 struct vop *vop = data;
4134
- struct drm_crtc *crtc = &vop->crtc;
4370
+ struct drm_crtc *crtc = &vop->rockchip_crtc.crtc;
41354371 uint32_t active_irqs;
41364372 unsigned long flags;
41374373 int ret = IRQ_NONE;
....@@ -4182,6 +4418,7 @@
41824418 * frame effective, but actually it's effective immediately, so
41834419 * we config this register at frame start.
41844420 */
4421
+ rockchip_drm_dbg(vop->dev, VOP_DEBUG_VSYNC, "vsync\n");
41854422 spin_lock_irqsave(&vop->irq_lock, flags);
41864423 VOP_CTRL_SET(vop, level2_overlay_en, vop->pre_overlay);
41874424 VOP_CTRL_SET(vop, alpha_hard_calc, vop->pre_overlay);
....@@ -4228,27 +4465,49 @@
42284465
42294466 flags |= (VOP_WIN_SUPPORT(vop, win, xmirror)) ? DRM_MODE_REFLECT_X : 0;
42304467 flags |= (VOP_WIN_SUPPORT(vop, win, ymirror)) ? DRM_MODE_REFLECT_Y : 0;
4468
+
42314469 if (flags)
42324470 drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
42334471 DRM_MODE_ROTATE_0 | flags);
4472
+}
4473
+
4474
+static int vop_plane_create_name_property(struct vop *vop, struct vop_win *win)
4475
+{
4476
+ struct drm_prop_enum_list *props = vop->plane_name_list;
4477
+ struct drm_property *prop;
4478
+ uint64_t bits = BIT_ULL(win->plane_id);
4479
+
4480
+ prop = drm_property_create_bitmask(vop->drm_dev,
4481
+ DRM_MODE_PROP_IMMUTABLE, "NAME",
4482
+ props, vop->num_wins, bits);
4483
+ if (!prop) {
4484
+ DRM_DEV_ERROR(vop->dev, "create Name prop for %s failed\n", win->name);
4485
+ return -ENOMEM;
4486
+ }
4487
+ win->name_prop = prop;
4488
+ drm_object_attach_property(&win->base.base, win->name_prop, bits);
4489
+
4490
+ return 0;
42344491 }
42354492
42364493 static int vop_plane_init(struct vop *vop, struct vop_win *win,
42374494 unsigned long possible_crtcs)
42384495 {
42394496 struct rockchip_drm_private *private = vop->drm_dev->dev_private;
4497
+ unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) | BIT(DRM_MODE_BLEND_PREMULTI) |
4498
+ BIT(DRM_MODE_BLEND_COVERAGE);
4499
+ const struct vop_data *vop_data = vop->data;
42404500 uint64_t feature = 0;
42414501 int ret;
42424502
42434503 ret = drm_universal_plane_init(vop->drm_dev, &win->base, possible_crtcs, &vop_plane_funcs,
4244
- win->data_formats, win->nformats, NULL, win->type, NULL);
4504
+ win->data_formats, win->nformats, win->format_modifiers,
4505
+ win->type, win->name);
42454506 if (ret) {
42464507 DRM_ERROR("failed to initialize plane %d\n", ret);
42474508 return ret;
42484509 }
42494510 drm_plane_helper_add(&win->base, &plane_helper_funcs);
4250
- drm_object_attach_property(&win->base.base,
4251
- vop->plane_zpos_prop, win->win_id);
42524511
42534512 if (win->phy->scl)
42544513 feature |= BIT(ROCKCHIP_DRM_PLANE_FEATURE_SCALE);
....@@ -4268,15 +4527,9 @@
42684527 drm_object_attach_property(&win->base.base,
42694528 private->color_space_prop, 0);
42704529 if (VOP_WIN_SUPPORT(vop, win, global_alpha_val))
4271
- drm_object_attach_property(&win->base.base,
4272
- private->global_alpha_prop, 0xff);
4273
- drm_object_attach_property(&win->base.base,
4274
- private->blend_mode_prop, 0);
4530
+ drm_plane_create_alpha_property(&win->base);
42754531 drm_object_attach_property(&win->base.base,
42764532 private->async_commit_prop, 0);
4277
- if (VOP_WIN_SUPPORT(vop, win, color_key))
4278
- drm_object_attach_property(&win->base.base,
4279
- win->color_key_prop, 0);
42804533
42814534 if (win->parent)
42824535 drm_object_attach_property(&win->base.base, private->share_id_prop,
....@@ -4284,6 +4537,45 @@
42844537 else
42854538 drm_object_attach_property(&win->base.base, private->share_id_prop,
42864539 win->base.base.id);
4540
+
4541
+ drm_plane_create_blend_mode_property(&win->base, blend_caps);
4542
+ drm_plane_create_zpos_property(&win->base, win->win_id, 0, vop->num_wins - 1);
4543
+ vop_plane_create_name_property(vop, win);
4544
+
4545
+
4546
+ win->input_width_prop = drm_property_create_range(vop->drm_dev, DRM_MODE_PROP_IMMUTABLE,
4547
+ "INPUT_WIDTH", 0, vop_data->max_input.width);
4548
+ win->input_height_prop = drm_property_create_range(vop->drm_dev, DRM_MODE_PROP_IMMUTABLE,
4549
+ "INPUT_HEIGHT", 0, vop_data->max_input.height);
4550
+
4551
+ win->output_width_prop = drm_property_create_range(vop->drm_dev, DRM_MODE_PROP_IMMUTABLE,
4552
+ "OUTPUT_WIDTH", 0, vop_data->max_input.width);
4553
+ win->output_height_prop = drm_property_create_range(vop->drm_dev, DRM_MODE_PROP_IMMUTABLE,
4554
+ "OUTPUT_HEIGHT", 0, vop_data->max_input.height);
4555
+
4556
+ win->scale_prop = drm_property_create_range(vop->drm_dev, DRM_MODE_PROP_IMMUTABLE,
4557
+ "SCALE_RATE", 8, 8);
4558
+ /*
4559
+ * Support 24 bit(RGB888) or 16 bit(rgb565) color key.
4560
+ * Bit 31 is used as a flag to disable (0) or enable
4561
+ * color keying (1).
4562
+ */
4563
+ if (VOP_WIN_SUPPORT(vop, win, color_key))
4564
+ win->color_key_prop = drm_property_create_range(vop->drm_dev, 0,
4565
+ "colorkey", 0, 0x80ffffff);
4566
+ if (!win->input_width_prop || !win->input_height_prop ||
4567
+ !win->scale_prop) {
4568
+ DRM_ERROR("failed to create property\n");
4569
+ return -ENOMEM;
4570
+ }
4571
+
4572
+ drm_object_attach_property(&win->base.base, win->input_width_prop, 0);
4573
+ drm_object_attach_property(&win->base.base, win->input_height_prop, 0);
4574
+ drm_object_attach_property(&win->base.base, win->output_width_prop, 0);
4575
+ drm_object_attach_property(&win->base.base, win->output_height_prop, 0);
4576
+ drm_object_attach_property(&win->base.base, win->scale_prop, 0);
4577
+ if (VOP_WIN_SUPPORT(vop, win, color_key))
4578
+ drm_object_attach_property(&win->base.base, win->color_key_prop, 0);
42874579
42884580 return 0;
42894581 }
....@@ -4345,16 +4637,49 @@
43454637 return 0;
43464638 }
43474639
4640
+static int vop_crtc_create_feature_property(struct vop *vop, struct drm_crtc *crtc)
4641
+{
4642
+ const struct vop_data *vop_data = vop->data;
4643
+
4644
+ struct drm_property *prop;
4645
+ u64 feature = 0;
4646
+
4647
+ static const struct drm_prop_enum_list props[] = {
4648
+ { ROCKCHIP_DRM_CRTC_FEATURE_ALPHA_SCALE, "ALPHA_SCALE" },
4649
+ { ROCKCHIP_DRM_CRTC_FEATURE_HDR10, "HDR10" },
4650
+ { ROCKCHIP_DRM_CRTC_FEATURE_NEXT_HDR, "NEXT_HDR" },
4651
+ };
4652
+
4653
+ if (vop_data->feature & VOP_FEATURE_ALPHA_SCALE)
4654
+ feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_ALPHA_SCALE);
4655
+ if (vop_data->feature & VOP_FEATURE_HDR10)
4656
+ feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_HDR10);
4657
+ if (vop_data->feature & VOP_FEATURE_NEXT_HDR)
4658
+ feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_NEXT_HDR);
4659
+
4660
+ prop = drm_property_create_bitmask(vop->drm_dev,
4661
+ DRM_MODE_PROP_IMMUTABLE, "FEATURE",
4662
+ props, ARRAY_SIZE(props),
4663
+ 0xffffffff);
4664
+ if (!prop) {
4665
+ DRM_DEV_ERROR(vop->dev, "create FEATURE prop for vop%d failed\n", vop->id);
4666
+ return -ENOMEM;
4667
+ }
4668
+
4669
+ vop->feature_prop = prop;
4670
+ drm_object_attach_property(&crtc->base, vop->feature_prop, feature);
4671
+
4672
+ return 0;
4673
+}
4674
+
43484675 static int vop_create_crtc(struct vop *vop)
43494676 {
43504677 struct device *dev = vop->dev;
4351
- const struct vop_data *vop_data = vop->data;
43524678 struct drm_device *drm_dev = vop->drm_dev;
43534679 struct rockchip_drm_private *private = drm_dev->dev_private;
43544680 struct drm_plane *primary = NULL, *cursor = NULL, *plane, *tmp;
4355
- struct drm_crtc *crtc = &vop->crtc;
4681
+ struct drm_crtc *crtc = &vop->rockchip_crtc.crtc;
43564682 struct device_node *port;
4357
- uint64_t feature = 0;
43584683 int ret = 0;
43594684 int i;
43604685
....@@ -4370,7 +4695,8 @@
43704695 win->type != DRM_PLANE_TYPE_CURSOR)
43714696 continue;
43724697
4373
- if (vop_plane_init(vop, win, 0)) {
4698
+ ret = vop_plane_init(vop, win, 0);
4699
+ if (ret) {
43744700 DRM_DEV_ERROR(vop->dev, "failed to init plane\n");
43754701 goto err_cleanup_planes;
43764702 }
....@@ -4400,7 +4726,8 @@
44004726 if (win->type != DRM_PLANE_TYPE_OVERLAY)
44014727 continue;
44024728
4403
- if (vop_plane_init(vop, win, possible_crtcs)) {
4729
+ ret = vop_plane_init(vop, win, possible_crtcs);
4730
+ if (ret) {
44044731 DRM_DEV_ERROR(vop->dev, "failed to init overlay\n");
44054732 goto err_cleanup_crtc;
44064733 }
....@@ -4423,6 +4750,12 @@
44234750 crtc->port = port;
44244751 rockchip_register_crtc_funcs(crtc, &private_crtc_funcs);
44254752
4753
+ drm_object_attach_property(&crtc->base, private->soc_id_prop, vop->soc_id);
4754
+ drm_object_attach_property(&crtc->base, private->port_id_prop, vop->id);
4755
+ drm_object_attach_property(&crtc->base, private->aclk_prop, 0);
4756
+ drm_object_attach_property(&crtc->base, private->bg_prop, 0);
4757
+ drm_object_attach_property(&crtc->base, private->line_flag_prop, 0);
4758
+
44264759 #define VOP_ATTACH_MODE_CONFIG_PROP(prop, v) \
44274760 drm_object_attach_property(&crtc->base, drm_dev->mode_config.prop, v)
44284761
....@@ -4430,13 +4763,14 @@
44304763 VOP_ATTACH_MODE_CONFIG_PROP(tv_right_margin_property, 100);
44314764 VOP_ATTACH_MODE_CONFIG_PROP(tv_top_margin_property, 100);
44324765 VOP_ATTACH_MODE_CONFIG_PROP(tv_bottom_margin_property, 100);
4433
-
44344766 #undef VOP_ATTACH_MODE_CONFIG_PROP
4435
- drm_object_attach_property(&crtc->base, private->alpha_scale_prop, 0);
4436
- if (vop_data->feature & VOP_FEATURE_AFBDC)
4437
- feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_AFBDC);
4438
- drm_object_attach_property(&crtc->base, vop->feature_prop,
4439
- feature);
4767
+ vop_crtc_create_feature_property(vop, crtc);
4768
+ ret = drm_self_refresh_helper_init(crtc);
4769
+ if (ret)
4770
+ DRM_DEV_DEBUG_KMS(vop->dev,
4771
+ "Failed to init %s with SR helpers %d, ignoring\n",
4772
+ crtc->name, ret);
4773
+
44404774 if (vop->lut_regs) {
44414775 u16 *r_base, *g_base, *b_base;
44424776 u32 lut_len = vop->lut_len;
....@@ -4483,9 +4817,11 @@
44834817
44844818 static void vop_destroy_crtc(struct vop *vop)
44854819 {
4486
- struct drm_crtc *crtc = &vop->crtc;
4820
+ struct drm_crtc *crtc = &vop->rockchip_crtc.crtc;
44874821 struct drm_device *drm_dev = vop->drm_dev;
44884822 struct drm_plane *plane, *tmp;
4823
+
4824
+ drm_self_refresh_helper_cleanup(crtc);
44894825
44904826 of_node_put(crtc->port);
44914827
....@@ -4537,16 +4873,15 @@
45374873 const struct vop_data *vop_data = vop->data;
45384874 unsigned int i, j;
45394875 unsigned int num_wins = 0;
4540
- struct drm_property *prop;
4876
+ char name[DRM_PROP_NAME_LEN];
4877
+ uint8_t plane_id = 0;
4878
+ struct drm_prop_enum_list *plane_name_list;
45414879 static const struct drm_prop_enum_list props[] = {
45424880 { ROCKCHIP_DRM_PLANE_FEATURE_SCALE, "scale" },
45434881 { ROCKCHIP_DRM_PLANE_FEATURE_ALPHA, "alpha" },
45444882 { ROCKCHIP_DRM_PLANE_FEATURE_HDR2SDR, "hdr2sdr" },
45454883 { ROCKCHIP_DRM_PLANE_FEATURE_SDR2HDR, "sdr2hdr" },
45464884 { ROCKCHIP_DRM_PLANE_FEATURE_AFBDC, "afbdc" },
4547
- };
4548
- static const struct drm_prop_enum_list crtc_props[] = {
4549
- { ROCKCHIP_DRM_CRTC_FEATURE_AFBDC, "afbdc" },
45504885 };
45514886
45524887 for (i = 0; i < vop_data->win_size; i++) {
....@@ -4562,16 +4897,16 @@
45624897 vop_win->type = win_data->type;
45634898 vop_win->data_formats = win_data->phy->data_formats;
45644899 vop_win->nformats = win_data->phy->nformats;
4900
+ vop_win->format_modifiers = win_data->format_modifiers;
45654901 vop_win->feature = win_data->feature;
45664902 vop_win->vop = vop;
45674903 vop_win->win_id = i;
45684904 vop_win->area_id = 0;
4905
+ vop_win->plane_id = plane_id++;
4906
+ snprintf(name, sizeof(name), "VOP%d-win%d-%d", vop->id, vop_win->win_id, vop_win->area_id);
4907
+ vop_win->name = devm_kstrdup(vop->dev, name, GFP_KERNEL);
45694908 vop_win->zpos = vop_plane_get_zpos(win_data->type,
45704909 vop_data->win_size);
4571
- if (VOP_WIN_SUPPORT(vop, vop_win, color_key))
4572
- vop_win->color_key_prop = drm_property_create_range(vop->drm_dev, 0,
4573
- "colorkey", 0,
4574
- 0x80ffffff);
45754910
45764911 num_wins++;
45774912
....@@ -4588,22 +4923,18 @@
45884923 vop_area->type = DRM_PLANE_TYPE_OVERLAY;
45894924 vop_area->data_formats = vop_win->data_formats;
45904925 vop_area->nformats = vop_win->nformats;
4926
+ vop_area->format_modifiers = win_data->format_modifiers;
45914927 vop_area->vop = vop;
45924928 vop_area->win_id = i;
45934929 vop_area->area_id = j + 1;
4930
+ vop_area->plane_id = plane_id++;
4931
+ snprintf(name, sizeof(name), "VOP%d-win%d-%d", vop->id, vop_area->win_id, vop_area->area_id);
4932
+ vop_area->name = devm_kstrdup(vop->dev, name, GFP_KERNEL);
45944933 num_wins++;
45954934 }
45964935 }
45974936
45984937 vop->num_wins = num_wins;
4599
-
4600
- prop = drm_property_create_range(vop->drm_dev, DRM_MODE_PROP_ATOMIC,
4601
- "ZPOS", 0, vop->data->win_size - 1);
4602
- if (!prop) {
4603
- DRM_ERROR("failed to create zpos property\n");
4604
- return -EINVAL;
4605
- }
4606
- vop->plane_zpos_prop = prop;
46074938
46084939 vop->plane_feature_prop = drm_property_create_bitmask(vop->drm_dev,
46094940 DRM_MODE_PROP_IMMUTABLE, "FEATURE",
....@@ -4618,66 +4949,25 @@
46184949 return -EINVAL;
46194950 }
46204951
4621
- vop->feature_prop = drm_property_create_bitmask(vop->drm_dev,
4622
- DRM_MODE_PROP_IMMUTABLE, "FEATURE",
4623
- crtc_props, ARRAY_SIZE(crtc_props),
4624
- BIT(ROCKCHIP_DRM_CRTC_FEATURE_AFBDC));
4625
- if (!vop->feature_prop) {
4626
- DRM_ERROR("failed to create vop feature property\n");
4627
- return -EINVAL;
4952
+ plane_name_list = devm_kzalloc(vop->dev,
4953
+ vop->num_wins * sizeof(*plane_name_list),
4954
+ GFP_KERNEL);
4955
+ if (!plane_name_list) {
4956
+ DRM_DEV_ERROR(vop->dev, "failed to alloc memory for plane_name_list\n");
4957
+ return -ENOMEM;
46284958 }
4959
+
4960
+ for (i = 0; i < vop->num_wins; i++) {
4961
+ struct vop_win *vop_win = &vop->win[i];
4962
+
4963
+ plane_name_list[i].type = vop_win->plane_id;
4964
+ plane_name_list[i].name = vop_win->name;
4965
+ }
4966
+
4967
+ vop->plane_name_list = plane_name_list;
46294968
46304969 return 0;
46314970 }
4632
-
4633
-/**
4634
- * rockchip_drm_wait_vact_end
4635
- * @crtc: CRTC to enable line flag
4636
- * @mstimeout: millisecond for timeout
4637
- *
4638
- * Wait for vact_end line flag irq or timeout.
4639
- *
4640
- * Returns:
4641
- * Zero on success, negative errno on failure.
4642
- */
4643
-int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout)
4644
-{
4645
- struct vop *vop = to_vop(crtc);
4646
- unsigned long jiffies_left;
4647
- int ret = 0;
4648
-
4649
- if (!crtc || !vop->is_enabled)
4650
- return -ENODEV;
4651
-
4652
- mutex_lock(&vop->vop_lock);
4653
- if (mstimeout <= 0) {
4654
- ret = -EINVAL;
4655
- goto out;
4656
- }
4657
-
4658
- if (vop_line_flag_irq_is_enabled(vop)) {
4659
- ret = -EBUSY;
4660
- goto out;
4661
- }
4662
-
4663
- reinit_completion(&vop->line_flag_completion);
4664
- vop_line_flag_irq_enable(vop);
4665
-
4666
- jiffies_left = wait_for_completion_timeout(&vop->line_flag_completion,
4667
- msecs_to_jiffies(mstimeout));
4668
- vop_line_flag_irq_disable(vop);
4669
-
4670
- if (jiffies_left == 0) {
4671
- DRM_DEV_ERROR(vop->dev, "Timeout waiting for IRQ\n");
4672
- ret = -ETIMEDOUT;
4673
- goto out;
4674
- }
4675
-
4676
-out:
4677
- mutex_unlock(&vop->vop_lock);
4678
- return ret;
4679
-}
4680
-EXPORT_SYMBOL(rockchip_drm_wait_vact_end);
46814971
46824972 static int vop_bind(struct device *dev, struct device *master, void *data)
46834973 {
....@@ -4713,6 +5003,8 @@
47135003 vop->drm_dev = drm_dev;
47145004 vop->num_wins = num_wins;
47155005 vop->version = vop_data->version;
5006
+ vop->soc_id = vop_data->soc_id;
5007
+ vop->id = vop_data->vop_id;
47165008 dev_set_drvdata(dev, vop);
47175009 vop->support_multi_area = of_property_read_bool(dev->of_node, "support-multi-area");
47185010