Skip to content

Commit

Permalink
drm/tve200: Add new driver for TVE200
Browse files Browse the repository at this point in the history
This adds a new DRM driver for the Faraday Technology TVE200
block. This "TV Encoder" encodes a ITU-T BT.656 stream and can
be found in the StorLink SL3516 (later Cortina Systems CS3516)
as well as the Grain Media GM8180.

I do not have definitive word from anyone at Faraday that this
IP block is theirs, but it bears the hallmark of their 3-digit
version code (200) and is used in two SoCs from completely
different companies. (Grain Media was fully owned by Faraday
until it was transferred to NovoTek this january, and
Faraday did lots of work on the StorLink SoCs.)

The D-Link DIR-685 uses this in connection with the Ilitek
ILI9322 panel driver that supports BT.656 input, while the
GM8180 apparently has been used with the Cirrus Logic CS4954
digital video encoder. The oldest user seems to be
something called Techwall 2835.

This driver is heavily inspired by Eric Anholt's PL111
driver and therefore I have mentioned all the ancestor authors
in the header file.

Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20170820100557.24991-2-linus.walleij@linaro.org
  • Loading branch information
linusw committed Aug 23, 2017
1 parent 8b17e80 commit 179c02f
Show file tree
Hide file tree
Showing 11 changed files with 912 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 @@ -15,6 +15,7 @@ Linux GPU Driver Developer's Guide
pl111
tegra
tinydrm
tve200
vc4
vga-switcheroo
vgaarbiter
Expand Down
6 changes: 6 additions & 0 deletions Documentation/gpu/tve200.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
==================================
drm/tve200 Faraday TV Encoder 200
==================================

.. kernel-doc:: drivers/gpu/drm/tve200/tve200_drv.c
:doc: Faraday TV Encoder 200
6 changes: 6 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -4300,6 +4300,12 @@ T: git git://anongit.freedesktop.org/drm/drm-misc
S: Maintained
F: drivers/gpu/drm/bochs/

DRM DRIVER FOR FARADAY TVE200 TV ENCODER
M: Linus Walleij <linus.walleij@linaro.org>
T: git git://anongit.freedesktop.org/drm/drm-misc
S: Maintained
F: drivers/gpu/drm/tve200/

DRM DRIVER FOR INTEL I810 VIDEO CARDS
S: Orphan / Obsolete
F: drivers/gpu/drm/i810/
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,8 @@ source "drivers/gpu/drm/tinydrm/Kconfig"

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

source "drivers/gpu/drm/tve200/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 @@ -100,3 +100,4 @@ obj-$(CONFIG_DRM_ZTE) += zte/
obj-$(CONFIG_DRM_MXSFB) += mxsfb/
obj-$(CONFIG_DRM_TINYDRM) += tinydrm/
obj-$(CONFIG_DRM_PL111) += pl111/
obj-$(CONFIG_DRM_TVE200) += tve200/
15 changes: 15 additions & 0 deletions drivers/gpu/drm/tve200/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
config DRM_TVE200
tristate "DRM Support for Faraday TV Encoder TVE200"
depends on DRM
depends on CMA
depends on ARM || COMPILE_TEST
depends on OF
select DRM_PANEL
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 Faraday TV Encoder
TVE200 Controller.
If M is selected the module will be called tve200_drm.
5 changes: 5 additions & 0 deletions drivers/gpu/drm/tve200/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
tve200_drm-y += tve200_connector.o \
tve200_display.o \
tve200_drv.o

obj-$(CONFIG_DRM_TVE200) += tve200_drm.o
125 changes: 125 additions & 0 deletions drivers/gpu/drm/tve200/tve200_connector.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
* Parts of this file were based on sources as follows:
*
* Copyright (C) 2006-2008 Intel Corporation
* Copyright (C) 2007 Amos Lee <amos_lee@storlinksemi.com>
* Copyright (C) 2007 Dave Airlie <airlied@linux.ie>
* Copyright (C) 2011 Texas Instruments
* Copyright (C) 2017 Eric Anholt
*
* 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.
*/

/**
* tve200_drm_connector.c
* Implementation of the connector functions for the Faraday TV Encoder
*/
#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 "tve200_drm.h"

static void tve200_connector_destroy(struct drm_connector *connector)
{
struct tve200_drm_connector *tve200con =
to_tve200_connector(connector);

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

drm_connector_unregister(connector);
drm_connector_cleanup(connector);
}

static enum drm_connector_status tve200_connector_detect(struct drm_connector
*connector, bool force)
{
struct tve200_drm_connector *tve200con =
to_tve200_connector(connector);

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

static int tve200_connector_helper_get_modes(struct drm_connector *connector)
{
struct tve200_drm_connector *tve200con =
to_tve200_connector(connector);

if (!tve200con->panel)
return 0;

return drm_panel_get_modes(tve200con->panel);
}

static const struct drm_connector_funcs connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = tve200_connector_destroy,
.detect = tve200_connector_detect,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};

static const struct drm_connector_helper_funcs connector_helper_funcs = {
.get_modes = tve200_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 *tve200_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 tve200_connector_init(struct drm_device *dev)
{
struct tve200_drm_dev_private *priv = dev->dev_private;
struct tve200_drm_connector *tve200con = &priv->connector;
struct drm_connector *connector = &tve200con->connector;

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

tve200con->panel = tve200_get_panel(dev->dev);
if (tve200con->panel)
drm_panel_attach(tve200con->panel, connector);

return 0;
}

0 comments on commit 179c02f

Please sign in to comment.