• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
4  * Author:Mark Yao <mark.yao@rock-chips.com>
5  */
6 
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 
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 #include <dt-bindings/soc/rockchip-system-status.h>
43 
44 #include <soc/rockchip/rockchip_dmc.h>
45 #include <soc/rockchip/rockchip-system-status.h>
46 #include <uapi/linux/videodev2.h>
47 #include "../drm_crtc_internal.h"
48 
49 #include "rockchip_drm_drv.h"
50 #include "rockchip_drm_gem.h"
51 #include "rockchip_drm_fb.h"
52 #include "rockchip_drm_vop.h"
53 #include "rockchip_rgb.h"
54 
55 #define VOP_REG_SUPPORT(vop, reg)                                                                                      \
56     ((reg).mask &&                                                                                                     \
57      (!(reg).major || ((reg).major == VOP_MAJOR((vop)->version) && (reg).begin_minor <= VOP_MINOR((vop)->version) &&   \
58                        (reg).end_minor >= VOP_MINOR((vop)->version))))
59 
60 #define VOP_WIN_SUPPORT(vop, win, name) VOP_REG_SUPPORT(vop, (win)->phy->name)
61 
62 #define VOP_WIN_SCL_EXT_SUPPORT(vop, win, name) ((win)->phy->scl->ext && \
63         VOP_REG_SUPPORT(vop, (win)->phy->scl->ext->name))
64 
65 #define VOP_CTRL_SUPPORT(vop, name) VOP_REG_SUPPORT(vop, (vop)->data->ctrl->name)
66 
67 #define VOP_INTR_SUPPORT(vop, name) VOP_REG_SUPPORT(vop, (vop)->data->intr->name)
68 
69 #define REG_SET_EX(x, off, mask, shift, v, write_mask, relaxed)                                                        \
70     vop_mask_write((x), (off), (mask), (shift), (v), (write_mask), (relaxed))
71 
72 #define REG_SET_E(vop, name, off, reg, mask, v, relaxed)                                                               \
73     do {                                                                                                               \
74         if (VOP_REG_SUPPORT(vop, reg))                                                                                 \
75             REG_SET_EX(vop, (off) + (reg).offset, mask, (reg).shift, v, (reg).write_mask, relaxed);                    \
76         else                                                                                                           \
77             dev_dbg((vop)->dev, "Warning: not support " #name "\n");                                                   \
78     } while (0)
79 
80 #define REG_SET(x, name, off, reg, v, relaxed) REG_SET_E(x, name, off, reg, (reg).mask, v, relaxed)
81 #define REG_SET_MASK(x, name, off, reg, mask, v, relaxed)                                                              \
82     REG_SET_E((x), (name), (off), (reg), (reg).mask &(mask), (v), (relaxed))
83 
84 #define VOP_WIN_SET(x, win, name, v) REG_SET((x), (name), (win)->offset, VOP_WIN_NAME(win, name), (v), true)
85 #define VOP_WIN_SET_EXT(x, win, ext, name, v) REG_SET((x), (name), 0, (win)->ext->name, (v), true)
86 #define VOP_SCL_SET(x, win, name, v) REG_SET((x), (name), (win)->offset, (win)->phy->scl->name, (v), true)
87 #define VOP_SCL_SET_EXT(x, win, name, v) REG_SET((x), (name), (win)->offset, (win)->phy->scl->ext->name, (v), true)
88 
89 #define VOP_CTRL_SET(x, name, v) REG_SET((x), (name), 0, (x)->data->ctrl->name, (v), false)
90 
91 #define VOP_INTR_GET(vop, name) vop_read_reg((vop), 0, &(vop)->data->ctrl->name)
92 
93 #define VOP_INTR_SET(vop, name, v) REG_SET((vop), name, 0, (vop)->data->intr->name, v, false)
94 #define VOP_INTR_SET_MASK(vop, name, mask, v) REG_SET_MASK((vop), name, 0, (vop)->data->intr->name, mask, v, false)
95 
96 #define VOP_REG_SET(vop, group, name, v) vop_reg_set((vop), &(vop)->data->group->name, 0, ~0, (v), #name)
97 
98 #define VOP_INTR_SET_TYPE(vop, name, type, v)                                                                          \
99     do {                                                                                                               \
100         int i, reg = 0, mask = 0;                                                                                      \
101         for (i = 0; i < (vop)->data->intr->nintrs; i++) {                                                              \
102             if ((vop)->data->intr->intrs[i] & (type)) {                                                                \
103                 reg |= (v) << i;                                                                                       \
104                 mask |= 1 << i;                                                                                        \
105             }                                                                                                          \
106         }                                                                                                              \
107         VOP_INTR_SET_MASK(vop, name, mask, reg);                                                                       \
108     } while (0)
109 #define VOP_INTR_GET_TYPE(vop, name, type) vop_get_intr_type((vop), &(vop)->data->intr->name, (type))
110 
111 #define VOP_CTRL_GET(x, name) vop_read_reg((x), 0, &vop->data->ctrl->name)
112 
113 #define VOP_WIN_GET(vop, win, name) vop_read_reg((vop), (win)->offset, &VOP_WIN_NAME(win, name))
114 
115 #define VOP_WIN_NAME(win, name) (vop_get_win_phy((win), &(win)->phy->name)->name)
116 
117 #define VOP_WIN_TO_INDEX(vop_win) ((vop_win) - (vop_win)->vop->win)
118 
119 #define VOP_GRF_SET(vop, reg, v)                                                                                       \
120     do {                                                                                                               \
121         if ((vop)->data->grf_ctrl) {                                                                                   \
122             vop_grf_writel((vop), (vop)->data->grf_ctrl->reg, (v));                                                    \
123         }                                                                                                              \
124     } while (0)
125 
126 #define to_vop_win(x) container_of((x), struct vop_win, base)
127 #define to_vop_plane_state(x) container_of((x), struct vop_plane_state, base)
128 
129 enum vop_pending {
130     VOP_PENDING_FB_UNREF,
131 };
132 
133 struct vop_zpos {
134     int win_id;
135     int zpos;
136 };
137 
138 struct vop_plane_state {
139     struct drm_plane_state base;
140     int format;
141     int zpos;
142     struct drm_rect src;
143     struct drm_rect dest;
144     dma_addr_t yrgb_mst;
145     dma_addr_t uv_mst;
146     const uint32_t *y2r_table;
147     const uint32_t *r2r_table;
148     const uint32_t *r2y_table;
149     int eotf;
150     bool y2r_en;
151     bool r2r_en;
152     bool r2y_en;
153     int color_space;
154     u32 color_key;
155     unsigned int csc_mode;
156     int global_alpha;
157     int blend_mode;
158     unsigned long offset;
159     int pdaf_data_type;
160     bool async_commit;
161     struct vop_dump_list *planlist;
162 };
163 
164 struct rockchip_mcu_timing {
165     int mcu_pix_total;
166     int mcu_cs_pst;
167     int mcu_cs_pend;
168     int mcu_rw_pst;
169     int mcu_rw_pend;
170     int mcu_hold_mode;
171 };
172 
173 struct vop_win {
174     struct vop_win *parent;
175     struct drm_plane base;
176 
177     int win_id;
178     int area_id;
179     u8 plane_id; /* unique plane id */
180     const char *name;
181 
182     int zpos;
183     uint32_t offset;
184     enum drm_plane_type type;
185     const struct vop_win_phy *phy;
186     const struct vop_csc *csc;
187     const uint32_t *data_formats;
188     uint32_t nformats;
189     const uint64_t *format_modifiers;
190     u64 feature;
191     struct vop *vop;
192     struct vop_plane_state state;
193 
194     struct drm_property *input_width_prop;
195     struct drm_property *input_height_prop;
196     struct drm_property *output_width_prop;
197     struct drm_property *output_height_prop;
198     struct drm_property *color_key_prop;
199     struct drm_property *scale_prop;
200     struct drm_property *name_prop;
201 };
202 
203 struct vop {
204     struct rockchip_crtc rockchip_crtc;
205     struct device *dev;
206     struct drm_device *drm_dev;
207     struct dentry *debugfs;
208     struct drm_info_list *debugfs_files;
209     struct drm_property *plane_feature_prop;
210     struct drm_property *plane_mask_prop;
211     struct drm_property *feature_prop;
212 
213     bool is_iommu_enabled;
214     bool is_iommu_needed;
215     bool is_enabled;
216     bool support_multi_area;
217 
218     u32 version;
219     u32 background;
220     u32 line_flag;
221     u8 id;
222     u8 plane_mask;
223     u64 soc_id;
224     struct drm_prop_enum_list *plane_name_list;
225 
226     struct drm_tv_connector_state active_tv_state;
227     bool pre_overlay;
228     bool loader_protect;
229     struct completion dsp_hold_completion;
230 
231     /* protected by dev->event_lock */
232     struct drm_pending_vblank_event *event;
233 
234     struct drm_flip_work fb_unref_work;
235     unsigned long pending;
236 
237     struct completion line_flag_completion;
238 
239     const struct vop_data *data;
240     int num_wins;
241 
242     uint32_t *regsbak;
243     void __iomem *regs;
244     struct regmap *grf;
245 
246     /* physical map length of vop register */
247     uint32_t len;
248 
249     void __iomem *lut_regs;
250     u32 *lut;
251     u32 lut_len;
252     bool lut_active;
253     /* gamma look up table */
254     struct drm_color_lut *gamma_lut;
255     bool dual_channel_swap;
256     /* one time only one process allowed to config the register */
257     spinlock_t reg_lock;
258     /* lock vop irq reg */
259     spinlock_t irq_lock;
260     /* protects crtc enable/disable */
261     struct mutex vop_lock;
262 
263     unsigned int irq;
264 
265     /* vop AHP clk */
266     struct clk *hclk;
267     /* vop dclk */
268     struct clk *dclk;
269     /* vop share memory frequency */
270     struct clk *aclk;
271     /* vop source handling, optional */
272     struct clk *dclk_source;
273 
274     /* vop dclk reset */
275     struct reset_control *dclk_rst;
276 
277     struct rockchip_dclk_pll *pll;
278 
279     struct rockchip_mcu_timing mcu_timing;
280 
281     struct vop_win win[];
282 };
283 
284 /*
285  * bus-format types.
286  */
287 struct drm_bus_format_enum_list {
288     int type;
289     const char *name;
290 };
291 
292 static const struct drm_bus_format_enum_list drm_bus_format_enum_list_ex[] = {
293     {DRM_MODE_CONNECTOR_Unknown, "Unknown"},
294     {MEDIA_BUS_FMT_RGB565_1X16, "RGB565_1X16"},
295     {MEDIA_BUS_FMT_RGB666_1X18, "RGB666_1X18"},
296     {MEDIA_BUS_FMT_RGB666_1X24_CPADHI, "RGB666_1X24_CPADHI"},
297     {MEDIA_BUS_FMT_RGB666_1X7X3_SPWG, "RGB666_1X7X3_SPWG"},
298     {MEDIA_BUS_FMT_YUV8_1X24, "YUV8_1X24"},
299     {MEDIA_BUS_FMT_UYYVYY8_0_5X24, "UYYVYY8_0_5X24"},
300     {MEDIA_BUS_FMT_YUV10_1X30, "YUV10_1X30"},
301     {MEDIA_BUS_FMT_UYYVYY10_0_5X30, "UYYVYY10_0_5X30"},
302     {MEDIA_BUS_FMT_RGB888_3X8, "RGB888_3X8"},
303     {MEDIA_BUS_FMT_RGB888_DUMMY_4X8, "RGB888_DUMMY_4X8"},
304     {MEDIA_BUS_FMT_RGB888_1X24, "RGB888_1X24"},
305     {MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, "RGB888_1X7X4_SPWG"},
306     {MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, "RGB888_1X7X4_JEIDA"},
307     {MEDIA_BUS_FMT_UYVY8_2X8, "UYVY8_2X8"},
308     {MEDIA_BUS_FMT_YUYV8_1X16, "YUYV8_1X16"},
309     {MEDIA_BUS_FMT_UYVY8_1X16, "UYVY8_1X16"},
310 };
311 
DRM_ENUM_NAME_FN(drm_get_bus_format_name,drm_bus_format_enum_list_ex)312 static DRM_ENUM_NAME_FN(drm_get_bus_format_name, drm_bus_format_enum_list_ex)
313 
314 static inline struct vop *to_vop(struct drm_crtc *crtc)
315 {
316     struct rockchip_crtc *rockchip_crtc;
317 
318     rockchip_crtc = container_of(crtc, struct rockchip_crtc, crtc);
319 
320     return container_of(rockchip_crtc, struct vop, rockchip_crtc);
321 }
322 
vop_lock(struct vop * vop)323 static void vop_lock(struct vop *vop)
324 {
325     mutex_lock(&vop->vop_lock);
326     rockchip_dmcfreq_lock();
327 }
328 
vop_unlock(struct vop * vop)329 static void vop_unlock(struct vop *vop)
330 {
331     rockchip_dmcfreq_unlock();
332     mutex_unlock(&vop->vop_lock);
333 }
334 
vop_grf_writel(struct vop * vop,struct vop_reg reg,u32 v)335 static inline void vop_grf_writel(struct vop *vop, struct vop_reg reg, u32 v)
336 {
337     u32 val = 0;
338 
339     if (IS_ERR_OR_NULL(vop->grf)) {
340         return;
341     }
342 
343     if (VOP_REG_SUPPORT(vop, reg)) {
344         val = (v << reg.shift) | (reg.mask << (reg.shift + 0x10));
345         regmap_write(vop->grf, reg.offset, val);
346     }
347 }
348 
vop_writel(struct vop * vop,uint32_t offset,uint32_t v)349 static inline void vop_writel(struct vop *vop, uint32_t offset, uint32_t v)
350 {
351     writel(v, vop->regs + offset);
352     vop->regsbak[offset >> 0x2] = v;
353 }
354 
vop_readl(struct vop * vop,uint32_t offset)355 static inline uint32_t vop_readl(struct vop *vop, uint32_t offset)
356 {
357     return readl(vop->regs + offset);
358 }
359 
vop_read_reg(struct vop * vop,uint32_t base,const struct vop_reg * reg)360 static inline uint32_t vop_read_reg(struct vop *vop, uint32_t base, const struct vop_reg *reg)
361 {
362     return (vop_readl(vop, base + reg->offset) >> reg->shift) & reg->mask;
363 }
364 
vop_mask_write(struct vop * vop,uint32_t offset,uint32_t mask,uint32_t shift,uint32_t v,bool write_mask,bool relaxed)365 static inline void vop_mask_write(struct vop *vop, uint32_t offset, uint32_t mask, uint32_t shift, uint32_t v,
366                                   bool write_mask, bool relaxed)
367 {
368     if (!mask) {
369         return;
370     }
371 
372     if (write_mask) {
373         v = ((v & mask) << shift) | (mask << (shift + 0x10));
374     } else {
375         uint32_t cached_val = vop->regsbak[offset >> 0x2];
376 
377         v = (cached_val & ~(mask << shift)) | ((v & mask) << shift);
378         vop->regsbak[offset >> 0x2] = v;
379     }
380 
381     if (relaxed) {
382         writel_relaxed(v, vop->regs + offset);
383     } else {
384         writel(v, vop->regs + offset);
385     }
386 }
387 
vop_get_win_phy(struct vop_win * win,const struct vop_reg * reg)388 static inline const struct vop_win_phy *vop_get_win_phy(struct vop_win *win, const struct vop_reg *reg)
389 {
390     if (!reg->mask && win->parent) {
391         return win->parent->phy;
392     }
393 
394     return win->phy;
395 }
396 
vop_get_intr_type(struct vop * vop,const struct vop_reg * reg,int type)397 static inline uint32_t vop_get_intr_type(struct vop *vop, const struct vop_reg *reg, int type)
398 {
399     uint32_t i, ret = 0;
400     uint32_t regs = vop_read_reg(vop, 0, reg);
401 
402     for (i = 0; i < vop->data->intr->nintrs; i++) {
403         if ((type & vop->data->intr->intrs[i]) && (regs & (1 << i))) {
404             ret |= vop->data->intr->intrs[i];
405         }
406     }
407 
408     return ret;
409 }
410 
vop_load_hdr2sdr_table(struct vop * vop)411 static void vop_load_hdr2sdr_table(struct vop *vop)
412 {
413     int i;
414     const struct vop_hdr_table *table = vop->data->hdr_table;
415     uint32_t hdr2sdr_eetf_oetf_yn[0x21];
416 
417     for (i = 0; i < 0x21; i++) {
418         hdr2sdr_eetf_oetf_yn[i] = table->hdr2sdr_eetf_yn[i] + (table->hdr2sdr_bt1886oetf_yn[i] << 0x10);
419     }
420 
421     vop_writel(vop, table->hdr2sdr_eetf_oetf_y0_offset, hdr2sdr_eetf_oetf_yn[0]);
422     for (i = 0x1; i < 0x21; i++) {
423         vop_writel(vop, table->hdr2sdr_eetf_oetf_y1_offset + (i - 1) * 0x4, hdr2sdr_eetf_oetf_yn[i]);
424     }
425 
426     vop_writel(vop, table->hdr2sdr_sat_y0_offset, table->hdr2sdr_sat_yn[0]);
427     for (i = 0x1; i < 0x9; i++) {
428         vop_writel(vop, table->hdr2sdr_sat_y1_offset + (i - 1) * 0x4, table->hdr2sdr_sat_yn[i]);
429     }
430 
431     VOP_CTRL_SET(vop, hdr2sdr_src_min, table->hdr2sdr_src_range_min);
432     VOP_CTRL_SET(vop, hdr2sdr_src_max, table->hdr2sdr_src_range_max);
433     VOP_CTRL_SET(vop, hdr2sdr_normfaceetf, table->hdr2sdr_normfaceetf);
434     VOP_CTRL_SET(vop, hdr2sdr_dst_min, table->hdr2sdr_dst_range_min);
435     VOP_CTRL_SET(vop, hdr2sdr_dst_max, table->hdr2sdr_dst_range_max);
436     VOP_CTRL_SET(vop, hdr2sdr_normfacgamma, table->hdr2sdr_normfacgamma);
437 }
438 
vop_load_sdr2hdr_table(struct vop * vop,uint32_t cmd)439 static void vop_load_sdr2hdr_table(struct vop *vop, uint32_t cmd)
440 {
441     int i;
442     const struct vop_hdr_table *table = vop->data->hdr_table;
443     uint32_t sdr2hdr_eotf_oetf_yn[0x41];
444     uint32_t sdr2hdr_oetf_dx_dxpow[0x40];
445 
446     for (i = 0; i < 0x41; i++) {
447         if (cmd == SDR2HDR_FOR_BT2020) {
448             sdr2hdr_eotf_oetf_yn[i] =
449                 table->sdr2hdr_bt1886eotf_yn_for_bt2020[i] + (table->sdr2hdr_st2084oetf_yn_for_bt2020[i] << 0x12);
450         } else if (cmd == SDR2HDR_FOR_HDR) {
451             sdr2hdr_eotf_oetf_yn[i] =
452                 table->sdr2hdr_bt1886eotf_yn_for_hdr[i] + (table->sdr2hdr_st2084oetf_yn_for_hdr[i] << 0x12);
453         } else if (cmd == SDR2HDR_FOR_HLG_HDR) {
454             sdr2hdr_eotf_oetf_yn[i] =
455                 table->sdr2hdr_bt1886eotf_yn_for_hlg_hdr[i] + (table->sdr2hdr_st2084oetf_yn_for_hlg_hdr[i] << 0x12);
456         }
457     }
458     vop_writel(vop, table->sdr2hdr_eotf_oetf_y0_offset, sdr2hdr_eotf_oetf_yn[0]);
459     for (i = 1; i < 0x41; i++) {
460         vop_writel(vop, table->sdr2hdr_eotf_oetf_y1_offset + (i - 1) * 0x4, sdr2hdr_eotf_oetf_yn[i]);
461     }
462 
463     for (i = 0; i < 0x40; i++) {
464         sdr2hdr_oetf_dx_dxpow[i] = table->sdr2hdr_st2084oetf_dxn[i] + (table->sdr2hdr_st2084oetf_dxn_pow2[i] << 0x10);
465         vop_writel(vop, table->sdr2hdr_oetf_dx_dxpow1_offset + i * 0x4, sdr2hdr_oetf_dx_dxpow[i]);
466     }
467 
468     for (i = 0; i < 0x3f; i++) {
469         vop_writel(vop, table->sdr2hdr_oetf_xn1_offset + i * 0x4, table->sdr2hdr_st2084oetf_xn[i]);
470     }
471 }
472 
vop_load_csc_table(struct vop * vop,u32 offset,const u32 * table)473 static void vop_load_csc_table(struct vop *vop, u32 offset, const u32 *table)
474 {
475     int i;
476 
477     /*
478      * so far the csc offset is not 0 and in the feature the csc offset
479      * impossible be 0, so when the offset is 0, should return here.
480      */
481     if (!table || offset == 0) {
482         return;
483     }
484 
485     for (i = 0; i < 0x8; i++) {
486         vop_writel(vop, offset + i * 0x4, table[i]);
487     }
488 }
489 
vop_cfg_done(struct vop * vop)490 static inline void vop_cfg_done(struct vop *vop)
491 {
492     VOP_CTRL_SET(vop, cfg_done, 1);
493 }
494 
vop_is_allwin_disabled(struct vop * vop)495 static bool vop_is_allwin_disabled(struct vop *vop)
496 {
497     int i;
498 
499     for (i = 0; i < vop->num_wins; i++) {
500         struct vop_win *win = &vop->win[i];
501 
502         if (VOP_WIN_GET(vop, win, enable) != 0) {
503             return false;
504         }
505     }
506 
507     return true;
508 }
509 
vop_win_disable(struct vop * vop,struct vop_win * win)510 static void vop_win_disable(struct vop *vop, struct vop_win *win)
511 {
512     /*
513      * FIXUP: some of the vop scale would be abnormal after windows power
514      * on/off so deinit scale to scale_none mode.
515      */
516     if (win->phy->scl && win->phy->scl->ext) {
517         VOP_SCL_SET_EXT(vop, win, yrgb_hor_scl_mode, SCALE_NONE);
518         VOP_SCL_SET_EXT(vop, win, yrgb_ver_scl_mode, SCALE_NONE);
519         VOP_SCL_SET_EXT(vop, win, cbcr_hor_scl_mode, SCALE_NONE);
520         VOP_SCL_SET_EXT(vop, win, cbcr_ver_scl_mode, SCALE_NONE);
521     }
522 
523     VOP_WIN_SET(vop, win, enable, 0);
524     if (win->area_id == 0) {
525         VOP_WIN_SET(vop, win, gate, 0);
526     }
527 }
528 
vop_disable_allwin(struct vop * vop)529 static void vop_disable_allwin(struct vop *vop)
530 {
531     int i;
532 
533     for (i = 0; i < vop->num_wins; i++) {
534         struct vop_win *win = &vop->win[i];
535 
536         vop_win_disable(vop, win);
537     }
538 }
539 
vop_write_lut(struct vop * vop,uint32_t offset,uint32_t v)540 static inline void vop_write_lut(struct vop *vop, uint32_t offset, uint32_t v)
541 {
542     writel(v, vop->lut_regs + offset);
543 }
544 
vop_read_lut(struct vop * vop,uint32_t offset)545 static inline uint32_t vop_read_lut(struct vop *vop, uint32_t offset)
546 {
547     return readl(vop->lut_regs + offset);
548 }
549 
has_rb_swapped(uint32_t format)550 static bool has_rb_swapped(uint32_t format)
551 {
552     switch (format) {
553         case DRM_FORMAT_XBGR8888:
554         case DRM_FORMAT_ABGR8888:
555         case DRM_FORMAT_BGR888:
556         case DRM_FORMAT_BGR565:
557             return true;
558         default:
559             return false;
560     }
561 }
562 
vop_convert_format(uint32_t format)563 static enum vop_data_format vop_convert_format(uint32_t format)
564 {
565     switch (format) {
566         case DRM_FORMAT_XRGB8888:
567         case DRM_FORMAT_ARGB8888:
568         case DRM_FORMAT_XBGR8888:
569         case DRM_FORMAT_ABGR8888:
570             return VOP_FMT_ARGB8888;
571         case DRM_FORMAT_RGB888:
572         case DRM_FORMAT_BGR888:
573             return VOP_FMT_RGB888;
574         case DRM_FORMAT_RGB565:
575         case DRM_FORMAT_BGR565:
576             return VOP_FMT_RGB565;
577         case DRM_FORMAT_NV12:
578         case DRM_FORMAT_NV15:
579             return VOP_FMT_YUV420SP;
580         case DRM_FORMAT_NV16:
581         case DRM_FORMAT_NV20:
582             return VOP_FMT_YUV422SP;
583         case DRM_FORMAT_NV24:
584         case DRM_FORMAT_NV30:
585             return VOP_FMT_YUV444SP;
586         case DRM_FORMAT_YVYU:
587         case DRM_FORMAT_VYUY:
588         case DRM_FORMAT_YUYV:
589         case DRM_FORMAT_UYVY:
590             return VOP_FMT_YUYV;
591         default:
592             DRM_ERROR("unsupported format[%08x]\n", format);
593             return -EINVAL;
594     }
595 }
596 
is_uv_swap(uint32_t bus_format,uint32_t output_mode)597 static bool is_uv_swap(uint32_t bus_format, uint32_t output_mode)
598 {
599     /*
600      * There is no media type for YUV444 output,
601      * so when out_mode is AAAA or P888, assume output is YUV444 on
602      * yuv format.
603      *
604      * From H/W testing, YUV444 mode need a rb swap.
605      */
606     if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 || bus_format == MEDIA_BUS_FMT_VYUY8_1X16 ||
607         bus_format == MEDIA_BUS_FMT_YVYU8_2X8 || bus_format == MEDIA_BUS_FMT_VYUY8_2X8 ||
608         ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 || bus_format == MEDIA_BUS_FMT_YUV10_1X30) &&
609          (output_mode == ROCKCHIP_OUT_MODE_AAAA || output_mode == ROCKCHIP_OUT_MODE_P888))) {
610         return true;
611     } else {
612         return false;
613     }
614 }
615 
is_yc_swap(uint32_t bus_format)616 static bool is_yc_swap(uint32_t bus_format)
617 {
618     switch (bus_format) {
619         case MEDIA_BUS_FMT_YUYV8_1X16:
620         case MEDIA_BUS_FMT_YVYU8_1X16:
621         case MEDIA_BUS_FMT_YUYV8_2X8:
622         case MEDIA_BUS_FMT_YVYU8_2X8:
623             return true;
624         default:
625             return false;
626     }
627 }
628 
is_yuv_output(uint32_t bus_format)629 static bool is_yuv_output(uint32_t bus_format)
630 {
631     switch (bus_format) {
632         case MEDIA_BUS_FMT_YUV8_1X24:
633         case MEDIA_BUS_FMT_YUV10_1X30:
634         case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
635         case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
636         case MEDIA_BUS_FMT_YUYV8_2X8:
637         case MEDIA_BUS_FMT_YVYU8_2X8:
638         case MEDIA_BUS_FMT_UYVY8_2X8:
639         case MEDIA_BUS_FMT_VYUY8_2X8:
640         case MEDIA_BUS_FMT_YUYV8_1X16:
641         case MEDIA_BUS_FMT_YVYU8_1X16:
642         case MEDIA_BUS_FMT_UYVY8_1X16:
643         case MEDIA_BUS_FMT_VYUY8_1X16:
644             return true;
645         default:
646             return false;
647     }
648 }
649 
is_yuv_support(uint32_t format)650 static bool is_yuv_support(uint32_t format)
651 {
652     switch (format) {
653         case DRM_FORMAT_NV12:
654         case DRM_FORMAT_NV15:
655         case DRM_FORMAT_NV16:
656         case DRM_FORMAT_NV20:
657         case DRM_FORMAT_NV24:
658         case DRM_FORMAT_NV30:
659         case DRM_FORMAT_YVYU:
660         case DRM_FORMAT_VYUY:
661         case DRM_FORMAT_YUYV:
662         case DRM_FORMAT_UYVY:
663             return true;
664         default:
665             return false;
666     }
667 }
668 
is_yuyv_format(uint32_t format)669 static bool is_yuyv_format(uint32_t format)
670 {
671     switch (format) {
672         case DRM_FORMAT_YVYU:
673         case DRM_FORMAT_VYUY:
674         case DRM_FORMAT_YUYV:
675         case DRM_FORMAT_UYVY:
676             return true;
677         default:
678             return false;
679     }
680 }
681 
is_yuv_10bit(uint32_t format)682 static bool is_yuv_10bit(uint32_t format)
683 {
684     switch (format) {
685         case DRM_FORMAT_NV15:
686         case DRM_FORMAT_NV20:
687         case DRM_FORMAT_NV30:
688             return true;
689         default:
690             return false;
691     }
692 }
693 
is_alpha_support(uint32_t format)694 static bool is_alpha_support(uint32_t format)
695 {
696     switch (format) {
697         case DRM_FORMAT_ARGB8888:
698         case DRM_FORMAT_ABGR8888:
699             return true;
700         default:
701             return false;
702     }
703 }
704 
rockchip_afbc(struct drm_plane * plane,u64 modifier)705 static inline bool rockchip_afbc(struct drm_plane *plane, u64 modifier)
706 {
707     int i;
708 
709     if (modifier == DRM_FORMAT_MOD_LINEAR) {
710         return false;
711     }
712 
713     for (i = 0; i < plane->modifier_count; i++) {
714         if (plane->modifiers[i] == modifier) {
715             break;
716         }
717     }
718 
719     return (i < plane->modifier_count) ? true : false;
720 }
721 
scl_vop_cal_scale(enum scale_mode mode,uint32_t src,uint32_t dst,bool is_horizontal,int vsu_mode,int * vskiplines)722 static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src, uint32_t dst, bool is_horizontal, int vsu_mode,
723                                   int *vskiplines)
724 {
725     uint16_t val = 1 << SCL_FT_DEFAULT_FIXPOINT_SHIFT;
726 
727     if (vskiplines) {
728         *vskiplines = 0;
729     }
730 
731     if (is_horizontal) {
732         if (mode == SCALE_UP) {
733             val = GET_SCL_FT_BIC(src, dst);
734         } else if (mode == SCALE_DOWN) {
735             val = GET_SCL_FT_BILI_DN(src, dst);
736         }
737     } else {
738         if (mode == SCALE_UP) {
739             if (vsu_mode == SCALE_UP_BIL) {
740                 val = GET_SCL_FT_BILI_UP(src, dst);
741             } else {
742                 val = GET_SCL_FT_BIC(src, dst);
743             }
744         } else if (mode == SCALE_DOWN) {
745             if (vskiplines) {
746                 *vskiplines = scl_get_vskiplines(src, dst);
747                 val = scl_get_bili_dn_vskip(src, dst, *vskiplines);
748             } else {
749                 val = GET_SCL_FT_BILI_DN(src, dst);
750             }
751         }
752     }
753 
754     return val;
755 }
756 
scl_vop_cal_scl_fac(struct vop * vop,const struct vop_win * win,uint32_t src_w,uint32_t src_h,uint32_t dst_w,uint32_t dst_h,uint32_t pixel_format)757 static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win *win, uint32_t src_w, uint32_t src_h,
758                                 uint32_t dst_w, uint32_t dst_h, uint32_t pixel_format)
759 {
760     uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;
761     uint16_t cbcr_hor_scl_mode = SCALE_NONE;
762     uint16_t cbcr_ver_scl_mode = SCALE_NONE;
763     const struct drm_format_info *info = drm_format_info(pixel_format);
764     uint8_t hsub = info->hsub;
765     uint8_t vsub = info->vsub;
766     bool is_yuv = false;
767     uint16_t cbcr_src_w = src_w / hsub;
768     uint16_t cbcr_src_h = src_h / vsub;
769     uint16_t vsu_mode;
770     uint16_t lb_mode;
771     uint32_t val;
772     const struct vop_data *vop_data = vop->data;
773     int vskiplines;
774 
775     if (!win->phy->scl) {
776         return;
777     }
778 
779     if (!(vop_data->feature & VOP_FEATURE_ALPHA_SCALE)) {
780         if (is_alpha_support(pixel_format) && (src_w != dst_w || src_h != dst_h)) {
781             DRM_ERROR("ERROR: unsupported ppixel alpha&scale\n");
782         }
783     }
784 
785     if (info->is_yuv) {
786         is_yuv = true;
787     }
788 
789     if (!win->phy->scl->ext) {
790         VOP_SCL_SET(vop, win, scale_yrgb_x, scl_cal_scale2(src_w, dst_w));
791         VOP_SCL_SET(vop, win, scale_yrgb_y, scl_cal_scale2(src_h, dst_h));
792         if (is_yuv) {
793             VOP_SCL_SET(vop, win, scale_cbcr_x, scl_cal_scale2(cbcr_src_w, dst_w));
794             VOP_SCL_SET(vop, win, scale_cbcr_y, scl_cal_scale2(cbcr_src_h, dst_h));
795         }
796         return;
797     }
798 
799     yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
800     yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h);
801 
802     if (is_yuv) {
803         cbcr_hor_scl_mode = scl_get_scl_mode(cbcr_src_w, dst_w);
804         cbcr_ver_scl_mode = scl_get_scl_mode(cbcr_src_h, dst_h);
805         if (cbcr_hor_scl_mode == SCALE_DOWN) {
806             lb_mode = scl_vop_cal_lb_mode(dst_w, true);
807         } else {
808             lb_mode = scl_vop_cal_lb_mode(cbcr_src_w, true);
809         }
810     } else {
811         if (yrgb_hor_scl_mode == SCALE_DOWN) {
812             lb_mode = scl_vop_cal_lb_mode(dst_w, false);
813         } else {
814             lb_mode = scl_vop_cal_lb_mode(src_w, false);
815         }
816     }
817 
818     VOP_SCL_SET_EXT(vop, win, lb_mode, lb_mode);
819     if (lb_mode == LB_RGB_3840X2) {
820         if (yrgb_ver_scl_mode != SCALE_NONE) {
821             DRM_DEV_ERROR(vop->dev, "not allow yrgb ver scale\n");
822             return;
823         }
824         if (cbcr_ver_scl_mode != SCALE_NONE) {
825             DRM_DEV_ERROR(vop->dev, "not allow cbcr ver scale\n");
826             return;
827         }
828         vsu_mode = SCALE_UP_BIL;
829     } else if (lb_mode == LB_RGB_2560X4) {
830         vsu_mode = SCALE_UP_BIL;
831     } else {
832         vsu_mode = SCALE_UP_BIC;
833     }
834 
835     val = scl_vop_cal_scale(yrgb_hor_scl_mode, src_w, dst_w, true, 0, NULL);
836     VOP_SCL_SET(vop, win, scale_yrgb_x, val);
837     val = scl_vop_cal_scale(yrgb_ver_scl_mode, src_h, dst_h, false, vsu_mode, &vskiplines);
838     VOP_SCL_SET(vop, win, scale_yrgb_y, val);
839 
840     VOP_SCL_SET_EXT(vop, win, vsd_yrgb_gt4, vskiplines == 0x4);
841     VOP_SCL_SET_EXT(vop, win, vsd_yrgb_gt2, vskiplines == 0x2);
842 
843     VOP_SCL_SET_EXT(vop, win, yrgb_hor_scl_mode, yrgb_hor_scl_mode);
844     VOP_SCL_SET_EXT(vop, win, yrgb_ver_scl_mode, yrgb_ver_scl_mode);
845     VOP_SCL_SET_EXT(vop, win, yrgb_hsd_mode, SCALE_DOWN_BIL);
846     VOP_SCL_SET_EXT(vop, win, yrgb_vsd_mode, SCALE_DOWN_BIL);
847     VOP_SCL_SET_EXT(vop, win, yrgb_vsu_mode, vsu_mode);
848     if (is_yuv) {
849         val = scl_vop_cal_scale(cbcr_hor_scl_mode, cbcr_src_w, dst_w, true, 0, NULL);
850         VOP_SCL_SET(vop, win, scale_cbcr_x, val);
851         val = scl_vop_cal_scale(cbcr_ver_scl_mode, cbcr_src_h, dst_h, false, vsu_mode, &vskiplines);
852         VOP_SCL_SET(vop, win, scale_cbcr_y, val);
853 
854         VOP_SCL_SET_EXT(vop, win, vsd_cbcr_gt4, vskiplines == 0x4);
855         VOP_SCL_SET_EXT(vop, win, vsd_cbcr_gt2, vskiplines == 0x2);
856         VOP_SCL_SET_EXT(vop, win, cbcr_hor_scl_mode, cbcr_hor_scl_mode);
857         VOP_SCL_SET_EXT(vop, win, cbcr_ver_scl_mode, cbcr_ver_scl_mode);
858         VOP_SCL_SET_EXT(vop, win, cbcr_hsd_mode, SCALE_DOWN_BIL);
859         VOP_SCL_SET_EXT(vop, win, cbcr_vsd_mode, SCALE_DOWN_BIL);
860         VOP_SCL_SET_EXT(vop, win, cbcr_vsu_mode, vsu_mode);
861     }
862 }
863 
864 /*
865  * rk3328 HDR/CSC path
866  *
867  * HDR/SDR --> win0  --> HDR2SDR ----\
868  *          \              MUX --\
869  *                 \ --> SDR2HDR/CSC--/      \
870  *                                            \
871  * SDR --> win1 -->pre_overlay ->SDR2HDR/CSC --> post_ovrlay-->post CSC-->output
872  * SDR --> win2 -/
873  *
874  */
875 
vop_hdr_atomic_check(struct drm_crtc * crtc,struct drm_crtc_state * crtc_state)876 static int vop_hdr_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state)
877 {
878     struct drm_atomic_state *state = crtc_state->state;
879     struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
880     struct drm_plane_state *pstate;
881     struct drm_plane *plane;
882     struct vop *vop = to_vop(crtc);
883     int pre_sdr2hdr_state = 0, post_sdr2hdr_state = 0;
884     int pre_sdr2hdr_mode = 0, post_sdr2hdr_mode = 0, sdr2hdr_func = 0;
885     bool pre_overlay = false;
886     int hdr2sdr_en = 0, plane_id = 0;
887 
888     if (!vop->data->hdr_table) {
889         return 0;
890     }
891     /* hdr cover */
892     drm_atomic_crtc_state_for_each_plane(plane, crtc_state)
893     {
894         struct vop_plane_state *vop_plane_state;
895         struct vop_win *win = to_vop_win(plane);
896 
897         pstate = drm_atomic_get_plane_state(state, plane);
898         if (IS_ERR(pstate)) {
899             return PTR_ERR(pstate);
900         }
901         vop_plane_state = to_vop_plane_state(pstate);
902         if (!pstate->fb) {
903             continue;
904         }
905 
906         if (vop_plane_state->eotf > s->eotf) {
907             if (win->feature & WIN_FEATURE_HDR2SDR) {
908                 hdr2sdr_en = 1;
909             }
910         }
911         if (vop_plane_state->eotf < s->eotf) {
912             if (win->feature & WIN_FEATURE_PRE_OVERLAY) {
913                 pre_sdr2hdr_state |= BIT(plane_id);
914             } else {
915                 post_sdr2hdr_state |= BIT(plane_id);
916             }
917         }
918         plane_id++;
919     }
920 
921     if (pre_sdr2hdr_state || post_sdr2hdr_state || hdr2sdr_en) {
922         pre_overlay = true;
923         pre_sdr2hdr_mode = BT709_TO_BT2020;
924         post_sdr2hdr_mode = BT709_TO_BT2020;
925         sdr2hdr_func = SDR2HDR_FOR_HDR;
926         goto exit_hdr_convert;
927     }
928 
929     /* overlay mode */
930     plane_id = 0;
931     pre_overlay = false;
932     pre_sdr2hdr_mode = 0;
933     post_sdr2hdr_mode = 0;
934     pre_sdr2hdr_state = 0;
935     post_sdr2hdr_state = 0;
936     drm_atomic_crtc_state_for_each_plane(plane, crtc_state)
937     {
938         struct vop_plane_state *vop_plane_state;
939         struct vop_win *win = to_vop_win(plane);
940 
941         pstate = drm_atomic_get_plane_state(state, plane);
942         if (IS_ERR(pstate)) {
943             return PTR_ERR(pstate);
944         }
945         vop_plane_state = to_vop_plane_state(pstate);
946         if (!pstate->fb) {
947             continue;
948         }
949 
950         if (vop_plane_state->color_space == V4L2_COLORSPACE_BT2020 && vop_plane_state->color_space > s->color_space) {
951             if (win->feature & WIN_FEATURE_PRE_OVERLAY) {
952                 pre_sdr2hdr_mode = BT2020_TO_BT709;
953                 pre_sdr2hdr_state |= BIT(plane_id);
954             } else {
955                 post_sdr2hdr_mode = BT2020_TO_BT709;
956                 post_sdr2hdr_state |= BIT(plane_id);
957             }
958         }
959         if (s->color_space == V4L2_COLORSPACE_BT2020 && vop_plane_state->color_space < s->color_space) {
960             if (win->feature & WIN_FEATURE_PRE_OVERLAY) {
961                 pre_sdr2hdr_mode = BT709_TO_BT2020;
962                 pre_sdr2hdr_state |= BIT(plane_id);
963             } else {
964                 post_sdr2hdr_mode = BT709_TO_BT2020;
965                 post_sdr2hdr_state |= BIT(plane_id);
966             }
967         }
968         plane_id++;
969     }
970 
971     if (pre_sdr2hdr_state || post_sdr2hdr_state) {
972         pre_overlay = true;
973         sdr2hdr_func = SDR2HDR_FOR_BT2020;
974     }
975 
976 exit_hdr_convert:
977     s->hdr.pre_overlay = pre_overlay;
978     s->hdr.hdr2sdr_en = hdr2sdr_en;
979     if (s->hdr.pre_overlay) {
980         s->yuv_overlay = 0;
981     }
982 
983     s->hdr.sdr2hdr_state.bt1886eotf_pre_conv_en = !!pre_sdr2hdr_state;
984     s->hdr.sdr2hdr_state.rgb2rgb_pre_conv_en = !!pre_sdr2hdr_state;
985     s->hdr.sdr2hdr_state.rgb2rgb_pre_conv_mode = pre_sdr2hdr_mode;
986     s->hdr.sdr2hdr_state.st2084oetf_pre_conv_en = !!pre_sdr2hdr_state;
987 
988     s->hdr.sdr2hdr_state.bt1886eotf_post_conv_en = !!post_sdr2hdr_state;
989     s->hdr.sdr2hdr_state.rgb2rgb_post_conv_en = !!post_sdr2hdr_state;
990     s->hdr.sdr2hdr_state.rgb2rgb_post_conv_mode = post_sdr2hdr_mode;
991     s->hdr.sdr2hdr_state.st2084oetf_post_conv_en = !!post_sdr2hdr_state;
992     s->hdr.sdr2hdr_state.sdr2hdr_func = sdr2hdr_func;
993 
994     return 0;
995 }
996 
to_vop_csc_mode(int csc_mode)997 static int to_vop_csc_mode(int csc_mode)
998 {
999     switch (csc_mode) {
1000         case V4L2_COLORSPACE_SMPTE170M:
1001         case V4L2_COLORSPACE_470_SYSTEM_M:
1002         case V4L2_COLORSPACE_470_SYSTEM_BG:
1003             return CSC_BT601L;
1004         case V4L2_COLORSPACE_REC709:
1005         case V4L2_COLORSPACE_SMPTE240M:
1006         case V4L2_COLORSPACE_DEFAULT:
1007             return CSC_BT709L;
1008         case V4L2_COLORSPACE_JPEG:
1009             return CSC_BT601F;
1010         case V4L2_COLORSPACE_BT2020:
1011             return CSC_BT2020;
1012         default:
1013             return CSC_BT709L;
1014     }
1015 }
1016 
vop_disable_all_planes(struct vop * vop)1017 static void vop_disable_all_planes(struct vop *vop)
1018 {
1019     bool active;
1020     int ret;
1021 
1022     vop_disable_allwin(vop);
1023     vop_cfg_done(vop);
1024     ret = readx_poll_timeout_atomic(vop_is_allwin_disabled, vop, active, active, 0, 0x7a120);
1025     if (ret) {
1026         dev_err(vop->dev, "wait win close timeout\n");
1027     }
1028 }
1029 
1030 /*
1031  * rk3399 colorspace path:
1032  *      Input        Win csc                     Output
1033  * 1. YUV(2020)  --> Y2R->2020To709->R2Y   --> YUV_OUTPUT(601/709)
1034  *    RGB        --> R2Y                  __/
1035  *
1036  * 2. YUV(2020)  --> bypasss               --> YUV_OUTPUT(2020)
1037  *    RGB        --> 709To2020->R2Y       __/
1038  *
1039  * 3. YUV(2020)  --> Y2R->2020To709        --> RGB_OUTPUT(709)
1040  *    RGB        --> R2Y                  __/
1041  *
1042  * 4. YUV(601/709)-> Y2R->709To2020->R2Y   --> YUV_OUTPUT(2020)
1043  *    RGB        --> 709To2020->R2Y       __/
1044  *
1045  * 5. YUV(601/709)-> bypass                --> YUV_OUTPUT(709)
1046  *    RGB        --> R2Y                  __/
1047  *
1048  * 6. YUV(601/709)-> bypass                --> YUV_OUTPUT(601)
1049  *    RGB        --> R2Y(601)             __/
1050  *
1051  * 7. YUV        --> Y2R(709)              --> RGB_OUTPUT(709)
1052  *    RGB        --> bypass               __/
1053  *
1054  * 8. RGB        --> 709To2020->R2Y        --> YUV_OUTPUT(2020)
1055  *
1056  * 9. RGB        --> R2Y(709)              --> YUV_OUTPUT(709)
1057  *
1058  * 10. RGB       --> R2Y(601)              --> YUV_OUTPUT(601)
1059  *
1060  * 11. RGB       --> bypass                --> RGB_OUTPUT(709)
1061  */
vop_setup_csc_table(const struct vop_csc_table * csc_table,bool is_input_yuv,bool is_output_yuv,int input_csc,int output_csc,const uint32_t ** y2r_table,const uint32_t ** r2r_table,const uint32_t ** r2y_table)1062 static int vop_setup_csc_table(const struct vop_csc_table *csc_table, bool is_input_yuv, bool is_output_yuv,
1063                                int input_csc, int output_csc, const uint32_t **y2r_table, const uint32_t **r2r_table,
1064                                const uint32_t **r2y_table)
1065 {
1066     *y2r_table = NULL;
1067     *r2r_table = NULL;
1068     *r2y_table = NULL;
1069 
1070     if (!csc_table) {
1071         return 0;
1072     }
1073 
1074     if (is_output_yuv) {
1075         if (output_csc == V4L2_COLORSPACE_BT2020) {
1076             if (is_input_yuv) {
1077                 if (input_csc == V4L2_COLORSPACE_BT2020) {
1078                     return 0;
1079                 }
1080                 *y2r_table = csc_table->y2r_bt709;
1081             }
1082             if (input_csc != V4L2_COLORSPACE_BT2020) {
1083                 *r2r_table = csc_table->r2r_bt709_to_bt2020;
1084             }
1085             *r2y_table = csc_table->r2y_bt2020;
1086         } else {
1087             if (is_input_yuv && input_csc == V4L2_COLORSPACE_BT2020) {
1088                 *y2r_table = csc_table->y2r_bt2020;
1089             }
1090             if (input_csc == V4L2_COLORSPACE_BT2020) {
1091                 *r2r_table = csc_table->r2r_bt2020_to_bt709;
1092             }
1093             if (!is_input_yuv || *y2r_table) {
1094                 if (output_csc == V4L2_COLORSPACE_REC709 || output_csc == V4L2_COLORSPACE_SMPTE240M ||
1095                     output_csc == V4L2_COLORSPACE_DEFAULT) {
1096                     *r2y_table = csc_table->r2y_bt709;
1097                 } else if (output_csc == V4L2_COLORSPACE_SMPTE170M || output_csc == V4L2_COLORSPACE_470_SYSTEM_M ||
1098                            output_csc == V4L2_COLORSPACE_470_SYSTEM_BG) {
1099                     *r2y_table = csc_table->r2y_bt601_12_235; /* bt601 limit */
1100                 } else {
1101                     *r2y_table = csc_table->r2y_bt601; /* bt601 full */
1102                 }
1103             }
1104         }
1105     } else {
1106         if (!is_input_yuv) {
1107             return 0;
1108         }
1109 
1110         /*
1111          * is possible use bt2020 on rgb mode?
1112          */
1113         if (WARN_ON(output_csc == V4L2_COLORSPACE_BT2020)) {
1114             return -EINVAL;
1115         }
1116 
1117         if (input_csc == V4L2_COLORSPACE_BT2020) {
1118             *y2r_table = csc_table->y2r_bt2020;
1119         } else if (input_csc == V4L2_COLORSPACE_REC709 || input_csc == V4L2_COLORSPACE_SMPTE240M ||
1120                    input_csc == V4L2_COLORSPACE_DEFAULT) {
1121             *y2r_table = csc_table->y2r_bt709;
1122         } else if (input_csc == V4L2_COLORSPACE_SMPTE170M || input_csc == V4L2_COLORSPACE_470_SYSTEM_M ||
1123                    input_csc == V4L2_COLORSPACE_470_SYSTEM_BG) {
1124             *y2r_table = csc_table->y2r_bt601_12_235; /* bt601 limit */
1125         } else {
1126             *y2r_table = csc_table->y2r_bt601; /* bt601 full */
1127         }
1128 
1129         if (input_csc == V4L2_COLORSPACE_BT2020) {
1130             /*
1131              * We don't have bt601 to bt709 table, force use bt709.
1132              */
1133             *r2r_table = csc_table->r2r_bt2020_to_bt709;
1134         }
1135     }
1136 
1137     return 0;
1138 }
1139 
vop_setup_csc_mode(bool is_input_yuv,bool is_output_yuv,int input_csc,int output_csc,bool * y2r_en,bool * r2y_en,int * csc_mode)1140 static void vop_setup_csc_mode(bool is_input_yuv, bool is_output_yuv, int input_csc, int output_csc, bool *y2r_en,
1141                                bool *r2y_en, int *csc_mode)
1142 {
1143     if (is_input_yuv && !is_output_yuv) {
1144         *y2r_en = true;
1145         *csc_mode = to_vop_csc_mode(input_csc);
1146     } else if (!is_input_yuv && is_output_yuv) {
1147         *r2y_en = true;
1148         *csc_mode = to_vop_csc_mode(output_csc);
1149     }
1150 }
1151 
vop_csc_atomic_check(struct drm_crtc * crtc,struct drm_crtc_state * crtc_state)1152 static int vop_csc_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state)
1153 {
1154     struct vop *vop = to_vop(crtc);
1155     struct drm_atomic_state *state = crtc_state->state;
1156     struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
1157     const struct vop_csc_table *csc_table = vop->data->csc_table;
1158     struct drm_plane_state *pstate;
1159     struct drm_plane *plane;
1160     bool is_input_yuv, is_output_yuv;
1161     int ret;
1162 
1163     is_output_yuv = is_yuv_output(s->bus_format);
1164 
1165     drm_atomic_crtc_state_for_each_plane(plane, crtc_state)
1166     {
1167         struct vop_plane_state *vop_plane_state;
1168         struct vop_win *win = to_vop_win(plane);
1169 
1170         pstate = drm_atomic_get_plane_state(state, plane);
1171         if (IS_ERR(pstate)) {
1172             return PTR_ERR(pstate);
1173         }
1174         vop_plane_state = to_vop_plane_state(pstate);
1175 
1176         if (!pstate->fb) {
1177             continue;
1178         }
1179         is_input_yuv = is_yuv_support(pstate->fb->format->format);
1180         vop_plane_state->y2r_en = false;
1181         vop_plane_state->r2r_en = false;
1182         vop_plane_state->r2y_en = false;
1183 
1184         ret =
1185             vop_setup_csc_table(csc_table, is_input_yuv, is_output_yuv, vop_plane_state->color_space, s->color_space,
1186                                 &vop_plane_state->y2r_table, &vop_plane_state->r2r_table, &vop_plane_state->r2y_table);
1187         if (ret) {
1188             return ret;
1189         }
1190 
1191         vop_setup_csc_mode(is_input_yuv, s->yuv_overlay, vop_plane_state->color_space, s->color_space,
1192                            &vop_plane_state->y2r_en, &vop_plane_state->r2y_en, &vop_plane_state->csc_mode);
1193 
1194         if (csc_table) {
1195             vop_plane_state->y2r_en = !!vop_plane_state->y2r_table;
1196             vop_plane_state->r2r_en = !!vop_plane_state->r2r_table;
1197             vop_plane_state->r2y_en = !!vop_plane_state->r2y_table;
1198             continue;
1199         }
1200 
1201         /*
1202          * This is update for IC design not reasonable, when enable
1203          * hdr2sdr on rk3328, vop can't support per-pixel alpha * global
1204          * alpha,so we must back to gpu, but gpu can't support hdr2sdr,
1205          * gpu output hdr UI, vop will do:
1206          * UI(rgbx) -> yuv -> rgb ->hdr2sdr -> overlay -> output.
1207          */
1208         if (s->hdr.hdr2sdr_en && vop_plane_state->eotf == HDMI_EOTF_SMPTE_ST2084 &&
1209             !is_yuv_support(pstate->fb->format->format)) {
1210             vop_plane_state->r2y_en = true;
1211         }
1212         if (win->feature & WIN_FEATURE_PRE_OVERLAY) {
1213             vop_plane_state->r2r_en = s->hdr.sdr2hdr_state.rgb2rgb_pre_conv_en;
1214         } else if (win->feature & WIN_FEATURE_HDR2SDR) {
1215             vop_plane_state->r2r_en = s->hdr.sdr2hdr_state.rgb2rgb_post_conv_en;
1216         }
1217     }
1218 
1219     return 0;
1220 }
1221 
vop_enable_debug_irq(struct drm_crtc * crtc)1222 static void vop_enable_debug_irq(struct drm_crtc *crtc)
1223 {
1224     struct vop *vop = to_vop(crtc);
1225     uint32_t irqs;
1226 
1227     irqs = BUS_ERROR_INTR | WIN0_EMPTY_INTR | WIN1_EMPTY_INTR | WIN2_EMPTY_INTR | WIN3_EMPTY_INTR | HWC_EMPTY_INTR |
1228            POST_BUF_EMPTY_INTR;
1229     VOP_INTR_SET_TYPE(vop, clear, irqs, 1);
1230     VOP_INTR_SET_TYPE(vop, enable, irqs, 1);
1231 }
1232 
vop_dsp_hold_valid_irq_enable(struct vop * vop)1233 static void vop_dsp_hold_valid_irq_enable(struct vop *vop)
1234 {
1235     unsigned long flags;
1236 
1237     if (WARN_ON(!vop->is_enabled)) {
1238         return;
1239     }
1240 
1241     spin_lock_irqsave(&vop->irq_lock, flags);
1242 
1243     VOP_INTR_SET_TYPE(vop, clear, DSP_HOLD_VALID_INTR, 1);
1244     VOP_INTR_SET_TYPE(vop, enable, DSP_HOLD_VALID_INTR, 1);
1245 
1246     spin_unlock_irqrestore(&vop->irq_lock, flags);
1247 }
1248 
vop_dsp_hold_valid_irq_disable(struct vop * vop)1249 static void vop_dsp_hold_valid_irq_disable(struct vop *vop)
1250 {
1251     unsigned long flags;
1252 
1253     if (WARN_ON(!vop->is_enabled)) {
1254         return;
1255     }
1256 
1257     spin_lock_irqsave(&vop->irq_lock, flags);
1258 
1259     VOP_INTR_SET_TYPE(vop, enable, DSP_HOLD_VALID_INTR, 0);
1260 
1261     spin_unlock_irqrestore(&vop->irq_lock, flags);
1262 }
1263 
1264 /*
1265  * (1) each frame starts at the start of the Vsync pulse which is signaled by
1266  *     the "FRAME_SYNC" interrupt.
1267  * (2) the active data region of each frame ends at dsp_vact_end
1268  * (3) we should program this same number (dsp_vact_end) into dsp_line_frag_num,
1269  *      to get "LINE_FLAG" interrupt at the end of the active on screen data.
1270  *
1271  * VOP_INTR_CTRL0.dsp_line_frag_num = VOP_DSP_VACT_ST_END.dsp_vact_end
1272  * Interrupts
1273  * LINE_FLAG -------------------------------+
1274  * FRAME_SYNC ----+                         |
1275  *                |                         |
1276  *                v                         v
1277  *                | Vsync | Vbp |  Vactive  | Vfp |
1278  *                        ^     ^           ^     ^
1279  *                        |     |           |     |
1280  *                        |     |           |     |
1281  * dsp_vs_end ------------+     |           |     |   VOP_DSP_VTOTAL_VS_END
1282  * dsp_vact_start --------------+           |     |   VOP_DSP_VACT_ST_END
1283  * dsp_vact_end ----------------------------+     |   VOP_DSP_VACT_ST_END
1284  * dsp_total -------------------------------------+   VOP_DSP_VTOTAL_VS_END
1285  */
vop_line_flag_irq_is_enabled(struct vop * vop)1286 static bool vop_line_flag_irq_is_enabled(struct vop *vop)
1287 {
1288     uint32_t line_flag_irq;
1289     unsigned long flags;
1290 
1291     spin_lock_irqsave(&vop->irq_lock, flags);
1292 
1293     line_flag_irq = VOP_INTR_GET_TYPE(vop, enable, LINE_FLAG_INTR);
1294 
1295     spin_unlock_irqrestore(&vop->irq_lock, flags);
1296 
1297     return !!line_flag_irq;
1298 }
1299 
vop_line_flag_irq_enable(struct vop * vop)1300 static void vop_line_flag_irq_enable(struct vop *vop)
1301 {
1302     unsigned long flags;
1303 
1304     if (WARN_ON(!vop->is_enabled)) {
1305         return;
1306     }
1307 
1308     spin_lock_irqsave(&vop->irq_lock, flags);
1309 
1310     VOP_INTR_SET_TYPE(vop, clear, LINE_FLAG_INTR, 1);
1311     VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 1);
1312 
1313     spin_unlock_irqrestore(&vop->irq_lock, flags);
1314 }
1315 
vop_line_flag_irq_disable(struct vop * vop)1316 static void vop_line_flag_irq_disable(struct vop *vop)
1317 {
1318     unsigned long flags;
1319 
1320     if (WARN_ON(!vop->is_enabled)) {
1321         return;
1322     }
1323 
1324     spin_lock_irqsave(&vop->irq_lock, flags);
1325 
1326     VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 0);
1327 
1328     spin_unlock_irqrestore(&vop->irq_lock, flags);
1329 }
1330 
vop_core_clks_enable(struct vop * vop)1331 static int vop_core_clks_enable(struct vop *vop)
1332 {
1333     int ret;
1334 
1335     ret = clk_enable(vop->hclk);
1336     if (ret < 0) {
1337         return ret;
1338     }
1339 
1340     ret = clk_enable(vop->aclk);
1341     if (ret < 0) {
1342         goto err_disable_hclk;
1343     }
1344 
1345     return 0;
1346 
1347 err_disable_hclk:
1348     clk_disable(vop->hclk);
1349     return ret;
1350 }
1351 
vop_core_clks_disable(struct vop * vop)1352 static void vop_core_clks_disable(struct vop *vop)
1353 {
1354     clk_disable(vop->aclk);
1355     clk_disable(vop->hclk);
1356 }
1357 
vop_crtc_load_lut(struct drm_crtc * crtc)1358 static void vop_crtc_load_lut(struct drm_crtc *crtc)
1359 {
1360     struct vop *vop = to_vop(crtc);
1361     int i, dle, lut_idx = 0;
1362 
1363     if (!vop->is_enabled || !vop->lut || !vop->lut_regs) {
1364         return;
1365     }
1366 
1367     if (WARN_ON(!drm_modeset_is_locked(&crtc->mutex))) {
1368         return;
1369     }
1370 
1371     if (!VOP_CTRL_SUPPORT(vop, update_gamma_lut)) {
1372         spin_lock(&vop->reg_lock);
1373         VOP_CTRL_SET(vop, dsp_lut_en, 0);
1374         vop_cfg_done(vop);
1375         spin_unlock(&vop->reg_lock);
1376 
1377 #define CTRL_GET(name) VOP_CTRL_GET(vop, name)
1378         readx_poll_timeout(CTRL_GET, dsp_lut_en, dle, !dle, 0x5, 0x8235);
1379     } else {
1380         lut_idx = CTRL_GET(lut_buffer_index);
1381     }
1382 
1383     for (i = 0; i < vop->lut_len; i++) {
1384         vop_write_lut(vop, i << 0x2, vop->lut[i]);
1385     }
1386 
1387     spin_lock(&vop->reg_lock);
1388 
1389     VOP_CTRL_SET(vop, dsp_lut_en, 1);
1390     VOP_CTRL_SET(vop, update_gamma_lut, 1);
1391     vop_cfg_done(vop);
1392     vop->lut_active = true;
1393 
1394     spin_unlock(&vop->reg_lock);
1395 
1396     if (VOP_CTRL_SUPPORT(vop, update_gamma_lut)) {
1397         readx_poll_timeout(CTRL_GET, lut_buffer_index, dle, dle != lut_idx, 0x5, 0x8235);
1398         /*
1399          * update_gamma value auto clean to 0 by HW, should not
1400          * bakeup it.
1401          */
1402         VOP_CTRL_SET(vop, update_gamma_lut, 0);
1403     }
1404 #undef CTRL_GET
1405 }
1406 
rockchip_vop_crtc_fb_gamma_set(struct drm_crtc * crtc,u16 red,u16 green,u16 blue,int regno)1407 static void rockchip_vop_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, int regno)
1408 {
1409     struct vop *vop = to_vop(crtc);
1410     u32 lut_len = vop->lut_len;
1411     u32 r, g, b;
1412 
1413     if (regno >= lut_len || !vop->lut) {
1414         return;
1415     }
1416 
1417     r = red * (lut_len - 1) / 0xffff;
1418     g = green * (lut_len - 1) / 0xffff;
1419     b = blue * (lut_len - 1) / 0xffff;
1420     vop->lut[regno] = r * lut_len * lut_len + g * lut_len + b;
1421 }
1422 
rockchip_vop_crtc_fb_gamma_get(struct drm_crtc * crtc,u16 * red,u16 * green,u16 * blue,int regno)1423 static void rockchip_vop_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, int regno)
1424 {
1425     struct vop *vop = to_vop(crtc);
1426     u32 lut_len = vop->lut_len;
1427     u32 r, g, b;
1428 
1429     if (regno >= lut_len || !vop->lut) {
1430         return;
1431     }
1432 
1433     r = (vop->lut[regno] / lut_len / lut_len) & (lut_len - 1);
1434     g = (vop->lut[regno] / lut_len) & (lut_len - 1);
1435     b = vop->lut[regno] & (lut_len - 1);
1436     *red = r * 0xffff / (lut_len - 1);
1437     *green = g * 0xffff / (lut_len - 1);
1438     *blue = b * 0xffff / (lut_len - 1);
1439 }
1440 
vop_crtc_legacy_gamma_set(struct drm_crtc * crtc,u16 * red,u16 * green,u16 * blue,uint32_t size,struct drm_modeset_acquire_ctx * ctx)1441 static int vop_crtc_legacy_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, uint32_t size,
1442                                      struct drm_modeset_acquire_ctx *ctx)
1443 {
1444     struct vop *vop = to_vop(crtc);
1445     int len = min(size, vop->lut_len);
1446     int i;
1447 
1448     if (!vop->lut) {
1449         return -EINVAL;
1450     }
1451 
1452     for (i = 0; i < len; i++) {
1453         rockchip_vop_crtc_fb_gamma_set(crtc, red[i], green[i], blue[i], i);
1454     }
1455 
1456     vop_crtc_load_lut(crtc);
1457 
1458     return 0;
1459 }
1460 
vop_crtc_atomic_gamma_set(struct drm_crtc * crtc,struct drm_crtc_state * old_state)1461 static int vop_crtc_atomic_gamma_set(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
1462 {
1463     struct vop *vop = to_vop(crtc);
1464     struct drm_color_lut *lut = vop->gamma_lut;
1465     unsigned int i;
1466 
1467     for (i = 0; i < vop->lut_len; i++) {
1468         rockchip_vop_crtc_fb_gamma_set(crtc, lut[i].red, lut[i].green, lut[i].blue, i);
1469     }
1470     vop_crtc_load_lut(crtc);
1471 
1472     return 0;
1473 }
1474 
vop_power_enable(struct drm_crtc * crtc)1475 static void vop_power_enable(struct drm_crtc *crtc)
1476 {
1477     struct vop *vop = to_vop(crtc);
1478     int ret;
1479 
1480     ret = clk_prepare_enable(vop->hclk);
1481     if (ret < 0) {
1482         dev_err(vop->dev, "failed to enable hclk - %d\n", ret);
1483         return;
1484     }
1485 
1486     ret = clk_prepare_enable(vop->dclk);
1487     if (ret < 0) {
1488         dev_err(vop->dev, "failed to enable dclk - %d\n", ret);
1489         goto err_disable_hclk;
1490     }
1491 
1492     ret = clk_prepare_enable(vop->aclk);
1493     if (ret < 0) {
1494         dev_err(vop->dev, "failed to enable aclk - %d\n", ret);
1495         goto err_disable_dclk;
1496     }
1497 
1498     ret = pm_runtime_get_sync(vop->dev);
1499     if (ret < 0) {
1500         dev_err(vop->dev, "failed to get pm runtime: %d\n", ret);
1501         return;
1502     }
1503 
1504     memcpy(vop->regsbak, vop->regs, vop->len);
1505 
1506     if (VOP_CTRL_SUPPORT(vop, version)) {
1507         uint32_t version = VOP_CTRL_GET(vop, version);
1508         /*
1509          * Fixup rk3288w version.
1510          */
1511         if (version && version == 0x0a05) {
1512             vop->version = VOP_VERSION(0x3, 1);
1513         }
1514     }
1515 
1516     vop->is_enabled = true;
1517 
1518     return;
1519 
1520 err_disable_dclk:
1521     clk_disable_unprepare(vop->dclk);
1522 err_disable_hclk:
1523     clk_disable_unprepare(vop->hclk);
1524 }
1525 
vop_initial(struct drm_crtc * crtc)1526 static void vop_initial(struct drm_crtc *crtc)
1527 {
1528     struct vop *vop = to_vop(crtc);
1529     int i;
1530 
1531     vop_power_enable(crtc);
1532 
1533     VOP_CTRL_SET(vop, global_regdone_en, 1);
1534     VOP_CTRL_SET(vop, dsp_blank, 0);
1535     VOP_CTRL_SET(vop, axi_outstanding_max_num, 0x1e);
1536     VOP_CTRL_SET(vop, axi_max_outstanding_en, 1);
1537     VOP_CTRL_SET(vop, dither_up_en, 1);
1538 
1539     /*
1540      * We need to make sure that all windows are disabled before resume
1541      * the crtc. Otherwise we might try to scan from a destroyed
1542      * buffer later.
1543      */
1544     for (i = 0; i < vop->num_wins; i++) {
1545         struct vop_win *win = &vop->win[i];
1546         int channel = i * 0x2 + 1;
1547 
1548         VOP_WIN_SET(vop, win, channel, ((channel + 1) << 0x4) | channel);
1549     }
1550     VOP_CTRL_SET(vop, afbdc_en, 0);
1551     vop_enable_debug_irq(crtc);
1552 }
1553 
vop_crtc_atomic_disable(struct drm_crtc * crtc,struct drm_crtc_state * old_state)1554 static void vop_crtc_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
1555 {
1556     struct vop *vop = to_vop(crtc);
1557     int sys_status = drm_crtc_index(crtc) ? SYS_STATUS_LCDC1 : SYS_STATUS_LCDC0;
1558 
1559     WARN_ON(vop->event);
1560 
1561     vop_lock(vop);
1562     VOP_CTRL_SET(vop, reg_done_frm, 1);
1563     VOP_CTRL_SET(vop, dsp_interlace, 0);
1564     drm_crtc_vblank_off(crtc);
1565     VOP_CTRL_SET(vop, out_mode, ROCKCHIP_OUT_MODE_P888);
1566     VOP_CTRL_SET(vop, afbdc_en, 0);
1567     vop_disable_all_planes(vop);
1568 
1569     /*
1570      * Vop standby will take effect at end of current frame,
1571      * if dsp hold valid irq happen, it means standby complete.
1572      *
1573      * we must wait standby complete when we want to disable aclk,
1574      * if not, memory bus maybe dead.
1575      */
1576     reinit_completion(&vop->dsp_hold_completion);
1577     vop_dsp_hold_valid_irq_enable(vop);
1578 
1579     spin_lock(&vop->reg_lock);
1580 
1581     VOP_CTRL_SET(vop, standby, 1);
1582 
1583     spin_unlock(&vop->reg_lock);
1584 
1585     WARN_ON(!wait_for_completion_timeout(&vop->dsp_hold_completion, msecs_to_jiffies(0x32)));
1586 
1587     vop_dsp_hold_valid_irq_disable(vop);
1588 
1589     vop->is_enabled = false;
1590     if (vop->is_iommu_enabled) {
1591         /*
1592          * vop standby complete, so iommu detach is safe.
1593          */
1594         VOP_CTRL_SET(vop, dma_stop, 1);
1595         rockchip_drm_dma_detach_device(vop->drm_dev, vop->dev);
1596         vop->is_iommu_enabled = false;
1597     }
1598 
1599     pm_runtime_put_sync(vop->dev);
1600     clk_disable_unprepare(vop->dclk);
1601     clk_disable_unprepare(vop->aclk);
1602     clk_disable_unprepare(vop->hclk);
1603     vop_unlock(vop);
1604 
1605     rockchip_clear_system_status(sys_status);
1606 
1607     if (crtc->state->event && !crtc->state->active) {
1608         spin_lock_irq(&crtc->dev->event_lock);
1609         drm_crtc_send_vblank_event(crtc, crtc->state->event);
1610         spin_unlock_irq(&crtc->dev->event_lock);
1611 
1612         crtc->state->event = NULL;
1613     }
1614 }
1615 
vop_plane_prepare_fb(struct drm_plane * plane,struct drm_plane_state * new_state)1616 static int vop_plane_prepare_fb(struct drm_plane *plane, struct drm_plane_state *new_state)
1617 {
1618     if (plane->state->fb) {
1619         drm_framebuffer_get(plane->state->fb);
1620     }
1621 
1622     return 0;
1623 }
1624 
vop_plane_cleanup_fb(struct drm_plane * plane,struct drm_plane_state * old_state)1625 static void vop_plane_cleanup_fb(struct drm_plane *plane, struct drm_plane_state *old_state)
1626 {
1627     if (old_state->fb) {
1628         drm_framebuffer_put(old_state->fb);
1629     }
1630 }
1631 
vop_plane_atomic_check(struct drm_plane * plane,struct drm_plane_state * state)1632 static int vop_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
1633 {
1634     struct drm_crtc *crtc = state->crtc;
1635     struct drm_crtc_state *crtc_state;
1636     struct drm_framebuffer *fb = state->fb;
1637     struct vop_win *win = to_vop_win(plane);
1638     struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
1639     const struct vop_data *vop_data;
1640     struct vop *vop;
1641     int ret;
1642     struct drm_rect *dest = &vop_plane_state->dest;
1643     struct drm_rect *src = &vop_plane_state->src;
1644     struct drm_gem_object *obj, *uv_obj;
1645     struct rockchip_gem_object *rk_obj, *rk_uv_obj;
1646     int min_scale = win->phy->scl ? FRAC_16_16(1, 0x8) : DRM_PLANE_HELPER_NO_SCALING;
1647     int max_scale = win->phy->scl ? FRAC_16_16(0x8, 1) : DRM_PLANE_HELPER_NO_SCALING;
1648     unsigned long offset;
1649     dma_addr_t dma_addr;
1650 
1651     crtc = crtc ? crtc : plane->state->crtc;
1652     if (!crtc || !fb) {
1653         plane->state->visible = false;
1654         return 0;
1655     }
1656 
1657     crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
1658     if (WARN_ON(!crtc_state)) {
1659         return -EINVAL;
1660     }
1661 
1662     src->x1 = state->src_x;
1663     src->y1 = state->src_y;
1664     src->x2 = state->src_x + state->src_w;
1665     src->y2 = state->src_y + state->src_h;
1666     dest->x1 = state->crtc_x;
1667     dest->y1 = state->crtc_y;
1668     dest->x2 = state->crtc_x + state->crtc_w;
1669     dest->y2 = state->crtc_y + state->crtc_h;
1670     vop_plane_state->zpos = state->zpos;
1671     vop_plane_state->blend_mode = state->pixel_blend_mode;
1672 
1673     ret = drm_atomic_helper_check_plane_state(state, crtc_state, min_scale, max_scale, true, true);
1674     if (ret) {
1675         return ret;
1676     }
1677 
1678     if (!state->visible) {
1679         return 0;
1680     }
1681 
1682     vop_plane_state->format = vop_convert_format(fb->format->format);
1683     if (vop_plane_state->format < 0) {
1684         return vop_plane_state->format;
1685     }
1686 
1687     vop = to_vop(crtc);
1688     vop_data = vop->data;
1689 
1690     if (state->src_w >> 0x10 < 0x4 || state->src_h >> 0x10 < 0x4 || state->crtc_w < 0x4 || state->crtc_h < 0x4) {
1691         DRM_ERROR("Invalid size: %dx%d->%dx%d, min size is 4x4\n", state->src_w >> 0x10, state->src_h >> 0x10,
1692                   state->crtc_w, state->crtc_h);
1693         return -EINVAL;
1694     }
1695 
1696     if (((drm_rect_width(src) >> 0x10) > vop_data->max_input.width) ||
1697         ((drm_rect_height(src) >> 0x10) > vop_data->max_input.height)) {
1698         DRM_ERROR("Invalid source: %dx%d. max input: %dx%d\n", drm_rect_width(src) >> 0x10,
1699                   drm_rect_height(src) >> 0x10, vop_data->max_input.width, vop_data->max_input.height);
1700         return -EINVAL;
1701     }
1702 
1703     /*
1704      * Src.x1 can be odd when do clip, but yuv plane start point
1705      * need align with 2 pixel.
1706      */
1707     if (fb->format->is_yuv && ((state->src.x1 >> 0x10) % 0x2)) {
1708         DRM_ERROR("Invalid Source: Yuv format not support odd xpos\n");
1709         return -EINVAL;
1710     }
1711 
1712     if (fb->format->is_yuv && (state->rotation & DRM_MODE_REFLECT_Y)) {
1713         DRM_ERROR("Invalid Source: Yuv format does not support this rotation\n");
1714         return -EINVAL;
1715     }
1716 
1717     offset = (src->x1 >> 0x10) * fb->format->cpp[0];
1718     vop_plane_state->offset = offset + fb->offsets[0];
1719     if (state->rotation & DRM_MODE_REFLECT_Y) {
1720         offset += ((src->y2 >> 0x10) - 1) * fb->pitches[0];
1721     } else {
1722         offset += (src->y1 >> 0x10) * fb->pitches[0];
1723     }
1724 
1725     obj = fb->obj[0];
1726     rk_obj = to_rockchip_obj(obj);
1727     vop_plane_state->yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
1728     if (fb->format->is_yuv) {
1729         int hsub = fb->format->hsub;
1730         int vsub = fb->format->vsub;
1731 
1732         offset = (src->x1 >> 0x10) * fb->format->cpp[1] / hsub;
1733         offset += (src->y1 >> 0x10) * fb->pitches[1] / vsub;
1734 
1735         uv_obj = fb->obj[1];
1736         rk_uv_obj = to_rockchip_obj(uv_obj);
1737 
1738         dma_addr = rk_uv_obj->dma_addr + offset + fb->offsets[1];
1739         vop_plane_state->uv_mst = dma_addr;
1740     }
1741 
1742     return 0;
1743 }
1744 
vop_plane_atomic_disable(struct drm_plane * plane,struct drm_plane_state * old_state)1745 static void vop_plane_atomic_disable(struct drm_plane *plane, struct drm_plane_state *old_state)
1746 {
1747     struct vop_win *win = to_vop_win(plane);
1748     struct vop *vop = to_vop(old_state->crtc);
1749 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
1750     struct vop_plane_state *vop_plane_state = to_vop_plane_state(plane->state);
1751 #endif
1752 
1753     if (!old_state->crtc) {
1754         return;
1755     }
1756 
1757     spin_lock(&vop->reg_lock);
1758 
1759     vop_win_disable(vop, win);
1760 
1761     /*
1762      * IC design bug: in the bandwidth tension environment when close win2,
1763      * vop will access the freed memory lead to iommu pagefault.
1764      * so we add this reset to workaround.
1765      */
1766     if (VOP_MAJOR(vop->version) == 0x2 && VOP_MINOR(vop->version) == 0x5 && win->win_id == 0x2) {
1767         VOP_WIN_SET(vop, win, yrgb_mst, 0);
1768     }
1769 
1770 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
1771     kfree(vop_plane_state->planlist);
1772     vop_plane_state->planlist = NULL;
1773 #endif
1774 
1775     spin_unlock(&vop->reg_lock);
1776 }
1777 
vop_plane_atomic_update(struct drm_plane * plane,struct drm_plane_state * old_state)1778 static void vop_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *old_state)
1779 {
1780     struct drm_plane_state *state = plane->state;
1781     struct drm_crtc *crtc = state->crtc;
1782     struct drm_display_mode *mode = NULL;
1783     struct vop_win *win = to_vop_win(plane);
1784     struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
1785     struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
1786     struct rockchip_crtc_state *s;
1787     struct vop *vop = to_vop(state->crtc);
1788     struct drm_framebuffer *fb = state->fb;
1789     unsigned int actual_w, actual_h, dsp_w, dsp_h;
1790     unsigned int dsp_stx, dsp_sty;
1791     uint32_t act_info, dsp_info, dsp_st;
1792     struct drm_rect *src = &vop_plane_state->src;
1793     struct drm_rect *dest = &vop_plane_state->dest;
1794     const uint32_t *y2r_table = vop_plane_state->y2r_table;
1795     const uint32_t *r2r_table = vop_plane_state->r2r_table;
1796     const uint32_t *r2y_table = vop_plane_state->r2y_table;
1797     uint32_t val;
1798     bool rb_swap, global_alpha_en;
1799     int is_yuv = fb->format->is_yuv;
1800 
1801 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
1802     bool AFBC_flag = false;
1803     struct vop_dump_list *planlist;
1804     unsigned long num_pages;
1805     struct page **pages;
1806     struct drm_gem_object *obj;
1807     struct rockchip_gem_object *rk_obj;
1808 
1809     num_pages = 0;
1810     pages = NULL;
1811     obj = fb->obj[0];
1812     rk_obj = to_rockchip_obj(obj);
1813     if (rk_obj) {
1814         num_pages = rk_obj->num_pages;
1815         pages = rk_obj->pages;
1816     }
1817     if (fb->modifier == DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16)) {
1818         AFBC_flag = true;
1819     } else {
1820         AFBC_flag = false;
1821     }
1822 #endif
1823 
1824     /*
1825      * can't update plane when vop is disabled.
1826      */
1827     if (WARN_ON(!crtc)) {
1828         return;
1829     }
1830 
1831     if (WARN_ON(!vop->is_enabled)) {
1832         return;
1833     }
1834 
1835     if (!state->visible) {
1836         vop_plane_atomic_disable(plane, old_state);
1837         return;
1838     }
1839 
1840     mode = &crtc->state->adjusted_mode;
1841     actual_w = drm_rect_width(src) >> 0x10;
1842     actual_h = drm_rect_height(src) >> 0x10;
1843 
1844     dsp_w = drm_rect_width(dest);
1845     if (dest->x1 + dsp_w > adjusted_mode->hdisplay) {
1846         DRM_ERROR("%s win%d dest->x1[%d] + dsp_w[%d] exceed mode hdisplay[%d]\n", crtc->name, win->win_id, dest->x1,
1847                   dsp_w, adjusted_mode->hdisplay);
1848         dsp_w = adjusted_mode->hdisplay - dest->x1;
1849         if (dsp_w < 0x4) {
1850             dsp_w = 0x4;
1851         }
1852         actual_w = dsp_w * actual_w / drm_rect_width(dest);
1853     }
1854     dsp_h = drm_rect_height(dest);
1855     if (dest->y1 + dsp_h > adjusted_mode->vdisplay) {
1856         DRM_ERROR("%s win%d dest->y1[%d] + dsp_h[%d] exceed mode vdisplay[%d]\n", crtc->name, win->win_id, dest->y1,
1857                   dsp_h, adjusted_mode->vdisplay);
1858         dsp_h = adjusted_mode->vdisplay - dest->y1;
1859         if (dsp_h < 0x4) {
1860             dsp_h = 0x4;
1861         }
1862         actual_h = dsp_h * actual_h / drm_rect_height(dest);
1863     }
1864 
1865     act_info = ((actual_h - 1) << 0x10) | ((actual_w - 1) & 0xffff);
1866 
1867     dsp_info = (dsp_h - 1) << 0x10;
1868     dsp_info |= (dsp_w - 1) & 0xffff;
1869 
1870     dsp_stx = dest->x1 + mode->crtc_htotal - mode->crtc_hsync_start;
1871     dsp_sty = dest->y1 + mode->crtc_vtotal - mode->crtc_vsync_start;
1872     dsp_st = (dsp_sty << 0x10) | (dsp_stx & 0xffff);
1873 
1874     s = to_rockchip_crtc_state(crtc->state);
1875     spin_lock(&vop->reg_lock);
1876 
1877     VOP_WIN_SET(vop, win, format, vop_plane_state->format);
1878     VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 0x4));
1879     VOP_WIN_SET(vop, win, yrgb_mst, vop_plane_state->yrgb_mst);
1880 
1881     VOP_WIN_SET(vop, win, ymirror, (state->rotation & DRM_MODE_REFLECT_Y) ? 1 : 0);
1882     VOP_WIN_SET(vop, win, xmirror, (state->rotation & DRM_MODE_REFLECT_X) ? 1 : 0);
1883 
1884     if (is_yuv) {
1885         VOP_WIN_SET(vop, win, uv_vir, DIV_ROUND_UP(fb->pitches[1], 0x4));
1886         VOP_WIN_SET(vop, win, uv_mst, vop_plane_state->uv_mst);
1887     }
1888     VOP_WIN_SET(vop, win, fmt_10, is_yuv_10bit(fb->format->format));
1889     VOP_WIN_SET(vop, win, fmt_yuyv, is_yuyv_format(fb->format->format));
1890 
1891     if (win->phy->scl) {
1892         scl_vop_cal_scl_fac(vop, win, actual_w, actual_h, drm_rect_width(dest), drm_rect_height(dest),
1893                             fb->format->format);
1894     }
1895 
1896     VOP_WIN_SET(vop, win, act_info, act_info);
1897     VOP_WIN_SET(vop, win, dsp_info, dsp_info);
1898     VOP_WIN_SET(vop, win, dsp_st, dsp_st);
1899 
1900     rb_swap = has_rb_swapped(fb->format->format);
1901     /*
1902      * VOP full need to do rb swap to show rgb888/bgr888 format color correctly
1903      */
1904     if ((fb->format->format == DRM_FORMAT_RGB888 || fb->format->format == DRM_FORMAT_BGR888) &&
1905         VOP_MAJOR(vop->version) == 0x3) {
1906         rb_swap = !rb_swap;
1907     }
1908     VOP_WIN_SET(vop, win, rb_swap, rb_swap);
1909 
1910     global_alpha_en = (vop_plane_state->global_alpha == 0xff) ? 0 : 1;
1911     if ((is_alpha_support(fb->format->format) || global_alpha_en) && (s->dsp_layer_sel & 0x3) != win->win_id) {
1912         int src_blend_m0;
1913 
1914         if (is_alpha_support(fb->format->format) && global_alpha_en) {
1915             src_blend_m0 = ALPHA_PER_PIX_GLOBAL;
1916         } else if (is_alpha_support(fb->format->format)) {
1917             src_blend_m0 = ALPHA_PER_PIX;
1918         } else {
1919             src_blend_m0 = ALPHA_GLOBAL;
1920         }
1921 
1922         VOP_WIN_SET(vop, win, dst_alpha_ctl, DST_FACTOR_M0(ALPHA_SRC_INVERSE));
1923         val = SRC_ALPHA_EN(1) | SRC_COLOR_M0(ALPHA_SRC_PRE_MUL) | SRC_ALPHA_M0(ALPHA_STRAIGHT) |
1924               SRC_BLEND_M0(src_blend_m0) | SRC_ALPHA_CAL_M0(ALPHA_SATURATION) |
1925               SRC_FACTOR_M0(global_alpha_en ? ALPHA_SRC_GLOBAL : ALPHA_ONE);
1926         VOP_WIN_SET(vop, win, src_alpha_ctl, val);
1927         VOP_WIN_SET(vop, win, alpha_pre_mul, vop_plane_state->blend_mode == DRM_MODE_BLEND_PREMULTI ? 1 : 0);
1928         VOP_WIN_SET(vop, win, alpha_mode, 1);
1929         VOP_WIN_SET(vop, win, alpha_en, 1);
1930     } else {
1931         VOP_WIN_SET(vop, win, src_alpha_ctl, SRC_ALPHA_EN(0));
1932         VOP_WIN_SET(vop, win, alpha_en, 0);
1933     }
1934     VOP_WIN_SET(vop, win, global_alpha_val, vop_plane_state->global_alpha);
1935 
1936     VOP_WIN_SET(vop, win, csc_mode, vop_plane_state->csc_mode);
1937     if (win->csc) {
1938         vop_load_csc_table(vop, win->csc->y2r_offset, y2r_table);
1939         vop_load_csc_table(vop, win->csc->r2r_offset, r2r_table);
1940         vop_load_csc_table(vop, win->csc->r2y_offset, r2y_table);
1941         VOP_WIN_SET_EXT(vop, win, csc, y2r_en, vop_plane_state->y2r_en);
1942         VOP_WIN_SET_EXT(vop, win, csc, r2r_en, vop_plane_state->r2r_en);
1943         VOP_WIN_SET_EXT(vop, win, csc, r2y_en, vop_plane_state->r2y_en);
1944         VOP_WIN_SET_EXT(vop, win, csc, csc_mode, vop_plane_state->csc_mode);
1945     }
1946     VOP_WIN_SET(vop, win, enable, 1);
1947     VOP_WIN_SET(vop, win, gate, 1);
1948     spin_unlock(&vop->reg_lock);
1949     /*
1950      * spi interface(vop_plane_state->yrgb_kvaddr, fb->pixel_format,
1951      * actual_w, actual_h)
1952      */
1953     vop->is_iommu_needed = true;
1954 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
1955     kfree(vop_plane_state->planlist);
1956     vop_plane_state->planlist = NULL;
1957 
1958     planlist = kmalloc(sizeof(*planlist), GFP_KERNEL);
1959     if (planlist) {
1960         planlist->dump_info.AFBC_flag = AFBC_flag;
1961         planlist->dump_info.area_id = win->area_id;
1962         planlist->dump_info.win_id = win->win_id;
1963         planlist->dump_info.yuv_format = is_yuv_support(fb->format->format);
1964         planlist->dump_info.num_pages = num_pages;
1965         planlist->dump_info.pages = pages;
1966         planlist->dump_info.offset = vop_plane_state->offset;
1967         planlist->dump_info.pitches = fb->pitches[0];
1968         planlist->dump_info.height = actual_h;
1969         planlist->dump_info.format = fb->format;
1970         list_add_tail(&planlist->entry, &vop->rockchip_crtc.vop_dump_list_head);
1971         vop_plane_state->planlist = planlist;
1972     } else {
1973         DRM_ERROR("can't alloc a node of planlist %p\n", planlist);
1974         return;
1975     }
1976     if (vop->rockchip_crtc.vop_dump_status == DUMP_KEEP || vop->rockchip_crtc.vop_dump_times > 0) {
1977         rockchip_drm_dump_plane_buffer(&planlist->dump_info, vop->rockchip_crtc.frame_count);
1978         vop->rockchip_crtc.vop_dump_times--;
1979     }
1980 #endif
1981 }
1982 
1983 static const struct drm_plane_helper_funcs plane_helper_funcs = {
1984     .prepare_fb = vop_plane_prepare_fb,
1985     .cleanup_fb = vop_plane_cleanup_fb,
1986     .atomic_check = vop_plane_atomic_check,
1987     .atomic_update = vop_plane_atomic_update,
1988     .atomic_disable = vop_plane_atomic_disable,
1989 };
1990 
1991 /**
1992  * rockchip_atomic_helper_update_plane copy from drm_atomic_helper_update_plane
1993  * be designed to support async commit at ioctl DRM_IOCTL_MODE_SETPLANE.
1994  * @plane: plane object to update
1995  * @crtc: owning CRTC of owning plane
1996  * @fb: framebuffer to flip onto plane
1997  * @crtc_x: x offset of primary plane on crtc
1998  * @crtc_y: y offset of primary plane on crtc
1999  * @crtc_w: width of primary plane rectangle on crtc
2000  * @crtc_h: height of primary plane rectangle on crtc
2001  * @src_x: x offset of @fb for panning
2002  * @src_y: y offset of @fb for panning
2003  * @src_w: width of source rectangle in @fb
2004  * @src_h: height of source rectangle in @fb
2005  * @ctx: lock acquire context
2006  *
2007  * Provides a default plane update handler using the atomic driver interface.
2008  *
2009  * RETURNS:
2010  * Zero on success, error code on failure
2011  */
rockchip_atomic_helper_update_plane(struct drm_plane * plane,struct drm_crtc * crtc,struct drm_framebuffer * fb,int crtc_x,int crtc_y,unsigned int crtc_w,unsigned int crtc_h,uint32_t src_x,uint32_t src_y,uint32_t src_w,uint32_t src_h,struct drm_modeset_acquire_ctx * ctx)2012 static int __maybe_unused rockchip_atomic_helper_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
2013                                                               struct drm_framebuffer *fb, int crtc_x, int crtc_y,
2014                                                               unsigned int crtc_w, unsigned int crtc_h, uint32_t src_x,
2015                                                               uint32_t src_y, uint32_t src_w, uint32_t src_h,
2016                                                               struct drm_modeset_acquire_ctx *ctx)
2017 {
2018     struct drm_atomic_state *state;
2019     struct drm_plane_state *plane_state;
2020     struct vop_plane_state *vop_plane_state;
2021     int ret = 0;
2022 
2023     state = drm_atomic_state_alloc(plane->dev);
2024     if (!state) {
2025         return -ENOMEM;
2026     }
2027 
2028     state->acquire_ctx = ctx;
2029     plane_state = drm_atomic_get_plane_state(state, plane);
2030     if (IS_ERR(plane_state)) {
2031         ret = PTR_ERR(plane_state);
2032         goto fail;
2033     }
2034 
2035     vop_plane_state = to_vop_plane_state(plane_state);
2036 
2037     ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
2038     if (ret != 0) {
2039         goto fail;
2040     }
2041     drm_atomic_set_fb_for_plane(plane_state, fb);
2042     plane_state->crtc_x = crtc_x;
2043     plane_state->crtc_y = crtc_y;
2044     plane_state->crtc_w = crtc_w;
2045     plane_state->crtc_h = crtc_h;
2046     plane_state->src_x = src_x;
2047     plane_state->src_y = src_y;
2048     plane_state->src_w = src_w;
2049     plane_state->src_h = src_h;
2050 
2051     if (plane == crtc->cursor || vop_plane_state->async_commit) {
2052         state->legacy_cursor_update = true;
2053     }
2054 
2055     ret = drm_atomic_commit(state);
2056 fail:
2057     drm_atomic_state_put(state);
2058     return ret;
2059 }
2060 
2061 /**
2062  * drm_atomic_helper_disable_plane copy from drm_atomic_helper_disable_plane
2063  * be designed to support async commit at ioctl DRM_IOCTL_MODE_SETPLANE.
2064  *
2065  * @plane: plane to disable
2066  * @ctx: lock acquire context
2067  *
2068  * Provides a default plane disable handler using the atomic driver interface.
2069  *
2070  * RETURNS:
2071  * Zero on success, error code on failure
2072  */
rockchip_atomic_helper_disable_plane(struct drm_plane * plane,struct drm_modeset_acquire_ctx * ctx)2073 static int __maybe_unused rockchip_atomic_helper_disable_plane(struct drm_plane *plane,
2074                                                                struct drm_modeset_acquire_ctx *ctx)
2075 {
2076     struct drm_atomic_state *state;
2077     struct drm_plane_state *plane_state;
2078     struct vop_plane_state *vop_plane_state;
2079     int ret = 0;
2080 
2081     state = drm_atomic_state_alloc(plane->dev);
2082     if (!state) {
2083         return -ENOMEM;
2084     }
2085 
2086     state->acquire_ctx = ctx;
2087     plane_state = drm_atomic_get_plane_state(state, plane);
2088     if (IS_ERR(plane_state)) {
2089         ret = PTR_ERR(plane_state);
2090         goto fail;
2091     }
2092     vop_plane_state = to_vop_plane_state(plane_state);
2093 
2094     if ((plane_state->crtc && plane_state->crtc->cursor == plane) || vop_plane_state->async_commit) {
2095         plane_state->state->legacy_cursor_update = true;
2096     }
2097 
2098     ret = __drm_atomic_helper_disable_plane(plane, plane_state);
2099     if (ret != 0) {
2100         goto fail;
2101     }
2102 
2103     ret = drm_atomic_commit(state);
2104 fail:
2105     drm_atomic_state_put(state);
2106     return ret;
2107 }
2108 
vop_plane_destroy(struct drm_plane * plane)2109 static void vop_plane_destroy(struct drm_plane *plane)
2110 {
2111     drm_plane_cleanup(plane);
2112 }
2113 
vop_atomic_plane_reset(struct drm_plane * plane)2114 static void vop_atomic_plane_reset(struct drm_plane *plane)
2115 {
2116     struct vop_plane_state *vop_plane_state = to_vop_plane_state(plane->state);
2117     struct vop_win *win = to_vop_win(plane);
2118 
2119     if (plane->state && plane->state->fb) {
2120         __drm_atomic_helper_plane_destroy_state(plane->state);
2121     }
2122     kfree(vop_plane_state);
2123     vop_plane_state = kzalloc(sizeof(*vop_plane_state), GFP_KERNEL);
2124     if (!vop_plane_state) {
2125         return;
2126     }
2127 
2128     __drm_atomic_helper_plane_reset(plane, &vop_plane_state->base);
2129     win->state.zpos = win->zpos;
2130     vop_plane_state->global_alpha = 0xff;
2131 }
2132 
vop_atomic_plane_duplicate_state(struct drm_plane * plane)2133 static struct drm_plane_state *vop_atomic_plane_duplicate_state(struct drm_plane *plane)
2134 {
2135     struct vop_plane_state *old_vop_plane_state;
2136     struct vop_plane_state *vop_plane_state;
2137 
2138     if (WARN_ON(!plane->state)) {
2139         return NULL;
2140     }
2141 
2142     old_vop_plane_state = to_vop_plane_state(plane->state);
2143     vop_plane_state = kmemdup(old_vop_plane_state, sizeof(*vop_plane_state), GFP_KERNEL);
2144     if (!vop_plane_state) {
2145         return NULL;
2146     }
2147 
2148     __drm_atomic_helper_plane_duplicate_state(plane, &vop_plane_state->base);
2149 
2150     return &vop_plane_state->base;
2151 }
2152 
vop_atomic_plane_destroy_state(struct drm_plane * plane,struct drm_plane_state * state)2153 static void vop_atomic_plane_destroy_state(struct drm_plane *plane, struct drm_plane_state *state)
2154 {
2155     struct vop_plane_state *vop_state = to_vop_plane_state(state);
2156 
2157     __drm_atomic_helper_plane_destroy_state(state);
2158 
2159     kfree(vop_state);
2160 }
2161 
vop_atomic_plane_set_property(struct drm_plane * plane,struct drm_plane_state * state,struct drm_property * property,uint64_t val)2162 static int vop_atomic_plane_set_property(struct drm_plane *plane, struct drm_plane_state *state,
2163                                          struct drm_property *property, uint64_t val)
2164 {
2165     struct rockchip_drm_private *private = plane->dev->dev_private;
2166     struct vop_win *win = to_vop_win(plane);
2167     struct vop_plane_state *plane_state = to_vop_plane_state(state);
2168 
2169     if (property == private->eotf_prop) {
2170         plane_state->eotf = val;
2171         return 0;
2172     }
2173 
2174     if (property == private->color_space_prop) {
2175         plane_state->color_space = val;
2176         return 0;
2177     }
2178 
2179     if (property == private->async_commit_prop) {
2180         plane_state->async_commit = val;
2181         return 0;
2182     }
2183 
2184     if (property == win->color_key_prop) {
2185         plane_state->color_key = val;
2186         return 0;
2187     }
2188 
2189     DRM_ERROR("failed to set vop plane property id:%d, name:%s\n", property->base.id, property->name);
2190 
2191     return -EINVAL;
2192 }
2193 
vop_atomic_plane_get_property(struct drm_plane * plane,const struct drm_plane_state * state,struct drm_property * property,uint64_t * val)2194 static int vop_atomic_plane_get_property(struct drm_plane *plane, const struct drm_plane_state *state,
2195                                          struct drm_property *property, uint64_t *val)
2196 {
2197     struct vop_plane_state *plane_state = to_vop_plane_state(state);
2198     struct vop_win *win = to_vop_win(plane);
2199     struct rockchip_drm_private *private = plane->dev->dev_private;
2200 
2201     if (property == private->eotf_prop) {
2202         *val = plane_state->eotf;
2203         return 0;
2204     }
2205 
2206     if (property == private->color_space_prop) {
2207         *val = plane_state->color_space;
2208         return 0;
2209     }
2210 
2211     if (property == private->async_commit_prop) {
2212         *val = plane_state->async_commit;
2213         return 0;
2214     }
2215 
2216     if (property == private->share_id_prop) {
2217         int i;
2218         struct drm_mode_object *obj = &plane->base;
2219 
2220         for (i = 0; i < obj->properties->count; i++) {
2221             if (obj->properties->properties[i] == property) {
2222                 *val = obj->properties->values[i];
2223                 return 0;
2224             }
2225         }
2226     }
2227 
2228     if (property == win->color_key_prop) {
2229         *val = plane_state->color_key;
2230         return 0;
2231     }
2232 
2233     DRM_ERROR("failed to get vop plane property id:%d, name:%s\n", property->base.id, property->name);
2234 
2235     return -EINVAL;
2236 }
2237 
2238 static const struct drm_plane_funcs vop_plane_funcs = {
2239     .update_plane = rockchip_atomic_helper_update_plane,
2240     .disable_plane = rockchip_atomic_helper_disable_plane,
2241     .destroy = vop_plane_destroy,
2242     .reset = vop_atomic_plane_reset,
2243     .atomic_duplicate_state = vop_atomic_plane_duplicate_state,
2244     .atomic_destroy_state = vop_atomic_plane_destroy_state,
2245     .atomic_set_property = vop_atomic_plane_set_property,
2246     .atomic_get_property = vop_atomic_plane_get_property,
2247 };
2248 
vop_crtc_enable_vblank(struct drm_crtc * crtc)2249 static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
2250 {
2251     struct vop *vop = to_vop(crtc);
2252     unsigned long flags;
2253 
2254     if (WARN_ON(!vop->is_enabled)) {
2255         return -EPERM;
2256     }
2257 
2258     spin_lock_irqsave(&vop->irq_lock, flags);
2259 
2260     if (VOP_MAJOR(vop->version) == 0x3 && VOP_MINOR(vop->version) >= 0x7) {
2261         VOP_INTR_SET_TYPE(vop, clear, FS_FIELD_INTR, 1);
2262         VOP_INTR_SET_TYPE(vop, enable, FS_FIELD_INTR, 1);
2263     } else {
2264         VOP_INTR_SET_TYPE(vop, clear, FS_INTR, 1);
2265         VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 1);
2266     }
2267 
2268     spin_unlock_irqrestore(&vop->irq_lock, flags);
2269 
2270     return 0;
2271 }
2272 
vop_crtc_disable_vblank(struct drm_crtc * crtc)2273 static void vop_crtc_disable_vblank(struct drm_crtc *crtc)
2274 {
2275     struct vop *vop = to_vop(crtc);
2276     unsigned long flags;
2277 
2278     if (WARN_ON(!vop->is_enabled)) {
2279         return;
2280     }
2281 
2282     spin_lock_irqsave(&vop->irq_lock, flags);
2283 
2284     if (VOP_MAJOR(vop->version) == 0x3 && VOP_MINOR(vop->version) >= 0x7) {
2285         VOP_INTR_SET_TYPE(vop, enable, FS_FIELD_INTR, 0);
2286     } else {
2287         VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 0);
2288     }
2289 
2290     spin_unlock_irqrestore(&vop->irq_lock, flags);
2291 }
2292 
vop_crtc_cancel_pending_vblank(struct drm_crtc * crtc,struct drm_file * file_priv)2293 static void vop_crtc_cancel_pending_vblank(struct drm_crtc *crtc, struct drm_file *file_priv)
2294 {
2295     struct drm_device *drm = crtc->dev;
2296     struct vop *vop = to_vop(crtc);
2297     struct drm_pending_vblank_event *e;
2298     unsigned long flags;
2299 
2300     spin_lock_irqsave(&drm->event_lock, flags);
2301     e = vop->event;
2302     if (e && e->base.file_priv == file_priv) {
2303         vop->event = NULL;
2304         file_priv->event_space += sizeof(e->event);
2305     }
2306     spin_unlock_irqrestore(&drm->event_lock, flags);
2307 }
2308 
vop_crtc_loader_protect(struct drm_crtc * crtc,bool on)2309 static int vop_crtc_loader_protect(struct drm_crtc *crtc, bool on)
2310 {
2311     struct rockchip_drm_private *private = crtc->dev->dev_private;
2312     struct vop *vop = to_vop(crtc);
2313     int sys_status = drm_crtc_index(crtc) ? SYS_STATUS_LCDC1 : SYS_STATUS_LCDC0;
2314 
2315     if (on == vop->loader_protect) {
2316         return 0;
2317     }
2318 
2319     if (on) {
2320         if (vop->dclk_source) {
2321             struct clk *parent;
2322 
2323             parent = clk_get_parent(vop->dclk_source);
2324             if (parent) {
2325                 if (clk_is_match(private->default_pll.pll, parent)) {
2326                     vop->pll = &private->default_pll;
2327                 } else if (clk_is_match(private->hdmi_pll.pll, parent)) {
2328                     vop->pll = &private->hdmi_pll;
2329                 }
2330                 if (vop->pll) {
2331                     vop->pll->use_count++;
2332                 }
2333             }
2334         }
2335 
2336         rockchip_set_system_status(sys_status);
2337         vop_initial(crtc);
2338         drm_crtc_vblank_on(crtc);
2339         vop->loader_protect = true;
2340     } else {
2341         vop_crtc_atomic_disable(crtc, NULL);
2342 
2343         if (vop->dclk_source && vop->pll) {
2344             vop->pll->use_count--;
2345             vop->pll = NULL;
2346         }
2347         vop->loader_protect = false;
2348     }
2349 
2350     return 0;
2351 }
2352 
2353 #define DEBUG_PRINT(args...)                                                                                       \
2354     do {                                                                                                           \
2355             pr_err(args);                                                                                          \
2356     } while (0)
2357 
2358 #define DEBUG_PRINT_S(s, args...)                                                                                  \
2359     do {                                                                                                           \
2360             seq_printf(s, args);                                                                                   \
2361     } while (0)
2362 
vop_plane_info_dump(struct seq_file * s,struct drm_plane * plane)2363 static int vop_plane_info_dump(struct seq_file *s, struct drm_plane *plane)
2364 {
2365     struct vop_win *win = to_vop_win(plane);
2366     struct drm_plane_state *state = plane->state;
2367     struct vop_plane_state *pstate = to_vop_plane_state(state);
2368     struct drm_rect *src, *dest;
2369     struct drm_framebuffer *fb = state->fb;
2370     struct drm_format_name_buf format_name;
2371     int i;
2372     struct drm_gem_object *obj;
2373     struct rockchip_gem_object *rk_obj;
2374     dma_addr_t fb_addr;
2375     u64 afbdc_format = DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16);
2376 
2377     DEBUG_PRINT("    win%d-%d: %s\n", win->win_id, win->area_id, state->crtc ? "ACTIVE" : "DISABLED");
2378     if (!fb) {
2379         return 0;
2380     }
2381 
2382     src = &pstate->src;
2383     dest = &pstate->dest;
2384 
2385     drm_get_format_name(fb->format->format, &format_name);
2386     DEBUG_PRINT("\tformat: %s%s%s[%d] color_space[%d]\n", format_name.str, fb->modifier == afbdc_format ? "[AFBC]" : "",
2387                 pstate->eotf ? " HDR" : " SDR", pstate->eotf, pstate->color_space);
2388     DEBUG_PRINT("\tcsc: y2r[%d] r2r[%d] r2y[%d] csc mode[%d]\n", pstate->y2r_en, pstate->r2r_en, pstate->r2y_en,
2389                 pstate->csc_mode);
2390     DEBUG_PRINT("\tzpos: %d\n", pstate->zpos);
2391     DEBUG_PRINT("\tsrc: pos[%dx%d] rect[%dx%d]\n", src->x1 >> 0x10, src->y1 >> 0x10, drm_rect_width(src) >> 0x10,
2392                 drm_rect_height(src) >> 0x10);
2393     DEBUG_PRINT("\tdst: pos[%dx%d] rect[%dx%d]\n", dest->x1, dest->y1, drm_rect_width(dest), drm_rect_height(dest));
2394 
2395     for (i = 0; i < fb->format->num_planes; i++) {
2396         obj = fb->obj[0];
2397         rk_obj = to_rockchip_obj(obj);
2398         fb_addr = rk_obj->dma_addr + fb->offsets[0];
2399 
2400         DEBUG_PRINT("\tbuf[%d]: addr: %pad pitch: %d offset: %d\n", i, &fb_addr, fb->pitches[i], fb->offsets[i]);
2401     }
2402 
2403     return 0;
2404 }
2405 
vop_dump_connector_on_crtc(struct drm_crtc * crtc,struct seq_file * s)2406 static void vop_dump_connector_on_crtc(struct drm_crtc *crtc, struct seq_file *s)
2407 {
2408     struct drm_connector_list_iter conn_iter;
2409     struct drm_connector *connector;
2410 
2411     drm_connector_list_iter_begin(crtc->dev, &conn_iter);
2412     drm_for_each_connector_iter(connector, &conn_iter)
2413     {
2414         if (crtc->state->connector_mask & drm_connector_mask(connector)) {
2415             DEBUG_PRINT_S(s, "    Connector: %s\n", connector->name);
2416         }
2417     }
2418     drm_connector_list_iter_end(&conn_iter);
2419 }
2420 
vop_crtc_debugfs_dump(struct drm_crtc * crtc,struct seq_file * s)2421 static int vop_crtc_debugfs_dump(struct drm_crtc *crtc, struct seq_file *s)
2422 {
2423     struct vop *vop = to_vop(crtc);
2424     struct drm_crtc_state *crtc_state = crtc->state;
2425     struct drm_display_mode *mode = &crtc->state->adjusted_mode;
2426     struct rockchip_crtc_state *state = to_rockchip_crtc_state(crtc->state);
2427     bool interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
2428     struct drm_plane *plane;
2429     int i;
2430 
2431     DEBUG_PRINT_S(s, "VOP [%s]: %s\n", dev_name(vop->dev), crtc_state->active ? "ACTIVE" : "DISABLED");
2432 
2433     if (!crtc_state->active) {
2434         return 0;
2435     }
2436 
2437     vop_dump_connector_on_crtc(crtc, s);
2438     DEBUG_PRINT_S(s, "\tbus_format[%x]: %s\n", state->bus_format, drm_get_bus_format_name(state->bus_format));
2439     DEBUG_PRINT_S(s, "\toverlay_mode[%d] output_mode[%x]", state->yuv_overlay, state->output_mode);
2440     DEBUG_PRINT_S(s, " color_space[%d]\n", state->color_space);
2441     DEBUG_PRINT_S(s, "    Display mode: %dx%d%s%d\n", mode->hdisplay, mode->vdisplay, interlaced ? "i" : "p",
2442                 drm_mode_vrefresh(mode));
2443     DEBUG_PRINT_S(s, "\tclk[%d] real_clk[%d] type[%x] flag[%x]\n", mode->clock, mode->crtc_clock, mode->type, \
2444                   mode->flags);
2445     DEBUG_PRINT_S(s, "\tH: %d %d %d %d\n", mode->hdisplay, mode->hsync_start, mode->hsync_end, mode->htotal);
2446     DEBUG_PRINT_S(s, "\tV: %d %d %d %d\n", mode->vdisplay, mode->vsync_start, mode->vsync_end, mode->vtotal);
2447 
2448     for (i = 0; i < vop->num_wins; i++) {
2449         plane = &vop->win[i].base;
2450         vop_plane_info_dump(s, plane);
2451     }
2452     DEBUG_PRINT_S(s, "    post: sdr2hdr[%d] hdr2sdr[%d]\n", state->hdr.sdr2hdr_state.bt1886eotf_post_conv_en,
2453                 state->hdr.hdr2sdr_en);
2454     DEBUG_PRINT_S(s, "    pre : sdr2hdr[%d]\n", state->hdr.sdr2hdr_state.bt1886eotf_pre_conv_en);
2455     DEBUG_PRINT_S(s, "    post CSC: r2y[%d] y2r[%d] CSC mode[%d]\n", state->post_r2y_en, state->post_y2r_en,
2456                 state->post_csc_mode);
2457 
2458     return 0;
2459 }
2460 
vop_crtc_regs_dump(struct drm_crtc * crtc,struct seq_file * s)2461 static void vop_crtc_regs_dump(struct drm_crtc *crtc, struct seq_file *s)
2462 {
2463     struct vop *vop = to_vop(crtc);
2464     struct drm_crtc_state *crtc_state = crtc->state;
2465     int dump_len = vop->len > 0x400 ? 0x400 : vop->len;
2466     int i;
2467 
2468     if (!crtc_state->active) {
2469         return;
2470     }
2471 
2472     for (i = 0; i < dump_len; i += 0x10) {
2473         DEBUG_PRINT_S(s, "0x%08x: %08x %08x %08x %08x\n", i, vop_readl(vop, i), vop_readl(vop, i + 4),
2474                     vop_readl(vop, i + 0x8), vop_readl(vop, i + 0xc));
2475     }
2476 }
2477 
vop_gamma_show(struct seq_file * s,void * data)2478 static int vop_gamma_show(struct seq_file *s, void *data)
2479 {
2480     struct drm_info_node *node = s->private;
2481     struct vop *vop = node->info_ent->data;
2482     int i;
2483 
2484     if (!vop->lut || !vop->lut_active || !vop->lut_regs) {
2485         return 0;
2486     }
2487 
2488     for (i = 0; i < vop->lut_len; i++) {
2489         if (i % 0x8 == 0) {
2490             DEBUG_PRINT_S(s, "\n");
2491         }
2492         DEBUG_PRINT_S(s, "0x%08x ", vop->lut[i]);
2493     }
2494     DEBUG_PRINT_S(s, "\n");
2495 
2496     return 0;
2497 }
2498 
2499 #undef DEBUG_PRINT
2500 #undef DEBUG_PRINT_S
2501 
2502 static struct drm_info_list vop_debugfs_files[] = {
2503     {"gamma_lut", vop_gamma_show, 0, NULL},
2504 };
2505 
vop_crtc_debugfs_init(struct drm_minor * minor,struct drm_crtc * crtc)2506 static int vop_crtc_debugfs_init(struct drm_minor *minor, struct drm_crtc *crtc)
2507 {
2508     struct vop *vop = to_vop(crtc);
2509     int ret, i;
2510 
2511     vop->debugfs = debugfs_create_dir(dev_name(vop->dev), minor->debugfs_root);
2512 
2513     if (!vop->debugfs) {
2514         return -ENOMEM;
2515     }
2516 
2517     vop->debugfs_files = kmemdup(vop_debugfs_files, sizeof(vop_debugfs_files), GFP_KERNEL);
2518     if (!vop->debugfs_files) {
2519         ret = -ENOMEM;
2520         goto remove;
2521     }
2522 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
2523     rockchip_drm_add_dump_buffer(crtc, vop->debugfs);
2524 #endif
2525     for (i = 0; i < ARRAY_SIZE(vop_debugfs_files); i++) {
2526         vop->debugfs_files[i].data = vop;
2527     }
2528 
2529     drm_debugfs_create_files(vop->debugfs_files, ARRAY_SIZE(vop_debugfs_files), vop->debugfs, minor);
2530 
2531     return 0;
2532 remove:
2533     debugfs_remove(vop->debugfs);
2534     vop->debugfs = NULL;
2535     return ret;
2536 }
2537 
vop_crtc_mode_valid(struct drm_crtc * crtc,const struct drm_display_mode * mode,int output_type)2538 static enum drm_mode_status vop_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode,
2539                                                 int output_type)
2540 {
2541     struct vop *vop = to_vop(crtc);
2542     const struct vop_data *vop_data = vop->data;
2543     int request_clock = mode->clock;
2544     int clock;
2545 
2546     if (mode->hdisplay > vop_data->max_output.width) {
2547         return MODE_BAD_HVALUE;
2548     }
2549 
2550     if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && VOP_MAJOR(vop->version) == 0x3 && VOP_MINOR(vop->version) <= 0x2) {
2551         return MODE_BAD;
2552     }
2553 
2554     if (mode->flags & DRM_MODE_FLAG_DBLCLK) {
2555         request_clock *= 0x2;
2556     }
2557     clock = clk_round_rate(vop->dclk, request_clock * 0x3e8) / 0x3e8;
2558 
2559     /*
2560      * Hdmi or DisplayPort request a Accurate clock.
2561      */
2562     if (output_type == DRM_MODE_CONNECTOR_HDMIA || output_type == DRM_MODE_CONNECTOR_DisplayPort) {
2563         if (clock != request_clock) {
2564             return MODE_CLOCK_RANGE;
2565         }
2566     }
2567 
2568     return MODE_OK;
2569 }
2570 
2571 struct vop_bandwidth {
2572     size_t bandwidth;
2573     int y1;
2574     int y2;
2575 };
2576 
vop_bandwidth_cmp(const void * a,const void * b)2577 static int vop_bandwidth_cmp(const void *a, const void *b)
2578 {
2579     struct vop_bandwidth *pa = (struct vop_bandwidth *)a;
2580     struct vop_bandwidth *pb = (struct vop_bandwidth *)b;
2581 
2582     return pa->y1 - pb->y2;
2583 }
2584 
vop_plane_line_bandwidth(struct drm_plane_state * pstate)2585 static size_t vop_plane_line_bandwidth(struct drm_plane_state *pstate)
2586 {
2587     struct vop_plane_state *vop_plane_state = to_vop_plane_state(pstate);
2588     struct vop_win *win = to_vop_win(pstate->plane);
2589     struct drm_crtc *crtc = pstate->crtc;
2590     struct vop *vop = to_vop(crtc);
2591     struct drm_framebuffer *fb = pstate->fb;
2592     struct drm_rect *dest = &vop_plane_state->dest;
2593     struct drm_rect *src = &vop_plane_state->src;
2594     int bpp = fb->format->cpp[0] << 0x3;
2595     int src_width = drm_rect_width(src) >> 0x10;
2596     int src_height = drm_rect_height(src) >> 0x10;
2597     int dest_width = drm_rect_width(dest);
2598     int dest_height = drm_rect_height(dest);
2599     int vskiplines = scl_get_vskiplines(src_height, dest_height);
2600     size_t bandwidth;
2601 
2602     if (src_width <= 0 || src_height <= 0 || dest_width <= 0 || dest_height <= 0) {
2603         return 0;
2604     }
2605     bandwidth = src_width * bpp / 0x8;
2606 
2607     if (dest_width == 0 || dest_height == 0) {
2608         return 0;
2609     }
2610     bandwidth = bandwidth * src_width / dest_width;
2611     bandwidth = bandwidth * src_height / dest_height;
2612     if (vskiplines == 0x2 && VOP_WIN_SCL_EXT_SUPPORT(vop, win, vsd_yrgb_gt2)) {
2613         bandwidth /= 0x2;
2614     } else if (vskiplines == 0x4 && VOP_WIN_SCL_EXT_SUPPORT(vop, win, vsd_yrgb_gt4)) {
2615         bandwidth /= 0x4;
2616     }
2617 
2618     return bandwidth;
2619 }
2620 
vop_calc_max_bandwidth(struct vop_bandwidth * bw,int start,int count,int y2)2621 static u64 vop_calc_max_bandwidth(struct vop_bandwidth *bw, int start, int count, int y2)
2622 {
2623     u64 max_bandwidth = 0;
2624     int i;
2625 
2626     for (i = start; i < count; i++) {
2627         u64 bandwidth = 0;
2628 
2629         if (bw[i].y1 > y2) {
2630             continue;
2631         }
2632         bandwidth = bw[i].bandwidth;
2633         bandwidth += vop_calc_max_bandwidth(bw, i + 1, count, min(bw[i].y2, y2));
2634         if (bandwidth > max_bandwidth) {
2635             max_bandwidth = bandwidth;
2636         }
2637     }
2638 
2639     return max_bandwidth;
2640 }
2641 
vop_crtc_bandwidth(struct drm_crtc * crtc,struct drm_crtc_state * crtc_state,struct dmcfreq_vop_info * vop_bw_info)2642 static size_t vop_crtc_bandwidth(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state,
2643                                  struct dmcfreq_vop_info *vop_bw_info)
2644 {
2645     struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
2646     u16 htotal = adjusted_mode->crtc_htotal;
2647     u16 vdisplay = adjusted_mode->crtc_vdisplay;
2648     int clock = adjusted_mode->crtc_clock;
2649     struct vop_plane_state *vop_plane_state;
2650     struct drm_plane_state *pstate;
2651     struct vop_bandwidth *pbandwidth;
2652     struct drm_plane *plane;
2653     u64 line_bw_mbyte = 0;
2654     int cnt = 0, plane_num = 0;
2655     struct drm_atomic_state *state = crtc_state->state;
2656 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
2657     struct vop_dump_list *pos, *n;
2658     struct vop *vop = to_vop(crtc);
2659 #endif
2660 
2661     if (!htotal || !vdisplay) {
2662         return 0;
2663     }
2664 
2665 #if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
2666     if (!vop->rockchip_crtc.vop_dump_list_init_flag) {
2667         INIT_LIST_HEAD(&vop->rockchip_crtc.vop_dump_list_head);
2668         vop->rockchip_crtc.vop_dump_list_init_flag = true;
2669     }
2670     list_for_each_entry_safe(pos, n, &vop->rockchip_crtc.vop_dump_list_head, entry)
2671     {
2672         list_del(&pos->entry);
2673     }
2674     if (vop->rockchip_crtc.vop_dump_status == DUMP_KEEP || vop->rockchip_crtc.vop_dump_times > 0) {
2675         vop->rockchip_crtc.frame_count++;
2676     }
2677 #endif
2678 
2679     drm_atomic_crtc_state_for_each_plane(plane, crtc_state) plane_num++;
2680 
2681     vop_bw_info->plane_num += plane_num;
2682     pbandwidth = kmalloc_array(plane_num, sizeof(*pbandwidth), GFP_KERNEL);
2683     if (!pbandwidth) {
2684         return -ENOMEM;
2685     }
2686 
2687     drm_atomic_crtc_state_for_each_plane(plane, crtc_state)
2688     {
2689         int act_w, act_h, cpp, afbc_fac;
2690 
2691         pstate = drm_atomic_get_existing_plane_state(state, plane);
2692         if (pstate->crtc != crtc || !pstate->fb) {
2693             continue;
2694         }
2695 
2696         /* This is an empirical value, if it's afbc format, the frame buffer size div 2 */
2697         afbc_fac = rockchip_afbc(plane, pstate->fb->modifier) ? 2 : 1;
2698 
2699         vop_plane_state = to_vop_plane_state(pstate);
2700         pbandwidth[cnt].y1 = vop_plane_state->dest.y1;
2701         pbandwidth[cnt].y2 = vop_plane_state->dest.y2;
2702         pbandwidth[cnt++].bandwidth = vop_plane_line_bandwidth(pstate) / afbc_fac;
2703 
2704         act_w = drm_rect_width(&pstate->src) >> 0x10;
2705         act_h = drm_rect_height(&pstate->src) >> 0x10;
2706         cpp = pstate->fb->format->cpp[0];
2707 
2708         vop_bw_info->frame_bw_mbyte += act_w * act_h / 0x3e8 * cpp * drm_mode_vrefresh(adjusted_mode) / 0x3e8;
2709     }
2710 
2711     sort(pbandwidth, cnt, sizeof(pbandwidth[0]), vop_bandwidth_cmp, NULL);
2712 
2713     vop_bw_info->line_bw_mbyte = vop_calc_max_bandwidth(pbandwidth, 0, cnt, vdisplay);
2714     kfree(pbandwidth);
2715     /*
2716      * line_bandwidth(MB/s)
2717      *    = line_bandwidth / line_time
2718      *    = line_bandwidth(Byte) * clock(KHZ) / 1000 / htotal
2719      */
2720     line_bw_mbyte *= clock;
2721     do_div(line_bw_mbyte, htotal * 0x3e8);
2722     vop_bw_info->line_bw_mbyte = line_bw_mbyte;
2723 
2724     return vop_bw_info->line_bw_mbyte;
2725 }
2726 
vop_crtc_close(struct drm_crtc * crtc)2727 static void vop_crtc_close(struct drm_crtc *crtc)
2728 {
2729     struct vop *vop = NULL;
2730 
2731     if (!crtc) {
2732         return;
2733     }
2734     vop = to_vop(crtc);
2735     mutex_lock(&vop->vop_lock);
2736     if (!vop->is_enabled) {
2737         mutex_unlock(&vop->vop_lock);
2738         return;
2739     }
2740 
2741     vop_disable_all_planes(vop);
2742     mutex_unlock(&vop->vop_lock);
2743 }
2744 
vop_mode_done(struct vop * vop)2745 static u32 vop_mode_done(struct vop *vop)
2746 {
2747     return VOP_CTRL_GET(vop, out_mode);
2748 }
2749 
vop_set_out_mode(struct vop * vop,u32 mode)2750 static void vop_set_out_mode(struct vop *vop, u32 mode)
2751 {
2752     int ret;
2753     u32 val;
2754 
2755     VOP_CTRL_SET(vop, out_mode, mode);
2756     vop_cfg_done(vop);
2757     ret = readx_poll_timeout(vop_mode_done, vop, val, val == mode, 0x3e8, 0x1f4 * 0x3e8);
2758     if (ret) {
2759         dev_err(vop->dev, "wait mode 0x%x timeout\n", mode);
2760     }
2761 }
2762 
vop_crtc_send_mcu_cmd(struct drm_crtc * crtc,u32 type,u32 value)2763 static void vop_crtc_send_mcu_cmd(struct drm_crtc *crtc, u32 type, u32 value)
2764 {
2765     struct rockchip_crtc_state *state;
2766     struct vop *vop = NULL;
2767 
2768     if (!crtc) {
2769         return;
2770     }
2771 
2772     vop = to_vop(crtc);
2773     state = to_rockchip_crtc_state(crtc->state);
2774 
2775     /*
2776      * set output mode to P888 when start send cmd.
2777      */
2778     if ((type == MCU_SETBYPASS) && value) {
2779         vop_set_out_mode(vop, ROCKCHIP_OUT_MODE_P888);
2780     }
2781     mutex_lock(&vop->vop_lock);
2782     if (vop && vop->is_enabled) {
2783         switch (type) {
2784             case MCU_WRCMD:
2785                 VOP_CTRL_SET(vop, mcu_rs, 0);
2786                 VOP_CTRL_SET(vop, mcu_rw_bypass_port, value);
2787                 VOP_CTRL_SET(vop, mcu_rs, 1);
2788                 break;
2789             case MCU_WRDATA:
2790                 VOP_CTRL_SET(vop, mcu_rs, 1);
2791                 VOP_CTRL_SET(vop, mcu_rw_bypass_port, value);
2792                 break;
2793             case MCU_SETBYPASS:
2794                 VOP_CTRL_SET(vop, mcu_bypass, value ? 1 : 0);
2795                 break;
2796             default:
2797                 break;
2798         }
2799     }
2800     mutex_unlock(&vop->vop_lock);
2801 
2802     /*
2803      * restore output mode at the end
2804      */
2805     if ((type == MCU_SETBYPASS) && !value) {
2806         vop_set_out_mode(vop, state->output_mode);
2807     }
2808 }
2809 
2810 static const struct rockchip_crtc_funcs private_crtc_funcs = {
2811     .loader_protect = vop_crtc_loader_protect,
2812     .cancel_pending_vblank = vop_crtc_cancel_pending_vblank,
2813     .debugfs_init = vop_crtc_debugfs_init,
2814     .debugfs_dump = vop_crtc_debugfs_dump,
2815     .regs_dump = vop_crtc_regs_dump,
2816     .mode_valid = vop_crtc_mode_valid,
2817     .bandwidth = vop_crtc_bandwidth,
2818     .crtc_close = vop_crtc_close,
2819     .crtc_send_mcu_cmd = vop_crtc_send_mcu_cmd,
2820 };
2821 
vop_crtc_mode_fixup(struct drm_crtc * crtc,const struct drm_display_mode * mode,struct drm_display_mode * adj_mode)2822 static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode,
2823                                 struct drm_display_mode *adj_mode)
2824 {
2825     struct vop *vop = to_vop(crtc);
2826     const struct vop_data *vop_data = vop->data;
2827 
2828     if (mode->hdisplay > vop_data->max_output.width) {
2829         return false;
2830     }
2831 
2832     drm_mode_set_crtcinfo(adj_mode, CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE);
2833 
2834     if (mode->flags & DRM_MODE_FLAG_DBLCLK) {
2835         adj_mode->crtc_clock *= 0x2;
2836     }
2837 
2838     adj_mode->crtc_clock = DIV_ROUND_UP(clk_round_rate(vop->dclk, adj_mode->crtc_clock * 0x3e8), 0x3e8);
2839 
2840     return true;
2841 }
2842 
vop_dither_setup(struct drm_crtc * crtc)2843 static void vop_dither_setup(struct drm_crtc *crtc)
2844 {
2845     struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
2846     struct vop *vop = to_vop(crtc);
2847 
2848     /*
2849      * VOP MCU interface can't work right when dither enabled.
2850      * (1) the MCU CMD will be treated as data then changed by dither algorithm
2851      * (2) the dither algorithm works wrong in mcu mode
2852      */
2853     if (vop->mcu_timing.mcu_pix_total) {
2854         return;
2855     }
2856 
2857     switch (s->bus_format) {
2858         case MEDIA_BUS_FMT_RGB565_1X16:
2859             VOP_CTRL_SET(vop, dither_down_en, 1);
2860             VOP_CTRL_SET(vop, dither_down_mode, RGB888_TO_RGB565);
2861             break;
2862         case MEDIA_BUS_FMT_RGB666_1X18:
2863         case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
2864         case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
2865             VOP_CTRL_SET(vop, dither_down_en, 1);
2866             VOP_CTRL_SET(vop, dither_down_mode, RGB888_TO_RGB666);
2867             break;
2868         case MEDIA_BUS_FMT_YUV8_1X24:
2869         case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
2870             VOP_CTRL_SET(vop, dither_down_en, 0);
2871             VOP_CTRL_SET(vop, pre_dither_down_en, 1);
2872             break;
2873         case MEDIA_BUS_FMT_YUV10_1X30:
2874         case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
2875             VOP_CTRL_SET(vop, dither_down_en, 0);
2876             VOP_CTRL_SET(vop, pre_dither_down_en, 0);
2877             break;
2878         case MEDIA_BUS_FMT_RGB888_3X8:
2879         case MEDIA_BUS_FMT_RGB888_DUMMY_4X8:
2880         case MEDIA_BUS_FMT_RGB888_1X24:
2881         case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
2882         case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
2883         default:
2884             VOP_CTRL_SET(vop, dither_down_en, 0);
2885             VOP_CTRL_SET(vop, pre_dither_down_en, 0);
2886             break;
2887     }
2888 
2889     VOP_CTRL_SET(vop, pre_dither_down_en, s->output_mode == ROCKCHIP_OUT_MODE_AAAA ? 0 : 1);
2890     VOP_CTRL_SET(vop, dither_down_sel, DITHER_DOWN_ALLEGRO);
2891 }
2892 
vop_update_csc(struct drm_crtc * crtc)2893 static void vop_update_csc(struct drm_crtc *crtc)
2894 {
2895     struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
2896     struct vop *vop = to_vop(crtc);
2897     u32 val;
2898 
2899     if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA && !(vop->data->feature & VOP_FEATURE_OUTPUT_10BIT)) {
2900         s->output_mode = ROCKCHIP_OUT_MODE_P888;
2901     }
2902 
2903     if (is_uv_swap(s->bus_format, s->output_mode)) {
2904         VOP_CTRL_SET(vop, dsp_data_swap, DSP_RB_SWAP);
2905     } else {
2906         VOP_CTRL_SET(vop, dsp_data_swap, 0);
2907     }
2908 
2909     VOP_CTRL_SET(vop, out_mode, s->output_mode);
2910 
2911     vop_dither_setup(crtc);
2912     VOP_CTRL_SET(vop, dclk_ddr, s->output_mode == ROCKCHIP_OUT_MODE_YUV420 ? 1 : 0);
2913     VOP_CTRL_SET(vop, hdmi_dclk_out_en, s->output_mode == ROCKCHIP_OUT_MODE_YUV420 ? 1 : 0);
2914 
2915     VOP_CTRL_SET(vop, overlay_mode, s->yuv_overlay);
2916     VOP_CTRL_SET(vop, dsp_out_yuv, is_yuv_output(s->bus_format));
2917 
2918     /*
2919      * Background color is 10bit depth if vop version >= 3.5
2920      */
2921     if (!is_yuv_output(s->bus_format)) {
2922         val = 0;
2923     } else if (VOP_MAJOR(vop->version) == 0x3 && VOP_MINOR(vop->version) == 0x8 && s->hdr.pre_overlay) {
2924         val = 0;
2925     } else if (VOP_MAJOR(vop->version) == 0x3 && VOP_MINOR(vop->version) >= 0x5) {
2926         val = 0x20010200;
2927     } else {
2928         val = 0x801080;
2929     }
2930     VOP_CTRL_SET(vop, dsp_background, val);
2931 }
2932 
2933 /*
2934  * if adjusted mode update, return true, else return false
2935  */
vop_crtc_mode_update(struct drm_crtc * crtc)2936 static bool vop_crtc_mode_update(struct drm_crtc *crtc)
2937 {
2938     struct vop *vop = to_vop(crtc);
2939     struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
2940     u16 hsync_len = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
2941     u16 hdisplay = adjusted_mode->crtc_hdisplay;
2942     u16 htotal = adjusted_mode->crtc_htotal;
2943     u16 hact_st = adjusted_mode->crtc_htotal - adjusted_mode->crtc_hsync_start;
2944     u16 hact_end = hact_st + hdisplay;
2945     u16 vdisplay = adjusted_mode->crtc_vdisplay;
2946     u16 vtotal = adjusted_mode->crtc_vtotal;
2947     u16 vsync_len = adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start;
2948     u16 vact_st = adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vsync_start;
2949     u16 vact_end = vact_st + vdisplay;
2950     u32 htotal_sync = (htotal << 0x10) | hsync_len;
2951     u32 hactive_st_end = (hact_st << 0x10) | hact_end;
2952     u32 vtotal_sync = (vtotal << 0x10) | vsync_len;
2953     u32 vactive_st_end = (vact_st << 0x10) | vact_end;
2954     u32 crtc_clock = adjusted_mode->crtc_clock * 0x64;
2955 
2956     if (htotal_sync != VOP_CTRL_GET(vop, htotal_pw) || hactive_st_end != VOP_CTRL_GET(vop, hact_st_end) ||
2957         vtotal_sync != VOP_CTRL_GET(vop, vtotal_pw) || vactive_st_end != VOP_CTRL_GET(vop, vact_st_end) ||
2958         crtc_clock != clk_get_rate(vop->dclk)) {
2959         return true;
2960     }
2961 
2962     return false;
2963 }
2964 
vop_mcu_mode(struct drm_crtc * crtc)2965 static void vop_mcu_mode(struct drm_crtc *crtc)
2966 {
2967     struct vop *vop = to_vop(crtc);
2968 
2969     VOP_CTRL_SET(vop, mcu_clk_sel, 1);
2970     VOP_CTRL_SET(vop, mcu_type, 1);
2971 
2972     VOP_CTRL_SET(vop, mcu_hold_mode, 1);
2973     VOP_CTRL_SET(vop, mcu_pix_total, vop->mcu_timing.mcu_pix_total);
2974     VOP_CTRL_SET(vop, mcu_cs_pst, vop->mcu_timing.mcu_cs_pst);
2975     VOP_CTRL_SET(vop, mcu_cs_pend, vop->mcu_timing.mcu_cs_pend);
2976     VOP_CTRL_SET(vop, mcu_rw_pst, vop->mcu_timing.mcu_rw_pst);
2977     VOP_CTRL_SET(vop, mcu_rw_pend, vop->mcu_timing.mcu_rw_pend);
2978 }
2979 
vop_crtc_atomic_enable(struct drm_crtc * crtc,struct drm_crtc_state * old_state)2980 static void vop_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
2981 {
2982     struct vop *vop = to_vop(crtc);
2983     struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
2984     struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
2985     u16 hsync_len = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
2986     u16 hdisplay = adjusted_mode->crtc_hdisplay;
2987     u16 htotal = adjusted_mode->crtc_htotal;
2988     u16 hact_st = adjusted_mode->crtc_htotal - adjusted_mode->crtc_hsync_start;
2989     u16 hact_end = hact_st + hdisplay;
2990     u16 vdisplay = adjusted_mode->crtc_vdisplay;
2991     u16 vtotal = adjusted_mode->crtc_vtotal;
2992     u16 vsync_len = adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start;
2993     u16 vact_st = adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vsync_start;
2994     u16 vact_end = vact_st + vdisplay;
2995     int sys_status = drm_crtc_index(crtc) ? SYS_STATUS_LCDC1 : SYS_STATUS_LCDC0;
2996     uint32_t val;
2997     int act_end;
2998     bool interlaced = !!(adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE);
2999     int for_ddr_freq = 0;
3000     bool dclk_inv, yc_swap = false;
3001 
3002     rockchip_set_system_status(sys_status);
3003     vop_lock(vop);
3004     DRM_DEV_INFO(vop->dev, "Update mode to %dx%d%s%d, type: %d\n", hdisplay, vdisplay, interlaced ? "i" : "p",
3005                  drm_mode_vrefresh(adjusted_mode), s->output_type);
3006     vop_initial(crtc);
3007     vop_disable_allwin(vop);
3008     VOP_CTRL_SET(vop, standby, 0);
3009     s->mode_update = vop_crtc_mode_update(crtc);
3010     if (s->mode_update) {
3011         vop_disable_all_planes(vop);
3012     }
3013     /*
3014      * restore the lut table.
3015      */
3016     if (vop->lut_active) {
3017         vop_crtc_load_lut(crtc);
3018     }
3019 
3020     if (vop->mcu_timing.mcu_pix_total) {
3021         vop_mcu_mode(crtc);
3022     }
3023 
3024     dclk_inv = (s->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
3025 
3026     VOP_CTRL_SET(vop, dclk_pol, dclk_inv);
3027     val = (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
3028     val |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3029     VOP_CTRL_SET(vop, pin_pol, val);
3030 
3031     if (vop->dclk_source && vop->pll && vop->pll->pll) {
3032         if (clk_set_parent(vop->dclk_source, vop->pll->pll)) {
3033             DRM_DEV_ERROR(vop->dev, "failed to set dclk's parents\n");
3034         }
3035     }
3036 
3037     switch (s->output_type) {
3038         case DRM_MODE_CONNECTOR_DPI:
3039         case DRM_MODE_CONNECTOR_LVDS:
3040             VOP_CTRL_SET(vop, rgb_en, 1);
3041             VOP_CTRL_SET(vop, rgb_pin_pol, val);
3042             VOP_CTRL_SET(vop, rgb_dclk_pol, dclk_inv);
3043             VOP_CTRL_SET(vop, lvds_en, 1);
3044             VOP_CTRL_SET(vop, lvds_pin_pol, val);
3045             VOP_CTRL_SET(vop, lvds_dclk_pol, dclk_inv);
3046             VOP_GRF_SET(vop, grf_dclk_inv, dclk_inv);
3047             if (s->output_if & VOP_OUTPUT_IF_BT1120) {
3048                 VOP_CTRL_SET(vop, bt1120_en, 1);
3049                 yc_swap = is_yc_swap(s->bus_format);
3050                 VOP_CTRL_SET(vop, bt1120_yc_swap, yc_swap);
3051                 VOP_CTRL_SET(vop, yuv_clip, 1);
3052             }
3053             break;
3054         case DRM_MODE_CONNECTOR_eDP:
3055             VOP_CTRL_SET(vop, edp_en, 1);
3056             VOP_CTRL_SET(vop, edp_pin_pol, val);
3057             VOP_CTRL_SET(vop, edp_dclk_pol, dclk_inv);
3058             break;
3059         case DRM_MODE_CONNECTOR_HDMIA:
3060             VOP_CTRL_SET(vop, hdmi_en, 1);
3061             VOP_CTRL_SET(vop, hdmi_pin_pol, val);
3062             VOP_CTRL_SET(vop, hdmi_dclk_pol, 1);
3063             break;
3064         case DRM_MODE_CONNECTOR_DSI:
3065             VOP_CTRL_SET(vop, mipi_en, 1);
3066             VOP_CTRL_SET(vop, mipi_pin_pol, val);
3067             VOP_CTRL_SET(vop, mipi_dclk_pol, dclk_inv);
3068             VOP_CTRL_SET(vop, mipi_dual_channel_en, !!(s->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE));
3069             VOP_CTRL_SET(vop, data01_swap, !!(s->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) || vop->dual_channel_swap);
3070             break;
3071         case DRM_MODE_CONNECTOR_DisplayPort:
3072             VOP_CTRL_SET(vop, dp_dclk_pol, 0);
3073             VOP_CTRL_SET(vop, dp_pin_pol, val);
3074             VOP_CTRL_SET(vop, dp_en, 1);
3075             break;
3076         case DRM_MODE_CONNECTOR_TV:
3077             if (vdisplay == CVBS_PAL_VDISPLAY) {
3078                 VOP_CTRL_SET(vop, tve_sw_mode, 1);
3079             } else {
3080                 VOP_CTRL_SET(vop, tve_sw_mode, 0);
3081             }
3082 
3083             VOP_CTRL_SET(vop, tve_dclk_pol, 1);
3084             VOP_CTRL_SET(vop, tve_dclk_en, 1);
3085             /* use the same pol reg with hdmi */
3086             VOP_CTRL_SET(vop, hdmi_pin_pol, val);
3087             VOP_CTRL_SET(vop, sw_genlock, 1);
3088             VOP_CTRL_SET(vop, sw_uv_offset_en, 1);
3089             VOP_CTRL_SET(vop, dither_up_en, 1);
3090             break;
3091         default:
3092             DRM_ERROR("unsupported connector_type[%d]\n", s->output_type);
3093     }
3094     vop_update_csc(crtc);
3095     VOP_CTRL_SET(vop, htotal_pw, (htotal << 0x10) | hsync_len);
3096     val = hact_st << 0x10;
3097     val |= hact_end;
3098     VOP_CTRL_SET(vop, hact_st_end, val);
3099     VOP_CTRL_SET(vop, hpost_st_end, val);
3100 
3101     val = vact_st << 0x10;
3102     val |= vact_end;
3103     VOP_CTRL_SET(vop, vact_st_end, val);
3104     VOP_CTRL_SET(vop, vpost_st_end, val);
3105 
3106     if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
3107         u16 vact_st_f1 = vtotal + vact_st + 1;
3108         u16 vact_end_f1 = vact_st_f1 + vdisplay;
3109 
3110         val = (vact_st_f1 << 0x10) | vact_end_f1;
3111         VOP_CTRL_SET(vop, vact_st_end_f1, val);
3112         VOP_CTRL_SET(vop, vpost_st_end_f1, val);
3113 
3114         val = (vtotal << 0x10) | (vtotal + vsync_len);
3115         VOP_CTRL_SET(vop, vs_st_end_f1, val);
3116         VOP_CTRL_SET(vop, dsp_interlace, 1);
3117         VOP_CTRL_SET(vop, p2i_en, 1);
3118         vtotal += vtotal + 1;
3119         act_end = vact_end_f1;
3120     } else {
3121         VOP_CTRL_SET(vop, dsp_interlace, 0);
3122         VOP_CTRL_SET(vop, p2i_en, 0);
3123         act_end = vact_end;
3124     }
3125 
3126     if (VOP_MAJOR(vop->version) == 0x3 && (VOP_MINOR(vop->version) == 0x2 || VOP_MINOR(vop->version) == 0x8)) {
3127         for_ddr_freq = 0x3e8;
3128     }
3129     VOP_INTR_SET(vop, line_flag_num[0], act_end);
3130     VOP_INTR_SET(vop, line_flag_num[1], act_end - us_to_vertical_line(adjusted_mode, for_ddr_freq));
3131 
3132     VOP_CTRL_SET(vop, vtotal_pw, (vtotal << 0x10) | vsync_len);
3133 
3134     VOP_CTRL_SET(vop, core_dclk_div, !!(adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK));
3135 
3136     VOP_CTRL_SET(vop, win_csc_mode_sel, 1);
3137 
3138     clk_set_rate(vop->dclk, adjusted_mode->crtc_clock * 0x3e8);
3139 
3140     vop_cfg_done(vop);
3141 
3142     drm_crtc_vblank_on(crtc);
3143     vop_unlock(vop);
3144 }
3145 
vop_zpos_cmp(const void * a,const void * b)3146 static int vop_zpos_cmp(const void *a, const void *b)
3147 {
3148     struct vop_zpos *pa = (struct vop_zpos *)a;
3149     struct vop_zpos *pb = (struct vop_zpos *)b;
3150 
3151     return pa->zpos - pb->zpos;
3152 }
3153 
vop_afbdc_atomic_check(struct drm_crtc * crtc,struct drm_crtc_state * crtc_state)3154 static int vop_afbdc_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state)
3155 {
3156     struct vop *vop = to_vop(crtc);
3157     struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
3158     struct drm_atomic_state *state = crtc_state->state;
3159     struct drm_plane *plane;
3160     struct drm_plane_state *pstate;
3161     struct vop_plane_state *plane_state;
3162     struct drm_framebuffer *fb;
3163     struct drm_rect *src;
3164     struct vop_win *win;
3165     int afbdc_format;
3166 
3167     s->afbdc_en = 0;
3168 
3169     drm_atomic_crtc_state_for_each_plane(plane, crtc_state)
3170     {
3171         pstate = drm_atomic_get_existing_plane_state(state, plane);
3172         /*
3173          * plane might not have changed, in which case take
3174          * current state:
3175          */
3176         if (!pstate) {
3177             pstate = plane->state;
3178         }
3179 
3180         fb = pstate->fb;
3181 
3182         if (pstate->crtc != crtc || !fb) {
3183             continue;
3184         }
3185         if (fb->modifier != DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16)) {
3186             continue;
3187         }
3188 
3189         if (!VOP_CTRL_SUPPORT(vop, afbdc_en)) {
3190             DRM_INFO("not support afbdc\n");
3191             return -EINVAL;
3192         }
3193 
3194         plane_state = to_vop_plane_state(pstate);
3195 
3196         switch (plane_state->format) {
3197             case VOP_FMT_ARGB8888:
3198                 afbdc_format = AFBDC_FMT_U8U8U8U8;
3199                 break;
3200             case VOP_FMT_RGB888:
3201                 afbdc_format = AFBDC_FMT_U8U8U8;
3202                 break;
3203             case VOP_FMT_RGB565:
3204                 afbdc_format = AFBDC_FMT_RGB565;
3205                 break;
3206             default:
3207                 return -EINVAL;
3208         }
3209 
3210         if (s->afbdc_en) {
3211             DRM_ERROR("vop only support one afbc layer\n");
3212             return -EINVAL;
3213         }
3214 
3215         win = to_vop_win(plane);
3216         src = &plane_state->src;
3217         if (!(win->feature & WIN_FEATURE_AFBDC)) {
3218             DRM_ERROR("win[%d] feature:0x%llx, not support afbdc\n", win->win_id, win->feature);
3219             return -EINVAL;
3220         }
3221         if (!IS_ALIGNED(fb->width, 0x10)) {
3222             DRM_ERROR("win[%d] afbdc must 16 align, width: %d\n", win->win_id, fb->width);
3223             return -EINVAL;
3224         }
3225 
3226         if (VOP_CTRL_SUPPORT(vop, afbdc_pic_vir_width)) {
3227             u32 align_x1, align_x2, align_y1, align_y2, align_val;
3228             struct drm_gem_object *obj;
3229             struct rockchip_gem_object *rk_obj;
3230             dma_addr_t fb_addr;
3231 
3232             obj = fb->obj[0];
3233             rk_obj = to_rockchip_obj(obj);
3234             fb_addr = rk_obj->dma_addr + fb->offsets[0];
3235 
3236             s->afbdc_win_format = afbdc_format;
3237             s->afbdc_win_id = win->win_id;
3238             s->afbdc_win_ptr = fb_addr;
3239             s->afbdc_win_vir_width = fb->width;
3240             s->afbdc_win_xoffset = (src->x1 >> 0x10);
3241             s->afbdc_win_yoffset = (src->y1 >> 0x10);
3242 
3243             align_x1 = (src->x1 >> 0x10) - ((src->x1 >> 0x10) % 0x10);
3244             align_y1 = (src->y1 >> 0x10) - ((src->y1 >> 0x10) % 0x10);
3245 
3246             align_val = (src->x2 >> 0x10) % 0x10;
3247             if (align_val) {
3248                 align_x2 = (src->x2 >> 0x10) + (0x10 - align_val);
3249             } else {
3250                 align_x2 = src->x2 >> 0x10;
3251             }
3252 
3253             align_val = (src->y2 >> 0x10) % 0x10;
3254             if (align_val) {
3255                 align_y2 = (src->y2 >> 0x10) + (0x10 - align_val);
3256             } else {
3257                 align_y2 = src->y2 >> 0x10;
3258             }
3259 
3260             s->afbdc_win_width = align_x2 - align_x1 - 1;
3261             s->afbdc_win_height = align_y2 - align_y1 - 1;
3262 
3263             s->afbdc_en = 1;
3264 
3265             break;
3266         }
3267         if (src->x1 || src->y1 || fb->offsets[0]) {
3268             DRM_ERROR("win[%d] afbdc not support offset display\n", win->win_id);
3269             DRM_ERROR("xpos=%d, ypos=%d, offset=%d\n", src->x1, src->y1, fb->offsets[0]);
3270             return -EINVAL;
3271         }
3272         s->afbdc_win_format = afbdc_format;
3273         s->afbdc_win_width = fb->width - 1;
3274         s->afbdc_win_height = (drm_rect_height(src) >> 0x10) - 1;
3275         s->afbdc_win_id = win->win_id;
3276         s->afbdc_win_ptr = plane_state->yrgb_mst;
3277         s->afbdc_en = 1;
3278     }
3279 
3280     return 0;
3281 }
3282 
vop_dclk_source_generate(struct drm_crtc * crtc,struct drm_crtc_state * crtc_state)3283 static void vop_dclk_source_generate(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state)
3284 {
3285     struct rockchip_drm_private *private = crtc->dev->dev_private;
3286     struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
3287     struct rockchip_crtc_state *old_s = to_rockchip_crtc_state(crtc->state);
3288     struct vop *vop = to_vop(crtc);
3289     struct rockchip_dclk_pll *old_pll = vop->pll;
3290 
3291     if (!vop->dclk_source) {
3292         return;
3293     }
3294 
3295     if (crtc_state->active) {
3296         WARN_ON(vop->pll && !vop->pll->use_count);
3297         if (!vop->pll || vop->pll->use_count > 1 || s->output_type != old_s->output_type) {
3298             if (vop->pll) {
3299                 vop->pll->use_count--;
3300             }
3301 
3302             if (s->output_type != DRM_MODE_CONNECTOR_HDMIA && !private->default_pll.use_count) {
3303                 vop->pll = &private->default_pll;
3304             } else {
3305                 vop->pll = &private->hdmi_pll;
3306             }
3307 
3308             vop->pll->use_count++;
3309         }
3310     } else if (vop->pll) {
3311         vop->pll->use_count--;
3312         vop->pll = NULL;
3313     }
3314     if (vop->pll != old_pll) {
3315         crtc_state->mode_changed = true;
3316     }
3317 }
3318 
vop_crtc_atomic_check(struct drm_crtc * crtc,struct drm_crtc_state * crtc_state)3319 static int vop_crtc_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state)
3320 {
3321     struct drm_atomic_state *state = crtc_state->state;
3322     struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
3323     struct vop *vop = to_vop(crtc);
3324     const struct vop_data *vop_data = vop->data;
3325     struct drm_plane *plane;
3326     struct drm_plane_state *pstate;
3327     struct vop_plane_state *plane_state;
3328     struct vop_zpos *pzpos;
3329     int dsp_layer_sel = 0;
3330     int i, j, cnt = 0, ret = 0;
3331 
3332     ret = vop_afbdc_atomic_check(crtc, crtc_state);
3333     if (ret) {
3334         return ret;
3335     }
3336 
3337     s->yuv_overlay = 0;
3338     if (VOP_CTRL_SUPPORT(vop, overlay_mode)) {
3339         s->yuv_overlay = is_yuv_output(s->bus_format);
3340     }
3341 
3342     ret = vop_hdr_atomic_check(crtc, crtc_state);
3343     if (ret) {
3344         return ret;
3345     }
3346     ret = vop_csc_atomic_check(crtc, crtc_state);
3347     if (ret) {
3348         return ret;
3349     }
3350 
3351     pzpos = kmalloc_array(vop_data->win_size, sizeof(*pzpos), GFP_KERNEL);
3352     if (!pzpos) {
3353         return -ENOMEM;
3354     }
3355 
3356     for (i = 0; i < vop_data->win_size; i++) {
3357         const struct vop_win_data *win_data = &vop_data->win[i];
3358         struct vop_win *win;
3359 
3360         if (!win_data->phy) {
3361             continue;
3362         }
3363 
3364         for (j = 0; j < vop->num_wins; j++) {
3365             win = &vop->win[j];
3366 
3367             if (win->win_id == i && !win->area_id) {
3368                 break;
3369             }
3370         }
3371         if (WARN_ON(j >= vop->num_wins)) {
3372             ret = -EINVAL;
3373             goto err_free_pzpos;
3374         }
3375 
3376         plane = &win->base;
3377         pstate = state->planes[drm_plane_index(plane)].state;
3378         /*
3379          * plane might not have changed, in which case take
3380          * current state:
3381          */
3382         if (!pstate) {
3383             pstate = plane->state;
3384         }
3385         plane_state = to_vop_plane_state(pstate);
3386 
3387         if (!pstate->visible) {
3388             pzpos[cnt].zpos = INT_MAX;
3389         } else {
3390             pzpos[cnt].zpos = plane_state->zpos;
3391         }
3392         pzpos[cnt++].win_id = win->win_id;
3393     }
3394 
3395     sort(pzpos, cnt, sizeof(pzpos[0]), vop_zpos_cmp, NULL);
3396 
3397     for (i = 0, cnt = 0; i < vop_data->win_size; i++) {
3398         const struct vop_win_data *win_data = &vop_data->win[i];
3399         int shift = i * 0x2;
3400 
3401         if (win_data->phy) {
3402             struct vop_zpos *zpos = &pzpos[cnt++];
3403 
3404             dsp_layer_sel |= zpos->win_id << shift;
3405         } else {
3406             dsp_layer_sel |= i << shift;
3407         }
3408     }
3409 
3410     s->dsp_layer_sel = dsp_layer_sel;
3411 
3412     vop_dclk_source_generate(crtc, crtc_state);
3413 
3414 err_free_pzpos:
3415     kfree(pzpos);
3416     return ret;
3417 }
3418 
vop_post_config(struct drm_crtc * crtc)3419 static void vop_post_config(struct drm_crtc *crtc)
3420 {
3421     struct vop *vop = to_vop(crtc);
3422     struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
3423     struct drm_display_mode *mode = &crtc->state->adjusted_mode;
3424     u16 vtotal = mode->crtc_vtotal;
3425     u16 hdisplay = mode->crtc_hdisplay;
3426     u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
3427     u16 vdisplay = mode->crtc_vdisplay;
3428     u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
3429     u16 hsize = hdisplay * (s->left_margin + s->right_margin) / 0xc8;
3430     u16 vsize = vdisplay * (s->top_margin + s->bottom_margin) / 0xc8;
3431     u16 hact_end, vact_end;
3432     u32 val;
3433 
3434     if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
3435         vsize = rounddown(vsize, 0x2);
3436     }
3437 
3438     hact_st += hdisplay * (0x64 - s->left_margin) / 0xc8;
3439     hact_end = hact_st + hsize;
3440     val = hact_st << 0x10;
3441     val |= hact_end;
3442     VOP_CTRL_SET(vop, hpost_st_end, val);
3443     vact_st += vdisplay * (0x64 - s->top_margin) / 0xc8;
3444     vact_end = vact_st + vsize;
3445     val = vact_st << 0x10;
3446     val |= vact_end;
3447     VOP_CTRL_SET(vop, vpost_st_end, val);
3448     val = scl_cal_scale2(vdisplay, vsize) << 0x10;
3449     val |= scl_cal_scale2(hdisplay, hsize);
3450     VOP_CTRL_SET(vop, post_scl_factor, val);
3451 
3452 #define POST_HORIZONTAL_SCALEDOWN_EN(x) ((x) << 0)
3453 #define POST_VERTICAL_SCALEDOWN_EN(x) ((x) << 1)
3454     VOP_CTRL_SET(vop, post_scl_ctrl,
3455                  POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) | POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize));
3456     if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
3457         u16 vact_st_f1 = vtotal + vact_st + 1;
3458         u16 vact_end_f1 = vact_st_f1 + vsize;
3459 
3460         val = (vact_st_f1 << 0x10) | vact_end_f1;
3461         VOP_CTRL_SET(vop, vpost_st_end_f1, val);
3462     }
3463 }
3464 
vop_update_hdr(struct drm_crtc * crtc,struct drm_crtc_state * old_crtc_state)3465 static void vop_update_hdr(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state)
3466 {
3467     struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
3468     struct vop *vop = to_vop(crtc);
3469     struct rockchip_sdr2hdr_state *sdr2hdr_state = &s->hdr.sdr2hdr_state;
3470 
3471     if (!vop->data->hdr_table) {
3472         return;
3473     }
3474 
3475     if (s->hdr.hdr2sdr_en) {
3476         vop_load_hdr2sdr_table(vop);
3477         /* This is ic design bug, when in hdr2sdr mode, the overlay mode
3478          * is rgb domain, so the win0 is do yuv2rgb, but in this case,
3479          * we must close win0 y2r.
3480          */
3481         VOP_CTRL_SET(vop, hdr2sdr_en_win0_csc, 0);
3482     }
3483     VOP_CTRL_SET(vop, hdr2sdr_en, s->hdr.hdr2sdr_en);
3484 
3485     VOP_CTRL_SET(vop, bt1886eotf_pre_conv_en, sdr2hdr_state->bt1886eotf_pre_conv_en);
3486     VOP_CTRL_SET(vop, bt1886eotf_post_conv_en, sdr2hdr_state->bt1886eotf_post_conv_en);
3487 
3488     VOP_CTRL_SET(vop, rgb2rgb_pre_conv_en, sdr2hdr_state->rgb2rgb_pre_conv_en);
3489     VOP_CTRL_SET(vop, rgb2rgb_pre_conv_mode, sdr2hdr_state->rgb2rgb_pre_conv_mode);
3490     VOP_CTRL_SET(vop, st2084oetf_pre_conv_en, sdr2hdr_state->st2084oetf_pre_conv_en);
3491 
3492     VOP_CTRL_SET(vop, rgb2rgb_post_conv_en, sdr2hdr_state->rgb2rgb_post_conv_en);
3493     VOP_CTRL_SET(vop, rgb2rgb_post_conv_mode, sdr2hdr_state->rgb2rgb_post_conv_mode);
3494     VOP_CTRL_SET(vop, st2084oetf_post_conv_en, sdr2hdr_state->st2084oetf_post_conv_en);
3495 
3496     if (sdr2hdr_state->bt1886eotf_pre_conv_en || sdr2hdr_state->bt1886eotf_post_conv_en) {
3497         vop_load_sdr2hdr_table(vop, sdr2hdr_state->sdr2hdr_func);
3498     }
3499     VOP_CTRL_SET(vop, win_csc_mode_sel, 1);
3500 }
3501 
vop_tv_config_update(struct drm_crtc * crtc,struct drm_crtc_state * old_crtc_state)3502 static void vop_tv_config_update(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state)
3503 {
3504     struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
3505     struct rockchip_crtc_state *old_s = to_rockchip_crtc_state(old_crtc_state);
3506     int brightness, contrast, saturation, hue, sin_hue, cos_hue;
3507     struct vop *vop = to_vop(crtc);
3508     const struct vop_data *vop_data = vop->data;
3509 
3510     if (!s->tv_state) {
3511         return;
3512     }
3513 
3514     /*
3515      * The BCSH only need to config once except one of the following
3516      * condition changed:
3517      *   1. tv_state: include brightness,contrast,saturation and hue;
3518      *   2. yuv_overlay: it is related to BCSH r2y module;
3519      *   3. mode_update: it is indicate mode change and resume from suspend;
3520      *   4. bcsh_en: control the BCSH module enable or disable state;
3521      *   5. bus_format: it is related to BCSH y2r module;
3522      */
3523     if (!memcmp(s->tv_state, &vop->active_tv_state, sizeof(*s->tv_state)) && s->yuv_overlay == old_s->yuv_overlay &&
3524         s->mode_update && s->bcsh_en == old_s->bcsh_en && s->bus_format == old_s->bus_format) {
3525         return;
3526     }
3527 
3528     memcpy(&vop->active_tv_state, s->tv_state, sizeof(*s->tv_state));
3529     /* post BCSH CSC */
3530     s->post_r2y_en = 0;
3531     s->post_y2r_en = 0;
3532     s->bcsh_en = 0;
3533     if (s->tv_state) {
3534         if (s->tv_state->brightness != 0x32 || s->tv_state->contrast != 0x32 || s->tv_state->saturation != 0x32 ||
3535             s->tv_state->hue != 0x32) {
3536             s->bcsh_en = 1;
3537         }
3538     }
3539 
3540     if (s->bcsh_en) {
3541         if (!s->yuv_overlay) {
3542             s->post_r2y_en = 1;
3543         }
3544         if (!is_yuv_output(s->bus_format)) {
3545             s->post_y2r_en = 1;
3546         }
3547     } else {
3548         if (!s->yuv_overlay && is_yuv_output(s->bus_format)) {
3549             s->post_r2y_en = 1;
3550         }
3551         if (s->yuv_overlay && !is_yuv_output(s->bus_format)) {
3552             s->post_y2r_en = 1;
3553         }
3554     }
3555 
3556     s->post_csc_mode = to_vop_csc_mode(s->color_space);
3557     VOP_CTRL_SET(vop, bcsh_r2y_en, s->post_r2y_en);
3558     VOP_CTRL_SET(vop, bcsh_y2r_en, s->post_y2r_en);
3559     VOP_CTRL_SET(vop, bcsh_r2y_csc_mode, s->post_csc_mode);
3560     VOP_CTRL_SET(vop, bcsh_y2r_csc_mode, s->post_csc_mode);
3561     if (!s->bcsh_en) {
3562         VOP_CTRL_SET(vop, bcsh_en, s->bcsh_en);
3563         return;
3564     }
3565 
3566     if (vop_data->feature & VOP_FEATURE_OUTPUT_10BIT) {
3567         brightness = interpolate(0, -0x80, 0x64, 0x7f, s->tv_state->brightness);
3568     } else if (VOP_MAJOR(vop->version) == 0x2 && VOP_MINOR(vop->version) == 0x6) { /* px30 vopb */
3569         brightness = interpolate(0, -0x40, 0x64, 0x3f, s->tv_state->brightness);
3570     } else {
3571         brightness = interpolate(0, -0x20, 0x64, 0x1f, s->tv_state->brightness);
3572     }
3573 
3574     if ((VOP_MAJOR(vop->version) == 0x3) ||
3575         (VOP_MAJOR(vop->version) == 0x2 && VOP_MINOR(vop->version) == 0x6)) { /* px30 vopb */
3576         contrast = interpolate(0, 0, 0x64, 0x1ff, s->tv_state->contrast);
3577         saturation = interpolate(0, 0, 0x64, 0x1ff, s->tv_state->saturation);
3578         /*
3579          *  a:[-30~0]:
3580          *    sin_hue = 0x100 - sin(a)*256;
3581          *    cos_hue = cos(a)*256;
3582          *  a:[0~30]
3583          *    sin_hue = sin(a)*256;
3584          *    cos_hue = cos(a)*256;
3585          */
3586         hue = interpolate(0, -0x1e, 0x64, 0x1e, s->tv_state->hue);
3587         sin_hue = fixp_sin32(hue) >> 0x17;
3588         cos_hue = fixp_cos32(hue) >> 0x17;
3589         VOP_CTRL_SET(vop, bcsh_sat_con, saturation * contrast / 0x100);
3590     } else {
3591         contrast = interpolate(0, 0, 0x64, 0xff, s->tv_state->contrast);
3592         saturation = interpolate(0, 0, 0x64, 0xff, s->tv_state->saturation);
3593         /*
3594          *  a:[-30~0]:
3595          *    sin_hue = 0x100 - sin(a)*128;
3596          *    cos_hue = cos(a)*128;
3597          *  a:[0~30]
3598          *    sin_hue = sin(a)*128;
3599          *    cos_hue = cos(a)*128;
3600          */
3601         hue = interpolate(0, -0x1e, 0x64, 0x1e, s->tv_state->hue);
3602         sin_hue = fixp_sin32(hue) >> 0x18;
3603         cos_hue = fixp_cos32(hue) >> 0x18;
3604         VOP_CTRL_SET(vop, bcsh_sat_con, saturation * contrast / 0x80);
3605     }
3606 
3607     VOP_CTRL_SET(vop, bcsh_brightness, brightness);
3608     VOP_CTRL_SET(vop, bcsh_contrast, contrast);
3609     VOP_CTRL_SET(vop, bcsh_sin_hue, sin_hue);
3610     VOP_CTRL_SET(vop, bcsh_cos_hue, cos_hue);
3611     VOP_CTRL_SET(vop, bcsh_out_mode, BCSH_OUT_MODE_NORMAL_VIDEO);
3612     if (VOP_MAJOR(vop->version) == 0x3 && VOP_MINOR(vop->version) == 0) {
3613         VOP_CTRL_SET(vop, auto_gate_en, 0);
3614     }
3615     VOP_CTRL_SET(vop, bcsh_en, s->bcsh_en);
3616 }
3617 
vop_cfg_update(struct drm_crtc * crtc,struct drm_crtc_state * old_crtc_state)3618 static void vop_cfg_update(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state)
3619 {
3620     struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
3621     struct vop *vop = to_vop(crtc);
3622     const struct vop_data *vop_data = vop->data;
3623 
3624     spin_lock(&vop->reg_lock);
3625 
3626     vop_update_csc(crtc);
3627 
3628     vop_tv_config_update(crtc, old_crtc_state);
3629 
3630     if (s->afbdc_en) {
3631         u32 pic_size, pic_offset;
3632 
3633         VOP_CTRL_SET(vop, afbdc_format, s->afbdc_win_format | 1 << 0x4);
3634         VOP_CTRL_SET(vop, afbdc_hreg_block_split, 0);
3635         VOP_CTRL_SET(vop, afbdc_sel, s->afbdc_win_id);
3636         VOP_CTRL_SET(vop, afbdc_hdr_ptr, s->afbdc_win_ptr);
3637         pic_size = (s->afbdc_win_width & 0xffff);
3638         pic_size |= s->afbdc_win_height << 0x10;
3639         VOP_CTRL_SET(vop, afbdc_pic_size, pic_size);
3640 
3641         VOP_CTRL_SET(vop, afbdc_pic_vir_width, s->afbdc_win_vir_width);
3642         pic_offset = (s->afbdc_win_xoffset & 0xffff);
3643         pic_offset |= s->afbdc_win_yoffset << 0x10;
3644         VOP_CTRL_SET(vop, afbdc_pic_offset, pic_offset);
3645     }
3646 
3647     VOP_CTRL_SET(vop, afbdc_en, s->afbdc_en);
3648 
3649     VOP_CTRL_SET(vop, dsp_layer_sel, s->dsp_layer_sel);
3650     if (vop_data->feature & VOP_FEATURE_OVERSCAN) {
3651         vop_post_config(crtc);
3652     }
3653 
3654     spin_unlock(&vop->reg_lock);
3655 }
3656 
vop_fs_irq_is_pending(struct vop * vop)3657 static bool vop_fs_irq_is_pending(struct vop *vop)
3658 {
3659     if (VOP_MAJOR(vop->version) == 0x3 && VOP_MINOR(vop->version) >= 0x7) {
3660         return VOP_INTR_GET_TYPE(vop, status, FS_FIELD_INTR);
3661     } else {
3662         return VOP_INTR_GET_TYPE(vop, status, FS_INTR);
3663     }
3664 }
3665 
vop_wait_for_irq_handler(struct vop * vop)3666 static void vop_wait_for_irq_handler(struct vop *vop)
3667 {
3668     bool pending;
3669     int ret;
3670 
3671     /*
3672      * Spin until frame start interrupt status bit goes low, which means
3673      * that interrupt handler was invoked and cleared it. The timeout of
3674      * 10 msecs is really too long, but it is just a safety measure if
3675      * something goes really wrong. The wait will only happen in the very
3676      * unlikely case of a vblank happening exactly at the same time and
3677      * shouldn't exceed microseconds range.
3678      */
3679     ret = readx_poll_timeout_atomic(vop_fs_irq_is_pending, vop, pending, !pending, 0, 0xa * 0x3e8);
3680     if (ret) {
3681         DRM_DEV_ERROR(vop->dev, "VOP vblank IRQ stuck for 10 ms\n");
3682     }
3683 
3684     synchronize_irq(vop->irq);
3685 }
3686 
vop_crtc_atomic_flush(struct drm_crtc * crtc,struct drm_crtc_state * old_crtc_state)3687 static void vop_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state)
3688 {
3689     struct drm_atomic_state *old_state = old_crtc_state->state;
3690     struct drm_plane_state *old_plane_state;
3691     struct vop *vop = to_vop(crtc);
3692     struct drm_plane *plane;
3693     int i;
3694     unsigned long flags;
3695     struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
3696 
3697     vop_cfg_update(crtc, old_crtc_state);
3698 
3699     if (!vop->is_iommu_enabled && vop->is_iommu_needed) {
3700         int ret;
3701 
3702         if (s->mode_update) {
3703             VOP_CTRL_SET(vop, dma_stop, 1);
3704         }
3705 
3706         ret = rockchip_drm_dma_attach_device(vop->drm_dev, vop->dev);
3707         if (ret) {
3708             vop->is_iommu_enabled = false;
3709             vop_disable_all_planes(vop);
3710             dev_err(vop->dev, "failed to attach dma mapping, %d\n", ret);
3711         } else {
3712             vop->is_iommu_enabled = true;
3713             VOP_CTRL_SET(vop, dma_stop, 0);
3714         }
3715     }
3716 
3717     vop_update_hdr(crtc, old_crtc_state);
3718     if (old_crtc_state->color_mgmt_changed || old_crtc_state->active_changed) {
3719         if (crtc->state->gamma_lut || vop->gamma_lut) {
3720             if (old_crtc_state->gamma_lut) {
3721                 vop->gamma_lut = old_crtc_state->gamma_lut->data;
3722             }
3723             vop_crtc_atomic_gamma_set(crtc, old_crtc_state);
3724         }
3725     }
3726 
3727     spin_lock_irqsave(&vop->irq_lock, flags);
3728     vop->pre_overlay = s->hdr.pre_overlay;
3729     vop_cfg_done(vop);
3730     /*
3731      * rk322x and rk332x odd-even field will mistake when in interlace mode.
3732      * we must switch to frame effect before switch screen and switch to
3733      * field effect after switch screen complete.
3734      */
3735     if (VOP_MAJOR(vop->version) == 0x3 && (VOP_MINOR(vop->version) == 0x7 || VOP_MINOR(vop->version) == 0x8)) {
3736         if (!s->mode_update && VOP_CTRL_GET(vop, reg_done_frm)) {
3737             VOP_CTRL_SET(vop, reg_done_frm, 0);
3738         }
3739     } else {
3740         VOP_CTRL_SET(vop, reg_done_frm, 0);
3741     }
3742     if (vop->mcu_timing.mcu_pix_total) {
3743         VOP_CTRL_SET(vop, mcu_hold_mode, 0);
3744     }
3745 
3746     spin_unlock_irqrestore(&vop->irq_lock, flags);
3747 
3748     /*
3749      * There is a (rather unlikely) possiblity that a vblank interrupt
3750      * fired before we set the cfg_done bit. To avoid spuriously
3751      * signalling flip completion we need to wait for it to finish.
3752      */
3753     vop_wait_for_irq_handler(vop);
3754 
3755     spin_lock_irq(&crtc->dev->event_lock);
3756     if (crtc->state->event) {
3757         WARN_ON(drm_crtc_vblank_get(crtc) != 0);
3758         WARN_ON(vop->event);
3759 
3760         vop->event = crtc->state->event;
3761         crtc->state->event = NULL;
3762     }
3763     spin_unlock_irq(&crtc->dev->event_lock);
3764     for_each_old_plane_in_state(old_state, plane, old_plane_state, i)
3765     {
3766         if (!old_plane_state->fb) {
3767             continue;
3768         }
3769 
3770         if (old_plane_state->fb == plane->state->fb) {
3771             continue;
3772         }
3773 
3774         drm_framebuffer_get(old_plane_state->fb);
3775         WARN_ON(drm_crtc_vblank_get(crtc) != 0);
3776         drm_flip_work_queue(&vop->fb_unref_work, old_plane_state->fb);
3777         set_bit(VOP_PENDING_FB_UNREF, &vop->pending);
3778     }
3779 }
3780 
3781 static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = {
3782     .mode_fixup = vop_crtc_mode_fixup,
3783     .atomic_check = vop_crtc_atomic_check,
3784     .atomic_flush = vop_crtc_atomic_flush,
3785     .atomic_enable = vop_crtc_atomic_enable,
3786     .atomic_disable = vop_crtc_atomic_disable,
3787 };
3788 
vop_crtc_destroy(struct drm_crtc * crtc)3789 static void vop_crtc_destroy(struct drm_crtc *crtc)
3790 {
3791     drm_crtc_cleanup(crtc);
3792 }
3793 
vop_crtc_reset(struct drm_crtc * crtc)3794 static void vop_crtc_reset(struct drm_crtc *crtc)
3795 {
3796     struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
3797 
3798     if (crtc->state) {
3799         __drm_atomic_helper_crtc_destroy_state(crtc->state);
3800         kfree(s);
3801     }
3802 
3803     s = kzalloc(sizeof(*s), GFP_KERNEL);
3804     if (!s) {
3805         return;
3806     }
3807     crtc->state = &s->base;
3808     crtc->state->crtc = crtc;
3809 
3810     s->left_margin = 0x64;
3811     s->right_margin = 0x64;
3812     s->top_margin = 0x64;
3813     s->bottom_margin = 0x64;
3814 }
3815 
vop_crtc_duplicate_state(struct drm_crtc * crtc)3816 static struct drm_crtc_state *vop_crtc_duplicate_state(struct drm_crtc *crtc)
3817 {
3818     struct rockchip_crtc_state *rockchip_state, *old_state;
3819     if (WARN_ON(!crtc->state))
3820         return NULL;
3821 
3822     old_state = to_rockchip_crtc_state(crtc->state);
3823     rockchip_state = kmemdup(old_state, sizeof(*old_state), GFP_KERNEL);
3824     if (!rockchip_state) {
3825         return NULL;
3826     }
3827 
3828     __drm_atomic_helper_crtc_duplicate_state(crtc, &rockchip_state->base);
3829     return &rockchip_state->base;
3830 }
3831 
vop_crtc_destroy_state(struct drm_crtc * crtc,struct drm_crtc_state * state)3832 static void vop_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state)
3833 {
3834     struct rockchip_crtc_state *s = to_rockchip_crtc_state(state);
3835 
3836     __drm_atomic_helper_crtc_destroy_state(&s->base);
3837     kfree(s);
3838 }
3839 
3840 #ifdef CONFIG_DRM_ANALOGIX_DP
vop_get_edp_connector(struct vop * vop)3841 static struct drm_connector *vop_get_edp_connector(struct vop *vop)
3842 {
3843     struct drm_connector *connector;
3844     struct drm_connector_list_iter conn_iter;
3845 
3846     drm_connector_list_iter_begin(vop->drm_dev, &conn_iter);
3847     drm_for_each_connector_iter(connector, &conn_iter)
3848     {
3849         if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
3850             drm_connector_list_iter_end(&conn_iter);
3851             return connector;
3852         }
3853     }
3854     drm_connector_list_iter_end(&conn_iter);
3855 
3856     return NULL;
3857 }
3858 
vop_crtc_set_crc_source(struct drm_crtc * crtc,const char * source_name)3859 static int vop_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name)
3860 {
3861     struct vop *vop = to_vop(crtc);
3862     struct drm_connector *connector;
3863     int ret;
3864 
3865     connector = vop_get_edp_connector(vop);
3866     if (!connector) {
3867         return -EINVAL;
3868     }
3869 
3870     if (source_name && strcmp(source_name, "auto") == 0) {
3871         ret = analogix_dp_start_crc(connector);
3872     } else if (!source_name) {
3873         ret = analogix_dp_stop_crc(connector);
3874     } else {
3875         ret = -EINVAL;
3876     }
3877 
3878     return ret;
3879 }
3880 
vop_crtc_verify_crc_source(struct drm_crtc * crtc,const char * source_name,size_t * values_cnt)3881 static int vop_crtc_verify_crc_source(struct drm_crtc *crtc, const char *source_name, size_t *values_cnt)
3882 {
3883     if (source_name && strcmp(source_name, "auto") != 0) {
3884         return -EINVAL;
3885     }
3886 
3887     *values_cnt = 0x3;
3888     return 0;
3889 }
3890 
3891 #else
vop_crtc_set_crc_source(struct drm_crtc * crtc,const char * source_name)3892 static int vop_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name)
3893 {
3894     return -ENODEV;
3895 }
3896 
vop_crtc_verify_crc_source(struct drm_crtc * crtc,const char * source_name,size_t * values_cnt)3897 static int vop_crtc_verify_crc_source(struct drm_crtc *crtc, const char *source_name, size_t *values_cnt)
3898 {
3899     return -ENODEV;
3900 }
3901 #endif
3902 
vop_crtc_atomic_get_property(struct drm_crtc * crtc,const struct drm_crtc_state * state,struct drm_property * property,uint64_t * val)3903 static int vop_crtc_atomic_get_property(struct drm_crtc *crtc, const struct drm_crtc_state *state,
3904                                         struct drm_property *property, uint64_t *val)
3905 {
3906     struct drm_device *drm_dev = crtc->dev;
3907     struct rockchip_drm_private *private = drm_dev->dev_private;
3908     struct drm_mode_config *mode_config = &drm_dev->mode_config;
3909     struct rockchip_crtc_state *s = to_rockchip_crtc_state(state);
3910     struct vop *vop = to_vop(crtc);
3911 
3912     if (property == mode_config->tv_left_margin_property) {
3913         *val = s->left_margin;
3914         return 0;
3915     }
3916 
3917     if (property == mode_config->tv_right_margin_property) {
3918         *val = s->right_margin;
3919         return 0;
3920     }
3921 
3922     if (property == mode_config->tv_top_margin_property) {
3923         *val = s->top_margin;
3924         return 0;
3925     }
3926 
3927     if (property == mode_config->tv_bottom_margin_property) {
3928         *val = s->bottom_margin;
3929         return 0;
3930     }
3931 
3932     if (property == private->aclk_prop) {
3933         /* KHZ, keep align with mode->clock */
3934         *val = clk_get_rate(vop->aclk) / 0x3e8;
3935         return 0;
3936     }
3937 
3938     if (property == private->bg_prop) {
3939         *val = vop->background;
3940         return 0;
3941     }
3942 
3943     if (property == private->line_flag_prop) {
3944         *val = vop->line_flag;
3945         return 0;
3946     }
3947 
3948     DRM_ERROR("failed to get vop crtc property\n");
3949     return -EINVAL;
3950 }
3951 
vop_crtc_atomic_set_property(struct drm_crtc * crtc,struct drm_crtc_state * state,struct drm_property * property,uint64_t val)3952 static int vop_crtc_atomic_set_property(struct drm_crtc *crtc, struct drm_crtc_state *state,
3953                                         struct drm_property *property, uint64_t val)
3954 {
3955     struct drm_device *drm_dev = crtc->dev;
3956     struct rockchip_drm_private *private = drm_dev->dev_private;
3957     struct drm_mode_config *mode_config = &drm_dev->mode_config;
3958     struct rockchip_crtc_state *s = to_rockchip_crtc_state(state);
3959     struct vop *vop = to_vop(crtc);
3960 
3961     if (property == mode_config->tv_left_margin_property) {
3962         s->left_margin = val;
3963         return 0;
3964     }
3965 
3966     if (property == mode_config->tv_right_margin_property) {
3967         s->right_margin = val;
3968         return 0;
3969     }
3970 
3971     if (property == mode_config->tv_top_margin_property) {
3972         s->top_margin = val;
3973         return 0;
3974     }
3975 
3976     if (property == mode_config->tv_bottom_margin_property) {
3977         s->bottom_margin = val;
3978         return 0;
3979     }
3980 
3981     if (property == private->bg_prop) {
3982         vop->background = val;
3983         return 0;
3984     }
3985 
3986     if (property == private->line_flag_prop) {
3987         vop->line_flag = val;
3988         return 0;
3989     }
3990 
3991     DRM_ERROR("failed to set vop crtc property\n");
3992     return -EINVAL;
3993 }
3994 
3995 static const struct drm_crtc_funcs vop_crtc_funcs = {
3996     .gamma_set = vop_crtc_legacy_gamma_set,
3997     .set_config = drm_atomic_helper_set_config,
3998     .page_flip = drm_atomic_helper_page_flip,
3999     .destroy = vop_crtc_destroy,
4000     .reset = vop_crtc_reset,
4001     .atomic_get_property = vop_crtc_atomic_get_property,
4002     .atomic_set_property = vop_crtc_atomic_set_property,
4003     .atomic_duplicate_state = vop_crtc_duplicate_state,
4004     .atomic_destroy_state = vop_crtc_destroy_state,
4005     .enable_vblank = vop_crtc_enable_vblank,
4006     .disable_vblank = vop_crtc_disable_vblank,
4007     .set_crc_source = vop_crtc_set_crc_source,
4008     .verify_crc_source = vop_crtc_verify_crc_source,
4009 };
4010 
vop_fb_unref_worker(struct drm_flip_work * work,void * val)4011 static void vop_fb_unref_worker(struct drm_flip_work *work, void *val)
4012 {
4013     struct vop *vop = container_of(work, struct vop, fb_unref_work);
4014     struct drm_framebuffer *fb = val;
4015 
4016     drm_crtc_vblank_put(&vop->rockchip_crtc.crtc);
4017     drm_framebuffer_put(fb);
4018 }
4019 
vop_handle_vblank(struct vop * vop)4020 static void vop_handle_vblank(struct vop *vop)
4021 {
4022     struct drm_device *drm = vop->drm_dev;
4023     struct drm_crtc *crtc = &vop->rockchip_crtc.crtc;
4024     unsigned long flags;
4025 
4026     spin_lock_irqsave(&drm->event_lock, flags);
4027     if (vop->event) {
4028         drm_crtc_send_vblank_event(crtc, vop->event);
4029         drm_crtc_vblank_put(crtc);
4030         vop->event = NULL;
4031     }
4032     spin_unlock_irqrestore(&drm->event_lock, flags);
4033 
4034     if (test_and_clear_bit(VOP_PENDING_FB_UNREF, &vop->pending)) {
4035         drm_flip_work_commit(&vop->fb_unref_work, system_unbound_wq);
4036     }
4037 }
4038 
vop_isr(int irq,void * data)4039 static irqreturn_t vop_isr(int irq, void *data)
4040 {
4041     struct vop *vop = data;
4042     struct drm_crtc *crtc = &vop->rockchip_crtc.crtc;
4043     uint32_t active_irqs;
4044     unsigned long flags;
4045     int ret = IRQ_NONE;
4046 
4047     /*
4048      * The irq is shared with the iommu. If the runtime-pm state of the
4049      * vop-device is disabled the irq has to be targeted at the iommu.
4050      */
4051     if (!pm_runtime_get_if_in_use(vop->dev)) {
4052         return IRQ_NONE;
4053     }
4054 
4055     if (vop_core_clks_enable(vop)) {
4056         DRM_DEV_ERROR_RATELIMITED(vop->dev, "couldn't enable clocks\n");
4057         goto out;
4058     }
4059 
4060     /*
4061      * interrupt register has interrupt status, enable and clear bits, we
4062      * must hold irq_lock to avoid a race with enable/disable_vblank().
4063      */
4064     spin_lock_irqsave(&vop->irq_lock, flags);
4065 
4066     active_irqs = VOP_INTR_GET_TYPE(vop, status, INTR_MASK);
4067     /* Clear all active interrupt sources */
4068     if (active_irqs) {
4069         VOP_INTR_SET_TYPE(vop, clear, active_irqs, 1);
4070     }
4071 
4072     spin_unlock_irqrestore(&vop->irq_lock, flags);
4073 
4074     /* This is expected for vop iommu irqs, since the irq is shared */
4075     if (!active_irqs) {
4076         goto out_disable;
4077     }
4078 
4079     if (active_irqs & DSP_HOLD_VALID_INTR) {
4080         complete(&vop->dsp_hold_completion);
4081         active_irqs &= ~DSP_HOLD_VALID_INTR;
4082         ret = IRQ_HANDLED;
4083     }
4084 
4085     if (active_irqs & LINE_FLAG_INTR) {
4086         complete(&vop->line_flag_completion);
4087         active_irqs &= ~LINE_FLAG_INTR;
4088         ret = IRQ_HANDLED;
4089     }
4090 
4091     if ((active_irqs & FS_INTR) || (active_irqs & FS_FIELD_INTR)) {
4092         /* This is IC design not reasonable, this two register bit need
4093          * frame effective, but actually it's effective immediately, so
4094          * we config this register at frame start.
4095          */
4096         spin_lock_irqsave(&vop->irq_lock, flags);
4097         VOP_CTRL_SET(vop, level2_overlay_en, vop->pre_overlay);
4098         VOP_CTRL_SET(vop, alpha_hard_calc, vop->pre_overlay);
4099         spin_unlock_irqrestore(&vop->irq_lock, flags);
4100         drm_crtc_handle_vblank(crtc);
4101         vop_handle_vblank(vop);
4102         active_irqs &= ~(FS_INTR | FS_FIELD_INTR);
4103         ret = IRQ_HANDLED;
4104     }
4105 
4106 #define ERROR_HANDLER(x, val)                                                                                          \
4107     do {                                                                                                               \
4108         if (active_irqs & x##_INTR) {                                                                                  \
4109             DRM_DEV_ERROR_RATELIMITED(val, #x " irq err\n");                                                           \
4110             active_irqs &= ~x##_INTR;                                                                                  \
4111             ret = IRQ_HANDLED;                                                                                         \
4112         }                                                                                                              \
4113     } while (0)
4114 
4115     ERROR_HANDLER(BUS_ERROR, vop->dev);
4116     ERROR_HANDLER(WIN0_EMPTY, vop->dev);
4117     ERROR_HANDLER(WIN1_EMPTY, vop->dev);
4118     ERROR_HANDLER(WIN2_EMPTY, vop->dev);
4119     ERROR_HANDLER(WIN3_EMPTY, vop->dev);
4120     ERROR_HANDLER(HWC_EMPTY, vop->dev);
4121     ERROR_HANDLER(POST_BUF_EMPTY, vop->dev);
4122 
4123     /* Unhandled irqs are spurious. */
4124     if (active_irqs) {
4125         DRM_ERROR("Unknown VOP IRQs: %#02x\n", active_irqs);
4126     }
4127 
4128 out_disable:
4129     vop_core_clks_disable(vop);
4130 out:
4131     pm_runtime_put(vop->dev);
4132     return ret;
4133 }
4134 
vop_plane_add_properties(struct vop * vop,struct drm_plane * plane,const struct vop_win * win)4135 static void vop_plane_add_properties(struct vop *vop, struct drm_plane *plane, const struct vop_win *win)
4136 {
4137     unsigned int flags = 0;
4138 
4139     flags |= (VOP_WIN_SUPPORT(vop, win, xmirror)) ? DRM_MODE_REFLECT_X : 0;
4140     flags |= (VOP_WIN_SUPPORT(vop, win, ymirror)) ? DRM_MODE_REFLECT_Y : 0;
4141     if (flags) {
4142         drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0, DRM_MODE_ROTATE_0 | flags);
4143     }
4144 }
4145 
vop_plane_create_name_property(struct vop * vop,struct vop_win * win)4146 static int vop_plane_create_name_property(struct vop *vop, struct vop_win *win)
4147 {
4148     struct drm_prop_enum_list *props = vop->plane_name_list;
4149     struct drm_property *prop;
4150     uint64_t bits = BIT_ULL(win->plane_id);
4151 
4152     prop = drm_property_create_bitmask(vop->drm_dev, DRM_MODE_PROP_IMMUTABLE, "NAME", props, vop->num_wins, bits);
4153     if (!prop) {
4154         DRM_DEV_ERROR(vop->dev, "create Name prop for %s failed\n", win->name);
4155         return -ENOMEM;
4156     }
4157     win->name_prop = prop;
4158     drm_object_attach_property(&win->base.base, win->name_prop, bits);
4159 
4160     return 0;
4161 }
4162 
vop_plane_init(struct vop * vop,struct vop_win * win,unsigned long possible_crtcs)4163 static int vop_plane_init(struct vop *vop, struct vop_win *win, unsigned long possible_crtcs)
4164 {
4165     struct rockchip_drm_private *private = vop->drm_dev->dev_private;
4166     unsigned int blend_caps =
4167         BIT(DRM_MODE_BLEND_PIXEL_NONE) | BIT(DRM_MODE_BLEND_PREMULTI) | BIT(DRM_MODE_BLEND_COVERAGE);
4168     const struct vop_data *vop_data = vop->data;
4169     uint64_t feature = 0;
4170     int ret;
4171 
4172     ret = drm_universal_plane_init(vop->drm_dev, &win->base, possible_crtcs, &vop_plane_funcs, win->data_formats,
4173                                    win->nformats, win->format_modifiers, win->type, win->name);
4174     if (ret) {
4175         DRM_ERROR("failed to initialize plane %d\n", ret);
4176         return ret;
4177     }
4178     drm_plane_helper_add(&win->base, &plane_helper_funcs);
4179 
4180     if (win->phy->scl) {
4181         feature |= BIT(ROCKCHIP_DRM_PLANE_FEATURE_SCALE);
4182     }
4183     if (VOP_WIN_SUPPORT(vop, win, src_alpha_ctl) || VOP_WIN_SUPPORT(vop, win, alpha_en)) {
4184         feature |= BIT(ROCKCHIP_DRM_PLANE_FEATURE_ALPHA);
4185     }
4186     if (win->feature & WIN_FEATURE_HDR2SDR) {
4187         feature |= BIT(ROCKCHIP_DRM_PLANE_FEATURE_HDR2SDR);
4188     }
4189     if (win->feature & WIN_FEATURE_SDR2HDR) {
4190         feature |= BIT(ROCKCHIP_DRM_PLANE_FEATURE_SDR2HDR);
4191     }
4192     if (win->feature & WIN_FEATURE_AFBDC) {
4193         feature |= BIT(ROCKCHIP_DRM_PLANE_FEATURE_AFBDC);
4194     }
4195 
4196     drm_object_attach_property(&win->base.base, vop->plane_feature_prop, feature);
4197     drm_object_attach_property(&win->base.base, private->eotf_prop, 0);
4198     drm_object_attach_property(&win->base.base, private->color_space_prop, 0);
4199     if (VOP_WIN_SUPPORT(vop, win, global_alpha_val)) {
4200         drm_plane_create_alpha_property(&win->base);
4201     }
4202     drm_object_attach_property(&win->base.base, private->async_commit_prop, 0);
4203 
4204     if (win->parent) {
4205         drm_object_attach_property(&win->base.base, private->share_id_prop, win->parent->base.base.id);
4206     } else {
4207         drm_object_attach_property(&win->base.base, private->share_id_prop, win->base.base.id);
4208     }
4209 
4210     drm_plane_create_blend_mode_property(&win->base, blend_caps);
4211     drm_plane_create_zpos_property(&win->base, win->win_id, 0, vop->num_wins - 1);
4212     vop_plane_create_name_property(vop, win);
4213 
4214     win->input_width_prop =
4215         drm_property_create_range(vop->drm_dev, DRM_MODE_PROP_IMMUTABLE, "INPUT_WIDTH", 0, vop_data->max_input.width);
4216     win->input_height_prop =
4217         drm_property_create_range(vop->drm_dev, DRM_MODE_PROP_IMMUTABLE, "INPUT_HEIGHT", 0, vop_data->max_input.height);
4218 
4219     win->output_width_prop =
4220         drm_property_create_range(vop->drm_dev, DRM_MODE_PROP_IMMUTABLE, "OUTPUT_WIDTH", 0, vop_data->max_input.width);
4221     win->output_height_prop = drm_property_create_range(vop->drm_dev, DRM_MODE_PROP_IMMUTABLE, "OUTPUT_HEIGHT", 0,
4222                                                         vop_data->max_input.height);
4223 
4224     win->scale_prop = drm_property_create_range(vop->drm_dev, DRM_MODE_PROP_IMMUTABLE, "SCALE_RATE", 0x8, 0x8);
4225     /*
4226      * Support 24 bit(RGB888) or 16 bit(rgb565) color key.
4227      * Bit 31 is used as a flag to disable (0) or enable
4228      * color keying (1).
4229      */
4230     win->color_key_prop = drm_property_create_range(vop->drm_dev, 0, "colorkey", 0, 0x80ffffff);
4231     if (!win->input_width_prop || !win->input_height_prop || !win->scale_prop || !win->color_key_prop) {
4232         DRM_ERROR("failed to create property\n");
4233         return -ENOMEM;
4234     }
4235 
4236     drm_object_attach_property(&win->base.base, win->input_width_prop, 0);
4237     drm_object_attach_property(&win->base.base, win->input_height_prop, 0);
4238     drm_object_attach_property(&win->base.base, win->output_width_prop, 0);
4239     drm_object_attach_property(&win->base.base, win->output_height_prop, 0);
4240     drm_object_attach_property(&win->base.base, win->scale_prop, 0);
4241     drm_object_attach_property(&win->base.base, win->color_key_prop, 0);
4242 
4243     return 0;
4244 }
4245 
vop_of_init_display_lut(struct vop * vop)4246 static int vop_of_init_display_lut(struct vop *vop)
4247 {
4248     struct device_node *node = vop->dev->of_node;
4249     struct device_node *dsp_lut;
4250     u32 lut_len = vop->lut_len;
4251     struct property *prop;
4252     int length, i, j;
4253     int ret;
4254 
4255     if (!vop->lut) {
4256         return -ENOMEM;
4257     }
4258 
4259     dsp_lut = of_parse_phandle(node, "dsp-lut", 0);
4260     if (!dsp_lut) {
4261         return -ENXIO;
4262     }
4263 
4264     prop = of_find_property(dsp_lut, "gamma-lut", &length);
4265     if (!prop) {
4266         dev_err(vop->dev, "failed to find gamma_lut\n");
4267         return -ENXIO;
4268     }
4269 
4270     length >>= 0x2;
4271 
4272     if (length != lut_len) {
4273         u32 r, g, b;
4274         u32 *lut = kmalloc_array(length, sizeof(*lut), GFP_KERNEL);
4275 
4276         if (!lut) {
4277             return -ENOMEM;
4278         }
4279         ret = of_property_read_u32_array(dsp_lut, "gamma-lut", lut, length);
4280         if (ret) {
4281             dev_err(vop->dev, "load gamma-lut failed\n");
4282             kfree(lut);
4283             return -EINVAL;
4284         }
4285 
4286         if (lut_len == 0 || length == 0) {
4287             return  -EPERM;
4288         }
4289         for (i = 0; i < lut_len; i++) {
4290             j = i * length / lut_len;
4291             r = lut[j] / length / length * lut_len / length;
4292             g = lut[j] / length % length * lut_len / length;
4293             b = lut[j] % length * lut_len / length;
4294 
4295             vop->lut[i] = r * lut_len * lut_len + g * lut_len + b;
4296         }
4297 
4298         kfree(lut);
4299     } else {
4300         of_property_read_u32_array(dsp_lut, "gamma-lut", vop->lut, vop->lut_len);
4301     }
4302     vop->lut_active = true;
4303 
4304     return 0;
4305 }
4306 
vop_crtc_create_plane_mask_property(struct vop * vop,struct drm_crtc * crtc)4307 static int vop_crtc_create_plane_mask_property(struct vop *vop, struct drm_crtc *crtc)
4308 {
4309     struct drm_property *prop;
4310 
4311     static const struct drm_prop_enum_list props[] = {
4312         {ROCKCHIP_VOP_WIN0, "Win0"},
4313         {ROCKCHIP_VOP_WIN1, "Win1"},
4314         {ROCKCHIP_VOP_WIN2, "Win2"},
4315         {ROCKCHIP_VOP_WIN3, "Win3"},
4316     };
4317 
4318     prop = drm_property_create_bitmask(vop->drm_dev, DRM_MODE_PROP_IMMUTABLE, "PLANE_MASK", props, ARRAY_SIZE(props),
4319                                        0xffffffff);
4320     if (!prop) {
4321         DRM_DEV_ERROR(vop->dev, "create plane_mask prop for vp%d failed\n", vop->id);
4322         return -ENOMEM;
4323     }
4324 
4325     vop->plane_mask_prop = prop;
4326     drm_object_attach_property(&crtc->base, vop->plane_mask_prop, vop->plane_mask);
4327 
4328     return 0;
4329 }
4330 
vop_crtc_create_feature_property(struct vop * vop,struct drm_crtc * crtc)4331 static int vop_crtc_create_feature_property(struct vop *vop, struct drm_crtc *crtc)
4332 {
4333     const struct vop_data *vop_data = vop->data;
4334 
4335     struct drm_property *prop;
4336     u64 feature = 0;
4337 
4338     static const struct drm_prop_enum_list props[] = {
4339         {ROCKCHIP_DRM_CRTC_FEATURE_ALPHA_SCALE, "ALPHA_SCALE"},
4340         {ROCKCHIP_DRM_CRTC_FEATURE_HDR10, "HDR10"},
4341         {ROCKCHIP_DRM_CRTC_FEATURE_NEXT_HDR, "NEXT_HDR"},
4342     };
4343 
4344     if (vop_data->feature & VOP_FEATURE_ALPHA_SCALE) {
4345         feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_ALPHA_SCALE);
4346     }
4347     if (vop_data->feature & VOP_FEATURE_HDR10) {
4348         feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_HDR10);
4349     }
4350     if (vop_data->feature & VOP_FEATURE_NEXT_HDR) {
4351         feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_NEXT_HDR);
4352     }
4353 
4354     prop = drm_property_create_bitmask(vop->drm_dev, DRM_MODE_PROP_IMMUTABLE, "FEATURE", props, ARRAY_SIZE(props),
4355                                        0xffffffff);
4356     if (!prop) {
4357         DRM_DEV_ERROR(vop->dev, "create FEATURE prop for vop%d failed\n", vop->id);
4358         return -ENOMEM;
4359     }
4360 
4361     vop->feature_prop = prop;
4362     drm_object_attach_property(&crtc->base, vop->feature_prop, feature);
4363 
4364     return 0;
4365 }
4366 
vop_create_crtc(struct vop * vop)4367 static int vop_create_crtc(struct vop *vop)
4368 {
4369     struct device *dev = vop->dev;
4370     struct drm_device *drm_dev = vop->drm_dev;
4371     struct rockchip_drm_private *private = drm_dev->dev_private;
4372     struct drm_plane *primary = NULL, *cursor = NULL, *plane, *tmp;
4373     struct drm_crtc *crtc = &vop->rockchip_crtc.crtc;
4374     struct device_node *port;
4375     int ret = 0;
4376     int i;
4377 
4378     /*
4379      * Create drm_plane for primary and cursor planes first, since we need
4380      * to pass them to drm_crtc_init_with_planes, which sets the
4381      * "possible_crtcs" to the newly initialized crtc.
4382      */
4383     for (i = 0; i < vop->num_wins; i++) {
4384         struct vop_win *win = &vop->win[i];
4385 
4386         if (win->type != DRM_PLANE_TYPE_PRIMARY && win->type != DRM_PLANE_TYPE_CURSOR) {
4387             continue;
4388         }
4389 
4390         if (vop_plane_init(vop, win, 0)) {
4391             DRM_DEV_ERROR(vop->dev, "failed to init plane\n");
4392             goto err_cleanup_planes;
4393         }
4394 
4395         plane = &win->base;
4396         if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
4397             primary = plane;
4398         } else if (plane->type == DRM_PLANE_TYPE_CURSOR) {
4399             cursor = plane;
4400         }
4401     }
4402 
4403     ret = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor, &vop_crtc_funcs, NULL);
4404     if (ret) {
4405         goto err_cleanup_planes;
4406     }
4407 
4408     drm_crtc_helper_add(crtc, &vop_crtc_helper_funcs);
4409 
4410     /*
4411      * Create drm_planes for overlay windows with possible_crtcs restricted
4412      * to the newly created crtc.
4413      */
4414     for (i = 0; i < vop->num_wins; i++) {
4415         struct vop_win *win = &vop->win[i];
4416         unsigned long possible_crtcs = drm_crtc_mask(crtc);
4417 
4418         if (win->type != DRM_PLANE_TYPE_OVERLAY) {
4419             continue;
4420         }
4421 
4422         if (vop_plane_init(vop, win, possible_crtcs)) {
4423             DRM_DEV_ERROR(vop->dev, "failed to init overlay\n");
4424             goto err_cleanup_crtc;
4425         }
4426         vop_plane_add_properties(vop, &win->base, win);
4427     }
4428 
4429     port = of_get_child_by_name(dev->of_node, "port");
4430     if (!port) {
4431         DRM_DEV_ERROR(vop->dev, "no port node found in %pOF\n", dev->of_node);
4432         ret = -ENOENT;
4433         goto err_cleanup_crtc;
4434     }
4435 
4436     drm_flip_work_init(&vop->fb_unref_work, "fb_unref", vop_fb_unref_worker);
4437 
4438     init_completion(&vop->dsp_hold_completion);
4439     init_completion(&vop->line_flag_completion);
4440     crtc->port = port;
4441     rockchip_register_crtc_funcs(crtc, &private_crtc_funcs);
4442 
4443     drm_object_attach_property(&crtc->base, private->soc_id_prop, vop->soc_id);
4444     drm_object_attach_property(&crtc->base, private->port_id_prop, vop->id);
4445     drm_object_attach_property(&crtc->base, private->aclk_prop, 0);
4446     drm_object_attach_property(&crtc->base, private->bg_prop, 0);
4447     drm_object_attach_property(&crtc->base, private->line_flag_prop, 0);
4448 
4449 #define VOP_ATTACH_MODE_CONFIG_PROP(prop, v) drm_object_attach_property(&crtc->base, drm_dev->mode_config.prop, v)
4450 
4451     VOP_ATTACH_MODE_CONFIG_PROP(tv_left_margin_property, 0x64);
4452     VOP_ATTACH_MODE_CONFIG_PROP(tv_right_margin_property, 0x64);
4453     VOP_ATTACH_MODE_CONFIG_PROP(tv_top_margin_property, 0x64);
4454     VOP_ATTACH_MODE_CONFIG_PROP(tv_bottom_margin_property, 0x64);
4455 #undef VOP_ATTACH_MODE_CONFIG_PROP
4456     vop_crtc_create_plane_mask_property(vop, crtc);
4457     vop_crtc_create_feature_property(vop, crtc);
4458 
4459     if (vop->lut_regs) {
4460         u16 *r_base, *g_base, *b_base;
4461         u32 lut_len = vop->lut_len;
4462 
4463         vop->lut = devm_kmalloc_array(dev, lut_len, sizeof(*vop->lut), GFP_KERNEL);
4464         if (!vop->lut) {
4465             goto err_unregister_crtc_funcs;
4466         }
4467 
4468         if (vop_of_init_display_lut(vop)) {
4469             for (i = 0; i < lut_len; i++) {
4470                 u32 r = i * lut_len * lut_len;
4471                 u32 g = i * lut_len;
4472                 u32 b = i;
4473 
4474                 vop->lut[i] = r | g | b;
4475             }
4476         }
4477 
4478         drm_mode_crtc_set_gamma_size(crtc, lut_len);
4479         drm_crtc_enable_color_mgmt(crtc, 0, false, lut_len);
4480         r_base = crtc->gamma_store;
4481         g_base = r_base + crtc->gamma_size;
4482         b_base = g_base + crtc->gamma_size;
4483 
4484         for (i = 0; i < lut_len; i++) {
4485             rockchip_vop_crtc_fb_gamma_get(crtc, &r_base[i], &g_base[i], &b_base[i], i);
4486         }
4487     }
4488     return 0;
4489 
4490 err_unregister_crtc_funcs:
4491     rockchip_unregister_crtc_funcs(crtc);
4492 err_cleanup_crtc:
4493     drm_crtc_cleanup(crtc);
4494 err_cleanup_planes:
4495     list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list, head) drm_plane_cleanup(plane);
4496     return ret;
4497 }
4498 
vop_destroy_crtc(struct vop * vop)4499 static void vop_destroy_crtc(struct vop *vop)
4500 {
4501     struct drm_crtc *crtc = &vop->rockchip_crtc.crtc;
4502     struct drm_device *drm_dev = vop->drm_dev;
4503     struct drm_plane *plane, *tmp;
4504 
4505     of_node_put(crtc->port);
4506 
4507     /*
4508      * We need to cleanup the planes now.  Why?
4509      *
4510      * The planes are "&vop->win[i].base".  That means the memory is
4511      * all part of the big "struct vop" chunk of memory.  That memory
4512      * was devm allocated and associated with this component.  We need to
4513      * free it ourselves before vop_unbind() finishes.
4514      */
4515     list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list, head) vop_plane_destroy(plane);
4516 
4517     /*
4518      * Destroy CRTC after vop_plane_destroy() since vop_disable_plane()
4519      * references the CRTC.
4520      */
4521     drm_crtc_cleanup(crtc);
4522     drm_flip_work_cleanup(&vop->fb_unref_work);
4523 }
4524 
4525 /*
4526  * Win_id is the order in vop_win_data array.
4527  * This is related to the actual hardware plane.
4528  * But in the Linux platform, such as video hardware and camera preview,
4529  * it can only be played on the nv12 plane.
4530  * So set the order of zpos to PRIMARY < OVERLAY (if have) < CURSOR (if have).
4531  */
vop_plane_get_zpos(enum drm_plane_type type,unsigned int size)4532 static int vop_plane_get_zpos(enum drm_plane_type type, unsigned int size)
4533 {
4534     switch (type) {
4535         case DRM_PLANE_TYPE_PRIMARY:
4536             return 0;
4537         case DRM_PLANE_TYPE_OVERLAY:
4538             return 1;
4539         case DRM_PLANE_TYPE_CURSOR:
4540             return size - 1;
4541     }
4542     return 0;
4543 }
4544 
4545 /*
4546  * Initialize the vop->win array elements.
4547  */
vop_win_init(struct vop * vop)4548 static int vop_win_init(struct vop *vop)
4549 {
4550     const struct vop_data *vop_data = vop->data;
4551     unsigned int i, j, ret;
4552     unsigned int num_wins = 0;
4553     char name[DRM_PROP_NAME_LEN];
4554     uint8_t plane_id = 0;
4555     struct drm_prop_enum_list *plane_name_list;
4556     static const struct drm_prop_enum_list props[] = {
4557         {ROCKCHIP_DRM_PLANE_FEATURE_SCALE, "scale"},     {ROCKCHIP_DRM_PLANE_FEATURE_ALPHA, "alpha"},
4558         {ROCKCHIP_DRM_PLANE_FEATURE_HDR2SDR, "hdr2sdr"}, {ROCKCHIP_DRM_PLANE_FEATURE_SDR2HDR, "sdr2hdr"},
4559         {ROCKCHIP_DRM_PLANE_FEATURE_AFBDC, "afbdc"},
4560     };
4561 
4562     for (i = 0; i < vop_data->win_size; i++) {
4563         struct vop_win *vop_win = &vop->win[num_wins];
4564         const struct vop_win_data *win_data = &vop_data->win[i];
4565 
4566         if (!win_data->phy) {
4567             continue;
4568         }
4569 
4570         vop_win->phy = win_data->phy;
4571         vop_win->csc = win_data->csc;
4572         vop_win->offset = win_data->base;
4573         vop_win->type = win_data->type;
4574         vop_win->data_formats = win_data->phy->data_formats;
4575         vop_win->nformats = win_data->phy->nformats;
4576         vop_win->format_modifiers = win_data->format_modifiers;
4577         vop_win->feature = win_data->feature;
4578         vop_win->vop = vop;
4579         vop_win->win_id = i;
4580         vop_win->area_id = 0;
4581         vop_win->plane_id = plane_id++;
4582         ret = snprintf(name, sizeof(name), "VOP%d-win%d-%d", vop->id, vop_win->win_id, vop_win->area_id);
4583         vop_win->name = devm_kstrdup(vop->dev, name, GFP_KERNEL);
4584         vop_win->zpos = vop_plane_get_zpos(win_data->type, vop_data->win_size);
4585 
4586         num_wins++;
4587 
4588         if (!vop->support_multi_area) {
4589             continue;
4590         }
4591 
4592         for (j = 0; j < win_data->area_size; j++) {
4593             struct vop_win *vop_area = &vop->win[num_wins];
4594             const struct vop_win_phy *area = win_data->area[j];
4595 
4596             vop_area->parent = vop_win;
4597             vop_area->offset = vop_win->offset;
4598             vop_area->phy = area;
4599             vop_area->type = DRM_PLANE_TYPE_OVERLAY;
4600             vop_area->data_formats = vop_win->data_formats;
4601             vop_area->nformats = vop_win->nformats;
4602             vop_area->format_modifiers = win_data->format_modifiers;
4603             vop_area->vop = vop;
4604             vop_area->win_id = i;
4605             vop_area->area_id = j + 1;
4606             vop_area->plane_id = plane_id++;
4607             ret = snprintf(name, sizeof(name), "VOP%d-win%d-%d", vop->id, vop_area->win_id, vop_area->area_id);
4608             vop_area->name = devm_kstrdup(vop->dev, name, GFP_KERNEL);
4609             num_wins++;
4610         }
4611         vop->plane_mask |= BIT(vop_win->win_id);
4612     }
4613 
4614     vop->num_wins = num_wins;
4615 
4616     vop->plane_feature_prop = drm_property_create_bitmask(
4617         vop->drm_dev, DRM_MODE_PROP_IMMUTABLE, "FEATURE", props, ARRAY_SIZE(props),
4618         BIT(ROCKCHIP_DRM_PLANE_FEATURE_SCALE) | BIT(ROCKCHIP_DRM_PLANE_FEATURE_ALPHA) |
4619             BIT(ROCKCHIP_DRM_PLANE_FEATURE_HDR2SDR) | BIT(ROCKCHIP_DRM_PLANE_FEATURE_SDR2HDR) |
4620             BIT(ROCKCHIP_DRM_PLANE_FEATURE_AFBDC));
4621     if (!vop->plane_feature_prop) {
4622         DRM_ERROR("failed to create feature property\n");
4623         return -EINVAL;
4624     }
4625 
4626     plane_name_list = devm_kzalloc(vop->dev, vop->num_wins * sizeof(*plane_name_list), GFP_KERNEL);
4627     if (!plane_name_list) {
4628         DRM_DEV_ERROR(vop->dev, "failed to alloc memory for plane_name_list\n");
4629         return -ENOMEM;
4630     }
4631 
4632     for (i = 0; i < vop->num_wins; i++) {
4633         struct vop_win *vop_win = &vop->win[i];
4634 
4635         plane_name_list[i].type = vop_win->plane_id;
4636         plane_name_list[i].name = vop_win->name;
4637     }
4638 
4639     vop->plane_name_list = plane_name_list;
4640 
4641     return 0;
4642 }
4643 
4644 /**
4645  * rockchip_drm_wait_vact_end
4646  * @crtc: CRTC to enable line flag
4647  * @mstimeout: millisecond for timeout
4648  *
4649  * Wait for vact_end line flag irq or timeout.
4650  *
4651  * Returns:
4652  * Zero on success, negative errno on failure.
4653  */
rockchip_drm_wait_vact_end(struct drm_crtc * crtc,unsigned int mstimeout)4654 int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout)
4655 {
4656     struct vop *vop = to_vop(crtc);
4657     unsigned long jiffies_left;
4658     int ret = 0;
4659 
4660     if (!crtc || !vop->is_enabled) {
4661         return -ENODEV;
4662     }
4663 
4664     mutex_lock(&vop->vop_lock);
4665     if (mstimeout <= 0) {
4666         ret = -EINVAL;
4667         goto out;
4668     }
4669 
4670     if (vop_line_flag_irq_is_enabled(vop)) {
4671         ret = -EBUSY;
4672         goto out;
4673     }
4674 
4675     reinit_completion(&vop->line_flag_completion);
4676     vop_line_flag_irq_enable(vop);
4677 
4678     jiffies_left = wait_for_completion_timeout(&vop->line_flag_completion, msecs_to_jiffies(mstimeout));
4679     vop_line_flag_irq_disable(vop);
4680 
4681     if (jiffies_left == 0) {
4682         DRM_DEV_ERROR(vop->dev, "Timeout waiting for IRQ\n");
4683         ret = -ETIMEDOUT;
4684         goto out;
4685     }
4686 
4687 out:
4688     mutex_unlock(&vop->vop_lock);
4689     return ret;
4690 }
4691 EXPORT_SYMBOL(rockchip_drm_wait_vact_end);
4692 
vop_bind(struct device * dev,struct device * master,void * data)4693 static int vop_bind(struct device *dev, struct device *master, void *data)
4694 {
4695     struct platform_device *pdev = to_platform_device(dev);
4696     const struct vop_data *vop_data;
4697     struct drm_device *drm_dev = data;
4698     struct vop *vop;
4699     struct resource *res;
4700     size_t alloc_size;
4701     int ret, irq, i;
4702     int num_wins = 0;
4703     bool dual_channel_swap = false;
4704     struct device_node *mcu = NULL;
4705 
4706     vop_data = of_device_get_match_data(dev);
4707     if (!vop_data) {
4708         return -ENODEV;
4709     }
4710 
4711     for (i = 0; i < vop_data->win_size; i++) {
4712         const struct vop_win_data *win_data = &vop_data->win[i];
4713 
4714         num_wins += win_data->area_size + 1;
4715     }
4716 
4717     /* Allocate vop struct and its vop_win array */
4718     alloc_size = sizeof(*vop) + sizeof(*vop->win) * num_wins;
4719     vop = devm_kzalloc(dev, alloc_size, GFP_KERNEL);
4720     if (!vop) {
4721         return -ENOMEM;
4722     }
4723 
4724     vop->dev = dev;
4725     vop->data = vop_data;
4726     vop->drm_dev = drm_dev;
4727     vop->num_wins = num_wins;
4728     vop->version = vop_data->version;
4729     vop->soc_id = vop_data->soc_id;
4730     vop->id = vop_data->vop_id;
4731     dev_set_drvdata(dev, vop);
4732     vop->support_multi_area = of_property_read_bool(dev->of_node, "support-multi-area");
4733 
4734     ret = vop_win_init(vop);
4735     if (ret) {
4736         return ret;
4737     }
4738 
4739     res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
4740     if (!res) {
4741         dev_warn(vop->dev, "failed to get vop register byname\n");
4742         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
4743     }
4744     vop->regs = devm_ioremap_resource(dev, res);
4745     if (IS_ERR(vop->regs)) {
4746         return PTR_ERR(vop->regs);
4747     }
4748     vop->len = resource_size(res);
4749 
4750     vop->regsbak = devm_kzalloc(dev, vop->len, GFP_KERNEL);
4751     if (!vop->regsbak) {
4752         return -ENOMEM;
4753     }
4754 
4755     res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gamma_lut");
4756     if (res) {
4757         vop->lut_len = resource_size(res) / sizeof(*vop->lut);
4758         if (vop->lut_len != 0x100 && vop->lut_len != 0x400) {
4759             dev_err(vop->dev, "unsupported lut sizes %d\n", vop->lut_len);
4760             return -EINVAL;
4761         }
4762 
4763         vop->lut_regs = devm_ioremap_resource(dev, res);
4764         if (IS_ERR(vop->lut_regs)) {
4765             return PTR_ERR(vop->lut_regs);
4766         }
4767     }
4768     vop->grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
4769     if (IS_ERR(vop->grf)) {
4770         dev_err(dev, "missing rockchip,grf property\n");
4771     }
4772     vop->hclk = devm_clk_get(vop->dev, "hclk_vop");
4773     if (IS_ERR(vop->hclk)) {
4774         dev_err(vop->dev, "failed to get hclk source\n");
4775         return PTR_ERR(vop->hclk);
4776     }
4777     vop->aclk = devm_clk_get(vop->dev, "aclk_vop");
4778     if (IS_ERR(vop->aclk)) {
4779         dev_err(vop->dev, "failed to get aclk source\n");
4780         return PTR_ERR(vop->aclk);
4781     }
4782     vop->dclk = devm_clk_get(vop->dev, "dclk_vop");
4783     if (IS_ERR(vop->dclk)) {
4784         dev_err(vop->dev, "failed to get dclk source\n");
4785         return PTR_ERR(vop->dclk);
4786     }
4787     vop->dclk_source = devm_clk_get(vop->dev, "dclk_source");
4788     if (PTR_ERR(vop->dclk_source) == -ENOENT) {
4789         vop->dclk_source = NULL;
4790     } else if (PTR_ERR(vop->dclk_source) == -EPROBE_DEFER) {
4791         return -EPROBE_DEFER;
4792     } else if (IS_ERR(vop->dclk_source)) {
4793         dev_err(vop->dev, "failed to get dclk source parent\n");
4794         return PTR_ERR(vop->dclk_source);
4795     }
4796     irq = platform_get_irq(pdev, 0);
4797     if (irq < 0) {
4798         DRM_DEV_ERROR(dev, "cannot find irq for vop\n");
4799         return irq;
4800     }
4801     vop->irq = (unsigned int)irq;
4802 
4803     spin_lock_init(&vop->reg_lock);
4804     spin_lock_init(&vop->irq_lock);
4805     mutex_init(&vop->vop_lock);
4806 
4807     ret = devm_request_irq(dev, vop->irq, vop_isr, IRQF_SHARED, dev_name(dev), vop);
4808     if (ret) {
4809         return ret;
4810     }
4811     ret = vop_create_crtc(vop);
4812     if (ret) {
4813         return ret;
4814     }
4815 
4816     pm_runtime_enable(&pdev->dev);
4817 
4818     mcu = of_get_child_by_name(dev->of_node, "mcu-timing");
4819     if (!mcu) {
4820         dev_dbg(dev, "no mcu-timing node found in %s\n", dev->of_node->full_name);
4821     } else {
4822         u32 val;
4823 
4824         if (!of_property_read_u32(mcu, "mcu-pix-total", &val)) {
4825             vop->mcu_timing.mcu_pix_total = val;
4826         }
4827         if (!of_property_read_u32(mcu, "mcu-cs-pst", &val)) {
4828             vop->mcu_timing.mcu_cs_pst = val;
4829         }
4830         if (!of_property_read_u32(mcu, "mcu-cs-pend", &val)) {
4831             vop->mcu_timing.mcu_cs_pend = val;
4832         }
4833         if (!of_property_read_u32(mcu, "mcu-rw-pst", &val)) {
4834             vop->mcu_timing.mcu_rw_pst = val;
4835         }
4836         if (!of_property_read_u32(mcu, "mcu-rw-pend", &val)) {
4837             vop->mcu_timing.mcu_rw_pend = val;
4838         }
4839         if (!of_property_read_u32(mcu, "mcu-hold-mode", &val)) {
4840             vop->mcu_timing.mcu_hold_mode = val;
4841         }
4842     }
4843 
4844     dual_channel_swap = of_property_read_bool(dev->of_node, "rockchip,dual-channel-swap");
4845     vop->dual_channel_swap = dual_channel_swap;
4846 
4847     return 0;
4848 }
4849 
vop_unbind(struct device * dev,struct device * master,void * data)4850 static void vop_unbind(struct device *dev, struct device *master, void *data)
4851 {
4852     struct vop *vop = dev_get_drvdata(dev);
4853 
4854     pm_runtime_disable(dev);
4855     vop_destroy_crtc(vop);
4856 }
4857 
4858 const struct component_ops vop_component_ops = {
4859     .bind = vop_bind,
4860     .unbind = vop_unbind,
4861 };
4862 EXPORT_SYMBOL_GPL(vop_component_ops);
4863