File Index
Files and directories
Sign in
FILE

sprd_drm.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/sprd/sprd_drm.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (C) 2020 Unisoc Inc.
  4 */
  5
  6#include <linux/component.h>
  7#include <linux/dma-mapping.h>
  8#include <linux/mod_devicetable.h>
  9#include <linux/module.h>
 10#include <linux/mutex.h>
 11#include <linux/of_graph.h>
 12#include <linux/platform_device.h>
 13
 14#include <drm/drm_atomic_helper.h>
 15#include <drm/drm_drv.h>
 16#include <drm/drm_gem_dma_helper.h>
 17#include <drm/drm_gem_framebuffer_helper.h>
 18#include <drm/drm_of.h>
 19#include <drm/drm_probe_helper.h>
 20#include <drm/drm_vblank.h>
 21
 22#include "sprd_drm.h"
 23
 24#define DRIVER_NAME	"sprd"
 25#define DRIVER_DESC	"Spreadtrum SoCs' DRM Driver"
 26#define DRIVER_MAJOR	1
 27#define DRIVER_MINOR	0
 28
 29static const struct drm_mode_config_helper_funcs sprd_drm_mode_config_helper = {
 30	.atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
 31};
 32
 33static const struct drm_mode_config_funcs sprd_drm_mode_config_funcs = {
 34	.fb_create = drm_gem_fb_create,
 35	.atomic_check = drm_atomic_helper_check,
 36	.atomic_commit = drm_atomic_helper_commit,
 37};
 38
 39static void sprd_drm_mode_config_init(struct drm_device *drm)
 40{
 41	drm->mode_config.min_width = 0;
 42	drm->mode_config.min_height = 0;
 43	drm->mode_config.max_width = 8192;
 44	drm->mode_config.max_height = 8192;
 45
 46	drm->mode_config.funcs = &sprd_drm_mode_config_funcs;
 47	drm->mode_config.helper_private = &sprd_drm_mode_config_helper;
 48}
 49
 50DEFINE_DRM_GEM_DMA_FOPS(sprd_drm_fops);
 51
 52static struct drm_driver sprd_drm_drv = {
 53	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
 54	.fops			= &sprd_drm_fops,
 55
 56	/* GEM Operations */
 57	DRM_GEM_DMA_DRIVER_OPS,
 58
 59	.name			= DRIVER_NAME,
 60	.desc			= DRIVER_DESC,
 61	.major			= DRIVER_MAJOR,
 62	.minor			= DRIVER_MINOR,
 63};
 64
 65static int sprd_drm_bind(struct device *dev)
 66{
 67	struct platform_device *pdev = to_platform_device(dev);
 68	struct drm_device *drm;
 69	struct sprd_drm *sprd;
 70	int ret;
 71
 72	sprd = devm_drm_dev_alloc(dev, &sprd_drm_drv, struct sprd_drm, drm);
 73	if (IS_ERR(sprd))
 74		return PTR_ERR(sprd);
 75
 76	drm = &sprd->drm;
 77	platform_set_drvdata(pdev, drm);
 78
 79	ret = drmm_mode_config_init(drm);
 80	if (ret)
 81		return ret;
 82
 83	sprd_drm_mode_config_init(drm);
 84
 85	/* bind and init sub drivers */
 86	ret = component_bind_all(drm->dev, drm);
 87	if (ret) {
 88		drm_err(drm, "failed to bind all component.\n");
 89		return ret;
 90	}
 91
 92	/* vblank init */
 93	ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
 94	if (ret) {
 95		drm_err(drm, "failed to initialize vblank.\n");
 96		goto err_unbind_all;
 97	}
 98
 99	/* reset all the states of crtc/plane/encoder/connector */
100	drm_mode_config_reset(drm);
101
102	/* init kms poll for handling hpd */
103	drm_kms_helper_poll_init(drm);
104
105	ret = drm_dev_register(drm, 0);
106	if (ret < 0)
107		goto err_kms_helper_poll_fini;
108
109	return 0;
110
111err_kms_helper_poll_fini:
112	drm_kms_helper_poll_fini(drm);
113err_unbind_all:
114	component_unbind_all(drm->dev, drm);
115	return ret;
116}
117
118static void sprd_drm_unbind(struct device *dev)
119{
120	struct drm_device *drm = dev_get_drvdata(dev);
121
122	drm_dev_unregister(drm);
123
124	drm_kms_helper_poll_fini(drm);
125
126	component_unbind_all(drm->dev, drm);
127}
128
129static const struct component_master_ops drm_component_ops = {
130	.bind = sprd_drm_bind,
131	.unbind = sprd_drm_unbind,
132};
133
134static int sprd_drm_probe(struct platform_device *pdev)
135{
136	return drm_of_component_probe(&pdev->dev, component_compare_of, &drm_component_ops);
137}
138
139static void sprd_drm_remove(struct platform_device *pdev)
140{
141	component_master_del(&pdev->dev, &drm_component_ops);
142}
143
144static void sprd_drm_shutdown(struct platform_device *pdev)
145{
146	struct drm_device *drm = platform_get_drvdata(pdev);
147
148	if (!drm) {
149		dev_warn(&pdev->dev, "drm device is not available, no shutdown\n");
150		return;
151	}
152
153	drm_atomic_helper_shutdown(drm);
154}
155
156static const struct of_device_id drm_match_table[] = {
157	{ .compatible = "sprd,display-subsystem", },
158	{ /* sentinel */ },
159};
160MODULE_DEVICE_TABLE(of, drm_match_table);
161
162static struct platform_driver sprd_drm_driver = {
163	.probe = sprd_drm_probe,
164	.remove = sprd_drm_remove,
165	.shutdown = sprd_drm_shutdown,
166	.driver = {
167		.name = "sprd-drm-drv",
168		.of_match_table = drm_match_table,
169	},
170};
171
172static struct platform_driver *sprd_drm_drivers[]  = {
173	&sprd_drm_driver,
174	&sprd_dpu_driver,
175	&sprd_dsi_driver,
176};
177
178static int __init sprd_drm_init(void)
179{
180	if (drm_firmware_drivers_only())
181		return -ENODEV;
182
183	return platform_register_drivers(sprd_drm_drivers,
184					ARRAY_SIZE(sprd_drm_drivers));
185}
186
187static void __exit sprd_drm_exit(void)
188{
189	platform_unregister_drivers(sprd_drm_drivers,
190				    ARRAY_SIZE(sprd_drm_drivers));
191}
192
193module_init(sprd_drm_init);
194module_exit(sprd_drm_exit);
195
196MODULE_AUTHOR("Leon He <leon.he@unisoc.com>");
197MODULE_AUTHOR("Kevin Tang <kevin.tang@unisoc.com>");
198MODULE_DESCRIPTION("Unisoc DRM KMS Master Driver");
199MODULE_LICENSE("GPL v2");
~/ Read-only file preview.