| .. | .. |
|---|
| 39 | 39 | #ifdef CONFIG_DRM_ANALOGIX_DP |
|---|
| 40 | 40 | #include <drm/bridge/analogix_dp.h> |
|---|
| 41 | 41 | #endif |
|---|
| 42 | | -#include <dt-bindings/soc/rockchip-system-status.h> |
|---|
| 43 | 42 | |
|---|
| 44 | 43 | #include <soc/rockchip/rockchip_dmc.h> |
|---|
| 45 | 44 | #include <soc/rockchip/rockchip-system-status.h> |
|---|
| .. | .. |
|---|
| 223 | 222 | struct dentry *debugfs; |
|---|
| 224 | 223 | struct drm_info_list *debugfs_files; |
|---|
| 225 | 224 | struct drm_property *plane_feature_prop; |
|---|
| 226 | | - struct drm_property *plane_mask_prop; |
|---|
| 227 | 225 | struct drm_property *feature_prop; |
|---|
| 228 | 226 | |
|---|
| 229 | 227 | bool is_iommu_enabled; |
|---|
| .. | .. |
|---|
| 238 | 236 | u32 background; |
|---|
| 239 | 237 | u32 line_flag; |
|---|
| 240 | 238 | u8 id; |
|---|
| 241 | | - u8 plane_mask; |
|---|
| 242 | 239 | u64 soc_id; |
|---|
| 243 | 240 | struct drm_prop_enum_list *plane_name_list; |
|---|
| 244 | 241 | |
|---|
| .. | .. |
|---|
| 318 | 315 | { MEDIA_BUS_FMT_UYYVYY8_0_5X24, "UYYVYY8_0_5X24" }, |
|---|
| 319 | 316 | { MEDIA_BUS_FMT_YUV10_1X30, "YUV10_1X30" }, |
|---|
| 320 | 317 | { MEDIA_BUS_FMT_UYYVYY10_0_5X30, "UYYVYY10_0_5X30" }, |
|---|
| 318 | + { MEDIA_BUS_FMT_RGB565_2X8_LE, "RGB565_2X8_LE" }, |
|---|
| 319 | + { MEDIA_BUS_FMT_RGB666_3X6, "RGB666_3X6" }, |
|---|
| 321 | 320 | { MEDIA_BUS_FMT_RGB888_3X8, "RGB888_3X8" }, |
|---|
| 322 | 321 | { MEDIA_BUS_FMT_RGB888_DUMMY_4X8, "RGB888_DUMMY_4X8" }, |
|---|
| 323 | 322 | { MEDIA_BUS_FMT_RGB888_1X24, "RGB888_1X24" }, |
|---|
| .. | .. |
|---|
| 463 | 462 | const struct vop_hdr_table *table = vop->data->hdr_table; |
|---|
| 464 | 463 | uint32_t sdr2hdr_eotf_oetf_yn[65]; |
|---|
| 465 | 464 | uint32_t sdr2hdr_oetf_dx_dxpow[64]; |
|---|
| 465 | + |
|---|
| 466 | + if (cmd != SDR2HDR_FOR_BT2020 && cmd != SDR2HDR_FOR_HDR && cmd != SDR2HDR_FOR_HLG_HDR) { |
|---|
| 467 | + DRM_WARN("unknown sdr2hdr oetf: %d\n", cmd); |
|---|
| 468 | + return; |
|---|
| 469 | + } |
|---|
| 466 | 470 | |
|---|
| 467 | 471 | for (i = 0; i < 65; i++) { |
|---|
| 468 | 472 | if (cmd == SDR2HDR_FOR_BT2020) |
|---|
| .. | .. |
|---|
| 666 | 670 | static bool is_rb_swap(uint32_t bus_format, uint32_t output_mode) |
|---|
| 667 | 671 | { |
|---|
| 668 | 672 | /* |
|---|
| 669 | | - * The default component order of serial rgb3x8 formats |
|---|
| 673 | + * The default component order of serial formats |
|---|
| 670 | 674 | * is BGR. So it is needed to enable RB swap. |
|---|
| 671 | 675 | */ |
|---|
| 672 | 676 | if (bus_format == MEDIA_BUS_FMT_RGB888_3X8 || |
|---|
| 673 | | - bus_format == MEDIA_BUS_FMT_RGB888_DUMMY_4X8) |
|---|
| 677 | + bus_format == MEDIA_BUS_FMT_RGB888_DUMMY_4X8 || |
|---|
| 678 | + bus_format == MEDIA_BUS_FMT_RGB666_3X6 || |
|---|
| 679 | + bus_format == MEDIA_BUS_FMT_RGB565_2X8_LE) |
|---|
| 674 | 680 | return true; |
|---|
| 675 | 681 | else |
|---|
| 676 | 682 | return false; |
|---|
| .. | .. |
|---|
| 1874 | 1880 | if (!old_state->crtc) |
|---|
| 1875 | 1881 | return; |
|---|
| 1876 | 1882 | |
|---|
| 1883 | + rockchip_drm_dbg(vop->dev, VOP_DEBUG_PLANE, "disable win%d-area%d by %s\n", |
|---|
| 1884 | + win->win_id, win->area_id, current->comm); |
|---|
| 1885 | + |
|---|
| 1877 | 1886 | spin_lock(&vop->reg_lock); |
|---|
| 1878 | 1887 | |
|---|
| 1879 | 1888 | vop_win_disable(vop, win); |
|---|
| .. | .. |
|---|
| 1980 | 1989 | uint32_t val; |
|---|
| 1981 | 1990 | bool rb_swap, global_alpha_en; |
|---|
| 1982 | 1991 | int is_yuv = fb->format->is_yuv; |
|---|
| 1992 | + struct drm_format_name_buf format_name; |
|---|
| 1983 | 1993 | |
|---|
| 1984 | 1994 | #if defined(CONFIG_ROCKCHIP_DRM_DEBUG) |
|---|
| 1985 | 1995 | bool AFBC_flag = false; |
|---|
| .. | .. |
|---|
| 2144 | 2154 | VOP_WIN_SET(vop, win, enable, 1); |
|---|
| 2145 | 2155 | VOP_WIN_SET(vop, win, gate, 1); |
|---|
| 2146 | 2156 | spin_unlock(&vop->reg_lock); |
|---|
| 2157 | + |
|---|
| 2158 | + drm_get_format_name(fb->format->format, &format_name); |
|---|
| 2159 | + rockchip_drm_dbg(vop->dev, VOP_DEBUG_PLANE, |
|---|
| 2160 | + "update win%d-area%d [%dx%d->%dx%d@(%d, %d)] zpos:%d fmt[%s%s] addr[%pad] by %s\n", |
|---|
| 2161 | + win->win_id, win->area_id, actual_w, actual_h, |
|---|
| 2162 | + dsp_w, dsp_h, dsp_stx, dsp_sty, vop_plane_state->zpos, format_name.str, |
|---|
| 2163 | + fb->modifier ? "[AFBC]" : "", &vop_plane_state->yrgb_mst, current->comm); |
|---|
| 2147 | 2164 | /* |
|---|
| 2148 | 2165 | * spi interface(vop_plane_state->yrgb_kvaddr, fb->pixel_format, |
|---|
| 2149 | 2166 | * actual_w, actual_h) |
|---|
| .. | .. |
|---|
| 2325 | 2342 | return; |
|---|
| 2326 | 2343 | |
|---|
| 2327 | 2344 | __drm_atomic_helper_plane_reset(plane, &vop_plane_state->base); |
|---|
| 2328 | | - win->state.zpos = win->zpos; |
|---|
| 2345 | + vop_plane_state->base.zpos = win->zpos; |
|---|
| 2329 | 2346 | vop_plane_state->global_alpha = 0xff; |
|---|
| 2330 | 2347 | } |
|---|
| 2331 | 2348 | |
|---|
| .. | .. |
|---|
| 2514 | 2531 | spin_unlock_irqrestore(&drm->event_lock, flags); |
|---|
| 2515 | 2532 | } |
|---|
| 2516 | 2533 | |
|---|
| 2517 | | -static int vop_crtc_loader_protect(struct drm_crtc *crtc, bool on) |
|---|
| 2534 | +static int vop_crtc_loader_protect(struct drm_crtc *crtc, bool on, void *data) |
|---|
| 2518 | 2535 | { |
|---|
| 2519 | 2536 | struct rockchip_drm_private *private = crtc->dev->dev_private; |
|---|
| 2520 | 2537 | struct vop *vop = to_vop(crtc); |
|---|
| .. | .. |
|---|
| 3078 | 3095 | { |
|---|
| 3079 | 3096 | struct vop *vop = to_vop(crtc); |
|---|
| 3080 | 3097 | const struct vop_data *vop_data = vop->data; |
|---|
| 3081 | | - struct rockchip_crtc_state *s = |
|---|
| 3082 | | - to_rockchip_crtc_state(crtc->state); |
|---|
| 3098 | + struct drm_crtc_state *new_crtc_state = container_of(mode, struct drm_crtc_state, mode); |
|---|
| 3099 | + struct rockchip_crtc_state *s = to_rockchip_crtc_state(new_crtc_state); |
|---|
| 3083 | 3100 | |
|---|
| 3084 | 3101 | if (mode->hdisplay > vop_data->max_output.width) |
|---|
| 3085 | 3102 | return false; |
|---|
| .. | .. |
|---|
| 3094 | 3111 | (VOP_MAJOR(vop->version) == 2 && VOP_MINOR(vop->version) >= 12 && |
|---|
| 3095 | 3112 | s->output_if & VOP_OUTPUT_IF_BT656)) |
|---|
| 3096 | 3113 | adj_mode->crtc_clock *= 2; |
|---|
| 3114 | + |
|---|
| 3115 | + if (vop->mcu_timing.mcu_pix_total) |
|---|
| 3116 | + adj_mode->crtc_clock *= rockchip_drm_get_cycles_per_pixel(s->bus_format) * |
|---|
| 3117 | + (vop->mcu_timing.mcu_pix_total + 1); |
|---|
| 3097 | 3118 | |
|---|
| 3098 | 3119 | adj_mode->crtc_clock = |
|---|
| 3099 | 3120 | DIV_ROUND_UP(clk_round_rate(vop->dclk, adj_mode->crtc_clock * 1000), |
|---|
| .. | .. |
|---|
| 3118 | 3139 | |
|---|
| 3119 | 3140 | switch (s->bus_format) { |
|---|
| 3120 | 3141 | case MEDIA_BUS_FMT_RGB565_1X16: |
|---|
| 3142 | + case MEDIA_BUS_FMT_RGB565_2X8_LE: |
|---|
| 3121 | 3143 | VOP_CTRL_SET(vop, dither_down_en, 1); |
|---|
| 3122 | 3144 | VOP_CTRL_SET(vop, dither_down_mode, RGB888_TO_RGB565); |
|---|
| 3123 | 3145 | break; |
|---|
| 3124 | 3146 | case MEDIA_BUS_FMT_RGB666_1X18: |
|---|
| 3125 | 3147 | case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: |
|---|
| 3126 | 3148 | case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: |
|---|
| 3149 | + case MEDIA_BUS_FMT_RGB666_3X6: |
|---|
| 3127 | 3150 | VOP_CTRL_SET(vop, dither_down_en, 1); |
|---|
| 3128 | 3151 | VOP_CTRL_SET(vop, dither_down_mode, RGB888_TO_RGB666); |
|---|
| 3129 | 3152 | break; |
|---|
| .. | .. |
|---|
| 3239 | 3262 | { |
|---|
| 3240 | 3263 | struct vop *vop = to_vop(crtc); |
|---|
| 3241 | 3264 | |
|---|
| 3265 | + /* |
|---|
| 3266 | + * If mcu_hold_mode is 1, set 1 to mcu_frame_st will |
|---|
| 3267 | + * refresh one frame from ddr. So mcu_frame_st is needed |
|---|
| 3268 | + * to be initialized as 0. |
|---|
| 3269 | + */ |
|---|
| 3270 | + VOP_CTRL_SET(vop, mcu_frame_st, 0); |
|---|
| 3242 | 3271 | VOP_CTRL_SET(vop, mcu_clk_sel, 1); |
|---|
| 3243 | 3272 | VOP_CTRL_SET(vop, mcu_type, 1); |
|---|
| 3244 | 3273 | |
|---|
| .. | .. |
|---|
| 4023 | 4052 | spin_lock_irqsave(&vop->irq_lock, flags); |
|---|
| 4024 | 4053 | vop->pre_overlay = s->hdr.pre_overlay; |
|---|
| 4025 | 4054 | vop_cfg_done(vop); |
|---|
| 4055 | + rockchip_drm_dbg(vop->dev, VOP_DEBUG_CFG_DONE, "cfg_done\n\n"); |
|---|
| 4026 | 4056 | /* |
|---|
| 4027 | 4057 | * rk322x and rk332x odd-even field will mistake when in interlace mode. |
|---|
| 4028 | 4058 | * we must switch to frame effect before switch screen and switch to |
|---|
| .. | .. |
|---|
| 4388 | 4418 | * frame effective, but actually it's effective immediately, so |
|---|
| 4389 | 4419 | * we config this register at frame start. |
|---|
| 4390 | 4420 | */ |
|---|
| 4421 | + rockchip_drm_dbg(vop->dev, VOP_DEBUG_VSYNC, "vsync\n"); |
|---|
| 4391 | 4422 | spin_lock_irqsave(&vop->irq_lock, flags); |
|---|
| 4392 | 4423 | VOP_CTRL_SET(vop, level2_overlay_en, vop->pre_overlay); |
|---|
| 4393 | 4424 | VOP_CTRL_SET(vop, alpha_hard_calc, vop->pre_overlay); |
|---|
| .. | .. |
|---|
| 4606 | 4637 | return 0; |
|---|
| 4607 | 4638 | } |
|---|
| 4608 | 4639 | |
|---|
| 4609 | | -static int vop_crtc_create_plane_mask_property(struct vop *vop, struct drm_crtc *crtc) |
|---|
| 4610 | | -{ |
|---|
| 4611 | | - struct drm_property *prop; |
|---|
| 4612 | | - |
|---|
| 4613 | | - static const struct drm_prop_enum_list props[] = { |
|---|
| 4614 | | - { ROCKCHIP_VOP_WIN0, "Win0" }, |
|---|
| 4615 | | - { ROCKCHIP_VOP_WIN1, "Win1" }, |
|---|
| 4616 | | - { ROCKCHIP_VOP_WIN2, "Win2" }, |
|---|
| 4617 | | - { ROCKCHIP_VOP_WIN3, "Win3" }, |
|---|
| 4618 | | - }; |
|---|
| 4619 | | - |
|---|
| 4620 | | - prop = drm_property_create_bitmask(vop->drm_dev, |
|---|
| 4621 | | - DRM_MODE_PROP_IMMUTABLE, "PLANE_MASK", |
|---|
| 4622 | | - props, ARRAY_SIZE(props), |
|---|
| 4623 | | - 0xffffffff); |
|---|
| 4624 | | - if (!prop) { |
|---|
| 4625 | | - DRM_DEV_ERROR(vop->dev, "create plane_mask prop for vp%d failed\n", vop->id); |
|---|
| 4626 | | - return -ENOMEM; |
|---|
| 4627 | | - } |
|---|
| 4628 | | - |
|---|
| 4629 | | - vop->plane_mask_prop = prop; |
|---|
| 4630 | | - drm_object_attach_property(&crtc->base, vop->plane_mask_prop, vop->plane_mask); |
|---|
| 4631 | | - |
|---|
| 4632 | | - return 0; |
|---|
| 4633 | | -} |
|---|
| 4634 | | - |
|---|
| 4635 | 4640 | static int vop_crtc_create_feature_property(struct vop *vop, struct drm_crtc *crtc) |
|---|
| 4636 | 4641 | { |
|---|
| 4637 | 4642 | const struct vop_data *vop_data = vop->data; |
|---|
| .. | .. |
|---|
| 4759 | 4764 | VOP_ATTACH_MODE_CONFIG_PROP(tv_top_margin_property, 100); |
|---|
| 4760 | 4765 | VOP_ATTACH_MODE_CONFIG_PROP(tv_bottom_margin_property, 100); |
|---|
| 4761 | 4766 | #undef VOP_ATTACH_MODE_CONFIG_PROP |
|---|
| 4762 | | - vop_crtc_create_plane_mask_property(vop, crtc); |
|---|
| 4763 | 4767 | vop_crtc_create_feature_property(vop, crtc); |
|---|
| 4764 | 4768 | ret = drm_self_refresh_helper_init(crtc); |
|---|
| 4765 | 4769 | if (ret) |
|---|
| .. | .. |
|---|
| 4928 | 4932 | vop_area->name = devm_kstrdup(vop->dev, name, GFP_KERNEL); |
|---|
| 4929 | 4933 | num_wins++; |
|---|
| 4930 | 4934 | } |
|---|
| 4931 | | - vop->plane_mask |= BIT(vop_win->win_id); |
|---|
| 4932 | 4935 | } |
|---|
| 4933 | 4936 | |
|---|
| 4934 | 4937 | vop->num_wins = num_wins; |
|---|