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_crtc_helper.h>
19 #include <drm/drm_fb_cma_helper.h>
20 #include <drm/drm_fb_helper.h>
21 #include <drm/drm_gem_cma_helper.h>
22 #include <drm/drm_gem_framebuffer_helper.h>
23 #include <drm/drm_atomic_helper.h>
24 #include <linux/of_reserved_mem.h>
27 #include "arcpgu_regs.h"
29 static const struct drm_mode_config_funcs arcpgu_drm_modecfg_funcs
= {
30 .fb_create
= drm_gem_fb_create
,
31 .atomic_check
= drm_atomic_helper_check
,
32 .atomic_commit
= drm_atomic_helper_commit
,
35 static void arcpgu_setup_mode_config(struct drm_device
*drm
)
37 drm_mode_config_init(drm
);
38 drm
->mode_config
.min_width
= 0;
39 drm
->mode_config
.min_height
= 0;
40 drm
->mode_config
.max_width
= 1920;
41 drm
->mode_config
.max_height
= 1080;
42 drm
->mode_config
.funcs
= &arcpgu_drm_modecfg_funcs
;
45 DEFINE_DRM_GEM_CMA_FOPS(arcpgu_drm_ops
);
47 static int arcpgu_load(struct drm_device
*drm
)
49 struct platform_device
*pdev
= to_platform_device(drm
->dev
);
50 struct arcpgu_drm_private
*arcpgu
;
51 struct device_node
*encoder_node
;
55 arcpgu
= devm_kzalloc(&pdev
->dev
, sizeof(*arcpgu
), GFP_KERNEL
);
59 drm
->dev_private
= arcpgu
;
61 arcpgu
->clk
= devm_clk_get(drm
->dev
, "pxlclk");
62 if (IS_ERR(arcpgu
->clk
))
63 return PTR_ERR(arcpgu
->clk
);
65 arcpgu_setup_mode_config(drm
);
67 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
68 arcpgu
->regs
= devm_ioremap_resource(&pdev
->dev
, res
);
69 if (IS_ERR(arcpgu
->regs
))
70 return PTR_ERR(arcpgu
->regs
);
72 dev_info(drm
->dev
, "arc_pgu ID: 0x%x\n",
73 arc_pgu_read(arcpgu
, ARCPGU_REG_ID
));
75 /* Get the optional framebuffer memory resource */
76 ret
= of_reserved_mem_device_init(drm
->dev
);
77 if (ret
&& ret
!= -ENODEV
)
80 if (dma_set_mask_and_coherent(drm
->dev
, DMA_BIT_MASK(32)))
83 if (arc_pgu_setup_crtc(drm
) < 0)
86 /* find the encoder node and initialize it */
87 encoder_node
= of_parse_phandle(drm
->dev
->of_node
, "encoder-slave", 0);
89 ret
= arcpgu_drm_hdmi_init(drm
, encoder_node
);
90 of_node_put(encoder_node
);
94 ret
= arcpgu_drm_sim_init(drm
, NULL
);
99 drm_mode_config_reset(drm
);
100 drm_kms_helper_poll_init(drm
);
102 platform_set_drvdata(pdev
, drm
);
106 static int arcpgu_unload(struct drm_device
*drm
)
108 drm_kms_helper_poll_fini(drm
);
109 drm_atomic_helper_shutdown(drm
);
110 drm_mode_config_cleanup(drm
);
115 #ifdef CONFIG_DEBUG_FS
116 static int arcpgu_show_pxlclock(struct seq_file
*m
, void *arg
)
118 struct drm_info_node
*node
= (struct drm_info_node
*)m
->private;
119 struct drm_device
*drm
= node
->minor
->dev
;
120 struct arcpgu_drm_private
*arcpgu
= drm
->dev_private
;
121 unsigned long clkrate
= clk_get_rate(arcpgu
->clk
);
122 unsigned long mode_clock
= arcpgu
->crtc
.mode
.crtc_clock
* 1000;
124 seq_printf(m
, "hw : %lu\n", clkrate
);
125 seq_printf(m
, "mode: %lu\n", mode_clock
);
129 static struct drm_info_list arcpgu_debugfs_list
[] = {
130 { "clocks", arcpgu_show_pxlclock
, 0 },
133 static int arcpgu_debugfs_init(struct drm_minor
*minor
)
135 return drm_debugfs_create_files(arcpgu_debugfs_list
,
136 ARRAY_SIZE(arcpgu_debugfs_list
), minor
->debugfs_root
, minor
);
140 static struct drm_driver arcpgu_drm_driver
= {
141 .driver_features
= DRIVER_MODESET
| DRIVER_GEM
| DRIVER_PRIME
|
144 .desc
= "ARC PGU Controller",
149 .fops
= &arcpgu_drm_ops
,
150 .dumb_create
= drm_gem_cma_dumb_create
,
151 .prime_handle_to_fd
= drm_gem_prime_handle_to_fd
,
152 .prime_fd_to_handle
= drm_gem_prime_fd_to_handle
,
153 .gem_free_object_unlocked
= drm_gem_cma_free_object
,
154 .gem_print_info
= drm_gem_cma_print_info
,
155 .gem_vm_ops
= &drm_gem_cma_vm_ops
,
156 .gem_prime_export
= drm_gem_prime_export
,
157 .gem_prime_import
= drm_gem_prime_import
,
158 .gem_prime_get_sg_table
= drm_gem_cma_prime_get_sg_table
,
159 .gem_prime_import_sg_table
= drm_gem_cma_prime_import_sg_table
,
160 .gem_prime_vmap
= drm_gem_cma_prime_vmap
,
161 .gem_prime_vunmap
= drm_gem_cma_prime_vunmap
,
162 .gem_prime_mmap
= drm_gem_cma_prime_mmap
,
163 #ifdef CONFIG_DEBUG_FS
164 .debugfs_init
= arcpgu_debugfs_init
,
168 static int arcpgu_probe(struct platform_device
*pdev
)
170 struct drm_device
*drm
;
173 drm
= drm_dev_alloc(&arcpgu_drm_driver
, &pdev
->dev
);
177 ret
= arcpgu_load(drm
);
181 ret
= drm_dev_register(drm
, 0);
185 drm_fbdev_generic_setup(drm
, 16);
198 static int arcpgu_remove(struct platform_device
*pdev
)
200 struct drm_device
*drm
= platform_get_drvdata(pdev
);
202 drm_dev_unregister(drm
);
209 static const struct of_device_id arcpgu_of_table
[] = {
210 {.compatible
= "snps,arcpgu"},
214 MODULE_DEVICE_TABLE(of
, arcpgu_of_table
);
216 static struct platform_driver arcpgu_platform_driver
= {
217 .probe
= arcpgu_probe
,
218 .remove
= arcpgu_remove
,
221 .of_match_table
= arcpgu_of_table
,
225 module_platform_driver(arcpgu_platform_driver
);
227 MODULE_AUTHOR("Carlos Palminha <palminha@synopsys.com>");
228 MODULE_DESCRIPTION("ARC PGU DRM driver");
229 MODULE_LICENSE("GPL");