xref: /linux/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c (revision ae22a94997b8a03dcb3c922857c203246711f9d4)
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_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, /* yvu420_8bit linear mode, 2 plane */
48 	DRM_FORMAT_NV16, /* yuv422_8bit linear mode, 2 plane */
49 	DRM_FORMAT_NV61, /* yvu422_8bit linear mode, 2 plane */
50 	DRM_FORMAT_NV20, /* yuv422_10bit linear mode, 2 plane, no padding */
51 	DRM_FORMAT_NV24, /* yuv444_8bit linear mode, 2 plane */
52 	DRM_FORMAT_NV42, /* yvu444_8bit linear mode, 2 plane */
53 	DRM_FORMAT_NV30, /* yuv444_10bit linear mode, 2 plane, no padding */
54 	DRM_FORMAT_NV15, /* yuv420_10bit linear mode, 2 plane, no padding */
55 	DRM_FORMAT_YVYU, /* yuv422_8bit[YVYU] linear mode */
56 	DRM_FORMAT_VYUY, /* yuv422_8bit[VYUY] linear mode */
57 	DRM_FORMAT_YUYV, /* yuv422_8bit[YUYV] linear mode */
58 	DRM_FORMAT_UYVY, /* yuv422_8bit[UYVY] linear mode */
59 };
60 
61 static const uint32_t formats_rk356x_esmart[] = {
62 	DRM_FORMAT_XRGB8888,
63 	DRM_FORMAT_ARGB8888,
64 	DRM_FORMAT_XBGR8888,
65 	DRM_FORMAT_ABGR8888,
66 	DRM_FORMAT_RGB888,
67 	DRM_FORMAT_BGR888,
68 	DRM_FORMAT_RGB565,
69 	DRM_FORMAT_BGR565,
70 	DRM_FORMAT_NV12, /* yuv420_8bit linear mode, 2 plane */
71 	DRM_FORMAT_NV21, /* yuv420_8bit linear mode, 2 plane */
72 	DRM_FORMAT_NV15, /* yuv420_10bit linear mode, 2 plane, no padding */
73 	DRM_FORMAT_NV16, /* yuv422_8bit linear mode, 2 plane */
74 	DRM_FORMAT_NV61, /* yuv422_8bit linear mode, 2 plane */
75 	DRM_FORMAT_NV20, /* yuv422_10bit linear mode, 2 plane, no padding */
76 	DRM_FORMAT_NV24, /* yuv444_8bit linear mode, 2 plane */
77 	DRM_FORMAT_NV42, /* yuv444_8bit linear mode, 2 plane */
78 	DRM_FORMAT_NV30, /* yuv444_10bit linear mode, 2 plane, no padding */
79 	DRM_FORMAT_YVYU, /* yuv422_8bit[YVYU] linear mode */
80 	DRM_FORMAT_VYUY, /* yuv422_8bit[VYUY] linear mode */
81 };
82 
83 static const uint32_t formats_smart[] = {
84 	DRM_FORMAT_XRGB8888,
85 	DRM_FORMAT_ARGB8888,
86 	DRM_FORMAT_XBGR8888,
87 	DRM_FORMAT_ABGR8888,
88 	DRM_FORMAT_RGB888,
89 	DRM_FORMAT_BGR888,
90 	DRM_FORMAT_RGB565,
91 	DRM_FORMAT_BGR565,
92 };
93 
94 static const uint64_t format_modifiers[] = {
95 	DRM_FORMAT_MOD_LINEAR,
96 	DRM_FORMAT_MOD_INVALID,
97 };
98 
99 static const uint64_t format_modifiers_afbc[] = {
100 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16),
101 
102 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
103 				AFBC_FORMAT_MOD_SPARSE),
104 
105 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
106 				AFBC_FORMAT_MOD_YTR),
107 
108 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
109 				AFBC_FORMAT_MOD_CBR),
110 
111 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
112 				AFBC_FORMAT_MOD_YTR |
113 				AFBC_FORMAT_MOD_SPARSE),
114 
115 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
116 				AFBC_FORMAT_MOD_CBR |
117 				AFBC_FORMAT_MOD_SPARSE),
118 
119 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
120 				AFBC_FORMAT_MOD_YTR |
121 				AFBC_FORMAT_MOD_CBR),
122 
123 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
124 				AFBC_FORMAT_MOD_YTR |
125 				AFBC_FORMAT_MOD_CBR |
126 				AFBC_FORMAT_MOD_SPARSE),
127 
128 	/* SPLIT mandates SPARSE, RGB modes mandates YTR */
129 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
130 				AFBC_FORMAT_MOD_YTR |
131 				AFBC_FORMAT_MOD_SPARSE |
132 				AFBC_FORMAT_MOD_SPLIT),
133 	DRM_FORMAT_MOD_INVALID,
134 };
135 
136 static const struct vop2_video_port_data rk3568_vop_video_ports[] = {
137 	{
138 		.id = 0,
139 		.feature = VOP2_VP_FEATURE_OUTPUT_10BIT,
140 		.gamma_lut_len = 1024,
141 		.cubic_lut_len = 9 * 9 * 9,
142 		.max_output = { 4096, 2304 },
143 		.pre_scan_max_dly = { 69, 53, 53, 42 },
144 		.offset = 0xc00,
145 	}, {
146 		.id = 1,
147 		.gamma_lut_len = 1024,
148 		.max_output = { 2048, 1536 },
149 		.pre_scan_max_dly = { 40, 40, 40, 40 },
150 		.offset = 0xd00,
151 	}, {
152 		.id = 2,
153 		.gamma_lut_len = 1024,
154 		.max_output = { 1920, 1080 },
155 		.pre_scan_max_dly = { 40, 40, 40, 40 },
156 		.offset = 0xe00,
157 	},
158 };
159 
160 /*
161  * rk3568 vop with 2 cluster, 2 esmart win, 2 smart win.
162  * Every cluster can work as 4K win or split into two win.
163  * All win in cluster support AFBCD.
164  *
165  * Every esmart win and smart win support 4 Multi-region.
166  *
167  * Scale filter mode:
168  *
169  * * Cluster:  bicubic for horizontal scale up, others use bilinear
170  * * ESmart:
171  *    * nearest-neighbor/bilinear/bicubic for scale up
172  *    * nearest-neighbor/bilinear/average for scale down
173  *
174  *
175  * @TODO describe the wind like cpu-map dt nodes;
176  */
177 static const struct vop2_win_data rk3568_vop_win_data[] = {
178 	{
179 		.name = "Smart0-win0",
180 		.phys_id = ROCKCHIP_VOP2_SMART0,
181 		.base = 0x1c00,
182 		.formats = formats_smart,
183 		.nformats = ARRAY_SIZE(formats_smart),
184 		.format_modifiers = format_modifiers,
185 		.layer_sel_id = 3,
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 = "Smart1-win0",
193 		.phys_id = ROCKCHIP_VOP2_SMART1,
194 		.formats = formats_smart,
195 		.nformats = ARRAY_SIZE(formats_smart),
196 		.format_modifiers = format_modifiers,
197 		.base = 0x1e00,
198 		.layer_sel_id = 7,
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 = "Esmart1-win0",
206 		.phys_id = ROCKCHIP_VOP2_ESMART1,
207 		.formats = formats_rk356x_esmart,
208 		.nformats = ARRAY_SIZE(formats_rk356x_esmart),
209 		.format_modifiers = format_modifiers,
210 		.base = 0x1a00,
211 		.layer_sel_id = 6,
212 		.supported_rotations = DRM_MODE_REFLECT_Y,
213 		.type = DRM_PLANE_TYPE_PRIMARY,
214 		.max_upscale_factor = 8,
215 		.max_downscale_factor = 8,
216 		.dly = { 20, 47, 41 },
217 	}, {
218 		.name = "Esmart0-win0",
219 		.phys_id = ROCKCHIP_VOP2_ESMART0,
220 		.formats = formats_rk356x_esmart,
221 		.nformats = ARRAY_SIZE(formats_rk356x_esmart),
222 		.format_modifiers = format_modifiers,
223 		.base = 0x1800,
224 		.layer_sel_id = 2,
225 		.supported_rotations = DRM_MODE_REFLECT_Y,
226 		.type = DRM_PLANE_TYPE_PRIMARY,
227 		.max_upscale_factor = 8,
228 		.max_downscale_factor = 8,
229 		.dly = { 20, 47, 41 },
230 	}, {
231 		.name = "Cluster0-win0",
232 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
233 		.base = 0x1000,
234 		.formats = formats_cluster,
235 		.nformats = ARRAY_SIZE(formats_cluster),
236 		.format_modifiers = format_modifiers_afbc,
237 		.layer_sel_id = 0,
238 		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
239 					DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
240 		.max_upscale_factor = 4,
241 		.max_downscale_factor = 4,
242 		.dly = { 0, 27, 21 },
243 		.type = DRM_PLANE_TYPE_OVERLAY,
244 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
245 	}, {
246 		.name = "Cluster1-win0",
247 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
248 		.base = 0x1200,
249 		.formats = formats_cluster,
250 		.nformats = ARRAY_SIZE(formats_cluster),
251 		.format_modifiers = format_modifiers_afbc,
252 		.layer_sel_id = 1,
253 		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
254 					DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
255 		.type = DRM_PLANE_TYPE_OVERLAY,
256 		.max_upscale_factor = 4,
257 		.max_downscale_factor = 4,
258 		.dly = { 0, 27, 21 },
259 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
260 	},
261 };
262 
263 static const struct vop2_video_port_data rk3588_vop_video_ports[] = {
264 	{
265 		.id = 0,
266 		.feature = VOP2_VP_FEATURE_OUTPUT_10BIT,
267 		.gamma_lut_len = 1024,
268 		.cubic_lut_len = 9 * 9 * 9, /* 9x9x9 */
269 		.max_output = { 4096, 2304 },
270 		/* hdr2sdr sdr2hdr hdr2hdr sdr2sdr */
271 		.pre_scan_max_dly = { 76, 65, 65, 54 },
272 		.offset = 0xc00,
273 	}, {
274 		.id = 1,
275 		.feature = VOP2_VP_FEATURE_OUTPUT_10BIT,
276 		.gamma_lut_len = 1024,
277 		.cubic_lut_len = 729, /* 9x9x9 */
278 		.max_output = { 4096, 2304 },
279 		.pre_scan_max_dly = { 76, 65, 65, 54 },
280 		.offset = 0xd00,
281 	}, {
282 		.id = 2,
283 		.feature = VOP2_VP_FEATURE_OUTPUT_10BIT,
284 		.gamma_lut_len = 1024,
285 		.cubic_lut_len = 17 * 17 * 17, /* 17x17x17 */
286 		.max_output = { 4096, 2304 },
287 		.pre_scan_max_dly = { 52, 52, 52, 52 },
288 		.offset = 0xe00,
289 	}, {
290 		.id = 3,
291 		.gamma_lut_len = 1024,
292 		.max_output = { 2048, 1536 },
293 		.pre_scan_max_dly = { 52, 52, 52, 52 },
294 		.offset = 0xf00,
295 	},
296 };
297 
298 /*
299  * rk3588 vop with 4 cluster, 4 esmart win.
300  * Every cluster can work as 4K win or split into two win.
301  * All win in cluster support AFBCD.
302  *
303  * Every esmart win and smart win support 4 Multi-region.
304  *
305  * Scale filter mode:
306  *
307  * * Cluster:  bicubic for horizontal scale up, others use bilinear
308  * * ESmart:
309  *    * nearest-neighbor/bilinear/bicubic for scale up
310  *    * nearest-neighbor/bilinear/average for scale down
311  *
312  * AXI Read ID assignment:
313  * Two AXI bus:
314  * AXI0 is a read/write bus with a higher performance.
315  * AXI1 is a read only bus.
316  *
317  * Every window on a AXI bus must assigned two unique
318  * read id(yrgb_id/uv_id, valid id are 0x1~0xe).
319  *
320  * AXI0:
321  * Cluster0/1, Esmart0/1, WriteBack
322  *
323  * AXI 1:
324  * Cluster2/3, Esmart2/3
325  *
326  */
327 static const struct vop2_win_data rk3588_vop_win_data[] = {
328 	{
329 		.name = "Cluster0-win0",
330 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
331 		.base = 0x1000,
332 		.formats = formats_cluster,
333 		.nformats = ARRAY_SIZE(formats_cluster),
334 		.format_modifiers = format_modifiers_afbc,
335 		.layer_sel_id = 0,
336 		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
337 				       DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
338 		.max_upscale_factor = 4,
339 		.max_downscale_factor = 4,
340 		.dly = { 4, 26, 29 },
341 		.type = DRM_PLANE_TYPE_PRIMARY,
342 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
343 	}, {
344 		.name = "Cluster1-win0",
345 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
346 		.base = 0x1200,
347 		.formats = formats_cluster,
348 		.nformats = ARRAY_SIZE(formats_cluster),
349 		.format_modifiers = format_modifiers_afbc,
350 		.layer_sel_id = 1,
351 		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
352 				       DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
353 		.type = DRM_PLANE_TYPE_PRIMARY,
354 		.max_upscale_factor = 4,
355 		.max_downscale_factor = 4,
356 		.dly = { 4, 26, 29 },
357 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
358 	}, {
359 		.name = "Cluster2-win0",
360 		.phys_id = ROCKCHIP_VOP2_CLUSTER2,
361 		.base = 0x1400,
362 		.formats = formats_cluster,
363 		.nformats = ARRAY_SIZE(formats_cluster),
364 		.format_modifiers = format_modifiers_afbc,
365 		.layer_sel_id = 4,
366 		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
367 				       DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
368 		.type = DRM_PLANE_TYPE_PRIMARY,
369 		.max_upscale_factor = 4,
370 		.max_downscale_factor = 4,
371 		.dly = { 4, 26, 29 },
372 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
373 	}, {
374 		.name = "Cluster3-win0",
375 		.phys_id = ROCKCHIP_VOP2_CLUSTER3,
376 		.base = 0x1600,
377 		.formats = formats_cluster,
378 		.nformats = ARRAY_SIZE(formats_cluster),
379 		.format_modifiers = format_modifiers_afbc,
380 		.layer_sel_id = 5,
381 		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
382 				       DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
383 		.type = DRM_PLANE_TYPE_PRIMARY,
384 		.max_upscale_factor = 4,
385 		.max_downscale_factor = 4,
386 		.dly = { 4, 26, 29 },
387 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
388 	}, {
389 		.name = "Esmart0-win0",
390 		.phys_id = ROCKCHIP_VOP2_ESMART0,
391 		.formats = formats_esmart,
392 		.nformats = ARRAY_SIZE(formats_esmart),
393 		.format_modifiers = format_modifiers,
394 		.base = 0x1800,
395 		.layer_sel_id = 2,
396 		.supported_rotations = DRM_MODE_REFLECT_Y,
397 		.type = DRM_PLANE_TYPE_OVERLAY,
398 		.max_upscale_factor = 8,
399 		.max_downscale_factor = 8,
400 		.dly = { 23, 45, 48 },
401 	}, {
402 		.name = "Esmart1-win0",
403 		.phys_id = ROCKCHIP_VOP2_ESMART1,
404 		.formats = formats_esmart,
405 		.nformats = ARRAY_SIZE(formats_esmart),
406 		.format_modifiers = format_modifiers,
407 		.base = 0x1a00,
408 		.layer_sel_id = 3,
409 		.supported_rotations = DRM_MODE_REFLECT_Y,
410 		.type = DRM_PLANE_TYPE_OVERLAY,
411 		.max_upscale_factor = 8,
412 		.max_downscale_factor = 8,
413 		.dly = { 23, 45, 48 },
414 	}, {
415 		.name = "Esmart2-win0",
416 		.phys_id = ROCKCHIP_VOP2_ESMART2,
417 		.base = 0x1c00,
418 		.formats = formats_esmart,
419 		.nformats = ARRAY_SIZE(formats_esmart),
420 		.format_modifiers = format_modifiers,
421 		.layer_sel_id = 6,
422 		.supported_rotations = DRM_MODE_REFLECT_Y,
423 		.type = DRM_PLANE_TYPE_OVERLAY,
424 		.max_upscale_factor = 8,
425 		.max_downscale_factor = 8,
426 		.dly = { 23, 45, 48 },
427 	}, {
428 		.name = "Esmart3-win0",
429 		.phys_id = ROCKCHIP_VOP2_ESMART3,
430 		.formats = formats_esmart,
431 		.nformats = ARRAY_SIZE(formats_esmart),
432 		.format_modifiers = format_modifiers,
433 		.base = 0x1e00,
434 		.layer_sel_id = 7,
435 		.supported_rotations = DRM_MODE_REFLECT_Y,
436 		.type = DRM_PLANE_TYPE_OVERLAY,
437 		.max_upscale_factor = 8,
438 		.max_downscale_factor = 8,
439 		.dly = { 23, 45, 48 },
440 	},
441 };
442 
443 static const struct vop2_data rk3566_vop = {
444 	.feature = VOP2_FEATURE_HAS_SYS_GRF,
445 	.nr_vps = 3,
446 	.max_input = { 4096, 2304 },
447 	.max_output = { 4096, 2304 },
448 	.vp = rk3568_vop_video_ports,
449 	.win = rk3568_vop_win_data,
450 	.win_size = ARRAY_SIZE(rk3568_vop_win_data),
451 	.soc_id = 3566,
452 };
453 
454 static const struct vop2_data rk3568_vop = {
455 	.feature = VOP2_FEATURE_HAS_SYS_GRF,
456 	.nr_vps = 3,
457 	.max_input = { 4096, 2304 },
458 	.max_output = { 4096, 2304 },
459 	.vp = rk3568_vop_video_ports,
460 	.win = rk3568_vop_win_data,
461 	.win_size = ARRAY_SIZE(rk3568_vop_win_data),
462 	.soc_id = 3568,
463 };
464 
465 static const struct vop2_data rk3588_vop = {
466 	.feature = VOP2_FEATURE_HAS_SYS_GRF | VOP2_FEATURE_HAS_VO1_GRF |
467 		   VOP2_FEATURE_HAS_VOP_GRF | VOP2_FEATURE_HAS_SYS_PMU,
468 	.nr_vps = 4,
469 	.max_input = { 4096, 4320 },
470 	.max_output = { 4096, 4320 },
471 	.vp = rk3588_vop_video_ports,
472 	.win = rk3588_vop_win_data,
473 	.win_size = ARRAY_SIZE(rk3588_vop_win_data),
474 	.soc_id = 3588,
475 };
476 
477 static const struct of_device_id vop2_dt_match[] = {
478 	{
479 		.compatible = "rockchip,rk3566-vop",
480 		.data = &rk3566_vop,
481 	}, {
482 		.compatible = "rockchip,rk3568-vop",
483 		.data = &rk3568_vop,
484 	}, {
485 		.compatible = "rockchip,rk3588-vop",
486 		.data = &rk3588_vop
487 	}, {
488 	},
489 };
490 MODULE_DEVICE_TABLE(of, vop2_dt_match);
491 
492 static int vop2_probe(struct platform_device *pdev)
493 {
494 	struct device *dev = &pdev->dev;
495 
496 	return component_add(dev, &vop2_component_ops);
497 }
498 
499 static void vop2_remove(struct platform_device *pdev)
500 {
501 	component_del(&pdev->dev, &vop2_component_ops);
502 }
503 
504 struct platform_driver vop2_platform_driver = {
505 	.probe = vop2_probe,
506 	.remove_new = vop2_remove,
507 	.driver = {
508 		.name = "rockchip-vop2",
509 		.of_match_table = vop2_dt_match,
510 	},
511 };
512