xref: /linux/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c (revision ab475966455ce285c2c9978a3e3bfe97d75ff8d4)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) Rockchip Electronics Co.Ltd
4  * Author: Andy Yan <andy.yan@rock-chips.com>
5  */
6 
7 #include <linux/kernel.h>
8 #include <linux/component.h>
9 #include <linux/mod_devicetable.h>
10 #include <linux/platform_device.h>
11 #include <linux/of.h>
12 #include <drm/drm_fourcc.h>
13 #include <drm/drm_plane.h>
14 #include <drm/drm_print.h>
15 
16 #include "rockchip_drm_vop2.h"
17 
18 static const uint32_t formats_cluster[] = {
19 	DRM_FORMAT_XRGB2101010,
20 	DRM_FORMAT_ARGB2101010,
21 	DRM_FORMAT_XBGR2101010,
22 	DRM_FORMAT_ABGR2101010,
23 	DRM_FORMAT_XRGB8888,
24 	DRM_FORMAT_ARGB8888,
25 	DRM_FORMAT_XBGR8888,
26 	DRM_FORMAT_ABGR8888,
27 	DRM_FORMAT_RGB888,
28 	DRM_FORMAT_BGR888,
29 	DRM_FORMAT_RGB565,
30 	DRM_FORMAT_BGR565,
31 	DRM_FORMAT_YUV420_8BIT, /* yuv420_8bit non-Linear mode only */
32 	DRM_FORMAT_YUV420_10BIT, /* yuv420_10bit non-Linear mode only */
33 	DRM_FORMAT_YUYV, /* yuv422_8bit non-Linear mode only*/
34 	DRM_FORMAT_Y210, /* yuv422_10bit non-Linear mode only */
35 };
36 
37 static const uint32_t formats_rk356x_esmart[] = {
38 	DRM_FORMAT_XRGB8888,
39 	DRM_FORMAT_ARGB8888,
40 	DRM_FORMAT_XBGR8888,
41 	DRM_FORMAT_ABGR8888,
42 	DRM_FORMAT_RGB888,
43 	DRM_FORMAT_BGR888,
44 	DRM_FORMAT_RGB565,
45 	DRM_FORMAT_BGR565,
46 	DRM_FORMAT_NV12, /* yuv420_8bit linear mode, 2 plane */
47 	DRM_FORMAT_NV21, /* yuv420_8bit linear mode, 2 plane */
48 	DRM_FORMAT_NV15, /* yuv420_10bit linear mode, 2 plane, no padding */
49 	DRM_FORMAT_NV16, /* yuv422_8bit linear mode, 2 plane */
50 	DRM_FORMAT_NV61, /* yuv422_8bit linear mode, 2 plane */
51 	DRM_FORMAT_NV24, /* yuv444_8bit linear mode, 2 plane */
52 	DRM_FORMAT_NV42, /* yuv444_8bit linear mode, 2 plane */
53 	DRM_FORMAT_YVYU, /* yuv422_8bit[YVYU] linear mode */
54 	DRM_FORMAT_VYUY, /* yuv422_8bit[VYUY] linear mode */
55 };
56 
57 static const uint32_t formats_smart[] = {
58 	DRM_FORMAT_XRGB8888,
59 	DRM_FORMAT_ARGB8888,
60 	DRM_FORMAT_XBGR8888,
61 	DRM_FORMAT_ABGR8888,
62 	DRM_FORMAT_RGB888,
63 	DRM_FORMAT_BGR888,
64 	DRM_FORMAT_RGB565,
65 	DRM_FORMAT_BGR565,
66 };
67 
68 static const uint64_t format_modifiers[] = {
69 	DRM_FORMAT_MOD_LINEAR,
70 	DRM_FORMAT_MOD_INVALID,
71 };
72 
73 static const uint64_t format_modifiers_afbc[] = {
74 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16),
75 
76 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
77 				AFBC_FORMAT_MOD_SPARSE),
78 
79 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
80 				AFBC_FORMAT_MOD_YTR),
81 
82 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
83 				AFBC_FORMAT_MOD_CBR),
84 
85 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
86 				AFBC_FORMAT_MOD_YTR |
87 				AFBC_FORMAT_MOD_SPARSE),
88 
89 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
90 				AFBC_FORMAT_MOD_CBR |
91 				AFBC_FORMAT_MOD_SPARSE),
92 
93 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
94 				AFBC_FORMAT_MOD_YTR |
95 				AFBC_FORMAT_MOD_CBR),
96 
97 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
98 				AFBC_FORMAT_MOD_YTR |
99 				AFBC_FORMAT_MOD_CBR |
100 				AFBC_FORMAT_MOD_SPARSE),
101 
102 	/* SPLIT mandates SPARSE, RGB modes mandates YTR */
103 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
104 				AFBC_FORMAT_MOD_YTR |
105 				AFBC_FORMAT_MOD_SPARSE |
106 				AFBC_FORMAT_MOD_SPLIT),
107 	DRM_FORMAT_MOD_INVALID,
108 };
109 
110 static const struct vop2_video_port_data rk3568_vop_video_ports[] = {
111 	{
112 		.id = 0,
113 		.feature = VOP_FEATURE_OUTPUT_10BIT,
114 		.gamma_lut_len = 1024,
115 		.cubic_lut_len = 9 * 9 * 9,
116 		.max_output = { 4096, 2304 },
117 		.pre_scan_max_dly = { 69, 53, 53, 42 },
118 		.offset = 0xc00,
119 	}, {
120 		.id = 1,
121 		.gamma_lut_len = 1024,
122 		.max_output = { 2048, 1536 },
123 		.pre_scan_max_dly = { 40, 40, 40, 40 },
124 		.offset = 0xd00,
125 	}, {
126 		.id = 2,
127 		.gamma_lut_len = 1024,
128 		.max_output = { 1920, 1080 },
129 		.pre_scan_max_dly = { 40, 40, 40, 40 },
130 		.offset = 0xe00,
131 	},
132 };
133 
134 /*
135  * rk3568 vop with 2 cluster, 2 esmart win, 2 smart win.
136  * Every cluster can work as 4K win or split into two win.
137  * All win in cluster support AFBCD.
138  *
139  * Every esmart win and smart win support 4 Multi-region.
140  *
141  * Scale filter mode:
142  *
143  * * Cluster:  bicubic for horizontal scale up, others use bilinear
144  * * ESmart:
145  *    * nearest-neighbor/bilinear/bicubic for scale up
146  *    * nearest-neighbor/bilinear/average for scale down
147  *
148  *
149  * @TODO describe the wind like cpu-map dt nodes;
150  */
151 static const struct vop2_win_data rk3568_vop_win_data[] = {
152 	{
153 		.name = "Smart0-win0",
154 		.phys_id = ROCKCHIP_VOP2_SMART0,
155 		.base = 0x1c00,
156 		.formats = formats_smart,
157 		.nformats = ARRAY_SIZE(formats_smart),
158 		.format_modifiers = format_modifiers,
159 		.layer_sel_id = 3,
160 		.supported_rotations = DRM_MODE_REFLECT_Y,
161 		.type = DRM_PLANE_TYPE_PRIMARY,
162 		.max_upscale_factor = 8,
163 		.max_downscale_factor = 8,
164 		.dly = { 20, 47, 41 },
165 	}, {
166 		.name = "Smart1-win0",
167 		.phys_id = ROCKCHIP_VOP2_SMART1,
168 		.formats = formats_smart,
169 		.nformats = ARRAY_SIZE(formats_smart),
170 		.format_modifiers = format_modifiers,
171 		.base = 0x1e00,
172 		.layer_sel_id = 7,
173 		.supported_rotations = DRM_MODE_REFLECT_Y,
174 		.type = DRM_PLANE_TYPE_PRIMARY,
175 		.max_upscale_factor = 8,
176 		.max_downscale_factor = 8,
177 		.dly = { 20, 47, 41 },
178 	}, {
179 		.name = "Esmart1-win0",
180 		.phys_id = ROCKCHIP_VOP2_ESMART1,
181 		.formats = formats_rk356x_esmart,
182 		.nformats = ARRAY_SIZE(formats_rk356x_esmart),
183 		.format_modifiers = format_modifiers,
184 		.base = 0x1a00,
185 		.layer_sel_id = 6,
186 		.supported_rotations = DRM_MODE_REFLECT_Y,
187 		.type = DRM_PLANE_TYPE_PRIMARY,
188 		.max_upscale_factor = 8,
189 		.max_downscale_factor = 8,
190 		.dly = { 20, 47, 41 },
191 	}, {
192 		.name = "Esmart0-win0",
193 		.phys_id = ROCKCHIP_VOP2_ESMART0,
194 		.formats = formats_rk356x_esmart,
195 		.nformats = ARRAY_SIZE(formats_rk356x_esmart),
196 		.format_modifiers = format_modifiers,
197 		.base = 0x1800,
198 		.layer_sel_id = 2,
199 		.supported_rotations = DRM_MODE_REFLECT_Y,
200 		.type = DRM_PLANE_TYPE_PRIMARY,
201 		.max_upscale_factor = 8,
202 		.max_downscale_factor = 8,
203 		.dly = { 20, 47, 41 },
204 	}, {
205 		.name = "Cluster0-win0",
206 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
207 		.base = 0x1000,
208 		.formats = formats_cluster,
209 		.nformats = ARRAY_SIZE(formats_cluster),
210 		.format_modifiers = format_modifiers_afbc,
211 		.layer_sel_id = 0,
212 		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
213 					DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
214 		.max_upscale_factor = 4,
215 		.max_downscale_factor = 4,
216 		.dly = { 0, 27, 21 },
217 		.type = DRM_PLANE_TYPE_OVERLAY,
218 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
219 	}, {
220 		.name = "Cluster1-win0",
221 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
222 		.base = 0x1200,
223 		.formats = formats_cluster,
224 		.nformats = ARRAY_SIZE(formats_cluster),
225 		.format_modifiers = format_modifiers_afbc,
226 		.layer_sel_id = 1,
227 		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
228 					DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
229 		.type = DRM_PLANE_TYPE_OVERLAY,
230 		.max_upscale_factor = 4,
231 		.max_downscale_factor = 4,
232 		.dly = { 0, 27, 21 },
233 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
234 	},
235 };
236 
237 static const struct vop2_data rk3566_vop = {
238 	.nr_vps = 3,
239 	.max_input = { 4096, 2304 },
240 	.max_output = { 4096, 2304 },
241 	.vp = rk3568_vop_video_ports,
242 	.win = rk3568_vop_win_data,
243 	.win_size = ARRAY_SIZE(rk3568_vop_win_data),
244 	.soc_id = 3566,
245 };
246 
247 static const struct vop2_data rk3568_vop = {
248 	.nr_vps = 3,
249 	.max_input = { 4096, 2304 },
250 	.max_output = { 4096, 2304 },
251 	.vp = rk3568_vop_video_ports,
252 	.win = rk3568_vop_win_data,
253 	.win_size = ARRAY_SIZE(rk3568_vop_win_data),
254 	.soc_id = 3568,
255 };
256 
257 static const struct of_device_id vop2_dt_match[] = {
258 	{
259 		.compatible = "rockchip,rk3566-vop",
260 		.data = &rk3566_vop,
261 	}, {
262 		.compatible = "rockchip,rk3568-vop",
263 		.data = &rk3568_vop,
264 	}, {
265 	},
266 };
267 MODULE_DEVICE_TABLE(of, vop2_dt_match);
268 
269 static int vop2_probe(struct platform_device *pdev)
270 {
271 	struct device *dev = &pdev->dev;
272 
273 	return component_add(dev, &vop2_component_ops);
274 }
275 
276 static void vop2_remove(struct platform_device *pdev)
277 {
278 	component_del(&pdev->dev, &vop2_component_ops);
279 }
280 
281 struct platform_driver vop2_platform_driver = {
282 	.probe = vop2_probe,
283 	.remove_new = vop2_remove,
284 	.driver = {
285 		.name = "rockchip-vop2",
286 		.of_match_table = vop2_dt_match,
287 	},
288 };
289