Commit dd0421f4 authored by Maxime Ripard's avatar Maxime Ripard

drm/sun4i: Add a driver for the display frontend

The display frontend is an hardware block that can be used to implement
some more advanced features like hardware scaling or colorspace
conversions. It can also be used to implement the output format of the VPU.

Let's create a minimal driver for it that will only enable the hardware
scaling features.
Reviewed-by: default avatarChen-Yu Tsai <wens@csie.org>
Signed-off-by: default avatarMaxime Ripard <maxime.ripard@free-electrons.com>
Link: https://patchwork.freedesktop.org/patch/msgid/029cdc3478bf89d422f5e8d9e600baf5e48ce4db.1516613040.git-series.maxime.ripard@free-electrons.com
parent 6b8562c8
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
sun4i-backend-y += sun4i_backend.o sun4i_layer.o sun4i-backend-y += sun4i_backend.o sun4i_layer.o
sun4i-frontend-y += sun4i_frontend.o
sun4i-drm-y += sun4i_drv.o sun4i-drm-y += sun4i_drv.o
sun4i-drm-y += sun4i_framebuffer.o sun4i-drm-y += sun4i_framebuffer.o
...@@ -24,6 +25,6 @@ obj-$(CONFIG_DRM_SUN4I) += sun4i-tcon.o ...@@ -24,6 +25,6 @@ obj-$(CONFIG_DRM_SUN4I) += sun4i-tcon.o
obj-$(CONFIG_DRM_SUN4I) += sun4i_tv.o obj-$(CONFIG_DRM_SUN4I) += sun4i_tv.o
obj-$(CONFIG_DRM_SUN4I) += sun6i_drc.o obj-$(CONFIG_DRM_SUN4I) += sun6i_drc.o
obj-$(CONFIG_DRM_SUN4I_BACKEND) += sun4i-backend.o obj-$(CONFIG_DRM_SUN4I_BACKEND) += sun4i-backend.o sun4i-frontend.o
obj-$(CONFIG_DRM_SUN4I_HDMI) += sun4i-drm-hdmi.o obj-$(CONFIG_DRM_SUN4I_HDMI) += sun4i-drm-hdmi.o
obj-$(CONFIG_DRM_SUN8I_MIXER) += sun8i-mixer.o obj-$(CONFIG_DRM_SUN8I_MIXER) += sun8i-mixer.o
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <drm/drm_of.h> #include <drm/drm_of.h>
#include "sun4i_drv.h" #include "sun4i_drv.h"
#include "sun4i_frontend.h"
#include "sun4i_framebuffer.h" #include "sun4i_framebuffer.h"
#include "sun4i_tcon.h" #include "sun4i_tcon.h"
...@@ -91,6 +92,7 @@ static int sun4i_drv_bind(struct device *dev) ...@@ -91,6 +92,7 @@ static int sun4i_drv_bind(struct device *dev)
goto free_drm; goto free_drm;
} }
drm->dev_private = drv; drm->dev_private = drv;
INIT_LIST_HEAD(&drv->frontend_list);
INIT_LIST_HEAD(&drv->engine_list); INIT_LIST_HEAD(&drv->engine_list);
INIT_LIST_HEAD(&drv->tcon_list); INIT_LIST_HEAD(&drv->tcon_list);
...@@ -177,6 +179,14 @@ static bool sun4i_drv_node_is_frontend(struct device_node *node) ...@@ -177,6 +179,14 @@ static bool sun4i_drv_node_is_frontend(struct device_node *node)
of_device_is_compatible(node, "allwinner,sun8i-a33-display-frontend"); of_device_is_compatible(node, "allwinner,sun8i-a33-display-frontend");
} }
static bool sun4i_drv_node_is_supported_frontend(struct device_node *node)
{
if (IS_ENABLED(CONFIG_DRM_SUN4I_BACKEND))
return !!of_match_node(sun4i_frontend_of_table, node);
return false;
}
static bool sun4i_drv_node_is_tcon(struct device_node *node) static bool sun4i_drv_node_is_tcon(struct device_node *node)
{ {
return !!of_match_node(sun4i_tcon_of_table, node); return !!of_match_node(sun4i_tcon_of_table, node);
...@@ -225,9 +235,11 @@ static int sun4i_drv_add_endpoints(struct device *dev, ...@@ -225,9 +235,11 @@ static int sun4i_drv_add_endpoints(struct device *dev,
int count = 0; int count = 0;
/* /*
* We don't support the frontend for now, so we will never * The frontend has been disabled in some of our old device
* have a device bound. Just skip over it, but we still want * trees. If we find a node that is the frontend and is
* the rest our pipeline to be added. * disabled, we should just follow through and parse its
* child, but without adding it to the component list.
* Otherwise, we obviously want to add it to the list.
*/ */
if (!sun4i_drv_node_is_frontend(node) && if (!sun4i_drv_node_is_frontend(node) &&
!of_device_is_available(node)) !of_device_is_available(node))
...@@ -240,7 +252,14 @@ static int sun4i_drv_add_endpoints(struct device *dev, ...@@ -240,7 +252,14 @@ static int sun4i_drv_add_endpoints(struct device *dev,
if (sun4i_drv_node_is_connector(node)) if (sun4i_drv_node_is_connector(node))
return 0; return 0;
if (!sun4i_drv_node_is_frontend(node)) { /*
* If the device is either just a regular device, or an
* enabled frontend supported by the driver, we add it to our
* component list.
*/
if (!sun4i_drv_node_is_frontend(node) ||
(sun4i_drv_node_is_supported_frontend(node) &&
of_device_is_available(node))) {
/* Add current component */ /* Add current component */
DRM_DEBUG_DRIVER("Adding component %pOF\n", node); DRM_DEBUG_DRIVER("Adding component %pOF\n", node);
drm_of_component_match_add(dev, match, compare_of, node); drm_of_component_match_add(dev, match, compare_of, node);
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
struct sun4i_drv { struct sun4i_drv {
struct list_head engine_list; struct list_head engine_list;
struct list_head frontend_list;
struct list_head tcon_list; struct list_head tcon_list;
}; };
......
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Free Electrons
* Maxime Ripard <maxime.ripard@free-electrons.com>
*/
#ifndef _SUN4I_FRONTEND_H_
#define _SUN4I_FRONTEND_H_
#include <linux/list.h>
#define SUN4I_FRONTEND_EN_REG 0x000
#define SUN4I_FRONTEND_EN_EN BIT(0)
#define SUN4I_FRONTEND_FRM_CTRL_REG 0x004
#define SUN4I_FRONTEND_FRM_CTRL_COEF_ACCESS_CTRL BIT(23)
#define SUN4I_FRONTEND_FRM_CTRL_FRM_START BIT(16)
#define SUN4I_FRONTEND_FRM_CTRL_COEF_RDY BIT(1)
#define SUN4I_FRONTEND_FRM_CTRL_REG_RDY BIT(0)
#define SUN4I_FRONTEND_BYPASS_REG 0x008
#define SUN4I_FRONTEND_BYPASS_CSC_EN BIT(1)
#define SUN4I_FRONTEND_BUF_ADDR0_REG 0x020
#define SUN4I_FRONTEND_LINESTRD0_REG 0x040
#define SUN4I_FRONTEND_INPUT_FMT_REG 0x04c
#define SUN4I_FRONTEND_INPUT_FMT_DATA_MOD(mod) ((mod) << 8)
#define SUN4I_FRONTEND_INPUT_FMT_DATA_FMT(fmt) ((fmt) << 4)
#define SUN4I_FRONTEND_INPUT_FMT_PS(ps) (ps)
#define SUN4I_FRONTEND_OUTPUT_FMT_REG 0x05c
#define SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT(fmt) (fmt)
#define SUN4I_FRONTEND_CH0_INSIZE_REG 0x100
#define SUN4I_FRONTEND_INSIZE(h, w) ((((h) - 1) << 16) | (((w) - 1)))
#define SUN4I_FRONTEND_CH0_OUTSIZE_REG 0x104
#define SUN4I_FRONTEND_OUTSIZE(h, w) ((((h) - 1) << 16) | (((w) - 1)))
#define SUN4I_FRONTEND_CH0_HORZFACT_REG 0x108
#define SUN4I_FRONTEND_HORZFACT(i, f) (((i) << 16) | (f))
#define SUN4I_FRONTEND_CH0_VERTFACT_REG 0x10c
#define SUN4I_FRONTEND_VERTFACT(i, f) (((i) << 16) | (f))
#define SUN4I_FRONTEND_CH0_HORZPHASE_REG 0x110
#define SUN4I_FRONTEND_CH0_VERTPHASE0_REG 0x114
#define SUN4I_FRONTEND_CH0_VERTPHASE1_REG 0x118
#define SUN4I_FRONTEND_CH1_INSIZE_REG 0x200
#define SUN4I_FRONTEND_CH1_OUTSIZE_REG 0x204
#define SUN4I_FRONTEND_CH1_HORZFACT_REG 0x208
#define SUN4I_FRONTEND_CH1_VERTFACT_REG 0x20c
#define SUN4I_FRONTEND_CH1_HORZPHASE_REG 0x210
#define SUN4I_FRONTEND_CH1_VERTPHASE0_REG 0x214
#define SUN4I_FRONTEND_CH1_VERTPHASE1_REG 0x218
#define SUN4I_FRONTEND_CH0_HORZCOEF0_REG(i) (0x400 + i * 4)
#define SUN4I_FRONTEND_CH0_HORZCOEF1_REG(i) (0x480 + i * 4)
#define SUN4I_FRONTEND_CH0_VERTCOEF_REG(i) (0x500 + i * 4)
#define SUN4I_FRONTEND_CH1_HORZCOEF0_REG(i) (0x600 + i * 4)
#define SUN4I_FRONTEND_CH1_HORZCOEF1_REG(i) (0x680 + i * 4)
#define SUN4I_FRONTEND_CH1_VERTCOEF_REG(i) (0x700 + i * 4)
struct clk;
struct device_node;
struct drm_plane;
struct regmap;
struct reset_control;
struct sun4i_frontend {
struct list_head list;
struct device *dev;
struct device_node *node;
struct clk *bus_clk;
struct clk *mod_clk;
struct clk *ram_clk;
struct regmap *regs;
struct reset_control *reset;
};
extern const struct of_device_id sun4i_frontend_of_table[];
int sun4i_frontend_init(struct sun4i_frontend *frontend);
void sun4i_frontend_exit(struct sun4i_frontend *frontend);
int sun4i_frontend_enable(struct sun4i_frontend *frontend);
void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend,
struct drm_plane *plane);
void sun4i_frontend_update_coord(struct sun4i_frontend *frontend,
struct drm_plane *plane);
int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
struct drm_plane *plane, uint32_t out_fmt);
#endif /* _SUN4I_FRONTEND_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment