2 * Copyright (C) 2012 Russell King
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
9 #include <linux/module.h>
11 #include <drm/drm_crtc_helper.h>
12 #include "armada_crtc.h"
13 #include "armada_drm.h"
14 #include "armada_gem.h"
15 #include "armada_hw.h"
16 #include <drm/armada_drm.h>
17 #include "armada_ioctlP.h"
19 #ifdef CONFIG_DRM_ARMADA_TDA1998X
20 #include <drm/i2c/tda998x.h>
21 #include "armada_slave.h"
23 static struct tda998x_encoder_params params
= {
24 /* With 0x24, there is no translation between vp_out and int_vp
25 FB LCD out Pins VIP Int Vp
26 R:23:16 R:7:0 VPC7:0 7:0 7:0[R]
27 G:15:8 G:15:8 VPB7:0 23:16 23:16[G]
28 B:7:0 B:23:16 VPA7:0 15:8 15:8[B]
38 .audio_format
= AFMT_SPDIF
,
39 .audio_sample_rate
= 44100,
42 static const struct armada_drm_slave_config tda19988_config
= {
44 .crtcs
= 1 << 0, /* Only LCD0 at the moment */
45 .polled
= DRM_CONNECTOR_POLL_CONNECT
| DRM_CONNECTOR_POLL_DISCONNECT
,
46 .interlace_allowed
= true,
50 .platform_data
= ¶ms
,
55 static void armada_drm_unref_work(struct work_struct
*work
)
57 struct armada_private
*priv
=
58 container_of(work
, struct armada_private
, fb_unref_work
);
59 struct drm_framebuffer
*fb
;
61 while (kfifo_get(&priv
->fb_unref
, &fb
))
62 drm_framebuffer_unreference(fb
);
65 /* Must be called with dev->event_lock held */
66 void __armada_drm_queue_unref_work(struct drm_device
*dev
,
67 struct drm_framebuffer
*fb
)
69 struct armada_private
*priv
= dev
->dev_private
;
71 WARN_ON(!kfifo_put(&priv
->fb_unref
, fb
));
72 schedule_work(&priv
->fb_unref_work
);
75 void armada_drm_queue_unref_work(struct drm_device
*dev
,
76 struct drm_framebuffer
*fb
)
80 spin_lock_irqsave(&dev
->event_lock
, flags
);
81 __armada_drm_queue_unref_work(dev
, fb
);
82 spin_unlock_irqrestore(&dev
->event_lock
, flags
);
85 static int armada_drm_load(struct drm_device
*dev
, unsigned long flags
)
87 const struct platform_device_id
*id
;
88 struct armada_private
*priv
;
89 struct resource
*res
[ARRAY_SIZE(priv
->dcrtc
)];
90 struct resource
*mem
= NULL
;
93 memset(res
, 0, sizeof(res
));
95 for (n
= i
= 0; ; n
++) {
96 struct resource
*r
= platform_get_resource(dev
->platformdev
,
101 /* Resources above 64K are graphics memory */
102 if (resource_size(r
) > SZ_64K
)
104 else if (i
< ARRAY_SIZE(priv
->dcrtc
))
113 if (!devm_request_mem_region(dev
->dev
, mem
->start
,
114 resource_size(mem
), "armada-drm"))
117 priv
= devm_kzalloc(dev
->dev
, sizeof(*priv
), GFP_KERNEL
);
119 DRM_ERROR("failed to allocate private\n");
123 platform_set_drvdata(dev
->platformdev
, dev
);
124 dev
->dev_private
= priv
;
126 /* Get the implementation specific driver data. */
127 id
= platform_get_device_id(dev
->platformdev
);
131 priv
->variant
= (struct armada_variant
*)id
->driver_data
;
133 ret
= priv
->variant
->init(priv
, dev
->dev
);
137 INIT_WORK(&priv
->fb_unref_work
, armada_drm_unref_work
);
138 INIT_KFIFO(priv
->fb_unref
);
140 /* Mode setting support */
141 drm_mode_config_init(dev
);
142 dev
->mode_config
.min_width
= 320;
143 dev
->mode_config
.min_height
= 200;
146 * With vscale enabled, the maximum width is 1920 due to the
147 * 1920 by 3 lines RAM
149 dev
->mode_config
.max_width
= 1920;
150 dev
->mode_config
.max_height
= 2048;
152 dev
->mode_config
.preferred_depth
= 24;
153 dev
->mode_config
.funcs
= &armada_drm_mode_config_funcs
;
154 drm_mm_init(&priv
->linear
, mem
->start
, resource_size(mem
));
156 /* Create all LCD controllers */
157 for (n
= 0; n
< ARRAY_SIZE(priv
->dcrtc
); n
++) {
161 ret
= armada_drm_crtc_create(dev
, n
, res
[n
]);
166 #ifdef CONFIG_DRM_ARMADA_TDA1998X
167 ret
= armada_drm_connector_slave_create(dev
, &tda19988_config
);
172 ret
= drm_vblank_init(dev
, n
);
176 ret
= drm_irq_install(dev
);
180 dev
->vblank_disable_allowed
= 1;
182 ret
= armada_fbdev_init(dev
);
186 drm_kms_helper_poll_init(dev
);
191 drm_irq_uninstall(dev
);
193 drm_mode_config_cleanup(dev
);
194 drm_mm_takedown(&priv
->linear
);
195 flush_work(&priv
->fb_unref_work
);
200 static int armada_drm_unload(struct drm_device
*dev
)
202 struct armada_private
*priv
= dev
->dev_private
;
204 drm_kms_helper_poll_fini(dev
);
205 armada_fbdev_fini(dev
);
206 drm_irq_uninstall(dev
);
207 drm_mode_config_cleanup(dev
);
208 drm_mm_takedown(&priv
->linear
);
209 flush_work(&priv
->fb_unref_work
);
210 dev
->dev_private
= NULL
;
215 void armada_drm_vbl_event_add(struct armada_crtc
*dcrtc
,
216 struct armada_vbl_event
*evt
)
220 spin_lock_irqsave(&dcrtc
->irq_lock
, flags
);
221 if (list_empty(&evt
->node
)) {
222 list_add_tail(&evt
->node
, &dcrtc
->vbl_list
);
224 drm_vblank_get(dcrtc
->crtc
.dev
, dcrtc
->num
);
226 spin_unlock_irqrestore(&dcrtc
->irq_lock
, flags
);
229 void armada_drm_vbl_event_remove(struct armada_crtc
*dcrtc
,
230 struct armada_vbl_event
*evt
)
232 if (!list_empty(&evt
->node
)) {
233 list_del_init(&evt
->node
);
234 drm_vblank_put(dcrtc
->crtc
.dev
, dcrtc
->num
);
238 void armada_drm_vbl_event_remove_unlocked(struct armada_crtc
*dcrtc
,
239 struct armada_vbl_event
*evt
)
243 spin_lock_irqsave(&dcrtc
->irq_lock
, flags
);
244 armada_drm_vbl_event_remove(dcrtc
, evt
);
245 spin_unlock_irqrestore(&dcrtc
->irq_lock
, flags
);
248 /* These are called under the vbl_lock. */
249 static int armada_drm_enable_vblank(struct drm_device
*dev
, int crtc
)
251 struct armada_private
*priv
= dev
->dev_private
;
252 armada_drm_crtc_enable_irq(priv
->dcrtc
[crtc
], VSYNC_IRQ_ENA
);
256 static void armada_drm_disable_vblank(struct drm_device
*dev
, int crtc
)
258 struct armada_private
*priv
= dev
->dev_private
;
259 armada_drm_crtc_disable_irq(priv
->dcrtc
[crtc
], VSYNC_IRQ_ENA
);
262 static irqreturn_t
armada_drm_irq_handler(int irq
, void *arg
)
264 struct drm_device
*dev
= arg
;
265 struct armada_private
*priv
= dev
->dev_private
;
266 struct armada_crtc
*dcrtc
= priv
->dcrtc
[0];
267 uint32_t v
, stat
= readl_relaxed(dcrtc
->base
+ LCD_SPU_IRQ_ISR
);
268 irqreturn_t handled
= IRQ_NONE
;
271 * This is rediculous - rather than writing bits to clear, we
272 * have to set the actual status register value. This is racy.
274 writel_relaxed(0, dcrtc
->base
+ LCD_SPU_IRQ_ISR
);
276 /* Mask out those interrupts we haven't enabled */
277 v
= stat
& dcrtc
->irq_ena
;
279 if (v
& (VSYNC_IRQ
|GRA_FRAME_IRQ
|DUMB_FRAMEDONE
)) {
280 armada_drm_crtc_irq(dcrtc
, stat
);
281 handled
= IRQ_HANDLED
;
287 static int armada_drm_irq_postinstall(struct drm_device
*dev
)
289 struct armada_private
*priv
= dev
->dev_private
;
290 struct armada_crtc
*dcrtc
= priv
->dcrtc
[0];
292 spin_lock_irq(&dev
->vbl_lock
);
293 writel_relaxed(dcrtc
->irq_ena
, dcrtc
->base
+ LCD_SPU_IRQ_ENA
);
294 writel(0, dcrtc
->base
+ LCD_SPU_IRQ_ISR
);
295 spin_unlock_irq(&dev
->vbl_lock
);
300 static void armada_drm_irq_uninstall(struct drm_device
*dev
)
302 struct armada_private
*priv
= dev
->dev_private
;
303 struct armada_crtc
*dcrtc
= priv
->dcrtc
[0];
305 writel(0, dcrtc
->base
+ LCD_SPU_IRQ_ENA
);
308 static struct drm_ioctl_desc armada_ioctls
[] = {
309 DRM_IOCTL_DEF_DRV(ARMADA_GEM_CREATE
, armada_gem_create_ioctl
,
311 DRM_IOCTL_DEF_DRV(ARMADA_GEM_MMAP
, armada_gem_mmap_ioctl
,
313 DRM_IOCTL_DEF_DRV(ARMADA_GEM_PWRITE
, armada_gem_pwrite_ioctl
,
317 static void armada_drm_lastclose(struct drm_device
*dev
)
319 armada_fbdev_lastclose(dev
);
322 static const struct file_operations armada_drm_fops
= {
323 .owner
= THIS_MODULE
,
327 .unlocked_ioctl
= drm_ioctl
,
328 .mmap
= drm_gem_mmap
,
330 .release
= drm_release
,
333 static struct drm_driver armada_drm_driver
= {
334 .load
= armada_drm_load
,
338 .lastclose
= armada_drm_lastclose
,
339 .unload
= armada_drm_unload
,
340 .get_vblank_counter
= drm_vblank_count
,
341 .enable_vblank
= armada_drm_enable_vblank
,
342 .disable_vblank
= armada_drm_disable_vblank
,
343 .irq_handler
= armada_drm_irq_handler
,
344 .irq_postinstall
= armada_drm_irq_postinstall
,
345 .irq_uninstall
= armada_drm_irq_uninstall
,
346 #ifdef CONFIG_DEBUG_FS
347 .debugfs_init
= armada_drm_debugfs_init
,
348 .debugfs_cleanup
= armada_drm_debugfs_cleanup
,
350 .gem_free_object
= armada_gem_free_object
,
351 .prime_handle_to_fd
= drm_gem_prime_handle_to_fd
,
352 .prime_fd_to_handle
= drm_gem_prime_fd_to_handle
,
353 .gem_prime_export
= armada_gem_prime_export
,
354 .gem_prime_import
= armada_gem_prime_import
,
355 .dumb_create
= armada_gem_dumb_create
,
356 .dumb_map_offset
= armada_gem_dumb_map_offset
,
357 .dumb_destroy
= armada_gem_dumb_destroy
,
358 .gem_vm_ops
= &armada_gem_vm_ops
,
361 .name
= "armada-drm",
362 .desc
= "Armada SoC DRM",
364 .driver_features
= DRIVER_GEM
| DRIVER_MODESET
|
365 DRIVER_HAVE_IRQ
| DRIVER_PRIME
,
366 .ioctls
= armada_ioctls
,
367 .fops
= &armada_drm_fops
,
370 static int armada_drm_probe(struct platform_device
*pdev
)
372 return drm_platform_init(&armada_drm_driver
, pdev
);
375 static int armada_drm_remove(struct platform_device
*pdev
)
377 drm_put_dev(platform_get_drvdata(pdev
));
381 static const struct platform_device_id armada_drm_platform_ids
[] = {
383 .name
= "armada-drm",
384 .driver_data
= (unsigned long)&armada510_ops
,
386 .name
= "armada-510-drm",
387 .driver_data
= (unsigned long)&armada510_ops
,
391 MODULE_DEVICE_TABLE(platform
, armada_drm_platform_ids
);
393 static struct platform_driver armada_drm_platform_driver
= {
394 .probe
= armada_drm_probe
,
395 .remove
= armada_drm_remove
,
397 .name
= "armada-drm",
398 .owner
= THIS_MODULE
,
400 .id_table
= armada_drm_platform_ids
,
403 static int __init
armada_drm_init(void)
405 armada_drm_driver
.num_ioctls
= DRM_ARRAY_SIZE(armada_ioctls
);
406 return platform_driver_register(&armada_drm_platform_driver
);
408 module_init(armada_drm_init
);
410 static void __exit
armada_drm_exit(void)
412 platform_driver_unregister(&armada_drm_platform_driver
);
414 module_exit(armada_drm_exit
);
416 MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
417 MODULE_DESCRIPTION("Armada DRM Driver");
418 MODULE_LICENSE("GPL");
419 MODULE_ALIAS("platform:armada-drm");