drm/rockchip: Convert to platform remove callback returning void
[linux-2.6-block.git] / drivers / gpu / drm / rockchip / rockchip_vop2_reg.c
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_win_full_10bit[] = {
19         DRM_FORMAT_XRGB8888,
20         DRM_FORMAT_ARGB8888,
21         DRM_FORMAT_XBGR8888,
22         DRM_FORMAT_ABGR8888,
23         DRM_FORMAT_RGB888,
24         DRM_FORMAT_BGR888,
25         DRM_FORMAT_RGB565,
26         DRM_FORMAT_BGR565,
27         DRM_FORMAT_NV12,
28         DRM_FORMAT_NV16,
29         DRM_FORMAT_NV24,
30 };
31
32 static const uint32_t formats_win_full_10bit_yuyv[] = {
33         DRM_FORMAT_XRGB8888,
34         DRM_FORMAT_ARGB8888,
35         DRM_FORMAT_XBGR8888,
36         DRM_FORMAT_ABGR8888,
37         DRM_FORMAT_RGB888,
38         DRM_FORMAT_BGR888,
39         DRM_FORMAT_RGB565,
40         DRM_FORMAT_BGR565,
41         DRM_FORMAT_NV12,
42         DRM_FORMAT_NV16,
43         DRM_FORMAT_NV24,
44         DRM_FORMAT_YVYU,
45         DRM_FORMAT_VYUY,
46 };
47
48 static const uint32_t formats_win_lite[] = {
49         DRM_FORMAT_XRGB8888,
50         DRM_FORMAT_ARGB8888,
51         DRM_FORMAT_XBGR8888,
52         DRM_FORMAT_ABGR8888,
53         DRM_FORMAT_RGB888,
54         DRM_FORMAT_BGR888,
55         DRM_FORMAT_RGB565,
56         DRM_FORMAT_BGR565,
57 };
58
59 static const uint64_t format_modifiers[] = {
60         DRM_FORMAT_MOD_LINEAR,
61         DRM_FORMAT_MOD_INVALID,
62 };
63
64 static const uint64_t format_modifiers_afbc[] = {
65         DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16),
66
67         DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
68                                 AFBC_FORMAT_MOD_SPARSE),
69
70         DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
71                                 AFBC_FORMAT_MOD_YTR),
72
73         DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
74                                 AFBC_FORMAT_MOD_CBR),
75
76         DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
77                                 AFBC_FORMAT_MOD_YTR |
78                                 AFBC_FORMAT_MOD_SPARSE),
79
80         DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
81                                 AFBC_FORMAT_MOD_CBR |
82                                 AFBC_FORMAT_MOD_SPARSE),
83
84         DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
85                                 AFBC_FORMAT_MOD_YTR |
86                                 AFBC_FORMAT_MOD_CBR),
87
88         DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
89                                 AFBC_FORMAT_MOD_YTR |
90                                 AFBC_FORMAT_MOD_CBR |
91                                 AFBC_FORMAT_MOD_SPARSE),
92
93         /* SPLIT mandates SPARSE, RGB modes mandates YTR */
94         DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
95                                 AFBC_FORMAT_MOD_YTR |
96                                 AFBC_FORMAT_MOD_SPARSE |
97                                 AFBC_FORMAT_MOD_SPLIT),
98         DRM_FORMAT_MOD_INVALID,
99 };
100
101 static const struct vop2_video_port_data rk3568_vop_video_ports[] = {
102         {
103                 .id = 0,
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 },
109                 .offset = 0xc00,
110         }, {
111                 .id = 1,
112                 .gamma_lut_len = 1024,
113                 .max_output = { 2048, 1536 },
114                 .pre_scan_max_dly = { 40, 40, 40, 40 },
115                 .offset = 0xd00,
116         }, {
117                 .id = 2,
118                 .gamma_lut_len = 1024,
119                 .max_output = { 1920, 1080 },
120                 .pre_scan_max_dly = { 40, 40, 40, 40 },
121                 .offset = 0xe00,
122         },
123 };
124
125 /*
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.
129  *
130  * Every esmart win and smart win support 4 Multi-region.
131  *
132  * Scale filter mode:
133  *
134  * * Cluster:  bicubic for horizontal scale up, others use bilinear
135  * * ESmart:
136  *    * nearest-neighbor/bilinear/bicubic for scale up
137  *    * nearest-neighbor/bilinear/average for scale down
138  *
139  *
140  * @TODO describe the wind like cpu-map dt nodes;
141  */
142 static const struct vop2_win_data rk3568_vop_win_data[] = {
143         {
144                 .name = "Smart0-win0",
145                 .phys_id = ROCKCHIP_VOP2_SMART0,
146                 .base = 0x1c00,
147                 .formats = formats_win_lite,
148                 .nformats = ARRAY_SIZE(formats_win_lite),
149                 .format_modifiers = format_modifiers,
150                 .layer_sel_id = 3,
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 },
156         }, {
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,
162                 .base = 0x1e00,
163                 .layer_sel_id = 7,
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 },
169         }, {
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,
175                 .base = 0x1a00,
176                 .layer_sel_id = 6,
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 },
182         }, {
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,
188                 .base = 0x1800,
189                 .layer_sel_id = 2,
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 },
195         }, {
196                 .name = "Cluster0-win0",
197                 .phys_id = ROCKCHIP_VOP2_CLUSTER0,
198                 .base = 0x1000,
199                 .formats = formats_win_full_10bit,
200                 .nformats = ARRAY_SIZE(formats_win_full_10bit),
201                 .format_modifiers = format_modifiers_afbc,
202                 .layer_sel_id = 0,
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,
210         }, {
211                 .name = "Cluster1-win0",
212                 .phys_id = ROCKCHIP_VOP2_CLUSTER1,
213                 .base = 0x1200,
214                 .formats = formats_win_full_10bit,
215                 .nformats = ARRAY_SIZE(formats_win_full_10bit),
216                 .format_modifiers = format_modifiers_afbc,
217                 .layer_sel_id = 1,
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,
225         },
226 };
227
228 static const struct vop2_data rk3566_vop = {
229         .nr_vps = 3,
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),
235         .soc_id = 3566,
236 };
237
238 static const struct vop2_data rk3568_vop = {
239         .nr_vps = 3,
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),
245         .soc_id = 3568,
246 };
247
248 static const struct of_device_id vop2_dt_match[] = {
249         {
250                 .compatible = "rockchip,rk3566-vop",
251                 .data = &rk3566_vop,
252         }, {
253                 .compatible = "rockchip,rk3568-vop",
254                 .data = &rk3568_vop,
255         }, {
256         },
257 };
258 MODULE_DEVICE_TABLE(of, vop2_dt_match);
259
260 static int vop2_probe(struct platform_device *pdev)
261 {
262         struct device *dev = &pdev->dev;
263
264         return component_add(dev, &vop2_component_ops);
265 }
266
267 static void vop2_remove(struct platform_device *pdev)
268 {
269         component_del(&pdev->dev, &vop2_component_ops);
270 }
271
272 struct platform_driver vop2_platform_driver = {
273         .probe = vop2_probe,
274         .remove_new = vop2_remove,
275         .driver = {
276                 .name = "rockchip-vop2",
277                 .of_match_table = of_match_ptr(vop2_dt_match),
278         },
279 };