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_gem_cma_helper.h>
21 #include <drm/drm_atomic_helper.h>
22 #include <linux/of_reserved_mem.h>
25 #include "arcpgu_regs.h"
27 static void arcpgu_fb_output_poll_changed(struct drm_device
*dev
)
29 struct arcpgu_drm_private
*arcpgu
= dev
->dev_private
;
31 drm_fbdev_cma_hotplug_event(arcpgu
->fbdev
);
34 static struct drm_mode_config_funcs arcpgu_drm_modecfg_funcs
= {
35 .fb_create
= drm_fb_cma_create
,
36 .output_poll_changed
= arcpgu_fb_output_poll_changed
,
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 static int arcpgu_gem_mmap(struct file
*filp
, struct vm_area_struct
*vma
)
55 ret
= drm_gem_mmap(filp
, vma
);
59 vma
->vm_page_prot
= pgprot_noncached(vm_get_page_prot(vma
->vm_flags
));
63 static const struct file_operations arcpgu_drm_ops
= {
66 .release
= drm_release
,
67 .unlocked_ioctl
= drm_ioctl
,
68 .compat_ioctl
= drm_compat_ioctl
,
72 .mmap
= arcpgu_gem_mmap
,
75 static void arcpgu_lastclose(struct drm_device
*drm
)
77 struct arcpgu_drm_private
*arcpgu
= drm
->dev_private
;
79 drm_fbdev_cma_restore_mode(arcpgu
->fbdev
);
82 static int arcpgu_load(struct drm_device
*drm
)
84 struct platform_device
*pdev
= to_platform_device(drm
->dev
);
85 struct arcpgu_drm_private
*arcpgu
;
86 struct device_node
*encoder_node
;
90 arcpgu
= devm_kzalloc(&pdev
->dev
, sizeof(*arcpgu
), GFP_KERNEL
);
94 drm
->dev_private
= arcpgu
;
96 arcpgu
->clk
= devm_clk_get(drm
->dev
, "pxlclk");
97 if (IS_ERR(arcpgu
->clk
))
98 return PTR_ERR(arcpgu
->clk
);
100 arcpgu_setup_mode_config(drm
);
102 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
103 arcpgu
->regs
= devm_ioremap_resource(&pdev
->dev
, res
);
104 if (IS_ERR(arcpgu
->regs
))
105 return PTR_ERR(arcpgu
->regs
);
107 dev_info(drm
->dev
, "arc_pgu ID: 0x%x\n",
108 arc_pgu_read(arcpgu
, ARCPGU_REG_ID
));
110 /* Get the optional framebuffer memory resource */
111 ret
= of_reserved_mem_device_init(drm
->dev
);
112 if (ret
&& ret
!= -ENODEV
)
115 if (dma_set_mask_and_coherent(drm
->dev
, DMA_BIT_MASK(32)))
118 if (arc_pgu_setup_crtc(drm
) < 0)
121 /* find the encoder node and initialize it */
122 encoder_node
= of_parse_phandle(drm
->dev
->of_node
, "encoder-slave", 0);
124 ret
= arcpgu_drm_hdmi_init(drm
, encoder_node
);
125 of_node_put(encoder_node
);
129 ret
= arcpgu_drm_sim_init(drm
, NULL
);
134 drm_mode_config_reset(drm
);
135 drm_kms_helper_poll_init(drm
);
137 arcpgu
->fbdev
= drm_fbdev_cma_init(drm
, 16,
138 drm
->mode_config
.num_crtc
,
139 drm
->mode_config
.num_connector
);
140 if (IS_ERR(arcpgu
->fbdev
)) {
141 ret
= PTR_ERR(arcpgu
->fbdev
);
142 arcpgu
->fbdev
= NULL
;
146 platform_set_drvdata(pdev
, arcpgu
);
150 static int arcpgu_unload(struct drm_device
*drm
)
152 struct arcpgu_drm_private
*arcpgu
= drm
->dev_private
;
155 drm_fbdev_cma_fini(arcpgu
->fbdev
);
156 arcpgu
->fbdev
= NULL
;
158 drm_kms_helper_poll_fini(drm
);
159 drm_vblank_cleanup(drm
);
160 drm_mode_config_cleanup(drm
);
165 static struct drm_driver arcpgu_drm_driver
= {
166 .driver_features
= DRIVER_MODESET
| DRIVER_GEM
| DRIVER_PRIME
|
168 .lastclose
= arcpgu_lastclose
,
169 .name
= "drm-arcpgu",
170 .desc
= "ARC PGU Controller",
175 .fops
= &arcpgu_drm_ops
,
176 .dumb_create
= drm_gem_cma_dumb_create
,
177 .dumb_map_offset
= drm_gem_cma_dumb_map_offset
,
178 .dumb_destroy
= drm_gem_dumb_destroy
,
179 .get_vblank_counter
= drm_vblank_no_hw_counter
,
180 .prime_handle_to_fd
= drm_gem_prime_handle_to_fd
,
181 .prime_fd_to_handle
= drm_gem_prime_fd_to_handle
,
182 .gem_free_object_unlocked
= drm_gem_cma_free_object
,
183 .gem_vm_ops
= &drm_gem_cma_vm_ops
,
184 .gem_prime_export
= drm_gem_prime_export
,
185 .gem_prime_import
= drm_gem_prime_import
,
186 .gem_prime_get_sg_table
= drm_gem_cma_prime_get_sg_table
,
187 .gem_prime_import_sg_table
= drm_gem_cma_prime_import_sg_table
,
188 .gem_prime_vmap
= drm_gem_cma_prime_vmap
,
189 .gem_prime_vunmap
= drm_gem_cma_prime_vunmap
,
190 .gem_prime_mmap
= drm_gem_cma_prime_mmap
,
193 static int arcpgu_probe(struct platform_device
*pdev
)
195 struct drm_device
*drm
;
198 drm
= drm_dev_alloc(&arcpgu_drm_driver
, &pdev
->dev
);
202 ret
= arcpgu_load(drm
);
206 ret
= drm_dev_register(drm
, 0);
221 static int arcpgu_remove(struct platform_device
*pdev
)
223 struct drm_device
*drm
= platform_get_drvdata(pdev
);
225 drm_dev_unregister(drm
);
232 static const struct of_device_id arcpgu_of_table
[] = {
233 {.compatible
= "snps,arcpgu"},
237 MODULE_DEVICE_TABLE(of
, arcpgu_of_table
);
239 static struct platform_driver arcpgu_platform_driver
= {
240 .probe
= arcpgu_probe
,
241 .remove
= arcpgu_remove
,
244 .of_match_table
= arcpgu_of_table
,
248 module_platform_driver(arcpgu_platform_driver
);
250 MODULE_AUTHOR("Carlos Palminha <palminha@synopsys.com>");
251 MODULE_DESCRIPTION("ARC PGU DRM driver");
252 MODULE_LICENSE("GPL");