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
;
72 * Yes, we really must jump through these hoops just to store a
73 * _pointer_ to something into the kfifo. This is utterly insane
74 * and idiotic, because it kfifo requires the _data_ pointed to by
75 * the pointer const, not the pointer itself. Not only that, but
76 * you have to pass a pointer _to_ the pointer you want stored.
78 const struct drm_framebuffer
*silly_api_alert
= fb
;
79 WARN_ON(!kfifo_put(&priv
->fb_unref
, &silly_api_alert
));
80 schedule_work(&priv
->fb_unref_work
);
83 void armada_drm_queue_unref_work(struct drm_device
*dev
,
84 struct drm_framebuffer
*fb
)
88 spin_lock_irqsave(&dev
->event_lock
, flags
);
89 __armada_drm_queue_unref_work(dev
, fb
);
90 spin_unlock_irqrestore(&dev
->event_lock
, flags
);
93 static int armada_drm_load(struct drm_device
*dev
, unsigned long flags
)
95 const struct platform_device_id
*id
;
96 struct armada_private
*priv
;
97 struct resource
*res
[ARRAY_SIZE(priv
->dcrtc
)];
98 struct resource
*mem
= NULL
;
101 memset(res
, 0, sizeof(res
));
103 for (n
= i
= 0; ; n
++) {
104 struct resource
*r
= platform_get_resource(dev
->platformdev
,
109 /* Resources above 64K are graphics memory */
110 if (resource_size(r
) > SZ_64K
)
112 else if (i
< ARRAY_SIZE(priv
->dcrtc
))
121 if (!devm_request_mem_region(dev
->dev
, mem
->start
,
122 resource_size(mem
), "armada-drm"))
125 priv
= devm_kzalloc(dev
->dev
, sizeof(*priv
), GFP_KERNEL
);
127 DRM_ERROR("failed to allocate private\n");
131 platform_set_drvdata(dev
->platformdev
, dev
);
132 dev
->dev_private
= priv
;
134 /* Get the implementation specific driver data. */
135 id
= platform_get_device_id(dev
->platformdev
);
139 priv
->variant
= (struct armada_variant
*)id
->driver_data
;
141 ret
= priv
->variant
->init(priv
, dev
->dev
);
145 INIT_WORK(&priv
->fb_unref_work
, armada_drm_unref_work
);
146 INIT_KFIFO(priv
->fb_unref
);
148 /* Mode setting support */
149 drm_mode_config_init(dev
);
150 dev
->mode_config
.min_width
= 320;
151 dev
->mode_config
.min_height
= 200;
154 * With vscale enabled, the maximum width is 1920 due to the
155 * 1920 by 3 lines RAM
157 dev
->mode_config
.max_width
= 1920;
158 dev
->mode_config
.max_height
= 2048;
160 dev
->mode_config
.preferred_depth
= 24;
161 dev
->mode_config
.funcs
= &armada_drm_mode_config_funcs
;
162 drm_mm_init(&priv
->linear
, mem
->start
, resource_size(mem
));
164 /* Create all LCD controllers */
165 for (n
= 0; n
< ARRAY_SIZE(priv
->dcrtc
); n
++) {
169 ret
= armada_drm_crtc_create(dev
, n
, res
[n
]);
174 #ifdef CONFIG_DRM_ARMADA_TDA1998X
175 ret
= armada_drm_connector_slave_create(dev
, &tda19988_config
);
180 ret
= drm_vblank_init(dev
, n
);
184 ret
= drm_irq_install(dev
);
188 dev
->vblank_disable_allowed
= 1;
190 ret
= armada_fbdev_init(dev
);
194 drm_kms_helper_poll_init(dev
);
199 drm_irq_uninstall(dev
);
201 drm_mode_config_cleanup(dev
);
202 drm_mm_takedown(&priv
->linear
);
203 flush_work(&priv
->fb_unref_work
);
208 static int armada_drm_unload(struct drm_device
*dev
)
210 struct armada_private
*priv
= dev
->dev_private
;
212 drm_kms_helper_poll_fini(dev
);
213 armada_fbdev_fini(dev
);
214 drm_irq_uninstall(dev
);
215 drm_mode_config_cleanup(dev
);
216 drm_mm_takedown(&priv
->linear
);
217 flush_work(&priv
->fb_unref_work
);
218 dev
->dev_private
= NULL
;
223 void armada_drm_vbl_event_add(struct armada_crtc
*dcrtc
,
224 struct armada_vbl_event
*evt
)
228 spin_lock_irqsave(&dcrtc
->irq_lock
, flags
);
229 if (list_empty(&evt
->node
)) {
230 list_add_tail(&evt
->node
, &dcrtc
->vbl_list
);
232 drm_vblank_get(dcrtc
->crtc
.dev
, dcrtc
->num
);
234 spin_unlock_irqrestore(&dcrtc
->irq_lock
, flags
);
237 void armada_drm_vbl_event_remove(struct armada_crtc
*dcrtc
,
238 struct armada_vbl_event
*evt
)
240 if (!list_empty(&evt
->node
)) {
241 list_del_init(&evt
->node
);
242 drm_vblank_put(dcrtc
->crtc
.dev
, dcrtc
->num
);
246 void armada_drm_vbl_event_remove_unlocked(struct armada_crtc
*dcrtc
,
247 struct armada_vbl_event
*evt
)
251 spin_lock_irqsave(&dcrtc
->irq_lock
, flags
);
252 armada_drm_vbl_event_remove(dcrtc
, evt
);
253 spin_unlock_irqrestore(&dcrtc
->irq_lock
, flags
);
256 /* These are called under the vbl_lock. */
257 static int armada_drm_enable_vblank(struct drm_device
*dev
, int crtc
)
259 struct armada_private
*priv
= dev
->dev_private
;
260 armada_drm_crtc_enable_irq(priv
->dcrtc
[crtc
], VSYNC_IRQ_ENA
);
264 static void armada_drm_disable_vblank(struct drm_device
*dev
, int crtc
)
266 struct armada_private
*priv
= dev
->dev_private
;
267 armada_drm_crtc_disable_irq(priv
->dcrtc
[crtc
], VSYNC_IRQ_ENA
);
270 static irqreturn_t
armada_drm_irq_handler(int irq
, void *arg
)
272 struct drm_device
*dev
= arg
;
273 struct armada_private
*priv
= dev
->dev_private
;
274 struct armada_crtc
*dcrtc
= priv
->dcrtc
[0];
275 uint32_t v
, stat
= readl_relaxed(dcrtc
->base
+ LCD_SPU_IRQ_ISR
);
276 irqreturn_t handled
= IRQ_NONE
;
279 * This is rediculous - rather than writing bits to clear, we
280 * have to set the actual status register value. This is racy.
282 writel_relaxed(0, dcrtc
->base
+ LCD_SPU_IRQ_ISR
);
284 /* Mask out those interrupts we haven't enabled */
285 v
= stat
& dcrtc
->irq_ena
;
287 if (v
& (VSYNC_IRQ
|GRA_FRAME_IRQ
|DUMB_FRAMEDONE
)) {
288 armada_drm_crtc_irq(dcrtc
, stat
);
289 handled
= IRQ_HANDLED
;
295 static int armada_drm_irq_postinstall(struct drm_device
*dev
)
297 struct armada_private
*priv
= dev
->dev_private
;
298 struct armada_crtc
*dcrtc
= priv
->dcrtc
[0];
300 spin_lock_irq(&dev
->vbl_lock
);
301 writel_relaxed(dcrtc
->irq_ena
, dcrtc
->base
+ LCD_SPU_IRQ_ENA
);
302 writel(0, dcrtc
->base
+ LCD_SPU_IRQ_ISR
);
303 spin_unlock_irq(&dev
->vbl_lock
);
308 static void armada_drm_irq_uninstall(struct drm_device
*dev
)
310 struct armada_private
*priv
= dev
->dev_private
;
311 struct armada_crtc
*dcrtc
= priv
->dcrtc
[0];
313 writel(0, dcrtc
->base
+ LCD_SPU_IRQ_ENA
);
316 static struct drm_ioctl_desc armada_ioctls
[] = {
317 DRM_IOCTL_DEF_DRV(ARMADA_GEM_CREATE
, armada_gem_create_ioctl
,
319 DRM_IOCTL_DEF_DRV(ARMADA_GEM_MMAP
, armada_gem_mmap_ioctl
,
321 DRM_IOCTL_DEF_DRV(ARMADA_GEM_PWRITE
, armada_gem_pwrite_ioctl
,
325 static void armada_drm_lastclose(struct drm_device
*dev
)
327 armada_fbdev_lastclose(dev
);
330 static const struct file_operations armada_drm_fops
= {
331 .owner
= THIS_MODULE
,
335 .unlocked_ioctl
= drm_ioctl
,
336 .mmap
= drm_gem_mmap
,
338 .release
= drm_release
,
341 static struct drm_driver armada_drm_driver
= {
342 .load
= armada_drm_load
,
346 .lastclose
= armada_drm_lastclose
,
347 .unload
= armada_drm_unload
,
348 .get_vblank_counter
= drm_vblank_count
,
349 .enable_vblank
= armada_drm_enable_vblank
,
350 .disable_vblank
= armada_drm_disable_vblank
,
351 .irq_handler
= armada_drm_irq_handler
,
352 .irq_postinstall
= armada_drm_irq_postinstall
,
353 .irq_uninstall
= armada_drm_irq_uninstall
,
354 #ifdef CONFIG_DEBUG_FS
355 .debugfs_init
= armada_drm_debugfs_init
,
356 .debugfs_cleanup
= armada_drm_debugfs_cleanup
,
358 .gem_free_object
= armada_gem_free_object
,
359 .prime_handle_to_fd
= drm_gem_prime_handle_to_fd
,
360 .prime_fd_to_handle
= drm_gem_prime_fd_to_handle
,
361 .gem_prime_export
= armada_gem_prime_export
,
362 .gem_prime_import
= armada_gem_prime_import
,
363 .dumb_create
= armada_gem_dumb_create
,
364 .dumb_map_offset
= armada_gem_dumb_map_offset
,
365 .dumb_destroy
= armada_gem_dumb_destroy
,
366 .gem_vm_ops
= &armada_gem_vm_ops
,
369 .name
= "armada-drm",
370 .desc
= "Armada SoC DRM",
372 .driver_features
= DRIVER_GEM
| DRIVER_MODESET
|
373 DRIVER_HAVE_IRQ
| DRIVER_PRIME
,
374 .ioctls
= armada_ioctls
,
375 .fops
= &armada_drm_fops
,
378 static int armada_drm_probe(struct platform_device
*pdev
)
380 return drm_platform_init(&armada_drm_driver
, pdev
);
383 static int armada_drm_remove(struct platform_device
*pdev
)
385 drm_put_dev(platform_get_drvdata(pdev
));
389 static const struct platform_device_id armada_drm_platform_ids
[] = {
391 .name
= "armada-drm",
392 .driver_data
= (unsigned long)&armada510_ops
,
394 .name
= "armada-510-drm",
395 .driver_data
= (unsigned long)&armada510_ops
,
399 MODULE_DEVICE_TABLE(platform
, armada_drm_platform_ids
);
401 static struct platform_driver armada_drm_platform_driver
= {
402 .probe
= armada_drm_probe
,
403 .remove
= armada_drm_remove
,
405 .name
= "armada-drm",
406 .owner
= THIS_MODULE
,
408 .id_table
= armada_drm_platform_ids
,
411 static int __init
armada_drm_init(void)
413 armada_drm_driver
.num_ioctls
= DRM_ARRAY_SIZE(armada_ioctls
);
414 return platform_driver_register(&armada_drm_platform_driver
);
416 module_init(armada_drm_init
);
418 static void __exit
armada_drm_exit(void)
420 platform_driver_unregister(&armada_drm_platform_driver
);
422 module_exit(armada_drm_exit
);
424 MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
425 MODULE_DESCRIPTION("Armada DRM Driver");
426 MODULE_LICENSE("GPL");
427 MODULE_ALIAS("platform:armada-drm");