1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) Rockchip Electronics Co.Ltd
4 * Author: Andy Yan <andy.yan@rock-chips.com>
7 #include <linux/kernel.h>
8 #include <linux/component.h>
9 #include <linux/mod_devicetable.h>
10 #include <linux/platform_device.h>
12 #include <drm/drm_fourcc.h>
13 #include <drm/drm_plane.h>
14 #include <drm/drm_print.h>
16 #include "rockchip_drm_vop2.h"
18 static const uint32_t formats_win_full_10bit[] = {
32 static const uint32_t formats_win_full_10bit_yuyv[] = {
48 static const uint32_t formats_win_lite[] = {
59 static const uint64_t format_modifiers[] = {
60 DRM_FORMAT_MOD_LINEAR,
61 DRM_FORMAT_MOD_INVALID,
64 static const uint64_t format_modifiers_afbc[] = {
65 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16),
67 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
68 AFBC_FORMAT_MOD_SPARSE),
70 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
73 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
76 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
78 AFBC_FORMAT_MOD_SPARSE),
80 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
82 AFBC_FORMAT_MOD_SPARSE),
84 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
88 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
91 AFBC_FORMAT_MOD_SPARSE),
93 /* SPLIT mandates SPARSE, RGB modes mandates YTR */
94 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
96 AFBC_FORMAT_MOD_SPARSE |
97 AFBC_FORMAT_MOD_SPLIT),
98 DRM_FORMAT_MOD_INVALID,
101 static const struct vop2_video_port_data rk3568_vop_video_ports[] = {
104 .feature = VOP_FEATURE_OUTPUT_10BIT,
105 .gamma_lut_len = 1024,
106 .cubic_lut_len = 9 * 9 * 9,
107 .max_output = { 4096, 2304 },
108 .pre_scan_max_dly = { 69, 53, 53, 42 },
112 .gamma_lut_len = 1024,
113 .max_output = { 2048, 1536 },
114 .pre_scan_max_dly = { 40, 40, 40, 40 },
118 .gamma_lut_len = 1024,
119 .max_output = { 1920, 1080 },
120 .pre_scan_max_dly = { 40, 40, 40, 40 },
126 * rk3568 vop with 2 cluster, 2 esmart win, 2 smart win.
127 * Every cluster can work as 4K win or split into two win.
128 * All win in cluster support AFBCD.
130 * Every esmart win and smart win support 4 Multi-region.
134 * * Cluster: bicubic for horizontal scale up, others use bilinear
136 * * nearest-neighbor/bilinear/bicubic for scale up
137 * * nearest-neighbor/bilinear/average for scale down
140 * @TODO describe the wind like cpu-map dt nodes;
142 static const struct vop2_win_data rk3568_vop_win_data[] = {
144 .name = "Smart0-win0",
145 .phys_id = ROCKCHIP_VOP2_SMART0,
147 .formats = formats_win_lite,
148 .nformats = ARRAY_SIZE(formats_win_lite),
149 .format_modifiers = format_modifiers,
151 .supported_rotations = DRM_MODE_REFLECT_Y,
152 .type = DRM_PLANE_TYPE_PRIMARY,
153 .max_upscale_factor = 8,
154 .max_downscale_factor = 8,
155 .dly = { 20, 47, 41 },
157 .name = "Smart1-win0",
158 .phys_id = ROCKCHIP_VOP2_SMART1,
159 .formats = formats_win_lite,
160 .nformats = ARRAY_SIZE(formats_win_lite),
161 .format_modifiers = format_modifiers,
164 .supported_rotations = DRM_MODE_REFLECT_Y,
165 .type = DRM_PLANE_TYPE_PRIMARY,
166 .max_upscale_factor = 8,
167 .max_downscale_factor = 8,
168 .dly = { 20, 47, 41 },
170 .name = "Esmart1-win0",
171 .phys_id = ROCKCHIP_VOP2_ESMART1,
172 .formats = formats_win_full_10bit_yuyv,
173 .nformats = ARRAY_SIZE(formats_win_full_10bit_yuyv),
174 .format_modifiers = format_modifiers,
177 .supported_rotations = DRM_MODE_REFLECT_Y,
178 .type = DRM_PLANE_TYPE_PRIMARY,
179 .max_upscale_factor = 8,
180 .max_downscale_factor = 8,
181 .dly = { 20, 47, 41 },
183 .name = "Esmart0-win0",
184 .phys_id = ROCKCHIP_VOP2_ESMART0,
185 .formats = formats_win_full_10bit_yuyv,
186 .nformats = ARRAY_SIZE(formats_win_full_10bit_yuyv),
187 .format_modifiers = format_modifiers,
190 .supported_rotations = DRM_MODE_REFLECT_Y,
191 .type = DRM_PLANE_TYPE_PRIMARY,
192 .max_upscale_factor = 8,
193 .max_downscale_factor = 8,
194 .dly = { 20, 47, 41 },
196 .name = "Cluster0-win0",
197 .phys_id = ROCKCHIP_VOP2_CLUSTER0,
199 .formats = formats_win_full_10bit,
200 .nformats = ARRAY_SIZE(formats_win_full_10bit),
201 .format_modifiers = format_modifiers_afbc,
203 .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
204 DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
205 .max_upscale_factor = 4,
206 .max_downscale_factor = 4,
207 .dly = { 0, 27, 21 },
208 .type = DRM_PLANE_TYPE_OVERLAY,
209 .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
211 .name = "Cluster1-win0",
212 .phys_id = ROCKCHIP_VOP2_CLUSTER1,
214 .formats = formats_win_full_10bit,
215 .nformats = ARRAY_SIZE(formats_win_full_10bit),
216 .format_modifiers = format_modifiers_afbc,
218 .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
219 DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
220 .type = DRM_PLANE_TYPE_OVERLAY,
221 .max_upscale_factor = 4,
222 .max_downscale_factor = 4,
223 .dly = { 0, 27, 21 },
224 .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
228 static const struct vop2_data rk3566_vop = {
230 .max_input = { 4096, 2304 },
231 .max_output = { 4096, 2304 },
232 .vp = rk3568_vop_video_ports,
233 .win = rk3568_vop_win_data,
234 .win_size = ARRAY_SIZE(rk3568_vop_win_data),
238 static const struct vop2_data rk3568_vop = {
240 .max_input = { 4096, 2304 },
241 .max_output = { 4096, 2304 },
242 .vp = rk3568_vop_video_ports,
243 .win = rk3568_vop_win_data,
244 .win_size = ARRAY_SIZE(rk3568_vop_win_data),
248 static const struct of_device_id vop2_dt_match[] = {
250 .compatible = "rockchip,rk3566-vop",
253 .compatible = "rockchip,rk3568-vop",
258 MODULE_DEVICE_TABLE(of, vop2_dt_match);
260 static int vop2_probe(struct platform_device *pdev)
262 struct device *dev = &pdev->dev;
264 return component_add(dev, &vop2_component_ops);
267 static void vop2_remove(struct platform_device *pdev)
269 component_del(&pdev->dev, &vop2_component_ops);
272 struct platform_driver vop2_platform_driver = {
274 .remove_new = vop2_remove,
276 .name = "rockchip-vop2",
277 .of_match_table = of_match_ptr(vop2_dt_match),