Skip to content

Commit 4af2e5f

Browse files
kJugghal-feng
authored andcommitted
drm/vs: Register DRM device
Implement drm device registration interface Signed-off-by: Keith Zhao <keith.zhao@starfivetech.com>
1 parent 9f257a7 commit 4af2e5f

11 files changed

Lines changed: 871 additions & 0 deletions

File tree

drivers/gpu/drm/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,8 @@ source "drivers/gpu/drm/solomon/Kconfig"
363363

364364
source "drivers/gpu/drm/sprd/Kconfig"
365365

366+
source "drivers/gpu/drm/verisilicon/Kconfig"
367+
366368
config DRM_HYPERV
367369
tristate "DRM Support for Hyper-V synthetic video device"
368370
depends on DRM && PCI && MMU && HYPERV

drivers/gpu/drm/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,3 +194,4 @@ obj-y += gud/
194194
obj-$(CONFIG_DRM_HYPERV) += hyperv/
195195
obj-y += solomon/
196196
obj-$(CONFIG_DRM_SPRD) += sprd/
197+
obj-$(CONFIG_DRM_VERISILICON) += verisilicon/
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
config DRM_VERISILICON
3+
tristate "DRM Support for VeriSilicon"
4+
depends on DRM
5+
select DRM_KMS_HELPER
6+
select DRM_GEM_DMA_HELPER
7+
select CMA
8+
select DMA_CMA
9+
help
10+
Choose this option if you have a VeriSilicon soc chipset.
11+
This driver provides VeriSilicon kernel mode
12+
setting and buffer management. It does not
13+
provide 2D or 3D acceleration.
14+
15+
if DRM_VERISILICON
16+
17+
config STARFIVE_HDMI
18+
bool "Starfive specific extensions HDMI"
19+
help
20+
This selects support for StarFive SoC specific extensions
21+
for the Innosilicon HDMI driver. If you want to enable
22+
HDMI on JH7110 based SoC, you should select this option.
23+
24+
To compile this driver as a module, choose M here.
25+
endif
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
3+
vs_drm-objs := vs_dc_hw.o \
4+
vs_dc.o \
5+
vs_crtc.o \
6+
vs_drv.o \
7+
vs_modeset.o \
8+
vs_gem.o \
9+
vs_plane.o
10+
11+
vs_drm-$(CONFIG_STARFIVE_HDMI) += starfive_hdmi.o
12+
obj-$(CONFIG_DRM_VERISILICON) += vs_drm.o
13+
Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (C) 2023 VeriSilicon Holdings Co., Ltd.
4+
*/
5+
6+
#include <linux/clk.h>
7+
#include <linux/component.h>
8+
#include <linux/delay.h>
9+
#include <linux/dma-mapping.h>
10+
#include <linux/iommu.h>
11+
#include <linux/of_graph.h>
12+
#include <linux/of_reserved_mem.h>
13+
#include <linux/pm_runtime.h>
14+
#include <linux/reset.h>
15+
#include <linux/version.h>
16+
17+
#include <drm/drm_aperture.h>
18+
#include <drm/drm_atomic_helper.h>
19+
#include <drm/drm_crtc.h>
20+
#include <drm/drm_crtc_helper.h>
21+
#include <drm/drm_debugfs.h>
22+
#include <drm/drm_drv.h>
23+
#include <drm/drm_fb_helper.h>
24+
#include <drm/drm_fbdev_generic.h>
25+
#include <drm/drm_file.h>
26+
#include <drm/drm_fourcc.h>
27+
#include <drm/drm_ioctl.h>
28+
#include <drm/drm_of.h>
29+
#include <drm/drm_prime.h>
30+
#include <drm/drm_probe_helper.h>
31+
#include <drm/drm_vblank.h>
32+
33+
#include "vs_drv.h"
34+
#include "vs_modeset.h"
35+
#include "vs_gem.h"
36+
37+
#define DRV_NAME "starfive"
38+
#define DRV_DESC "Starfive DRM driver"
39+
#define DRV_DATE "202305161"
40+
#define DRV_MAJOR 1
41+
#define DRV_MINOR 0
42+
43+
static struct platform_driver vs_drm_platform_driver;
44+
45+
static const struct file_operations fops = {
46+
.owner = THIS_MODULE,
47+
.open = drm_open,
48+
.release = drm_release,
49+
.unlocked_ioctl = drm_ioctl,
50+
.compat_ioctl = drm_compat_ioctl,
51+
.poll = drm_poll,
52+
.read = drm_read,
53+
.mmap = drm_gem_mmap,
54+
};
55+
56+
static struct drm_driver vs_drm_driver = {
57+
.driver_features = DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_GEM,
58+
.lastclose = drm_fb_helper_lastclose,
59+
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
60+
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
61+
.gem_prime_import_sg_table = vs_gem_prime_import_sg_table,
62+
.gem_prime_mmap = drm_gem_prime_mmap,
63+
.dumb_create = vs_gem_dumb_create,
64+
.fops = &fops,
65+
.name = DRV_NAME,
66+
.desc = DRV_DESC,
67+
.date = DRV_DATE,
68+
.major = DRV_MAJOR,
69+
.minor = DRV_MINOR,
70+
};
71+
72+
void vs_drm_update_pitch_alignment(struct drm_device *drm_dev,
73+
unsigned int alignment)
74+
{
75+
struct vs_drm_private *priv = to_vs_dev(drm_dev);
76+
77+
if (alignment > priv->pitch_alignment)
78+
priv->pitch_alignment = alignment;
79+
}
80+
81+
static int vs_drm_bind(struct device *dev)
82+
{
83+
struct platform_device *pdev = to_platform_device(dev);
84+
struct vs_drm_private *priv;
85+
int ret;
86+
static u64 dma_mask = DMA_BIT_MASK(40);
87+
struct drm_device *drm_dev;
88+
89+
/* Remove existing drivers that may own the framebuffer memory. */
90+
ret = drm_aperture_remove_framebuffers(&vs_drm_driver);
91+
if (ret) {
92+
dev_err(dev,
93+
"Failed to remove existing framebuffers - %d.\n",
94+
ret);
95+
return ret;
96+
}
97+
98+
priv = devm_drm_dev_alloc(dev, &vs_drm_driver, struct vs_drm_private, base);
99+
if (IS_ERR(priv))
100+
return PTR_ERR(priv);
101+
102+
priv->pitch_alignment = 64;
103+
priv->dma_dev = priv->base.dev;
104+
priv->dma_dev->coherent_dma_mask = dma_mask;
105+
drm_dev = &priv->base;
106+
platform_set_drvdata(pdev, drm_dev);
107+
108+
vs_mode_config_init(drm_dev);
109+
110+
/* Now try and bind all our sub-components */
111+
ret = component_bind_all(dev, drm_dev);
112+
if (ret)
113+
goto err_mode;
114+
115+
ret = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc);
116+
if (ret)
117+
goto err_bind;
118+
119+
drm_mode_config_reset(drm_dev);
120+
121+
drm_kms_helper_poll_init(drm_dev);
122+
123+
ret = drm_dev_register(drm_dev, 0);
124+
if (ret)
125+
goto err_helper;
126+
127+
drm_fbdev_generic_setup(drm_dev, 32);
128+
129+
return 0;
130+
131+
err_helper:
132+
drm_kms_helper_poll_fini(drm_dev);
133+
err_bind:
134+
component_unbind_all(drm_dev->dev, drm_dev);
135+
err_mode:
136+
drm_mode_config_cleanup(drm_dev);
137+
138+
return ret;
139+
}
140+
141+
static void vs_drm_unbind(struct device *dev)
142+
{
143+
struct drm_device *drm_dev = dev_get_drvdata(dev);
144+
145+
drm_dev_unregister(drm_dev);
146+
147+
drm_kms_helper_poll_fini(drm_dev);
148+
149+
component_unbind_all(drm_dev->dev, drm_dev);
150+
}
151+
152+
static const struct component_master_ops vs_drm_ops = {
153+
.bind = vs_drm_bind,
154+
.unbind = vs_drm_unbind,
155+
};
156+
157+
static struct platform_driver *drm_sub_drivers[] = {
158+
159+
160+
/* connector + encoder*/
161+
#ifdef CONFIG_STARFIVE_HDMI
162+
&starfive_hdmi_driver,
163+
#endif
164+
165+
};
166+
167+
#define NUM_DRM_DRIVERS \
168+
(sizeof(drm_sub_drivers) / sizeof(struct platform_driver *))
169+
170+
static int compare_dev(struct device *dev, void *data)
171+
{
172+
return dev == (struct device *)data;
173+
}
174+
175+
static struct component_match *vs_drm_match_add(struct device *dev)
176+
{
177+
struct component_match *match = NULL;
178+
int i;
179+
180+
for (i = 0; i < NUM_DRM_DRIVERS; ++i) {
181+
struct platform_driver *drv = drm_sub_drivers[i];
182+
struct device *p = NULL, *d;
183+
184+
while ((d = platform_find_device_by_driver(p, &drv->driver))) {
185+
put_device(p);
186+
187+
component_match_add(dev, &match, compare_dev, d);
188+
p = d;
189+
}
190+
put_device(p);
191+
}
192+
193+
return match ?: ERR_PTR(-ENODEV);
194+
}
195+
196+
static int vs_drm_platform_probe(struct platform_device *pdev)
197+
{
198+
struct device *dev = &pdev->dev;
199+
struct component_match *match;
200+
201+
match = vs_drm_match_add(dev);
202+
if (IS_ERR(match))
203+
return PTR_ERR(match);
204+
205+
return component_master_add_with_match(dev, &vs_drm_ops, match);
206+
}
207+
208+
static int vs_drm_platform_remove(struct platform_device *pdev)
209+
{
210+
component_master_del(&pdev->dev, &vs_drm_ops);
211+
return 0;
212+
}
213+
214+
#ifdef CONFIG_PM_SLEEP
215+
static int vs_drm_suspend(struct device *dev)
216+
{
217+
return drm_mode_config_helper_suspend(dev_get_drvdata(dev));
218+
}
219+
220+
static int vs_drm_resume(struct device *dev)
221+
{
222+
drm_mode_config_helper_resume(dev_get_drvdata(dev));
223+
224+
return 0;
225+
}
226+
#endif
227+
228+
static SIMPLE_DEV_PM_OPS(vs_drm_pm_ops, vs_drm_suspend, vs_drm_resume);
229+
230+
static const struct of_device_id vs_drm_dt_ids[] = {
231+
{ .compatible = "starfive,display-subsystem", },
232+
{ },
233+
};
234+
235+
MODULE_DEVICE_TABLE(of, vs_drm_dt_ids);
236+
237+
static struct platform_driver vs_drm_platform_driver = {
238+
.probe = vs_drm_platform_probe,
239+
.remove = vs_drm_platform_remove,
240+
241+
.driver = {
242+
.name = DRV_NAME,
243+
.of_match_table = vs_drm_dt_ids,
244+
.pm = &vs_drm_pm_ops,
245+
},
246+
};
247+
248+
static int __init vs_drm_init(void)
249+
{
250+
int ret;
251+
252+
ret = platform_register_drivers(drm_sub_drivers, NUM_DRM_DRIVERS);
253+
if (ret)
254+
return ret;
255+
256+
ret = platform_driver_register(&vs_drm_platform_driver);
257+
if (ret)
258+
platform_unregister_drivers(drm_sub_drivers, NUM_DRM_DRIVERS);
259+
260+
return ret;
261+
}
262+
263+
static void __exit vs_drm_fini(void)
264+
{
265+
platform_driver_unregister(&vs_drm_platform_driver);
266+
platform_unregister_drivers(drm_sub_drivers, NUM_DRM_DRIVERS);
267+
}
268+
269+
module_init(vs_drm_init);
270+
module_exit(vs_drm_fini);
271+
272+
MODULE_DESCRIPTION("VeriSilicon DRM Driver");
273+
MODULE_LICENSE("GPL");
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Copyright (C) 2023 VeriSilicon Holdings Co., Ltd.
4+
*/
5+
6+
#ifndef __VS_DRV_H__
7+
#define __VS_DRV_H__
8+
9+
#include <linux/module.h>
10+
#include <linux/platform_device.h>
11+
#include <linux/version.h>
12+
#include <drm/drm_drv.h>
13+
#include <drm/drm_gem.h>
14+
#include <drm/drm_managed.h>
15+
16+
/*
17+
*
18+
* @dma_dev: device for DMA API.
19+
* - use the first attached device if support iommu
20+
else use drm device (only contiguous buffer support)
21+
* @domain: iommu domain for DRM.
22+
* - all DC IOMMU share same domain to reduce mapping
23+
* @pitch_alignment: buffer pitch alignment required by sub-devices.
24+
*
25+
*/
26+
struct vs_drm_private {
27+
struct drm_device base;
28+
struct device *dma_dev;
29+
struct iommu_domain *domain;
30+
unsigned int pitch_alignment;
31+
};
32+
33+
static inline struct vs_drm_private *
34+
to_vs_dev(const struct drm_device *dev)
35+
{
36+
return container_of(dev, struct vs_drm_private, base);
37+
}
38+
39+
void vs_drm_update_pitch_alignment(struct drm_device *drm_dev,
40+
unsigned int alignment);
41+
42+
43+
static inline bool is_iommu_enabled(struct drm_device *dev)
44+
{
45+
struct vs_drm_private *priv = to_vs_dev(dev);
46+
47+
return priv->domain ? true : false;
48+
}
49+
50+
#ifdef CONFIG_STARFIVE_HDMI
51+
extern struct platform_driver starfive_hdmi_driver;
52+
#endif
53+
54+
#endif /* __VS_DRV_H__ */

0 commit comments

Comments
 (0)