hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/gpu/drm/rockchip/rockchip_drm_vvop.c
....@@ -17,36 +17,48 @@
1717
1818 #define DRIVER_NAME "virtual-vop"
1919
20
-#define XRES_MIN 32
21
-#define YRES_MIN 32
20
+#define XRES_MIN 32
21
+#define YRES_MIN 32
2222
23
-#define XRES_DEF 1024
24
-#define YRES_DEF 768
23
+#define XRES_DEF 1024
24
+#define YRES_DEF 768
2525
26
-#define XRES_MAX 8192
27
-#define YRES_MAX 8192
26
+#define XRES_MAX 8192
27
+#define YRES_MAX 8192
2828
29
+#define VVOP_MAX_CRTC 8
2930
30
-struct vvop {
31
- struct device *dev;
32
- struct drm_device *drm_dev;
33
- struct platform_device *pdev;
31
+static struct platform_device *vvop_pdev;
32
+
33
+struct vvop_crtc {
3434 struct drm_crtc crtc;
35
- struct drm_plane *plane;
35
+ struct drm_plane plane;
3636 struct drm_encoder encoder;
3737 struct drm_connector connector;
3838 struct hrtimer vblank_hrtimer;
3939 ktime_t period_ns;
4040 struct drm_pending_vblank_event *event;
4141
42
+ struct drm_property *is_virtual_prop;
43
+ struct drm_property *soc_id_prop;
44
+};
45
+
46
+struct vvop {
47
+ struct device *dev;
48
+ struct drm_device *drm_dev;
49
+ struct platform_device *pdev;
50
+
51
+ struct vvop_crtc vcrtc[VVOP_MAX_CRTC];
52
+
53
+ uint32_t crtc_mask;
4254 };
4355
4456 static const u32 vvop_formats[] = {
4557 DRM_FORMAT_XRGB8888,
4658 };
4759
48
-#define drm_crtc_to_vvop(crtc) \
49
- container_of(crtc, struct vvop, crtc)
60
+#define drm_crtc_to_vvop_crtc(crtc) \
61
+ container_of(crtc, struct vvop_crtc, crtc)
5062
5163
5264 static const struct drm_plane_funcs vvop_plane_funcs = {
....@@ -59,7 +71,7 @@
5971 };
6072
6173 static void vvop_plane_atomic_update(struct drm_plane *plane,
62
- struct drm_plane_state *old_state)
74
+ struct drm_plane_state *old_state)
6375 {
6476 }
6577
....@@ -67,71 +79,60 @@
6779 .atomic_update = vvop_plane_atomic_update,
6880 };
6981
70
-static struct drm_plane *vvop_plane_init(struct vvop *vvop)
82
+static int vvop_plane_init(struct drm_device *dev, struct drm_plane *primary)
7183 {
72
- struct drm_device *dev = vvop->drm_dev;
73
- struct drm_plane *plane;
74
- const u32 *formats;
75
- int ret, nformats;
84
+ int ret;
7685
77
- plane = kzalloc(sizeof(*plane), GFP_KERNEL);
78
- if (!plane)
79
- return ERR_PTR(-ENOMEM);
80
-
81
- formats = vvop_formats;
82
- nformats = ARRAY_SIZE(vvop_formats);
83
-
84
- ret = drm_universal_plane_init(dev, plane, 0,
86
+ ret = drm_universal_plane_init(dev, primary, 0,
8587 &vvop_plane_funcs,
86
- formats, nformats,
88
+ vvop_formats, ARRAY_SIZE(vvop_formats),
8789 NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
88
- if (ret) {
89
- kfree(plane);
90
- return ERR_PTR(ret);
91
- }
90
+ if (ret)
91
+ return ret;
9292
93
- drm_plane_helper_add(plane, &vvop_plane_helper_funcs);
93
+ drm_plane_helper_add(primary, &vvop_plane_helper_funcs);
9494
95
- return plane;
95
+ return 0;
9696 }
9797
9898 static enum hrtimer_restart vvop_vblank_simulate(struct hrtimer *timer)
9999 {
100
- struct vvop *vvop = container_of(timer, struct vvop, vblank_hrtimer);
101
- struct drm_crtc *crtc = &vvop->crtc;
100
+ struct vvop_crtc *vcrtc = container_of(timer, struct vvop_crtc, vblank_hrtimer);
101
+ struct drm_crtc *crtc = &vcrtc->crtc;
102102 bool ret;
103103
104
- ret = drm_crtc_handle_vblank(crtc);
105
- if (!ret)
106
- DRM_ERROR("vvop failure on handling vblank");
104
+ hrtimer_forward_now(&vcrtc->vblank_hrtimer, vcrtc->period_ns);
107105
108
- hrtimer_forward_now(&vvop->vblank_hrtimer, vvop->period_ns);
106
+ ret = drm_crtc_handle_vblank(crtc);
107
+ /* Don't queue timer again when vblank is disabled. */
108
+ if (!ret) {
109
+ drm_dbg(crtc->dev, "vblank is already disabled\n");
110
+ return HRTIMER_NORESTART;
111
+ }
109112
110113 return HRTIMER_RESTART;
111114 }
112115
113116 static int vvop_enable_vblank(struct drm_crtc *crtc)
114117 {
118
+ struct vvop_crtc *vcrtc = drm_crtc_to_vvop_crtc(crtc);
115119 struct drm_device *dev = crtc->dev;
116120 unsigned int pipe = drm_crtc_index(crtc);
117121 struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
118
- struct vvop *vvop = drm_crtc_to_vvop(crtc);
119122
120123 drm_calc_timestamping_constants(crtc, &crtc->mode);
121124
122
- hrtimer_init(&vvop->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
123
- vvop->vblank_hrtimer.function = &vvop_vblank_simulate;
124
- vvop->period_ns = ktime_set(0, vblank->framedur_ns);
125
- hrtimer_start(&vvop->vblank_hrtimer, vvop->period_ns, HRTIMER_MODE_REL);
125
+ vcrtc->period_ns = ktime_set(0, vblank->framedur_ns);
126
+ hrtimer_start(&vcrtc->vblank_hrtimer, vcrtc->period_ns, HRTIMER_MODE_REL);
126127
127128 return 0;
128129 }
129130
130131 static void vvop_disable_vblank(struct drm_crtc *crtc)
131132 {
132
- struct vvop *vvop = drm_crtc_to_vvop(crtc);
133
+ struct vvop_crtc *vcrtc = drm_crtc_to_vvop_crtc(crtc);
133134
134
- hrtimer_cancel(&vvop->vblank_hrtimer);
135
+ hrtimer_try_to_cancel(&vcrtc->vblank_hrtimer);
135136 }
136137
137138 static void vvop_connector_destroy(struct drm_connector *connector)
....@@ -152,11 +153,231 @@
152153 .destroy = drm_encoder_cleanup,
153154 };
154155
156
+static struct drm_display_mode vvop_modes_builtin[] = {
157
+ /* 1280x720@30Hz */
158
+ { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 37125, 1280, 1390,
159
+ 1430, 1650, 0, 720, 725, 730, 750, 0,
160
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
161
+ /* 1920x1080@30Hz */
162
+ { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
163
+ 2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
164
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
165
+ /* 2560x1440@30Hz */
166
+ { DRM_MODE("2560x1440", DRM_MODE_TYPE_DRIVER, 120750, 2560, 2608,
167
+ 2640, 2720, 0, 1440, 1443, 1448, 1481, 0,
168
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
169
+ /* 3840x2160@30Hz */
170
+ { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016,
171
+ 4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
172
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
173
+ /* 4096x2160@30Hz */
174
+ { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 4184,
175
+ 4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
176
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
177
+ /* 720x1280@30Hz */
178
+ { DRM_MODE("720x1280", DRM_MODE_TYPE_DRIVER, 37125, 720, 725,
179
+ 730, 750, 0, 1280, 1390, 1430, 1650, 0,
180
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
181
+ /* 1080x1920@30Hz */
182
+ { DRM_MODE("1080x1920", DRM_MODE_TYPE_DRIVER, 74250, 1080, 1084,
183
+ 1089, 1125, 0, 1920, 2008, 2052, 2200, 0,
184
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
185
+ /* 1440x2560@30Hz */
186
+ { DRM_MODE("1440x2560", DRM_MODE_TYPE_DRIVER, 120750, 1440, 1443,
187
+ 1448, 1481, 0, 2560, 2608, 2640, 2720, 0,
188
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
189
+ /* 2160x3840@30Hz */
190
+ { DRM_MODE("2160x3840", DRM_MODE_TYPE_DRIVER, 297000, 2160, 2168,
191
+ 2178, 2250, 0, 3840, 4016, 4104, 4400, 0,
192
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
193
+ /* 2160x4096@30Hz */
194
+ { DRM_MODE("2160x4096", DRM_MODE_TYPE_DRIVER, 297000, 2160, 2168,
195
+ 2178, 2250, 0, 4096, 4184, 4272, 4400, 0,
196
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
197
+
198
+ /* 1280x720@60Hz */
199
+ { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1390,
200
+ 1430, 1650, 0, 720, 725, 730, 750, 0,
201
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
202
+ /* 1920x1080@60Hz */
203
+ { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
204
+ 2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
205
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
206
+ /* 2560x1440@60Hz */
207
+ { DRM_MODE("2560x1440", DRM_MODE_TYPE_DRIVER, 241500, 2560, 2608,
208
+ 2640, 2720, 0, 1440, 1443, 1448, 1481, 0,
209
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
210
+ /* 3840x2160@60Hz */
211
+ { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4016,
212
+ 4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
213
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
214
+ /* 4096x2160@60Hz */
215
+ { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 594000, 4096, 4184,
216
+ 4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
217
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
218
+ /* 720x1280@60Hz */
219
+ { DRM_MODE("720x1280", DRM_MODE_TYPE_DRIVER, 74250, 720, 725,
220
+ 730, 750, 0, 1280, 1390, 1430, 1650, 0,
221
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
222
+ /* 1080x1920@60Hz */
223
+ { DRM_MODE("1080x1920", DRM_MODE_TYPE_DRIVER, 148500, 1080, 1084,
224
+ 1089, 1125, 0, 1920, 2008, 2052, 2200, 0,
225
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
226
+ /* 1440x2560@60Hz */
227
+ { DRM_MODE("1440x2560", DRM_MODE_TYPE_DRIVER, 241500, 1440, 1443,
228
+ 1448, 1481, 0, 2560, 2608, 2640, 2720, 0,
229
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
230
+ /* 2160x3840@60Hz */
231
+ { DRM_MODE("2160x3840", DRM_MODE_TYPE_DRIVER, 594000, 2160, 2168,
232
+ 2178, 2250, 0, 3840, 4016, 4104, 4400, 0,
233
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
234
+ /* 2160x4096@60Hz */
235
+ { DRM_MODE("2160x4096", DRM_MODE_TYPE_DRIVER, 594000, 2160, 2168,
236
+ 2178, 2250, 0, 4096, 4184, 4272, 4400, 0,
237
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
238
+
239
+ /* 1280x720@90Hz */
240
+ { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 111375, 1280, 1390,
241
+ 1430, 1650, 0, 720, 725, 730, 750, 0,
242
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
243
+ /* 1920x1080@90Hz */
244
+ { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 222750, 1920, 2008,
245
+ 2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
246
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
247
+ /* 2560x1440@90Hz */
248
+ { DRM_MODE("2560x1440", DRM_MODE_TYPE_DRIVER, 362250, 2560, 2608,
249
+ 2640, 2720, 0, 1440, 1443, 1448, 1481, 0,
250
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
251
+ /* 3840x2160@90Hz */
252
+ { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 891000, 3840, 4016,
253
+ 4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
254
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
255
+ /* 4096x2160@90Hz */
256
+ { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 891000, 4096, 4184,
257
+ 4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
258
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
259
+ /* 720x1280@90Hz */
260
+ { DRM_MODE("720x1280", DRM_MODE_TYPE_DRIVER, 111375, 720, 725,
261
+ 730, 750, 0, 1280, 1390, 1430, 1650, 0,
262
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
263
+ /* 1080x1920@90Hz */
264
+ { DRM_MODE("1080x1920", DRM_MODE_TYPE_DRIVER, 222750, 1080, 1084,
265
+ 1089, 1125, 0, 1920, 2008, 2052, 2200, 0,
266
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
267
+ /* 1440x2560@90Hz */
268
+ { DRM_MODE("1440x2560", DRM_MODE_TYPE_DRIVER, 362250, 1440, 1443,
269
+ 1448, 1481, 0, 2560, 2608, 2640, 2720, 0,
270
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
271
+ /* 2160x3840@90Hz */
272
+ { DRM_MODE("2160x3840", DRM_MODE_TYPE_DRIVER, 891000, 2160, 2168,
273
+ 2178, 2250, 0, 3840, 4016, 4104, 4400, 0,
274
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
275
+ /* 2160x4096@90Hz */
276
+ { DRM_MODE("2160x4096", DRM_MODE_TYPE_DRIVER, 891000, 2160, 2168,
277
+ 2178, 2250, 0, 4096, 4184, 4272, 4400, 0,
278
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
279
+
280
+ /* 1280x720@120Hz */
281
+ { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1390,
282
+ 1430, 1650, 0, 720, 725, 730, 750, 0,
283
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
284
+ /* 1920x1080@120Hz */
285
+ { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2008,
286
+ 2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
287
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
288
+ /* 2560x1440@120Hz */
289
+ { DRM_MODE("2560x1440", DRM_MODE_TYPE_DRIVER, 483000, 2560, 2608,
290
+ 2640, 2720, 0, 1440, 1443, 1448, 1481, 0,
291
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
292
+ /* 3840x2160@120Hz */
293
+ { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 1188000, 3840, 4016,
294
+ 4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
295
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
296
+ /* 4096x2160@120Hz */
297
+ { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 1188000, 4096, 4184,
298
+ 4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
299
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
300
+ /* 720x1280@120Hz */
301
+ { DRM_MODE("720x1280", DRM_MODE_TYPE_DRIVER, 148500, 720, 725,
302
+ 730, 750, 0, 1280, 1390, 1430, 1650, 0,
303
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
304
+ /* 1080x1920@120Hz */
305
+ { DRM_MODE("1080x1920", DRM_MODE_TYPE_DRIVER, 297000, 1080, 1084,
306
+ 1089, 1125, 0, 1920, 2008, 2052, 2200, 0,
307
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
308
+ /* 1440x2560@120Hz */
309
+ { DRM_MODE("1440x2560", DRM_MODE_TYPE_DRIVER, 483000, 1440, 1443,
310
+ 1448, 1481, 0, 2560, 2608, 2640, 2720, 0,
311
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
312
+ /* 2160x3840@120Hz */
313
+ { DRM_MODE("2160x3840", DRM_MODE_TYPE_DRIVER, 1188000, 2160, 2168,
314
+ 2178, 2250, 0, 3840, 4016, 4104, 4400, 0,
315
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
316
+ /* 2160x4096@120Hz */
317
+ { DRM_MODE("2160x4096", DRM_MODE_TYPE_DRIVER, 1188000, 2160, 2168,
318
+ 2178, 2250, 0, 4096, 4184, 4272, 4400, 0,
319
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
320
+
321
+ /* 1280x720@144Hz */
322
+ { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 178200, 1280, 1390,
323
+ 1430, 1650, 0, 720, 725, 730, 750, 0,
324
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
325
+ /* 1920x1080@144Hz */
326
+ { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 356400, 1920, 2008,
327
+ 2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
328
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
329
+ /* 2560x1440@144Hz */
330
+ { DRM_MODE("2560x1440", DRM_MODE_TYPE_DRIVER, 483000, 2560, 2608,
331
+ 2640, 2720, 0, 1440, 1443, 1448, 1481, 0,
332
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
333
+ /* 3840x2160@144Hz */
334
+ { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 1425600, 3840, 4016,
335
+ 4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
336
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
337
+ /* 4096x2160@144Hz */
338
+ { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 1425600, 4096, 4184,
339
+ 4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
340
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
341
+ /* 720x1280@144Hz */
342
+ { DRM_MODE("720x1280", DRM_MODE_TYPE_DRIVER, 178200, 720, 725,
343
+ 730, 750, 0, 1280, 1390, 1430, 1650, 0,
344
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
345
+ /* 1080x1920@144Hz */
346
+ { DRM_MODE("1080x1920", DRM_MODE_TYPE_DRIVER, 356400, 1080, 1084,
347
+ 1089, 1125, 0, 1920, 2008, 2052, 2200, 0,
348
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
349
+ /* 1440x2560@144Hz */
350
+ { DRM_MODE("1440x2560", DRM_MODE_TYPE_DRIVER, 580000, 1440, 1443,
351
+ 1448, 1481, 0, 2560, 2608, 2640, 2720, 0,
352
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
353
+ /* 2160x3840@144Hz */
354
+ { DRM_MODE("2160x3840", DRM_MODE_TYPE_DRIVER, 1425600, 2160, 2168,
355
+ 2178, 2250, 0, 3840, 4016, 4104, 4400, 0,
356
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
357
+ /* 2160x4096@144Hz */
358
+ { DRM_MODE("2160x4096", DRM_MODE_TYPE_DRIVER, 1425600, 2160, 2168,
359
+ 2178, 2250, 0, 4096, 4184, 4272, 4400, 0,
360
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
361
+};
362
+
155363 static int vvop_conn_get_modes(struct drm_connector *connector)
156364 {
157
- int count;
365
+ struct drm_display_mode *mode = NULL;
366
+ struct drm_display_mode *bmode;
367
+ int count = 0;
368
+ int i;
158369
159
- count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
370
+ count += drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
371
+ for (i = 0; vvop_modes_builtin[i].type != 0; i++) {
372
+ bmode = &vvop_modes_builtin[i];
373
+
374
+ mode = drm_mode_duplicate(connector->dev, bmode);
375
+ if (!mode)
376
+ return 0;
377
+
378
+ drm_mode_probed_add(connector, mode);
379
+ count++;
380
+ }
160381 drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
161382
162383 return count;
....@@ -167,12 +388,12 @@
167388 };
168389
169390 static const struct drm_crtc_funcs vvop_crtc_funcs = {
170
- .set_config = drm_atomic_helper_set_config,
171
- .destroy = drm_crtc_cleanup,
172
- .page_flip = drm_atomic_helper_page_flip,
173
- .reset = drm_atomic_helper_crtc_reset,
174
- .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
175
- .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
391
+ .set_config = drm_atomic_helper_set_config,
392
+ .destroy = drm_crtc_cleanup,
393
+ .page_flip = drm_atomic_helper_page_flip,
394
+ .reset = drm_atomic_helper_crtc_reset,
395
+ .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
396
+ .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
176397 .enable_vblank = vvop_enable_vblank,
177398 .disable_vblank = vvop_disable_vblank,
178399 };
....@@ -224,9 +445,34 @@
224445 .atomic_disable = vvop_crtc_atomic_disable,
225446 };
226447
227
-static int vvop_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
228
- struct drm_plane *primary, struct drm_plane *cursor)
448
+static u64 vvop_get_soc_id(void)
229449 {
450
+ if (of_machine_is_compatible("rockchip,rk3588"))
451
+ return 0x3588;
452
+ else if (of_machine_is_compatible("rockchip,rk3568"))
453
+ return 0x3568;
454
+ else if (of_machine_is_compatible("rockchip,rk3566"))
455
+ return 0x3566;
456
+ else if (of_machine_is_compatible("rockchip,rk3562"))
457
+ return 0x3562;
458
+ else if (of_machine_is_compatible("rockchip,rk3528"))
459
+ return 0x3528;
460
+ else
461
+ return 0;
462
+}
463
+
464
+static void vvop_crtc_deinit(struct drm_crtc *crtc)
465
+{
466
+ struct vvop_crtc *vcrtc = drm_crtc_to_vvop_crtc(crtc);
467
+
468
+ hrtimer_cancel(&vcrtc->vblank_hrtimer);
469
+ drm_crtc_cleanup(crtc);
470
+}
471
+
472
+static int vvop_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
473
+ struct drm_plane *primary, struct drm_plane *cursor)
474
+{
475
+ struct vvop_crtc *vcrtc = drm_crtc_to_vvop_crtc(crtc);
230476 int ret;
231477
232478 ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor,
....@@ -238,18 +484,112 @@
238484
239485 drm_crtc_helper_add(crtc, &vvop_crtc_helper_funcs);
240486
487
+ vcrtc->is_virtual_prop = drm_property_create_object(dev,
488
+ DRM_MODE_PROP_ATOMIC |
489
+ DRM_MODE_PROP_IMMUTABLE,
490
+ "IS_VIRTUAL", DRM_MODE_OBJECT_CRTC);
491
+ drm_object_attach_property(&crtc->base, vcrtc->is_virtual_prop, 1);
492
+
493
+ vcrtc->soc_id_prop = drm_property_create_object(dev,
494
+ DRM_MODE_PROP_ATOMIC |
495
+ DRM_MODE_PROP_IMMUTABLE,
496
+ "SOC_ID", DRM_MODE_OBJECT_CRTC);
497
+ drm_object_attach_property(&crtc->base, vcrtc->soc_id_prop, vvop_get_soc_id());
498
+
499
+ hrtimer_init(&vcrtc->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
500
+ vcrtc->vblank_hrtimer.function = &vvop_vblank_simulate;
501
+
241502 return ret;
503
+}
504
+
505
+static int vvop_create_crtc(struct vvop *vvop, int index)
506
+{
507
+ struct drm_crtc *crtc = &vvop->vcrtc[index].crtc;
508
+ struct drm_connector *connector = &vvop->vcrtc[index].connector;
509
+ struct drm_encoder *encoder = &vvop->vcrtc[index].encoder;
510
+ struct drm_plane *primary = &vvop->vcrtc[index].plane;
511
+ int ret;
512
+
513
+ ret = vvop_plane_init(vvop->drm_dev, primary);
514
+ if (ret) {
515
+ DRM_ERROR("Failed to init primary plane for crtc-%d\n", index);
516
+ return ret;
517
+ }
518
+
519
+ ret = vvop_crtc_init(vvop->drm_dev, crtc, primary, NULL);
520
+ if (ret) {
521
+ DRM_ERROR("Failed to init crtc-%d\n", index);
522
+ goto err_crtc;
523
+ }
524
+
525
+ ret = drm_connector_init(vvop->drm_dev, connector, &vvop_connector_funcs,
526
+ DRM_MODE_CONNECTOR_VIRTUAL);
527
+ if (ret) {
528
+ DRM_ERROR("Failed to init connector-%d\n", index);
529
+ goto err_connector;
530
+ }
531
+ drm_connector_helper_add(connector, &vvop_conn_helper_funcs);
532
+
533
+ ret = drm_connector_register(connector);
534
+ if (ret) {
535
+ DRM_ERROR("Failed to register connector-%d\n", index);
536
+ goto err_connector_register;
537
+ }
538
+
539
+ ret = drm_encoder_init(vvop->drm_dev, encoder, &vvop_encoder_funcs,
540
+ DRM_MODE_ENCODER_VIRTUAL, NULL);
541
+ if (ret) {
542
+ DRM_ERROR("Failed to init encoder-%d\n", index);
543
+ goto err_encoder;
544
+ }
545
+ encoder->possible_crtcs = BIT(index);
546
+
547
+ ret = drm_connector_attach_encoder(connector, encoder);
548
+ if (ret) {
549
+ DRM_ERROR("Failed to attach connector-%d to encoder-%d\n", index, index);
550
+ goto err_attach;
551
+ }
552
+
553
+ vvop->crtc_mask |= drm_crtc_mask(crtc);
554
+
555
+ return 0;
556
+
557
+err_attach:
558
+ drm_encoder_cleanup(encoder);
559
+err_encoder:
560
+ drm_connector_unregister(connector);
561
+err_connector_register:
562
+ drm_connector_cleanup(connector);
563
+err_connector:
564
+ vvop_crtc_deinit(crtc);
565
+err_crtc:
566
+ drm_plane_cleanup(primary);
567
+
568
+ return ret;
569
+}
570
+
571
+static int vvop_create_crtcs(struct vvop *vvop)
572
+{
573
+ int ret;
574
+ int i;
575
+
576
+ for (i = 0; i < VVOP_MAX_CRTC; i++) {
577
+ ret = vvop_create_crtc(vvop, i);
578
+ if (ret) {
579
+ DRM_WARN("Failed to create virtual crtc, index = %d\n", i);
580
+ break;
581
+ }
582
+ }
583
+
584
+ DRM_INFO("Create %d(total: %d) virtual crtcs\n", i, VVOP_MAX_CRTC);
585
+
586
+ return 0;
242587 }
243588
244589 static int vvop_bind(struct device *dev, struct device *master, void *data)
245590 {
246591 struct drm_device *drm_dev = data;
247
- struct drm_connector *connector;
248
- struct drm_encoder *encoder;
249
- struct drm_plane *primary;
250
- struct drm_crtc *crtc;
251592 struct vvop *vvop;
252
- int ret;
253593
254594 vvop = devm_kzalloc(dev, sizeof(*vvop), GFP_KERNEL);
255595 if (!vvop)
....@@ -257,77 +597,33 @@
257597
258598 vvop->dev = dev;
259599 vvop->drm_dev = drm_dev;
260
- connector = &vvop->connector;
261
- encoder = &vvop->encoder;
262
- crtc = &vvop->crtc;
263
-
264600 dev_set_drvdata(dev, vvop);
265601
266
- primary = vvop_plane_init(vvop);
267
- if (IS_ERR(primary))
268
- return PTR_ERR(primary);
269
- vvop->plane = primary;
270
-
271
- ret = vvop_crtc_init(drm_dev, crtc, primary, NULL);
272
- if (ret)
273
- goto err_crtc;
274
-
275
- ret = drm_connector_init(drm_dev, connector, &vvop_connector_funcs,
276
- DRM_MODE_CONNECTOR_VIRTUAL);
277
- if (ret) {
278
- DRM_ERROR("Failed to init connector\n");
279
- goto err_connector;
280
- }
281
-
282
- drm_connector_helper_add(connector, &vvop_conn_helper_funcs);
283
-
284
- ret = drm_connector_register(connector);
285
- if (ret) {
286
- DRM_ERROR("Failed to register connector\n");
287
- goto err_connector_register;
288
- }
289
-
290
- ret = drm_encoder_init(drm_dev, encoder, &vvop_encoder_funcs,
291
- DRM_MODE_ENCODER_VIRTUAL, NULL);
292
- if (ret) {
293
- DRM_ERROR("Failed to init encoder\n");
294
- goto err_encoder;
295
- }
296
- encoder->possible_crtcs = 1;
297
-
298
- ret = drm_connector_attach_encoder(connector, encoder);
299
- if (ret) {
300
- DRM_ERROR("Failed to attach connector to encoder\n");
301
- goto err_attach;
302
- }
602
+ vvop_create_crtcs(vvop);
303603
304604 return 0;
305
-
306
-err_attach:
307
- drm_encoder_cleanup(encoder);
308
-
309
-err_encoder:
310
- drm_connector_unregister(connector);
311
-
312
-err_connector_register:
313
- drm_connector_cleanup(connector);
314
-
315
-err_connector:
316
- drm_crtc_cleanup(crtc);
317
-
318
-err_crtc:
319
- drm_plane_cleanup(primary);
320
-
321
- return ret;
322605 }
323606
324607 static void vvop_unbind(struct device *dev, struct device *master, void *data)
325608 {
326609 struct vvop *vvop = dev_get_drvdata(dev);
610
+ struct drm_device *drm_dev = vvop->drm_dev;
611
+ struct list_head *crtc_list = &drm_dev->mode_config.crtc_list;
612
+ struct drm_crtc *crtc, *tmp_crtc;
613
+ struct vvop_crtc *vcrtc;
327614
328
- drm_plane_cleanup(vvop->plane);
329
- drm_connector_cleanup(&vvop->connector);
330
- drm_crtc_cleanup(&vvop->crtc);
615
+ list_for_each_entry_safe(crtc, tmp_crtc, crtc_list, head) {
616
+ if (vvop->crtc_mask & drm_crtc_mask(crtc)) {
617
+ vcrtc = drm_crtc_to_vvop_crtc(crtc);
618
+
619
+ drm_encoder_cleanup(&vcrtc->encoder);
620
+ drm_connector_unregister(&vcrtc->connector);
621
+ drm_connector_cleanup(&vcrtc->connector);
622
+ drm_plane_cleanup(&vcrtc->plane);
623
+ vvop->crtc_mask &= ~(drm_crtc_mask(crtc));
624
+ vvop_crtc_deinit(crtc);
625
+ }
626
+ }
331627 }
332628
333629 const struct component_ops vvop_component_ops = {
....@@ -362,12 +658,10 @@
362658
363659 static int __init vvop_init(void)
364660 {
365
- struct platform_device *pdev;
366
-
367
- pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
368
- if (IS_ERR(pdev)) {
661
+ vvop_pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
662
+ if (IS_ERR(vvop_pdev)) {
369663 DRM_ERROR("failed to register platform device %s\n", DRIVER_NAME);
370
- return PTR_ERR(pdev);
664
+ return PTR_ERR(vvop_pdev);
371665 }
372666
373667 return 0;
....@@ -375,6 +669,7 @@
375669
376670 static void __exit vvop_exit(void)
377671 {
672
+ platform_device_unregister(vvop_pdev);
378673 }
379674
380675 rootfs_initcall(vvop_init);