1 // SPDX-License-Identifier: GPL-2.0-only
3 * (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved.
5 * Parts of this file were based on sources as follows:
7 * Copyright (c) 2006-2008 Intel Corporation
8 * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
9 * Copyright (C) 2011 Texas Instruments
13 * DOC: ARM PrimeCell PL110 and PL111 CLCD Driver
15 * The PL110/PL111 is a simple LCD controller that can support TFT
16 * and STN displays. This driver exposes a standard KMS interface
19 * The driver currently doesn't expose the cursor. The DRM API for
20 * cursors requires support for 64x64 ARGB8888 cursor images, while
21 * the hardware can only support 64x64 monochrome with masking
22 * cursors. While one could imagine trying to hack something together
23 * to look at the ARGB8888 and program reasonable in monochrome, we
24 * just don't expose the cursor at all instead, and leave cursor
25 * support to the application software cursor layer.
29 * - Fix race between setting plane base address and getting IRQ for
30 * vsync firing the pageflip completion.
32 * - Read back hardware state at boot to skip reprogramming the
33 * hardware when doing a no-op modeset.
35 * - Use the CLKSEL bit to support switching between the two external
39 #include <linux/amba/bus.h>
40 #include <linux/dma-buf.h>
41 #include <linux/module.h>
43 #include <linux/of_graph.h>
44 #include <linux/of_reserved_mem.h>
45 #include <linux/shmem_fs.h>
46 #include <linux/slab.h>
47 #include <linux/version.h>
49 #include <drm/drm_atomic_helper.h>
50 #include <drm/drm_bridge.h>
51 #include <drm/drm_drv.h>
52 #include <drm/drm_fb_cma_helper.h>
53 #include <drm/drm_fb_helper.h>
54 #include <drm/drm_gem_cma_helper.h>
55 #include <drm/drm_gem_framebuffer_helper.h>
56 #include <drm/drm_of.h>
57 #include <drm/drm_panel.h>
58 #include <drm/drm_probe_helper.h>
59 #include <drm/drm_vblank.h>
61 #include "pl111_drm.h"
62 #include "pl111_versatile.h"
63 #include "pl111_nomadik.h"
65 #define DRIVER_DESC "DRM module for PL111"
67 static const struct drm_mode_config_funcs mode_config_funcs
= {
68 .fb_create
= drm_gem_fb_create
,
69 .atomic_check
= drm_atomic_helper_check
,
70 .atomic_commit
= drm_atomic_helper_commit
,
73 static int pl111_modeset_init(struct drm_device
*dev
)
75 struct drm_mode_config
*mode_config
;
76 struct pl111_drm_dev_private
*priv
= dev
->dev_private
;
77 struct device_node
*np
= dev
->dev
->of_node
;
78 struct device_node
*remote
;
79 struct drm_panel
*panel
= NULL
;
80 struct drm_bridge
*bridge
= NULL
;
85 ret
= drmm_mode_config_init(dev
);
89 mode_config
= &dev
->mode_config
;
90 mode_config
->funcs
= &mode_config_funcs
;
91 mode_config
->min_width
= 1;
92 mode_config
->max_width
= 1024;
93 mode_config
->min_height
= 1;
94 mode_config
->max_height
= 768;
97 for_each_endpoint_of_node(np
, remote
) {
98 struct drm_panel
*tmp_panel
;
99 struct drm_bridge
*tmp_bridge
;
101 dev_dbg(dev
->dev
, "checking endpoint %d\n", i
);
103 ret
= drm_of_find_panel_or_bridge(dev
->dev
->of_node
,
108 if (ret
== -EPROBE_DEFER
) {
110 * Something deferred, but that is often just
111 * another way of saying -ENODEV, but let's
112 * cast a vote for later deferral.
115 } else if (ret
!= -ENODEV
) {
116 /* Continue, maybe something else is working */
118 "endpoint %d returns %d\n", i
, ret
);
124 "found panel on endpoint %d\n", i
);
129 "found bridge on endpoint %d\n", i
);
137 * If we can't find neither panel nor bridge on any of the
138 * endpoints, and any of them retured -EPROBE_DEFER, then
139 * let's defer this driver too.
141 if ((!panel
&& !bridge
) && defer
)
142 return -EPROBE_DEFER
;
145 bridge
= drm_panel_bridge_add_typed(panel
,
146 DRM_MODE_CONNECTOR_Unknown
);
147 if (IS_ERR(bridge
)) {
148 ret
= PTR_ERR(bridge
);
152 dev_info(dev
->dev
, "Using non-panel bridge\n");
154 dev_err(dev
->dev
, "No bridge, exiting\n");
158 priv
->bridge
= bridge
;
161 priv
->connector
= drm_panel_bridge_connector(bridge
);
164 ret
= pl111_display_init(dev
);
166 dev_err(dev
->dev
, "Failed to init display\n");
170 ret
= drm_simple_display_pipe_attach_bridge(&priv
->pipe
,
175 if (!priv
->variant
->broken_vblank
) {
176 ret
= drm_vblank_init(dev
, 1);
178 dev_err(dev
->dev
, "Failed to init vblank\n");
183 drm_mode_config_reset(dev
);
185 drm_kms_helper_poll_init(dev
);
191 drm_panel_bridge_remove(bridge
);
196 static struct drm_gem_object
*
197 pl111_gem_import_sg_table(struct drm_device
*dev
,
198 struct dma_buf_attachment
*attach
,
199 struct sg_table
*sgt
)
201 struct pl111_drm_dev_private
*priv
= dev
->dev_private
;
204 * When using device-specific reserved memory we can't import
205 * DMA buffers: those are passed by reference in any global
206 * memory and we can only handle a specific range of memory.
208 if (priv
->use_device_memory
)
209 return ERR_PTR(-EINVAL
);
211 return drm_gem_cma_prime_import_sg_table(dev
, attach
, sgt
);
214 DEFINE_DRM_GEM_CMA_FOPS(drm_fops
);
216 static const struct drm_driver pl111_drm_driver
= {
218 DRIVER_MODESET
| DRIVER_GEM
| DRIVER_ATOMIC
,
227 .dumb_create
= drm_gem_cma_dumb_create
,
228 .prime_handle_to_fd
= drm_gem_prime_handle_to_fd
,
229 .prime_fd_to_handle
= drm_gem_prime_fd_to_handle
,
230 .gem_prime_import_sg_table
= pl111_gem_import_sg_table
,
231 .gem_prime_mmap
= drm_gem_cma_prime_mmap
,
233 #if defined(CONFIG_DEBUG_FS)
234 .debugfs_init
= pl111_debugfs_init
,
238 static int pl111_amba_probe(struct amba_device
*amba_dev
,
239 const struct amba_id
*id
)
241 struct device
*dev
= &amba_dev
->dev
;
242 struct pl111_drm_dev_private
*priv
;
243 const struct pl111_variant_data
*variant
= id
->data
;
244 struct drm_device
*drm
;
247 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
251 drm
= drm_dev_alloc(&pl111_drm_driver
, dev
);
254 amba_set_drvdata(amba_dev
, drm
);
256 drm
->dev_private
= priv
;
257 priv
->variant
= variant
;
259 ret
= of_reserved_mem_device_init(dev
);
261 dev_info(dev
, "using device-specific reserved memory\n");
262 priv
->use_device_memory
= true;
265 if (of_property_read_u32(dev
->of_node
, "max-memory-bandwidth",
267 dev_info(dev
, "no max memory bandwidth specified, assume unlimited\n");
271 /* The two main variants swap this register */
272 if (variant
->is_pl110
|| variant
->is_lcdc
) {
273 priv
->ienb
= CLCD_PL110_IENB
;
274 priv
->ctrl
= CLCD_PL110_CNTL
;
276 priv
->ienb
= CLCD_PL111_IENB
;
277 priv
->ctrl
= CLCD_PL111_CNTL
;
280 priv
->regs
= devm_ioremap_resource(dev
, &amba_dev
->res
);
281 if (IS_ERR(priv
->regs
)) {
282 dev_err(dev
, "%s failed mmio\n", __func__
);
283 ret
= PTR_ERR(priv
->regs
);
287 /* This may override some variant settings */
288 ret
= pl111_versatile_init(dev
, priv
);
292 pl111_nomadik_init(dev
);
294 /* turn off interrupts before requesting the irq */
295 writel(0, priv
->regs
+ priv
->ienb
);
297 ret
= devm_request_irq(dev
, amba_dev
->irq
[0], pl111_irq
, 0,
298 variant
->name
, priv
);
300 dev_err(dev
, "%s failed irq %d\n", __func__
, ret
);
304 ret
= pl111_modeset_init(drm
);
308 ret
= drm_dev_register(drm
, 0);
312 drm_fbdev_generic_setup(drm
, priv
->variant
->fb_bpp
);
318 of_reserved_mem_device_release(dev
);
323 static int pl111_amba_remove(struct amba_device
*amba_dev
)
325 struct device
*dev
= &amba_dev
->dev
;
326 struct drm_device
*drm
= amba_get_drvdata(amba_dev
);
327 struct pl111_drm_dev_private
*priv
= drm
->dev_private
;
329 drm_dev_unregister(drm
);
331 drm_panel_bridge_remove(priv
->bridge
);
333 of_reserved_mem_device_release(dev
);
339 * This early variant lacks the 565 and 444 pixel formats.
341 static const u32 pl110_pixel_formats
[] = {
352 static const struct pl111_variant_data pl110_variant
= {
355 .formats
= pl110_pixel_formats
,
356 .nformats
= ARRAY_SIZE(pl110_pixel_formats
),
360 /* RealView, Versatile Express etc use this modern variant */
361 static const u32 pl111_pixel_formats
[] = {
378 static const struct pl111_variant_data pl111_variant
= {
380 .formats
= pl111_pixel_formats
,
381 .nformats
= ARRAY_SIZE(pl111_pixel_formats
),
385 static const u32 pl110_nomadik_pixel_formats
[] = {
404 static const struct pl111_variant_data pl110_nomadik_variant
= {
405 .name
= "LCDC (PL110 Nomadik)",
406 .formats
= pl110_nomadik_pixel_formats
,
407 .nformats
= ARRAY_SIZE(pl110_nomadik_pixel_formats
),
409 .st_bitmux_control
= true,
410 .broken_vblank
= true,
414 static const struct amba_id pl111_id_table
[] = {
418 .data
= (void *)&pl110_variant
,
423 .data
= (void *)&pl110_nomadik_variant
,
428 .data
= (void *)&pl111_variant
,
432 MODULE_DEVICE_TABLE(amba
, pl111_id_table
);
434 static struct amba_driver pl111_amba_driver __maybe_unused
= {
436 .name
= "drm-clcd-pl111",
438 .probe
= pl111_amba_probe
,
439 .remove
= pl111_amba_remove
,
440 .id_table
= pl111_id_table
,
443 #ifdef CONFIG_ARM_AMBA
444 module_amba_driver(pl111_amba_driver
);
447 MODULE_DESCRIPTION(DRIVER_DESC
);
448 MODULE_AUTHOR("ARM Ltd.");
449 MODULE_LICENSE("GPL");