Skip to content

Commit

Permalink
drm/pl111: Initial drm/kms driver for pl111
Browse files Browse the repository at this point in the history
This is a modesetting driver for the pl111 CLCD display controller
found on various ARM platforms such as the Versatile Express. The
driver has only been tested on the bcm911360_entphn platform so far,
with PRIME-based buffer sharing between vc4 and clcd.

It reuses the existing devicetree binding, while not using quite as
many of its properties as the fbdev driver does (those are left for
future work).

v2: Nearly complete rewrite by anholt, cutting 2/3 of the code thanks
    to DRM core's excellent new helpers.
v3: Don't match pl110 any more, don't attach if we don't have a DRM
    panel, use DRM_GEM_CMA_FOPS, update MAINTAINERS, use the simple
    display helper, use drm_gem_cma_dumb_create (same as our wrapper).
v4: Change the driver's .name to not clash with fbdev in sysfs, drop
    platform alias, drop redundant "drm" in DRM driver name, hook up
    .prepare_fb to the CMA helper so that DMA fences should work.
v5: Move register definitions inside the driver directory, fix build
    in COMPILE_TEST and !AMBA mode.
v6: Drop TIM2_CLKSEL for now to be consistent with existing DT
    bindings, switch back to external register definitions.

Signed-off-by: Tom Cooksey <tom.cooksey@arm.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org> (v5)
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/20170413031746.12921-2-eric@anholt.net
  • Loading branch information
Tom Cooksey authored and Eric Anholt committed May 8, 2017
1 parent 73c7346 commit bed4100
Show file tree
Hide file tree
Showing 11 changed files with 832 additions and 0 deletions.
1 change: 1 addition & 0 deletions Documentation/gpu/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Linux GPU Driver Developer's Guide
drm-uapi
i915
meson
pl111
tinydrm
vc4
vga-switcheroo
Expand Down
6 changes: 6 additions & 0 deletions Documentation/gpu/pl111.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
==========================================
drm/pl111 ARM PrimeCell PL111 CLCD Driver
==========================================

.. kernel-doc:: drivers/gpu/drm/pl111/pl111_drv.c
:doc: ARM PrimeCell PL111 CLCD Driver
6 changes: 6 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -4160,6 +4160,12 @@ F: include/drm/drm*
F: include/uapi/drm/drm*
F: include/linux/vga*

DRM DRIVER FOR ARM PL111 CLCD
M: Eric Anholt <eric@anholt.net>
T: git git://anongit.freedesktop.org/drm/drm-misc
S: Supported
F: drivers/gpu/drm/pl111/

DRM DRIVER FOR AST SERVER GRAPHICS CHIPS
M: Dave Airlie <airlied@redhat.com>
S: Odd Fixes
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,8 @@ source "drivers/gpu/drm/meson/Kconfig"

source "drivers/gpu/drm/tinydrm/Kconfig"

source "drivers/gpu/drm/pl111/Kconfig"

# Keep legacy drivers last

menuconfig DRM_LEGACY
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,4 @@ obj-y += hisilicon/
obj-$(CONFIG_DRM_ZTE) += zte/
obj-$(CONFIG_DRM_MXSFB) += mxsfb/
obj-$(CONFIG_DRM_TINYDRM) += tinydrm/
obj-$(CONFIG_DRM_PL111) += pl111/
12 changes: 12 additions & 0 deletions drivers/gpu/drm/pl111/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
config DRM_PL111
tristate "DRM Support for PL111 CLCD Controller"
depends on DRM
depends on ARM || ARM64 || COMPILE_TEST
select DRM_KMS_HELPER
select DRM_KMS_CMA_HELPER
select DRM_GEM_CMA_HELPER
select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
help
Choose this option for DRM support for the PL111 CLCD controller.
If M is selected the module will be called pl111_drm.

5 changes: 5 additions & 0 deletions drivers/gpu/drm/pl111/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pl111_drm-y += pl111_connector.o \
pl111_display.o \
pl111_drv.o

obj-$(CONFIG_DRM_PL111) += pl111_drm.o
127 changes: 127 additions & 0 deletions drivers/gpu/drm/pl111/pl111_connector.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved.
*
* Parts of this file were based on sources as follows:
*
* Copyright (c) 2006-2008 Intel Corporation
* Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
* Copyright (C) 2011 Texas Instruments
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation, and any use by you of this program is subject to the terms of
* such GNU licence.
*
*/

/**
* pl111_drm_connector.c
* Implementation of the connector functions for PL111 DRM
*/
#include <linux/amba/clcd-regs.h>
#include <linux/version.h>
#include <linux/shmem_fs.h>
#include <linux/dma-buf.h>

#include <drm/drmP.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h>

#include "pl111_drm.h"

static void pl111_connector_destroy(struct drm_connector *connector)
{
struct pl111_drm_connector *pl111_connector =
to_pl111_connector(connector);

if (pl111_connector->panel)
drm_panel_detach(pl111_connector->panel);

drm_connector_unregister(connector);
drm_connector_cleanup(connector);
}

static enum drm_connector_status pl111_connector_detect(struct drm_connector
*connector, bool force)
{
struct pl111_drm_connector *pl111_connector =
to_pl111_connector(connector);

return (pl111_connector->panel ?
connector_status_connected :
connector_status_disconnected);
}

static int pl111_connector_helper_get_modes(struct drm_connector *connector)
{
struct pl111_drm_connector *pl111_connector =
to_pl111_connector(connector);

if (!pl111_connector->panel)
return 0;

return drm_panel_get_modes(pl111_connector->panel);
}

const struct drm_connector_funcs connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = pl111_connector_destroy,
.detect = pl111_connector_detect,
.dpms = drm_atomic_helper_connector_dpms,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};

const struct drm_connector_helper_funcs connector_helper_funcs = {
.get_modes = pl111_connector_helper_get_modes,
};

/* Walks the OF graph to find the panel node and then asks DRM to look
* up the panel.
*/
static struct drm_panel *pl111_get_panel(struct device *dev)
{
struct device_node *endpoint, *panel_node;
struct device_node *np = dev->of_node;
struct drm_panel *panel;

endpoint = of_graph_get_next_endpoint(np, NULL);
if (!endpoint) {
dev_err(dev, "no endpoint to fetch panel\n");
return NULL;
}

/* don't proceed if we have an endpoint but no panel_node tied to it */
panel_node = of_graph_get_remote_port_parent(endpoint);
of_node_put(endpoint);
if (!panel_node) {
dev_err(dev, "no valid panel node\n");
return NULL;
}

panel = of_drm_find_panel(panel_node);
of_node_put(panel_node);

return panel;
}

int pl111_connector_init(struct drm_device *dev)
{
struct pl111_drm_dev_private *priv = dev->dev_private;
struct pl111_drm_connector *pl111_connector = &priv->connector;
struct drm_connector *connector = &pl111_connector->connector;

drm_connector_init(dev, connector, &connector_funcs,
DRM_MODE_CONNECTOR_DPI);
drm_connector_helper_add(connector, &connector_helper_funcs);

pl111_connector->panel = pl111_get_panel(dev->dev);
if (pl111_connector->panel)
drm_panel_attach(pl111_connector->panel, connector);

return 0;
}

Loading

0 comments on commit bed4100

Please sign in to comment.