Skip to content

Commit

Permalink
drm/sun4i: Use lists to track registered display backends and TCONs
Browse files Browse the repository at this point in the history
To support multiple display pipelines, we need to keep track of the
multiple display backends and TCONs registered with the driver.

Switch to lists to track registered components. Components are only
appended to their respective lists if the bind process was successful.
The TCON bind function now defers if a backend was not registered.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
  • Loading branch information
Chen-Yu Tsai authored and Maxime Ripard committed May 14, 2017
1 parent de120d0 commit 80a5824
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 5 deletions.
6 changes: 5 additions & 1 deletion drivers/gpu/drm/sun4i/sun4i_backend.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <drm/drm_plane_helper.h>

#include <linux/component.h>
#include <linux/list.h>
#include <linux/reset.h>

#include "sun4i_backend.h"
Expand Down Expand Up @@ -310,7 +311,6 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
if (!backend)
return -ENOMEM;
dev_set_drvdata(dev, backend);
drv->backend = backend;

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
regs = devm_ioremap_resource(dev, res);
Expand Down Expand Up @@ -369,6 +369,8 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
}
}

list_add_tail(&backend->list, &drv->backend_list);

/* Reset the registers */
for (i = 0x800; i < 0x1000; i += 4)
regmap_write(backend->regs, i, 0);
Expand Down Expand Up @@ -400,6 +402,8 @@ static void sun4i_backend_unbind(struct device *dev, struct device *master,
{
struct sun4i_backend *backend = dev_get_drvdata(dev);

list_del(&backend->list);

if (of_device_is_compatible(dev->of_node,
"allwinner,sun8i-a33-display-backend"))
sun4i_backend_free_sat(dev);
Expand Down
4 changes: 4 additions & 0 deletions drivers/gpu/drm/sun4i/sun4i_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#define _SUN4I_BACKEND_H_

#include <linux/clk.h>
#include <linux/list.h>
#include <linux/regmap.h>
#include <linux/reset.h>

Expand Down Expand Up @@ -149,6 +150,9 @@ struct sun4i_backend {

struct clk *sat_clk;
struct reset_control *sat_reset;

/* Backend list management */
struct list_head list;
};

void sun4i_backend_apply_color_correction(struct sun4i_backend *backend);
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/sun4i/sun4i_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ static int sun4i_drv_bind(struct device *dev)
goto free_drm;
}
drm->dev_private = drv;
INIT_LIST_HEAD(&drv->backend_list);
INIT_LIST_HEAD(&drv->tcon_list);

ret = of_reserved_mem_device_init(dev);
if (ret && ret != -ENODEV) {
Expand Down
5 changes: 3 additions & 2 deletions drivers/gpu/drm/sun4i/sun4i_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@
#define _SUN4I_DRV_H_

#include <linux/clk.h>
#include <linux/list.h>
#include <linux/regmap.h>

struct sun4i_drv {
struct sun4i_backend *backend;
struct sun4i_tcon *tcon;
struct list_head backend_list;
struct list_head tcon_list;

struct drm_fbdev_cma *fbdev;
};
Expand Down
14 changes: 12 additions & 2 deletions drivers/gpu/drm/sun4i/sun4i_tcon.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <linux/regmap.h>
#include <linux/reset.h>

#include "sun4i_backend.h"
#include "sun4i_crtc.h"
#include "sun4i_dotclock.h"
#include "sun4i_drv.h"
Expand Down Expand Up @@ -407,14 +408,18 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
{
struct drm_device *drm = data;
struct sun4i_drv *drv = drm->dev_private;
struct sun4i_backend *backend;
struct sun4i_tcon *tcon;
int ret;

/* Wait for a backend to be registered */
if (list_empty(&drv->backend_list))
return -EPROBE_DEFER;

tcon = devm_kzalloc(dev, sizeof(*tcon), GFP_KERNEL);
if (!tcon)
return -ENOMEM;
dev_set_drvdata(dev, tcon);
drv->tcon = tcon;
tcon->drm = drm;
tcon->dev = dev;
tcon->quirks = of_device_get_match_data(dev);
Expand Down Expand Up @@ -459,7 +464,9 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
goto err_free_dotclock;
}

tcon->crtc = sun4i_crtc_init(drm, drv->backend, tcon);
backend = list_first_entry(&drv->backend_list,
struct sun4i_backend, list);
tcon->crtc = sun4i_crtc_init(drm, backend, tcon);
if (IS_ERR(tcon->crtc)) {
dev_err(dev, "Couldn't create our CRTC\n");
ret = PTR_ERR(tcon->crtc);
Expand All @@ -470,6 +477,8 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
if (ret < 0)
goto err_free_clocks;

list_add_tail(&tcon->list, &drv->tcon_list);

return 0;

err_free_dotclock:
Expand All @@ -486,6 +495,7 @@ static void sun4i_tcon_unbind(struct device *dev, struct device *master,
{
struct sun4i_tcon *tcon = dev_get_drvdata(dev);

list_del(&tcon->list);
sun4i_dclk_free(tcon);
sun4i_tcon_free_clocks(tcon);
}
Expand Down
4 changes: 4 additions & 0 deletions drivers/gpu/drm/sun4i/sun4i_tcon.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <drm/drm_crtc.h>

#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/reset.h>

#define SUN4I_TCON_GCTL_REG 0x0
Expand Down Expand Up @@ -172,6 +173,9 @@ struct sun4i_tcon {

/* Associated crtc */
struct sun4i_crtc *crtc;

/* TCON list management */
struct list_head list;
};

struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node);
Expand Down

0 comments on commit 80a5824

Please sign in to comment.