2 * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
3 * Author: Liviu Dudau <Liviu.Dudau@arm.com>
5 * This program is free software and is provided to you under the terms of the
6 * GNU General Public License version 2 as published by the Free Software
7 * Foundation, and any use by you of this program is subject to the terms
10 * ARM Mali DP500/DP550/DP650 KMS/DRM driver
13 #include <linux/module.h>
14 #include <linux/clk.h>
15 #include <linux/component.h>
16 #include <linux/of_device.h>
17 #include <linux/of_graph.h>
18 #include <linux/of_reserved_mem.h>
21 #include <drm/drm_atomic.h>
22 #include <drm/drm_atomic_helper.h>
23 #include <drm/drm_crtc.h>
24 #include <drm/drm_crtc_helper.h>
25 #include <drm/drm_fb_helper.h>
26 #include <drm/drm_fb_cma_helper.h>
27 #include <drm/drm_gem_cma_helper.h>
28 #include <drm/drm_of.h>
30 #include "malidp_drv.h"
31 #include "malidp_regs.h"
32 #include "malidp_hw.h"
34 #define MALIDP_CONF_VALID_TIMEOUT 250
37 * set the "config valid" bit and wait until the hardware acts on it
39 static int malidp_set_and_wait_config_valid(struct drm_device
*drm
)
41 struct malidp_drm
*malidp
= drm
->dev_private
;
42 struct malidp_hw_device
*hwdev
= malidp
->dev
;
45 hwdev
->set_config_valid(hwdev
);
46 /* don't wait for config_valid flag if we are in config mode */
47 if (hwdev
->in_config_mode(hwdev
))
50 ret
= wait_event_interruptible_timeout(malidp
->wq
,
51 atomic_read(&malidp
->config_valid
) == 1,
52 msecs_to_jiffies(MALIDP_CONF_VALID_TIMEOUT
));
54 return (ret
> 0) ? 0 : -ETIMEDOUT
;
57 static void malidp_output_poll_changed(struct drm_device
*drm
)
59 struct malidp_drm
*malidp
= drm
->dev_private
;
61 drm_fbdev_cma_hotplug_event(malidp
->fbdev
);
64 static void malidp_atomic_commit_hw_done(struct drm_atomic_state
*state
)
66 struct drm_pending_vblank_event
*event
;
67 struct drm_device
*drm
= state
->dev
;
68 struct malidp_drm
*malidp
= drm
->dev_private
;
69 int ret
= malidp_set_and_wait_config_valid(drm
);
72 DRM_DEBUG_DRIVER("timed out waiting for updated configuration\n");
74 event
= malidp
->crtc
.state
->event
;
76 malidp
->crtc
.state
->event
= NULL
;
78 spin_lock_irq(&drm
->event_lock
);
79 if (drm_crtc_vblank_get(&malidp
->crtc
) == 0)
80 drm_crtc_arm_vblank_event(&malidp
->crtc
, event
);
82 drm_crtc_send_vblank_event(&malidp
->crtc
, event
);
83 spin_unlock_irq(&drm
->event_lock
);
85 drm_atomic_helper_commit_hw_done(state
);
88 static void malidp_atomic_commit_tail(struct drm_atomic_state
*state
)
90 struct drm_device
*drm
= state
->dev
;
92 drm_atomic_helper_commit_modeset_disables(drm
, state
);
93 drm_atomic_helper_commit_modeset_enables(drm
, state
);
94 drm_atomic_helper_commit_planes(drm
, state
, true);
96 malidp_atomic_commit_hw_done(state
);
98 drm_atomic_helper_wait_for_vblanks(drm
, state
);
100 drm_atomic_helper_cleanup_planes(drm
, state
);
103 static struct drm_mode_config_helper_funcs malidp_mode_config_helpers
= {
104 .atomic_commit_tail
= malidp_atomic_commit_tail
,
107 static const struct drm_mode_config_funcs malidp_mode_config_funcs
= {
108 .fb_create
= drm_fb_cma_create
,
109 .output_poll_changed
= malidp_output_poll_changed
,
110 .atomic_check
= drm_atomic_helper_check
,
111 .atomic_commit
= drm_atomic_helper_commit
,
114 static int malidp_enable_vblank(struct drm_device
*drm
, unsigned int crtc
)
116 struct malidp_drm
*malidp
= drm
->dev_private
;
117 struct malidp_hw_device
*hwdev
= malidp
->dev
;
119 malidp_hw_enable_irq(hwdev
, MALIDP_DE_BLOCK
,
120 hwdev
->map
.de_irq_map
.vsync_irq
);
124 static void malidp_disable_vblank(struct drm_device
*drm
, unsigned int pipe
)
126 struct malidp_drm
*malidp
= drm
->dev_private
;
127 struct malidp_hw_device
*hwdev
= malidp
->dev
;
129 malidp_hw_disable_irq(hwdev
, MALIDP_DE_BLOCK
,
130 hwdev
->map
.de_irq_map
.vsync_irq
);
133 static int malidp_init(struct drm_device
*drm
)
136 struct malidp_drm
*malidp
= drm
->dev_private
;
137 struct malidp_hw_device
*hwdev
= malidp
->dev
;
139 drm_mode_config_init(drm
);
141 drm
->mode_config
.min_width
= hwdev
->min_line_size
;
142 drm
->mode_config
.min_height
= hwdev
->min_line_size
;
143 drm
->mode_config
.max_width
= hwdev
->max_line_size
;
144 drm
->mode_config
.max_height
= hwdev
->max_line_size
;
145 drm
->mode_config
.funcs
= &malidp_mode_config_funcs
;
146 drm
->mode_config
.helper_private
= &malidp_mode_config_helpers
;
148 ret
= malidp_crtc_init(drm
);
150 drm_mode_config_cleanup(drm
);
157 static int malidp_irq_init(struct platform_device
*pdev
)
159 int irq_de
, irq_se
, ret
= 0;
160 struct drm_device
*drm
= dev_get_drvdata(&pdev
->dev
);
162 /* fetch the interrupts from DT */
163 irq_de
= platform_get_irq_byname(pdev
, "DE");
165 DRM_ERROR("no 'DE' IRQ specified!\n");
168 irq_se
= platform_get_irq_byname(pdev
, "SE");
170 DRM_ERROR("no 'SE' IRQ specified!\n");
174 ret
= malidp_de_irq_init(drm
, irq_de
);
178 ret
= malidp_se_irq_init(drm
, irq_se
);
180 malidp_de_irq_fini(drm
);
187 static void malidp_lastclose(struct drm_device
*drm
)
189 struct malidp_drm
*malidp
= drm
->dev_private
;
191 drm_fbdev_cma_restore_mode(malidp
->fbdev
);
194 static const struct file_operations fops
= {
195 .owner
= THIS_MODULE
,
197 .release
= drm_release
,
198 .unlocked_ioctl
= drm_ioctl
,
200 .compat_ioctl
= drm_compat_ioctl
,
204 .llseek
= noop_llseek
,
205 .mmap
= drm_gem_cma_mmap
,
208 static struct drm_driver malidp_driver
= {
209 .driver_features
= DRIVER_GEM
| DRIVER_MODESET
| DRIVER_ATOMIC
|
211 .lastclose
= malidp_lastclose
,
212 .get_vblank_counter
= drm_vblank_no_hw_counter
,
213 .enable_vblank
= malidp_enable_vblank
,
214 .disable_vblank
= malidp_disable_vblank
,
215 .gem_free_object_unlocked
= drm_gem_cma_free_object
,
216 .gem_vm_ops
= &drm_gem_cma_vm_ops
,
217 .dumb_create
= drm_gem_cma_dumb_create
,
218 .dumb_map_offset
= drm_gem_cma_dumb_map_offset
,
219 .dumb_destroy
= drm_gem_dumb_destroy
,
220 .prime_handle_to_fd
= drm_gem_prime_handle_to_fd
,
221 .prime_fd_to_handle
= drm_gem_prime_fd_to_handle
,
222 .gem_prime_export
= drm_gem_prime_export
,
223 .gem_prime_import
= drm_gem_prime_import
,
224 .gem_prime_get_sg_table
= drm_gem_cma_prime_get_sg_table
,
225 .gem_prime_import_sg_table
= drm_gem_cma_prime_import_sg_table
,
226 .gem_prime_vmap
= drm_gem_cma_prime_vmap
,
227 .gem_prime_vunmap
= drm_gem_cma_prime_vunmap
,
228 .gem_prime_mmap
= drm_gem_cma_prime_mmap
,
231 .desc
= "ARM Mali Display Processor driver",
237 static const struct of_device_id malidp_drm_of_match
[] = {
239 .compatible
= "arm,mali-dp500",
240 .data
= &malidp_device
[MALIDP_500
]
243 .compatible
= "arm,mali-dp550",
244 .data
= &malidp_device
[MALIDP_550
]
247 .compatible
= "arm,mali-dp650",
248 .data
= &malidp_device
[MALIDP_650
]
252 MODULE_DEVICE_TABLE(of
, malidp_drm_of_match
);
254 #define MAX_OUTPUT_CHANNELS 3
256 static int malidp_bind(struct device
*dev
)
258 struct resource
*res
;
259 struct drm_device
*drm
;
260 struct device_node
*ep
;
261 struct malidp_drm
*malidp
;
262 struct malidp_hw_device
*hwdev
;
263 struct platform_device
*pdev
= to_platform_device(dev
);
264 /* number of lines for the R, G and B output */
265 u8 output_width
[MAX_OUTPUT_CHANNELS
];
267 u32 version
, out_depth
= 0;
269 malidp
= devm_kzalloc(dev
, sizeof(*malidp
), GFP_KERNEL
);
273 hwdev
= devm_kzalloc(dev
, sizeof(*hwdev
), GFP_KERNEL
);
278 * copy the associated data from malidp_drm_of_match to avoid
279 * having to keep a reference to the OF node after binding
281 memcpy(hwdev
, of_device_get_match_data(dev
), sizeof(*hwdev
));
284 INIT_LIST_HEAD(&malidp
->event_list
);
286 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
287 hwdev
->regs
= devm_ioremap_resource(dev
, res
);
288 if (IS_ERR(hwdev
->regs
))
289 return PTR_ERR(hwdev
->regs
);
291 hwdev
->pclk
= devm_clk_get(dev
, "pclk");
292 if (IS_ERR(hwdev
->pclk
))
293 return PTR_ERR(hwdev
->pclk
);
295 hwdev
->aclk
= devm_clk_get(dev
, "aclk");
296 if (IS_ERR(hwdev
->aclk
))
297 return PTR_ERR(hwdev
->aclk
);
299 hwdev
->mclk
= devm_clk_get(dev
, "mclk");
300 if (IS_ERR(hwdev
->mclk
))
301 return PTR_ERR(hwdev
->mclk
);
303 hwdev
->pxlclk
= devm_clk_get(dev
, "pxlclk");
304 if (IS_ERR(hwdev
->pxlclk
))
305 return PTR_ERR(hwdev
->pxlclk
);
307 /* Get the optional framebuffer memory resource */
308 ret
= of_reserved_mem_device_init(dev
);
309 if (ret
&& ret
!= -ENODEV
)
312 drm
= drm_dev_alloc(&malidp_driver
, dev
);
318 /* Enable APB clock in order to get access to the registers */
319 clk_prepare_enable(hwdev
->pclk
);
321 * Enable AXI clock and main clock so that prefetch can start once
322 * the registers are set
324 clk_prepare_enable(hwdev
->aclk
);
325 clk_prepare_enable(hwdev
->mclk
);
327 ret
= hwdev
->query_hw(hwdev
);
329 DRM_ERROR("Invalid HW configuration\n");
333 version
= malidp_hw_read(hwdev
, hwdev
->map
.dc_base
+ MALIDP_DE_CORE_ID
);
334 DRM_INFO("found ARM Mali-DP%3x version r%dp%d\n", version
>> 16,
335 (version
>> 12) & 0xf, (version
>> 8) & 0xf);
337 /* set the number of lines used for output of RGB data */
338 ret
= of_property_read_u8_array(dev
->of_node
,
339 "arm,malidp-output-port-lines",
340 output_width
, MAX_OUTPUT_CHANNELS
);
344 for (i
= 0; i
< MAX_OUTPUT_CHANNELS
; i
++)
345 out_depth
= (out_depth
<< 8) | (output_width
[i
] & 0xf);
346 malidp_hw_write(hwdev
, out_depth
, hwdev
->map
.out_depth_base
);
348 drm
->dev_private
= malidp
;
349 dev_set_drvdata(dev
, drm
);
350 atomic_set(&malidp
->config_valid
, 0);
351 init_waitqueue_head(&malidp
->wq
);
353 ret
= malidp_init(drm
);
357 ret
= drm_dev_register(drm
, 0);
361 /* Set the CRTC's port so that the encoder component can find it */
362 ep
= of_graph_get_next_endpoint(dev
->of_node
, NULL
);
367 malidp
->crtc
.port
= of_get_next_parent(ep
);
369 ret
= component_bind_all(dev
, drm
);
371 DRM_ERROR("Failed to bind all components\n");
375 ret
= malidp_irq_init(pdev
);
379 ret
= drm_vblank_init(drm
, drm
->mode_config
.num_crtc
);
381 DRM_ERROR("failed to initialise vblank\n");
385 drm_mode_config_reset(drm
);
387 malidp
->fbdev
= drm_fbdev_cma_init(drm
, 32, drm
->mode_config
.num_crtc
,
388 drm
->mode_config
.num_connector
);
390 if (IS_ERR(malidp
->fbdev
)) {
391 ret
= PTR_ERR(malidp
->fbdev
);
392 malidp
->fbdev
= NULL
;
396 drm_kms_helper_poll_init(drm
);
400 drm_vblank_cleanup(drm
);
402 malidp_se_irq_fini(drm
);
403 malidp_de_irq_fini(drm
);
405 component_unbind_all(dev
, drm
);
407 of_node_put(malidp
->crtc
.port
);
408 malidp
->crtc
.port
= NULL
;
410 drm_dev_unregister(drm
);
412 malidp_de_planes_destroy(drm
);
413 drm_mode_config_cleanup(drm
);
415 drm
->dev_private
= NULL
;
416 dev_set_drvdata(dev
, NULL
);
418 clk_disable_unprepare(hwdev
->mclk
);
419 clk_disable_unprepare(hwdev
->aclk
);
420 clk_disable_unprepare(hwdev
->pclk
);
423 of_reserved_mem_device_release(dev
);
428 static void malidp_unbind(struct device
*dev
)
430 struct drm_device
*drm
= dev_get_drvdata(dev
);
431 struct malidp_drm
*malidp
= drm
->dev_private
;
432 struct malidp_hw_device
*hwdev
= malidp
->dev
;
435 drm_fbdev_cma_fini(malidp
->fbdev
);
436 malidp
->fbdev
= NULL
;
438 drm_kms_helper_poll_fini(drm
);
439 malidp_se_irq_fini(drm
);
440 malidp_de_irq_fini(drm
);
441 drm_vblank_cleanup(drm
);
442 component_unbind_all(dev
, drm
);
443 of_node_put(malidp
->crtc
.port
);
444 malidp
->crtc
.port
= NULL
;
445 drm_dev_unregister(drm
);
446 malidp_de_planes_destroy(drm
);
447 drm_mode_config_cleanup(drm
);
448 drm
->dev_private
= NULL
;
449 dev_set_drvdata(dev
, NULL
);
450 clk_disable_unprepare(hwdev
->mclk
);
451 clk_disable_unprepare(hwdev
->aclk
);
452 clk_disable_unprepare(hwdev
->pclk
);
454 of_reserved_mem_device_release(dev
);
457 static const struct component_master_ops malidp_master_ops
= {
459 .unbind
= malidp_unbind
,
462 static int malidp_compare_dev(struct device
*dev
, void *data
)
464 struct device_node
*np
= data
;
466 return dev
->of_node
== np
;
469 static int malidp_platform_probe(struct platform_device
*pdev
)
471 struct device_node
*port
, *ep
;
472 struct component_match
*match
= NULL
;
474 if (!pdev
->dev
.of_node
)
477 /* there is only one output port inside each device, find it */
478 ep
= of_graph_get_next_endpoint(pdev
->dev
.of_node
, NULL
);
482 if (!of_device_is_available(ep
)) {
487 /* add the remote encoder port as component */
488 port
= of_graph_get_remote_port_parent(ep
);
490 if (!port
|| !of_device_is_available(port
)) {
495 component_match_add(&pdev
->dev
, &match
, malidp_compare_dev
, port
);
496 return component_master_add_with_match(&pdev
->dev
, &malidp_master_ops
,
500 static int malidp_platform_remove(struct platform_device
*pdev
)
502 component_master_del(&pdev
->dev
, &malidp_master_ops
);
506 static struct platform_driver malidp_platform_driver
= {
507 .probe
= malidp_platform_probe
,
508 .remove
= malidp_platform_remove
,
511 .of_match_table
= malidp_drm_of_match
,
515 module_platform_driver(malidp_platform_driver
);
517 MODULE_AUTHOR("Liviu Dudau <Liviu.Dudau@arm.com>");
518 MODULE_DESCRIPTION("ARM Mali DP DRM driver");
519 MODULE_LICENSE("GPL v2");