4 * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
17 #include <linux/clk.h>
18 #include <drm/drm_atomic_helper.h>
19 #include <drm/drm_debugfs.h>
20 #include <drm/drm_device.h>
21 #include <drm/drm_drv.h>
22 #include <drm/drm_fb_cma_helper.h>
23 #include <drm/drm_fb_helper.h>
24 #include <drm/drm_gem_cma_helper.h>
25 #include <drm/drm_gem_framebuffer_helper.h>
26 #include <drm/drm_probe_helper.h>
27 #include <linux/dma-mapping.h>
28 #include <linux/module.h>
29 #include <linux/of_reserved_mem.h>
30 #include <linux/platform_device.h>
33 #include "arcpgu_regs.h"
35 static const struct drm_mode_config_funcs arcpgu_drm_modecfg_funcs
= {
36 .fb_create
= drm_gem_fb_create
,
37 .atomic_check
= drm_atomic_helper_check
,
38 .atomic_commit
= drm_atomic_helper_commit
,
41 static void arcpgu_setup_mode_config(struct drm_device
*drm
)
43 drm_mode_config_init(drm
);
44 drm
->mode_config
.min_width
= 0;
45 drm
->mode_config
.min_height
= 0;
46 drm
->mode_config
.max_width
= 1920;
47 drm
->mode_config
.max_height
= 1080;
48 drm
->mode_config
.funcs
= &arcpgu_drm_modecfg_funcs
;
51 DEFINE_DRM_GEM_CMA_FOPS(arcpgu_drm_ops
);
53 static int arcpgu_load(struct drm_device
*drm
)
55 struct platform_device
*pdev
= to_platform_device(drm
->dev
);
56 struct arcpgu_drm_private
*arcpgu
;
57 struct device_node
*encoder_node
;
61 arcpgu
= devm_kzalloc(&pdev
->dev
, sizeof(*arcpgu
), GFP_KERNEL
);
65 drm
->dev_private
= arcpgu
;
67 arcpgu
->clk
= devm_clk_get(drm
->dev
, "pxlclk");
68 if (IS_ERR(arcpgu
->clk
))
69 return PTR_ERR(arcpgu
->clk
);
71 arcpgu_setup_mode_config(drm
);
73 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
74 arcpgu
->regs
= devm_ioremap_resource(&pdev
->dev
, res
);
75 if (IS_ERR(arcpgu
->regs
))
76 return PTR_ERR(arcpgu
->regs
);
78 dev_info(drm
->dev
, "arc_pgu ID: 0x%x\n",
79 arc_pgu_read(arcpgu
, ARCPGU_REG_ID
));
81 /* Get the optional framebuffer memory resource */
82 ret
= of_reserved_mem_device_init(drm
->dev
);
83 if (ret
&& ret
!= -ENODEV
)
86 if (dma_set_mask_and_coherent(drm
->dev
, DMA_BIT_MASK(32)))
89 if (arc_pgu_setup_crtc(drm
) < 0)
92 /* find the encoder node and initialize it */
93 encoder_node
= of_parse_phandle(drm
->dev
->of_node
, "encoder-slave", 0);
95 ret
= arcpgu_drm_hdmi_init(drm
, encoder_node
);
96 of_node_put(encoder_node
);
100 ret
= arcpgu_drm_sim_init(drm
, NULL
);
105 drm_mode_config_reset(drm
);
106 drm_kms_helper_poll_init(drm
);
108 platform_set_drvdata(pdev
, drm
);
112 static int arcpgu_unload(struct drm_device
*drm
)
114 drm_kms_helper_poll_fini(drm
);
115 drm_atomic_helper_shutdown(drm
);
116 drm_mode_config_cleanup(drm
);
121 #ifdef CONFIG_DEBUG_FS
122 static int arcpgu_show_pxlclock(struct seq_file
*m
, void *arg
)
124 struct drm_info_node
*node
= (struct drm_info_node
*)m
->private;
125 struct drm_device
*drm
= node
->minor
->dev
;
126 struct arcpgu_drm_private
*arcpgu
= drm
->dev_private
;
127 unsigned long clkrate
= clk_get_rate(arcpgu
->clk
);
128 unsigned long mode_clock
= arcpgu
->crtc
.mode
.crtc_clock
* 1000;
130 seq_printf(m
, "hw : %lu\n", clkrate
);
131 seq_printf(m
, "mode: %lu\n", mode_clock
);
135 static struct drm_info_list arcpgu_debugfs_list
[] = {
136 { "clocks", arcpgu_show_pxlclock
, 0 },
139 static int arcpgu_debugfs_init(struct drm_minor
*minor
)
141 return drm_debugfs_create_files(arcpgu_debugfs_list
,
142 ARRAY_SIZE(arcpgu_debugfs_list
), minor
->debugfs_root
, minor
);
146 static struct drm_driver arcpgu_drm_driver
= {
147 .driver_features
= DRIVER_MODESET
| DRIVER_GEM
| DRIVER_PRIME
|
150 .desc
= "ARC PGU Controller",
155 .fops
= &arcpgu_drm_ops
,
156 .dumb_create
= drm_gem_cma_dumb_create
,
157 .prime_handle_to_fd
= drm_gem_prime_handle_to_fd
,
158 .prime_fd_to_handle
= drm_gem_prime_fd_to_handle
,
159 .gem_free_object_unlocked
= drm_gem_cma_free_object
,
160 .gem_print_info
= drm_gem_cma_print_info
,
161 .gem_vm_ops
= &drm_gem_cma_vm_ops
,
162 .gem_prime_export
= drm_gem_prime_export
,
163 .gem_prime_import
= drm_gem_prime_import
,
164 .gem_prime_get_sg_table
= drm_gem_cma_prime_get_sg_table
,
165 .gem_prime_import_sg_table
= drm_gem_cma_prime_import_sg_table
,
166 .gem_prime_vmap
= drm_gem_cma_prime_vmap
,
167 .gem_prime_vunmap
= drm_gem_cma_prime_vunmap
,
168 .gem_prime_mmap
= drm_gem_cma_prime_mmap
,
169 #ifdef CONFIG_DEBUG_FS
170 .debugfs_init
= arcpgu_debugfs_init
,
174 static int arcpgu_probe(struct platform_device
*pdev
)
176 struct drm_device
*drm
;
179 drm
= drm_dev_alloc(&arcpgu_drm_driver
, &pdev
->dev
);
183 ret
= arcpgu_load(drm
);
187 ret
= drm_dev_register(drm
, 0);
191 drm_fbdev_generic_setup(drm
, 16);
204 static int arcpgu_remove(struct platform_device
*pdev
)
206 struct drm_device
*drm
= platform_get_drvdata(pdev
);
208 drm_dev_unregister(drm
);
215 static const struct of_device_id arcpgu_of_table
[] = {
216 {.compatible
= "snps,arcpgu"},
220 MODULE_DEVICE_TABLE(of
, arcpgu_of_table
);
222 static struct platform_driver arcpgu_platform_driver
= {
223 .probe
= arcpgu_probe
,
224 .remove
= arcpgu_remove
,
227 .of_match_table
= arcpgu_of_table
,
231 module_platform_driver(arcpgu_platform_driver
);
233 MODULE_AUTHOR("Carlos Palminha <palminha@synopsys.com>");
234 MODULE_DESCRIPTION("ARC PGU DRM driver");
235 MODULE_LICENSE("GPL");