@@ -206,6 +206,8 @@ struct vop {
206206 u32 * lut ;
207207 u32 lut_len ;
208208 bool lut_active ;
209+ void __iomem * cabc_lut_regs ;
210+ u32 cabc_lut_len ;
209211
210212 /* one time only one process allowed to config the register */
211213 spinlock_t reg_lock ;
@@ -353,6 +355,11 @@ static inline uint32_t vop_read_lut(struct vop *vop, uint32_t offset)
353355 return readl (vop -> lut_regs + offset );
354356}
355357
358+ static inline void vop_write_cabc_lut (struct vop * vop , uint32_t offset , uint32_t v )
359+ {
360+ writel (v , vop -> cabc_lut_regs + offset );
361+ }
362+
356363static bool has_rb_swapped (uint32_t format )
357364{
358365 switch (format ) {
@@ -1795,6 +1802,13 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
17951802 VOP_CTRL_SET (vop , core_dclk_div ,
17961803 !!(adjusted_mode -> flags & DRM_MODE_FLAG_DBLCLK ));
17971804
1805+ VOP_CTRL_SET (vop , cabc_total_num , hdisplay * vdisplay );
1806+ VOP_CTRL_SET (vop , cabc_config_mode , STAGE_BY_STAGE );
1807+ VOP_CTRL_SET (vop , cabc_stage_up_mode , MUL_MODE );
1808+ VOP_CTRL_SET (vop , cabc_scale_cfg_value , 1 );
1809+ VOP_CTRL_SET (vop , cabc_scale_cfg_enable , 0 );
1810+ VOP_CTRL_SET (vop , cabc_global_dn_limit_en , 1 );
1811+
17981812 clk_set_rate (vop -> dclk , adjusted_mode -> crtc_clock * 1000 );
17991813
18001814 vop_cfg_done (vop );
@@ -2041,6 +2055,86 @@ static void vop_post_config(struct drm_crtc *crtc)
20412055 }
20422056}
20432057
2058+ static void vop_update_cabc_lut (struct drm_crtc * crtc ,
2059+ struct drm_crtc_state * old_crtc_state )
2060+ {
2061+ struct rockchip_crtc_state * s =
2062+ to_rockchip_crtc_state (crtc -> state );
2063+ struct rockchip_crtc_state * old_s =
2064+ to_rockchip_crtc_state (old_crtc_state );
2065+ struct drm_property_blob * cabc_lut = s -> cabc_lut ;
2066+ struct drm_property_blob * old_cabc_lut = old_s -> cabc_lut ;
2067+ struct vop * vop = to_vop (crtc );
2068+ int lut_size ;
2069+ u32 * lut ;
2070+ u32 lut_len = vop -> cabc_lut_len ;
2071+ int i , dle ;
2072+
2073+ if (!cabc_lut && old_cabc_lut ) {
2074+ VOP_CTRL_SET (vop , cabc_lut_en , 0 );
2075+ return ;
2076+ }
2077+ if (!cabc_lut )
2078+ return ;
2079+
2080+ if (old_cabc_lut && old_cabc_lut -> base .id == cabc_lut -> base .id )
2081+ return ;
2082+
2083+ lut = (u32 * )cabc_lut -> data ;
2084+ lut_size = cabc_lut -> length / sizeof (u32 );
2085+ if (WARN (lut_size != lut_len , "Unexpect cabc lut size not match\n" ))
2086+ return ;
2087+
2088+ #define CTRL_GET (name ) VOP_CTRL_GET(vop, name)
2089+ if (CTRL_GET (cabc_lut_en )) {
2090+ VOP_CTRL_SET (vop , cabc_lut_en , 0 );
2091+ vop_cfg_done (vop );
2092+ readx_poll_timeout (CTRL_GET , cabc_lut_en , dle , !dle , 5 , 33333 );
2093+ }
2094+
2095+ for (i = 0 ; i < lut_len ; i ++ )
2096+ vop_write_cabc_lut (vop , (i << 2 ), lut [i ]);
2097+ #undef CTRL_GET
2098+ VOP_CTRL_SET (vop , cabc_lut_en , 1 );
2099+ }
2100+
2101+ static void vop_update_cabc (struct drm_crtc * crtc ,
2102+ struct drm_crtc_state * old_crtc_state )
2103+ {
2104+ struct rockchip_crtc_state * s =
2105+ to_rockchip_crtc_state (crtc -> state );
2106+ struct vop * vop = to_vop (crtc );
2107+ struct drm_display_mode * mode = & crtc -> state -> adjusted_mode ;
2108+ int pixel_total = mode -> hdisplay * mode -> vdisplay ;
2109+
2110+ if (!vop -> cabc_lut_regs )
2111+ return ;
2112+
2113+ vop_update_cabc_lut (crtc , old_crtc_state );
2114+
2115+ if (s -> cabc_mode != ROCKCHIP_DRM_CABC_MODE_DISABLE ) {
2116+ VOP_CTRL_SET (vop , cabc_en , 1 );
2117+ VOP_CTRL_SET (vop , cabc_handle_en , 1 );
2118+ VOP_CTRL_SET (vop , cabc_stage_up , s -> cabc_stage_up );
2119+ VOP_CTRL_SET (vop , cabc_stage_down , s -> cabc_stage_down );
2120+ VOP_CTRL_SET (vop , cabc_global_dn , s -> cabc_global_dn );
2121+ VOP_CTRL_SET (vop , cabc_calc_pixel_num ,
2122+ s -> cabc_calc_pixel_num * pixel_total / 1000 );
2123+ } else {
2124+ /*
2125+ * There are some hardware issues on cabc disabling:
2126+ * 1: if cabc auto gating enable, cabc disabling will cause
2127+ * vop die
2128+ * 2: cabc disabling always would make timing several
2129+ * pixel cycle abnormal, cause some panel abnormal.
2130+ *
2131+ * So just keep cabc enable, and make it no work with max
2132+ * cabc_calc_pixel_num, it only has little power consume.
2133+ */
2134+ VOP_CTRL_SET (vop , cabc_calc_pixel_num , pixel_total );
2135+ }
2136+ }
2137+
20442138static void vop_cfg_update (struct drm_crtc * crtc ,
20452139 struct drm_crtc_state * old_crtc_state )
20462140{
@@ -2147,6 +2241,8 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
21472241 vop -> is_iommu_enabled = true;
21482242 }
21492243
2244+ vop_update_cabc (crtc , old_crtc_state );
2245+
21502246 vop_cfg_done (vop );
21512247
21522248 /*
@@ -2262,6 +2358,7 @@ static int vop_crtc_atomic_get_property(struct drm_crtc *crtc,
22622358 uint64_t * val )
22632359{
22642360 struct drm_device * drm_dev = crtc -> dev ;
2361+ struct rockchip_drm_private * private = drm_dev -> dev_private ;
22652362 struct drm_mode_config * mode_config = & drm_dev -> mode_config ;
22662363 struct rockchip_crtc_state * s = to_rockchip_crtc_state (state );
22672364
@@ -2285,6 +2382,36 @@ static int vop_crtc_atomic_get_property(struct drm_crtc *crtc,
22852382 return 0 ;
22862383 }
22872384
2385+ if (property == private -> cabc_mode_property ) {
2386+ * val = s -> cabc_mode ;
2387+ return 0 ;
2388+ }
2389+
2390+ if (property == private -> cabc_stage_up_property ) {
2391+ * val = s -> cabc_stage_up ;
2392+ return 0 ;
2393+ }
2394+
2395+ if (property == private -> cabc_stage_down_property ) {
2396+ * val = s -> cabc_stage_down ;
2397+ return 0 ;
2398+ }
2399+
2400+ if (property == private -> cabc_global_dn_property ) {
2401+ * val = s -> cabc_global_dn ;
2402+ return 0 ;
2403+ }
2404+
2405+ if (property == private -> cabc_calc_pixel_num_property ) {
2406+ * val = s -> cabc_calc_pixel_num ;
2407+ return 0 ;
2408+ }
2409+
2410+ if (property == private -> cabc_lut_property ) {
2411+ * val = s -> cabc_lut ? s -> cabc_lut -> base .id : 0 ;
2412+ return 0 ;
2413+ }
2414+
22882415 DRM_ERROR ("failed to get vop crtc property\n" );
22892416 return - EINVAL ;
22902417}
@@ -2295,8 +2422,10 @@ static int vop_crtc_atomic_set_property(struct drm_crtc *crtc,
22952422 uint64_t val )
22962423{
22972424 struct drm_device * drm_dev = crtc -> dev ;
2425+ struct rockchip_drm_private * private = drm_dev -> dev_private ;
22982426 struct drm_mode_config * mode_config = & drm_dev -> mode_config ;
22992427 struct rockchip_crtc_state * s = to_rockchip_crtc_state (state );
2428+ struct vop * vop = to_vop (crtc );
23002429
23012430 if (property == mode_config -> tv_left_margin_property ) {
23022431 s -> left_margin = val ;
@@ -2318,6 +2447,57 @@ static int vop_crtc_atomic_set_property(struct drm_crtc *crtc,
23182447 return 0 ;
23192448 }
23202449
2450+ if (property == private -> cabc_mode_property ) {
2451+ s -> cabc_mode = val ;
2452+ /*
2453+ * Pre-define lowpower and normal mode to make cabc
2454+ * easier to use.
2455+ */
2456+ if (s -> cabc_mode == ROCKCHIP_DRM_CABC_MODE_NORMAL ) {
2457+ s -> cabc_stage_up = 257 ;
2458+ s -> cabc_stage_down = 255 ;
2459+ s -> cabc_global_dn = 192 ;
2460+ s -> cabc_calc_pixel_num = 995 ;
2461+ } else if (s -> cabc_mode == ROCKCHIP_DRM_CABC_MODE_LOWPOWER ) {
2462+ s -> cabc_stage_up = 260 ;
2463+ s -> cabc_stage_down = 252 ;
2464+ s -> cabc_global_dn = 180 ;
2465+ s -> cabc_calc_pixel_num = 992 ;
2466+ }
2467+ return 0 ;
2468+ }
2469+
2470+ if (property == private -> cabc_stage_up_property ) {
2471+ s -> cabc_stage_up = val ;
2472+ return 0 ;
2473+ }
2474+
2475+ if (property == private -> cabc_stage_down_property ) {
2476+ s -> cabc_stage_down = val ;
2477+ return 0 ;
2478+ }
2479+
2480+ if (property == private -> cabc_calc_pixel_num_property ) {
2481+ s -> cabc_calc_pixel_num = val ;
2482+ return 0 ;
2483+ }
2484+
2485+ if (property == private -> cabc_global_dn_property ) {
2486+ s -> cabc_global_dn = val ;
2487+ return 0 ;
2488+ }
2489+
2490+ if (property == private -> cabc_lut_property ) {
2491+ bool replaced ;
2492+ ssize_t size = vop -> cabc_lut_len * 4 ;
2493+
2494+ return drm_atomic_replace_property_blob_from_id (crtc ,
2495+ & s -> cabc_lut ,
2496+ val ,
2497+ size ,
2498+ & replaced );
2499+ }
2500+
23212501 DRM_ERROR ("failed to set vop crtc property\n" );
23222502 return - EINVAL ;
23232503}
@@ -2502,6 +2682,7 @@ static int vop_create_crtc(struct vop *vop)
25022682 struct device * dev = vop -> dev ;
25032683 const struct vop_data * vop_data = vop -> data ;
25042684 struct drm_device * drm_dev = vop -> drm_dev ;
2685+ struct rockchip_drm_private * private = drm_dev -> dev_private ;
25052686 struct drm_plane * primary = NULL , * cursor = NULL , * plane , * tmp ;
25062687 struct drm_crtc * crtc = & vop -> crtc ;
25072688 struct device_node * port ;
@@ -2582,8 +2763,16 @@ static int vop_create_crtc(struct vop *vop)
25822763 VOP_ATTACH_MODE_CONFIG_PROP (tv_right_margin_property , 100 );
25832764 VOP_ATTACH_MODE_CONFIG_PROP (tv_top_margin_property , 100 );
25842765 VOP_ATTACH_MODE_CONFIG_PROP (tv_bottom_margin_property , 100 );
2766+
25852767#undef VOP_ATTACH_MODE_CONFIG_PROP
25862768
2769+ drm_object_attach_property (& crtc -> base , private -> cabc_lut_property , 0 );
2770+ drm_object_attach_property (& crtc -> base , private -> cabc_mode_property , 0 );
2771+ drm_object_attach_property (& crtc -> base , private -> cabc_stage_up_property , 0 );
2772+ drm_object_attach_property (& crtc -> base , private -> cabc_stage_down_property , 0 );
2773+ drm_object_attach_property (& crtc -> base , private -> cabc_global_dn_property , 0 );
2774+ drm_object_attach_property (& crtc -> base , private -> cabc_calc_pixel_num_property , 0 );
2775+
25872776 if (vop_data -> feature & VOP_FEATURE_AFBDC )
25882777 feature |= BIT (ROCKCHIP_DRM_CRTC_FEATURE_AFBDC );
25892778 drm_object_attach_property (& crtc -> base , vop -> feature_prop ,
@@ -2880,6 +3069,22 @@ static int vop_bind(struct device *dev, struct device *master, void *data)
28803069 }
28813070 }
28823071
3072+ res = platform_get_resource_byname (pdev , IORESOURCE_MEM , "cabc_lut" );
3073+ vop -> cabc_lut_regs = devm_ioremap_resource (dev , res );
3074+ if (IS_ERR (vop -> cabc_lut_regs )) {
3075+ dev_warn (vop -> dev , "failed to get vop cabc lut registers\n" );
3076+ vop -> cabc_lut_regs = NULL ;
3077+ }
3078+
3079+ if (vop -> cabc_lut_regs ) {
3080+ vop -> cabc_lut_len = resource_size (res ) >> 2 ;
3081+ if (vop -> cabc_lut_len != 128 ) {
3082+ dev_err (vop -> dev , "unsupport cabc lut sizes %d\n" ,
3083+ vop -> cabc_lut_len );
3084+ return - EINVAL ;
3085+ }
3086+ }
3087+
28833088 vop -> hclk = devm_clk_get (vop -> dev , "hclk_vop" );
28843089 if (IS_ERR (vop -> hclk )) {
28853090 dev_err (vop -> dev , "failed to get hclk source\n" );
0 commit comments