xref: /openbmc/linux/drivers/gpu/drm/tiny/simpledrm.c (revision ba8ff971)
1 // SPDX-License-Identifier: GPL-2.0-only
2 
3 #include <linux/clk.h>
4 #include <linux/of_clk.h>
5 #include <linux/minmax.h>
6 #include <linux/platform_data/simplefb.h>
7 #include <linux/platform_device.h>
8 #include <linux/regulator/consumer.h>
9 
10 #include <drm/drm_aperture.h>
11 #include <drm/drm_atomic.h>
12 #include <drm/drm_atomic_state_helper.h>
13 #include <drm/drm_connector.h>
14 #include <drm/drm_crtc_helper.h>
15 #include <drm/drm_damage_helper.h>
16 #include <drm/drm_device.h>
17 #include <drm/drm_drv.h>
18 #include <drm/drm_fbdev_generic.h>
19 #include <drm/drm_format_helper.h>
20 #include <drm/drm_gem_atomic_helper.h>
21 #include <drm/drm_gem_framebuffer_helper.h>
22 #include <drm/drm_gem_shmem_helper.h>
23 #include <drm/drm_managed.h>
24 #include <drm/drm_modeset_helper_vtables.h>
25 #include <drm/drm_plane_helper.h>
26 #include <drm/drm_probe_helper.h>
27 
28 #define DRIVER_NAME	"simpledrm"
29 #define DRIVER_DESC	"DRM driver for simple-framebuffer platform devices"
30 #define DRIVER_DATE	"20200625"
31 #define DRIVER_MAJOR	1
32 #define DRIVER_MINOR	0
33 
34 /*
35  * Helpers for simplefb
36  */
37 
38 static int
39 simplefb_get_validated_int(struct drm_device *dev, const char *name,
40 			   uint32_t value)
41 {
42 	if (value > INT_MAX) {
43 		drm_err(dev, "simplefb: invalid framebuffer %s of %u\n",
44 			name, value);
45 		return -EINVAL;
46 	}
47 	return (int)value;
48 }
49 
50 static int
51 simplefb_get_validated_int0(struct drm_device *dev, const char *name,
52 			    uint32_t value)
53 {
54 	if (!value) {
55 		drm_err(dev, "simplefb: invalid framebuffer %s of %u\n",
56 			name, value);
57 		return -EINVAL;
58 	}
59 	return simplefb_get_validated_int(dev, name, value);
60 }
61 
62 static const struct drm_format_info *
63 simplefb_get_validated_format(struct drm_device *dev, const char *format_name)
64 {
65 	static const struct simplefb_format formats[] = SIMPLEFB_FORMATS;
66 	const struct simplefb_format *fmt = formats;
67 	const struct simplefb_format *end = fmt + ARRAY_SIZE(formats);
68 	const struct drm_format_info *info;
69 
70 	if (!format_name) {
71 		drm_err(dev, "simplefb: missing framebuffer format\n");
72 		return ERR_PTR(-EINVAL);
73 	}
74 
75 	while (fmt < end) {
76 		if (!strcmp(format_name, fmt->name)) {
77 			info = drm_format_info(fmt->fourcc);
78 			if (!info)
79 				return ERR_PTR(-EINVAL);
80 			return info;
81 		}
82 		++fmt;
83 	}
84 
85 	drm_err(dev, "simplefb: unknown framebuffer format %s\n",
86 		format_name);
87 
88 	return ERR_PTR(-EINVAL);
89 }
90 
91 static int
92 simplefb_get_width_pd(struct drm_device *dev,
93 		      const struct simplefb_platform_data *pd)
94 {
95 	return simplefb_get_validated_int0(dev, "width", pd->width);
96 }
97 
98 static int
99 simplefb_get_height_pd(struct drm_device *dev,
100 		       const struct simplefb_platform_data *pd)
101 {
102 	return simplefb_get_validated_int0(dev, "height", pd->height);
103 }
104 
105 static int
106 simplefb_get_stride_pd(struct drm_device *dev,
107 		       const struct simplefb_platform_data *pd)
108 {
109 	return simplefb_get_validated_int(dev, "stride", pd->stride);
110 }
111 
112 static const struct drm_format_info *
113 simplefb_get_format_pd(struct drm_device *dev,
114 		       const struct simplefb_platform_data *pd)
115 {
116 	return simplefb_get_validated_format(dev, pd->format);
117 }
118 
119 static int
120 simplefb_read_u32_of(struct drm_device *dev, struct device_node *of_node,
121 		     const char *name, u32 *value)
122 {
123 	int ret = of_property_read_u32(of_node, name, value);
124 
125 	if (ret)
126 		drm_err(dev, "simplefb: cannot parse framebuffer %s: error %d\n",
127 			name, ret);
128 	return ret;
129 }
130 
131 static int
132 simplefb_read_string_of(struct drm_device *dev, struct device_node *of_node,
133 			const char *name, const char **value)
134 {
135 	int ret = of_property_read_string(of_node, name, value);
136 
137 	if (ret)
138 		drm_err(dev, "simplefb: cannot parse framebuffer %s: error %d\n",
139 			name, ret);
140 	return ret;
141 }
142 
143 static int
144 simplefb_get_width_of(struct drm_device *dev, struct device_node *of_node)
145 {
146 	u32 width;
147 	int ret = simplefb_read_u32_of(dev, of_node, "width", &width);
148 
149 	if (ret)
150 		return ret;
151 	return simplefb_get_validated_int0(dev, "width", width);
152 }
153 
154 static int
155 simplefb_get_height_of(struct drm_device *dev, struct device_node *of_node)
156 {
157 	u32 height;
158 	int ret = simplefb_read_u32_of(dev, of_node, "height", &height);
159 
160 	if (ret)
161 		return ret;
162 	return simplefb_get_validated_int0(dev, "height", height);
163 }
164 
165 static int
166 simplefb_get_stride_of(struct drm_device *dev, struct device_node *of_node)
167 {
168 	u32 stride;
169 	int ret = simplefb_read_u32_of(dev, of_node, "stride", &stride);
170 
171 	if (ret)
172 		return ret;
173 	return simplefb_get_validated_int(dev, "stride", stride);
174 }
175 
176 static const struct drm_format_info *
177 simplefb_get_format_of(struct drm_device *dev, struct device_node *of_node)
178 {
179 	const char *format;
180 	int ret = simplefb_read_string_of(dev, of_node, "format", &format);
181 
182 	if (ret)
183 		return ERR_PTR(ret);
184 	return simplefb_get_validated_format(dev, format);
185 }
186 
187 /*
188  * Simple Framebuffer device
189  */
190 
191 struct simpledrm_device {
192 	struct drm_device dev;
193 
194 	/* clocks */
195 #if defined CONFIG_OF && defined CONFIG_COMMON_CLK
196 	unsigned int clk_count;
197 	struct clk **clks;
198 #endif
199 	/* regulators */
200 #if defined CONFIG_OF && defined CONFIG_REGULATOR
201 	unsigned int regulator_count;
202 	struct regulator **regulators;
203 #endif
204 
205 	/* simplefb settings */
206 	struct drm_display_mode mode;
207 	const struct drm_format_info *format;
208 	unsigned int pitch;
209 
210 	/* memory management */
211 	void __iomem *screen_base;
212 
213 	/* modesetting */
214 	uint32_t formats[8];
215 	size_t nformats;
216 	struct drm_plane primary_plane;
217 	struct drm_crtc crtc;
218 	struct drm_encoder encoder;
219 	struct drm_connector connector;
220 };
221 
222 static struct simpledrm_device *simpledrm_device_of_dev(struct drm_device *dev)
223 {
224 	return container_of(dev, struct simpledrm_device, dev);
225 }
226 
227 /*
228  * Hardware
229  */
230 
231 #if defined CONFIG_OF && defined CONFIG_COMMON_CLK
232 /*
233  * Clock handling code.
234  *
235  * Here we handle the clocks property of our "simple-framebuffer" dt node.
236  * This is necessary so that we can make sure that any clocks needed by
237  * the display engine that the bootloader set up for us (and for which it
238  * provided a simplefb dt node), stay up, for the life of the simplefb
239  * driver.
240  *
241  * When the driver unloads, we cleanly disable, and then release the clocks.
242  *
243  * We only complain about errors here, no action is taken as the most likely
244  * error can only happen due to a mismatch between the bootloader which set
245  * up simplefb, and the clock definitions in the device tree. Chances are
246  * that there are no adverse effects, and if there are, a clean teardown of
247  * the fb probe will not help us much either. So just complain and carry on,
248  * and hope that the user actually gets a working fb at the end of things.
249  */
250 
251 static void simpledrm_device_release_clocks(void *res)
252 {
253 	struct simpledrm_device *sdev = simpledrm_device_of_dev(res);
254 	unsigned int i;
255 
256 	for (i = 0; i < sdev->clk_count; ++i) {
257 		if (sdev->clks[i]) {
258 			clk_disable_unprepare(sdev->clks[i]);
259 			clk_put(sdev->clks[i]);
260 		}
261 	}
262 }
263 
264 static int simpledrm_device_init_clocks(struct simpledrm_device *sdev)
265 {
266 	struct drm_device *dev = &sdev->dev;
267 	struct platform_device *pdev = to_platform_device(dev->dev);
268 	struct device_node *of_node = pdev->dev.of_node;
269 	struct clk *clock;
270 	unsigned int i;
271 	int ret;
272 
273 	if (dev_get_platdata(&pdev->dev) || !of_node)
274 		return 0;
275 
276 	sdev->clk_count = of_clk_get_parent_count(of_node);
277 	if (!sdev->clk_count)
278 		return 0;
279 
280 	sdev->clks = drmm_kzalloc(dev, sdev->clk_count * sizeof(sdev->clks[0]),
281 				  GFP_KERNEL);
282 	if (!sdev->clks)
283 		return -ENOMEM;
284 
285 	for (i = 0; i < sdev->clk_count; ++i) {
286 		clock = of_clk_get(of_node, i);
287 		if (IS_ERR(clock)) {
288 			ret = PTR_ERR(clock);
289 			if (ret == -EPROBE_DEFER)
290 				goto err;
291 			drm_err(dev, "clock %u not found: %d\n", i, ret);
292 			continue;
293 		}
294 		ret = clk_prepare_enable(clock);
295 		if (ret) {
296 			drm_err(dev, "failed to enable clock %u: %d\n",
297 				i, ret);
298 			clk_put(clock);
299 			continue;
300 		}
301 		sdev->clks[i] = clock;
302 	}
303 
304 	return devm_add_action_or_reset(&pdev->dev,
305 					simpledrm_device_release_clocks,
306 					sdev);
307 
308 err:
309 	while (i) {
310 		--i;
311 		if (sdev->clks[i]) {
312 			clk_disable_unprepare(sdev->clks[i]);
313 			clk_put(sdev->clks[i]);
314 		}
315 	}
316 	return ret;
317 }
318 #else
319 static int simpledrm_device_init_clocks(struct simpledrm_device *sdev)
320 {
321 	return 0;
322 }
323 #endif
324 
325 #if defined CONFIG_OF && defined CONFIG_REGULATOR
326 
327 #define SUPPLY_SUFFIX "-supply"
328 
329 /*
330  * Regulator handling code.
331  *
332  * Here we handle the num-supplies and vin*-supply properties of our
333  * "simple-framebuffer" dt node. This is necessary so that we can make sure
334  * that any regulators needed by the display hardware that the bootloader
335  * set up for us (and for which it provided a simplefb dt node), stay up,
336  * for the life of the simplefb driver.
337  *
338  * When the driver unloads, we cleanly disable, and then release the
339  * regulators.
340  *
341  * We only complain about errors here, no action is taken as the most likely
342  * error can only happen due to a mismatch between the bootloader which set
343  * up simplefb, and the regulator definitions in the device tree. Chances are
344  * that there are no adverse effects, and if there are, a clean teardown of
345  * the fb probe will not help us much either. So just complain and carry on,
346  * and hope that the user actually gets a working fb at the end of things.
347  */
348 
349 static void simpledrm_device_release_regulators(void *res)
350 {
351 	struct simpledrm_device *sdev = simpledrm_device_of_dev(res);
352 	unsigned int i;
353 
354 	for (i = 0; i < sdev->regulator_count; ++i) {
355 		if (sdev->regulators[i]) {
356 			regulator_disable(sdev->regulators[i]);
357 			regulator_put(sdev->regulators[i]);
358 		}
359 	}
360 }
361 
362 static int simpledrm_device_init_regulators(struct simpledrm_device *sdev)
363 {
364 	struct drm_device *dev = &sdev->dev;
365 	struct platform_device *pdev = to_platform_device(dev->dev);
366 	struct device_node *of_node = pdev->dev.of_node;
367 	struct property *prop;
368 	struct regulator *regulator;
369 	const char *p;
370 	unsigned int count = 0, i = 0;
371 	int ret;
372 
373 	if (dev_get_platdata(&pdev->dev) || !of_node)
374 		return 0;
375 
376 	/* Count the number of regulator supplies */
377 	for_each_property_of_node(of_node, prop) {
378 		p = strstr(prop->name, SUPPLY_SUFFIX);
379 		if (p && p != prop->name)
380 			++count;
381 	}
382 
383 	if (!count)
384 		return 0;
385 
386 	sdev->regulators = drmm_kzalloc(dev,
387 					count * sizeof(sdev->regulators[0]),
388 					GFP_KERNEL);
389 	if (!sdev->regulators)
390 		return -ENOMEM;
391 
392 	for_each_property_of_node(of_node, prop) {
393 		char name[32]; /* 32 is max size of property name */
394 		size_t len;
395 
396 		p = strstr(prop->name, SUPPLY_SUFFIX);
397 		if (!p || p == prop->name)
398 			continue;
399 		len = strlen(prop->name) - strlen(SUPPLY_SUFFIX) + 1;
400 		strscpy(name, prop->name, min(sizeof(name), len));
401 
402 		regulator = regulator_get_optional(&pdev->dev, name);
403 		if (IS_ERR(regulator)) {
404 			ret = PTR_ERR(regulator);
405 			if (ret == -EPROBE_DEFER)
406 				goto err;
407 			drm_err(dev, "regulator %s not found: %d\n",
408 				name, ret);
409 			continue;
410 		}
411 
412 		ret = regulator_enable(regulator);
413 		if (ret) {
414 			drm_err(dev, "failed to enable regulator %u: %d\n",
415 				i, ret);
416 			regulator_put(regulator);
417 			continue;
418 		}
419 
420 		sdev->regulators[i++] = regulator;
421 	}
422 	sdev->regulator_count = i;
423 
424 	return devm_add_action_or_reset(&pdev->dev,
425 					simpledrm_device_release_regulators,
426 					sdev);
427 
428 err:
429 	while (i) {
430 		--i;
431 		if (sdev->regulators[i]) {
432 			regulator_disable(sdev->regulators[i]);
433 			regulator_put(sdev->regulators[i]);
434 		}
435 	}
436 	return ret;
437 }
438 #else
439 static int simpledrm_device_init_regulators(struct simpledrm_device *sdev)
440 {
441 	return 0;
442 }
443 #endif
444 
445 /*
446  * Modesetting
447  */
448 
449 static const uint64_t simpledrm_primary_plane_format_modifiers[] = {
450 	DRM_FORMAT_MOD_LINEAR,
451 	DRM_FORMAT_MOD_INVALID
452 };
453 
454 static void simpledrm_primary_plane_helper_atomic_update(struct drm_plane *plane,
455 							 struct drm_atomic_state *state)
456 {
457 	struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
458 	struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
459 	struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
460 	struct drm_framebuffer *fb = plane_state->fb;
461 	struct drm_device *dev = plane->dev;
462 	struct simpledrm_device *sdev = simpledrm_device_of_dev(dev);
463 	struct drm_atomic_helper_damage_iter iter;
464 	struct drm_rect damage;
465 	int ret, idx;
466 
467 	ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
468 	if (ret)
469 		return;
470 
471 	if (!drm_dev_enter(dev, &idx))
472 		goto out_drm_gem_fb_end_cpu_access;
473 
474 	drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
475 	drm_atomic_for_each_plane_damage(&iter, &damage) {
476 		struct iosys_map dst = IOSYS_MAP_INIT_VADDR(sdev->screen_base);
477 		struct drm_rect dst_clip = plane_state->dst;
478 
479 		if (!drm_rect_intersect(&dst_clip, &damage))
480 			continue;
481 
482 		iosys_map_incr(&dst, drm_fb_clip_offset(sdev->pitch, sdev->format, &dst_clip));
483 		drm_fb_blit(&dst, &sdev->pitch, sdev->format->format, shadow_plane_state->data, fb,
484 			    &damage);
485 	}
486 
487 	drm_dev_exit(idx);
488 out_drm_gem_fb_end_cpu_access:
489 	drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
490 }
491 
492 static void simpledrm_primary_plane_helper_atomic_disable(struct drm_plane *plane,
493 							  struct drm_atomic_state *state)
494 {
495 	struct drm_device *dev = plane->dev;
496 	struct simpledrm_device *sdev = simpledrm_device_of_dev(dev);
497 	int idx;
498 
499 	if (!drm_dev_enter(dev, &idx))
500 		return;
501 
502 	/* Clear screen to black if disabled */
503 	memset_io(sdev->screen_base, 0, sdev->pitch * sdev->mode.vdisplay);
504 
505 	drm_dev_exit(idx);
506 }
507 
508 static const struct drm_plane_helper_funcs simpledrm_primary_plane_helper_funcs = {
509 	DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
510 	.atomic_check = drm_plane_helper_atomic_check,
511 	.atomic_update = simpledrm_primary_plane_helper_atomic_update,
512 	.atomic_disable = simpledrm_primary_plane_helper_atomic_disable,
513 };
514 
515 static const struct drm_plane_funcs simpledrm_primary_plane_funcs = {
516 	.update_plane = drm_atomic_helper_update_plane,
517 	.disable_plane = drm_atomic_helper_disable_plane,
518 	.destroy = drm_plane_cleanup,
519 	DRM_GEM_SHADOW_PLANE_FUNCS,
520 };
521 
522 static enum drm_mode_status simpledrm_crtc_helper_mode_valid(struct drm_crtc *crtc,
523 							     const struct drm_display_mode *mode)
524 {
525 	struct simpledrm_device *sdev = simpledrm_device_of_dev(crtc->dev);
526 
527 	return drm_crtc_helper_mode_valid_fixed(crtc, mode, &sdev->mode);
528 }
529 
530 /*
531  * The CRTC is always enabled. Screen updates are performed by
532  * the primary plane's atomic_update function. Disabling clears
533  * the screen in the primary plane's atomic_disable function.
534  */
535 static const struct drm_crtc_helper_funcs simpledrm_crtc_helper_funcs = {
536 	.mode_valid = simpledrm_crtc_helper_mode_valid,
537 	.atomic_check = drm_crtc_helper_atomic_check,
538 };
539 
540 static const struct drm_crtc_funcs simpledrm_crtc_funcs = {
541 	.reset = drm_atomic_helper_crtc_reset,
542 	.destroy = drm_crtc_cleanup,
543 	.set_config = drm_atomic_helper_set_config,
544 	.page_flip = drm_atomic_helper_page_flip,
545 	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
546 	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
547 };
548 
549 static const struct drm_encoder_funcs simpledrm_encoder_funcs = {
550 	.destroy = drm_encoder_cleanup,
551 };
552 
553 static int simpledrm_connector_helper_get_modes(struct drm_connector *connector)
554 {
555 	struct simpledrm_device *sdev = simpledrm_device_of_dev(connector->dev);
556 
557 	return drm_connector_helper_get_modes_fixed(connector, &sdev->mode);
558 }
559 
560 static const struct drm_connector_helper_funcs simpledrm_connector_helper_funcs = {
561 	.get_modes = simpledrm_connector_helper_get_modes,
562 };
563 
564 static const struct drm_connector_funcs simpledrm_connector_funcs = {
565 	.reset = drm_atomic_helper_connector_reset,
566 	.fill_modes = drm_helper_probe_single_connector_modes,
567 	.destroy = drm_connector_cleanup,
568 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
569 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
570 };
571 
572 static const struct drm_mode_config_funcs simpledrm_mode_config_funcs = {
573 	.fb_create = drm_gem_fb_create_with_dirty,
574 	.atomic_check = drm_atomic_helper_check,
575 	.atomic_commit = drm_atomic_helper_commit,
576 };
577 
578 /*
579  * Init / Cleanup
580  */
581 
582 static struct drm_display_mode simpledrm_mode(unsigned int width,
583 					      unsigned int height)
584 {
585 	/*
586 	 * Assume a monitor resolution of 96 dpi to
587 	 * get a somewhat reasonable screen size.
588 	 */
589 	const struct drm_display_mode mode = {
590 		DRM_MODE_INIT(60, width, height,
591 			      DRM_MODE_RES_MM(width, 96ul),
592 			      DRM_MODE_RES_MM(height, 96ul))
593 	};
594 
595 	return mode;
596 }
597 
598 static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv,
599 							struct platform_device *pdev)
600 {
601 	const struct simplefb_platform_data *pd = dev_get_platdata(&pdev->dev);
602 	struct device_node *of_node = pdev->dev.of_node;
603 	struct simpledrm_device *sdev;
604 	struct drm_device *dev;
605 	int width, height, stride;
606 	const struct drm_format_info *format;
607 	struct resource *res, *mem;
608 	void __iomem *screen_base;
609 	struct drm_plane *primary_plane;
610 	struct drm_crtc *crtc;
611 	struct drm_encoder *encoder;
612 	struct drm_connector *connector;
613 	unsigned long max_width, max_height;
614 	size_t nformats;
615 	int ret;
616 
617 	sdev = devm_drm_dev_alloc(&pdev->dev, drv, struct simpledrm_device, dev);
618 	if (IS_ERR(sdev))
619 		return ERR_CAST(sdev);
620 	dev = &sdev->dev;
621 	platform_set_drvdata(pdev, sdev);
622 
623 	/*
624 	 * Hardware settings
625 	 */
626 
627 	ret = simpledrm_device_init_clocks(sdev);
628 	if (ret)
629 		return ERR_PTR(ret);
630 	ret = simpledrm_device_init_regulators(sdev);
631 	if (ret)
632 		return ERR_PTR(ret);
633 
634 	if (pd) {
635 		width = simplefb_get_width_pd(dev, pd);
636 		if (width < 0)
637 			return ERR_PTR(width);
638 		height = simplefb_get_height_pd(dev, pd);
639 		if (height < 0)
640 			return ERR_PTR(height);
641 		stride = simplefb_get_stride_pd(dev, pd);
642 		if (stride < 0)
643 			return ERR_PTR(stride);
644 		format = simplefb_get_format_pd(dev, pd);
645 		if (IS_ERR(format))
646 			return ERR_CAST(format);
647 	} else if (of_node) {
648 		width = simplefb_get_width_of(dev, of_node);
649 		if (width < 0)
650 			return ERR_PTR(width);
651 		height = simplefb_get_height_of(dev, of_node);
652 		if (height < 0)
653 			return ERR_PTR(height);
654 		stride = simplefb_get_stride_of(dev, of_node);
655 		if (stride < 0)
656 			return ERR_PTR(stride);
657 		format = simplefb_get_format_of(dev, of_node);
658 		if (IS_ERR(format))
659 			return ERR_CAST(format);
660 	} else {
661 		drm_err(dev, "no simplefb configuration found\n");
662 		return ERR_PTR(-ENODEV);
663 	}
664 	if (!stride) {
665 		stride = drm_format_info_min_pitch(format, 0, width);
666 		if (drm_WARN_ON(dev, !stride))
667 			return ERR_PTR(-EINVAL);
668 	}
669 
670 	sdev->mode = simpledrm_mode(width, height);
671 	sdev->format = format;
672 	sdev->pitch = stride;
673 
674 	drm_dbg(dev, "display mode={" DRM_MODE_FMT "}\n", DRM_MODE_ARG(&sdev->mode));
675 	drm_dbg(dev, "framebuffer format=%p4cc, size=%dx%d, stride=%d byte\n",
676 		&format->format, width, height, stride);
677 
678 	/*
679 	 * Memory management
680 	 */
681 
682 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
683 	if (!res)
684 		return ERR_PTR(-EINVAL);
685 
686 	ret = devm_aperture_acquire_from_firmware(dev, res->start, resource_size(res));
687 	if (ret) {
688 		drm_err(dev, "could not acquire memory range %pr: error %d\n", res, ret);
689 		return ERR_PTR(ret);
690 	}
691 
692 	mem = devm_request_mem_region(&pdev->dev, res->start, resource_size(res), drv->name);
693 	if (!mem) {
694 		/*
695 		 * We cannot make this fatal. Sometimes this comes from magic
696 		 * spaces our resource handlers simply don't know about. Use
697 		 * the I/O-memory resource as-is and try to map that instead.
698 		 */
699 		drm_warn(dev, "could not acquire memory region %pr\n", res);
700 		mem = res;
701 	}
702 
703 	screen_base = devm_ioremap_wc(&pdev->dev, mem->start, resource_size(mem));
704 	if (!screen_base)
705 		return ERR_PTR(-ENOMEM);
706 	sdev->screen_base = screen_base;
707 
708 	/*
709 	 * Modesetting
710 	 */
711 
712 	ret = drmm_mode_config_init(dev);
713 	if (ret)
714 		return ERR_PTR(ret);
715 
716 	max_width = max_t(unsigned long, width, DRM_SHADOW_PLANE_MAX_WIDTH);
717 	max_height = max_t(unsigned long, height, DRM_SHADOW_PLANE_MAX_HEIGHT);
718 
719 	dev->mode_config.min_width = width;
720 	dev->mode_config.max_width = max_width;
721 	dev->mode_config.min_height = height;
722 	dev->mode_config.max_height = max_height;
723 	dev->mode_config.preferred_depth = format->depth;
724 	dev->mode_config.funcs = &simpledrm_mode_config_funcs;
725 
726 	/* Primary plane */
727 
728 	nformats = drm_fb_build_fourcc_list(dev, &format->format, 1,
729 					    sdev->formats, ARRAY_SIZE(sdev->formats));
730 
731 	primary_plane = &sdev->primary_plane;
732 	ret = drm_universal_plane_init(dev, primary_plane, 0, &simpledrm_primary_plane_funcs,
733 				       sdev->formats, nformats,
734 				       simpledrm_primary_plane_format_modifiers,
735 				       DRM_PLANE_TYPE_PRIMARY, NULL);
736 	if (ret)
737 		return ERR_PTR(ret);
738 	drm_plane_helper_add(primary_plane, &simpledrm_primary_plane_helper_funcs);
739 	drm_plane_enable_fb_damage_clips(primary_plane);
740 
741 	/* CRTC */
742 
743 	crtc = &sdev->crtc;
744 	ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
745 					&simpledrm_crtc_funcs, NULL);
746 	if (ret)
747 		return ERR_PTR(ret);
748 	drm_crtc_helper_add(crtc, &simpledrm_crtc_helper_funcs);
749 
750 	/* Encoder */
751 
752 	encoder = &sdev->encoder;
753 	ret = drm_encoder_init(dev, encoder, &simpledrm_encoder_funcs,
754 			       DRM_MODE_ENCODER_NONE, NULL);
755 	if (ret)
756 		return ERR_PTR(ret);
757 	encoder->possible_crtcs = drm_crtc_mask(crtc);
758 
759 	/* Connector */
760 
761 	connector = &sdev->connector;
762 	ret = drm_connector_init(dev, connector, &simpledrm_connector_funcs,
763 				 DRM_MODE_CONNECTOR_Unknown);
764 	if (ret)
765 		return ERR_PTR(ret);
766 	drm_connector_helper_add(connector, &simpledrm_connector_helper_funcs);
767 	drm_connector_set_panel_orientation_with_quirk(connector,
768 						       DRM_MODE_PANEL_ORIENTATION_UNKNOWN,
769 						       width, height);
770 
771 	ret = drm_connector_attach_encoder(connector, encoder);
772 	if (ret)
773 		return ERR_PTR(ret);
774 
775 	drm_mode_config_reset(dev);
776 
777 	return sdev;
778 }
779 
780 /*
781  * DRM driver
782  */
783 
784 DEFINE_DRM_GEM_FOPS(simpledrm_fops);
785 
786 static struct drm_driver simpledrm_driver = {
787 	DRM_GEM_SHMEM_DRIVER_OPS,
788 	.name			= DRIVER_NAME,
789 	.desc			= DRIVER_DESC,
790 	.date			= DRIVER_DATE,
791 	.major			= DRIVER_MAJOR,
792 	.minor			= DRIVER_MINOR,
793 	.driver_features	= DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET,
794 	.fops			= &simpledrm_fops,
795 };
796 
797 /*
798  * Platform driver
799  */
800 
801 static int simpledrm_probe(struct platform_device *pdev)
802 {
803 	struct simpledrm_device *sdev;
804 	struct drm_device *dev;
805 	unsigned int color_mode;
806 	int ret;
807 
808 	sdev = simpledrm_device_create(&simpledrm_driver, pdev);
809 	if (IS_ERR(sdev))
810 		return PTR_ERR(sdev);
811 	dev = &sdev->dev;
812 
813 	ret = drm_dev_register(dev, 0);
814 	if (ret)
815 		return ret;
816 
817 	color_mode = drm_format_info_bpp(sdev->format, 0);
818 	if (color_mode == 16)
819 		color_mode = sdev->format->depth; // can be 15 or 16
820 
821 	drm_fbdev_generic_setup(dev, color_mode);
822 
823 	return 0;
824 }
825 
826 static int simpledrm_remove(struct platform_device *pdev)
827 {
828 	struct simpledrm_device *sdev = platform_get_drvdata(pdev);
829 	struct drm_device *dev = &sdev->dev;
830 
831 	drm_dev_unplug(dev);
832 
833 	return 0;
834 }
835 
836 static const struct of_device_id simpledrm_of_match_table[] = {
837 	{ .compatible = "simple-framebuffer", },
838 	{ },
839 };
840 MODULE_DEVICE_TABLE(of, simpledrm_of_match_table);
841 
842 static struct platform_driver simpledrm_platform_driver = {
843 	.driver = {
844 		.name = "simple-framebuffer", /* connect to sysfb */
845 		.of_match_table = simpledrm_of_match_table,
846 	},
847 	.probe = simpledrm_probe,
848 	.remove = simpledrm_remove,
849 };
850 
851 module_platform_driver(simpledrm_platform_driver);
852 
853 MODULE_DESCRIPTION(DRIVER_DESC);
854 MODULE_LICENSE("GPL v2");
855