File Index
Files and directories
Sign in
FILE

simpledrm.c

File preview with syntax highlighting.

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