Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0364d4fe authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'exynos-drm-next' of...

Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next

  Add Exynos4415 SoC support, some fixups and cleanups.

   Summary:
   - Resolve kernel lockup issue incurred by probe request in probe context.
     . For this, it moves all register codes of sub drivers into init function
       and adds component binding support for vidi driver.
   - Add Exynos4415 SoC support.
   - Make each manager and display object to be embedded
     in each driver context.
   - Fix and clean up FIMD and MIPI-DSI drivers.
   - Clean up unnecesary or wrong descriptions.
   - And trivial cleanups.

* 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos: (58 commits)
  drm/exynos: avoid leak if exynos_dpi_probe() fails
  drm/exynos: Fix exynos_dpi_remove() parameter
  drm/exynos: vidi: add component support
  drm/exynos: fix exynos_drm_component_del
  drm/exynos/ipp: fix error return code
  drm/exynos: clean up machine compatible string check
  drm/exynos: move Exynos platform drivers registration to init
  Revert "drm/exynos: fix null pointer dereference issue"
  drm/exynos/dpi: stop using display->ctx pointer
  drm/exynos/dpi: embed display into private context
  drm/exynos/dp: stop using display->ctx pointer
  drm/exynos/dp: embed display into private context
  drm/exynos/vidi: stop using display->ctx pointer
  drm/exynos/vidi: embed display into private context
  drm/exynos/hdmi: stop using display->ctx pointer
  drm/exynos/hdmi: embed display into private context
  drm/exynos/fimd: stop using manager->ctx pointer
  drm/exynos/fimd: embed manager into private context
  drm/exynos/vidi: stop using manager->ctx pointer
  drm/exynos/vidi: embed manager into private context
  ...
parents 955289c7 5baf5d44
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@ Required properties:
  - compatible: value should be one of the following
		"samsung,exynos3250-mipi-dsi" /* for Exynos3250/3472 SoCs */
		"samsung,exynos4210-mipi-dsi" /* for Exynos4 SoCs */
		"samsung,exynos4415-mipi-dsi" /* for Exynos4415 SoC */
		"samsung,exynos5410-mipi-dsi" /* for Exynos5410/5420/5440 SoCs */
  - reg: physical base address and length of the registers set for the device
  - interrupts: should contain DSI interrupt
+1 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ Required properties:
		"samsung,s5pv210-fimd"; /* for S5PV210 SoC */
		"samsung,exynos3250-fimd"; /* for Exynos3250/3472 SoCs */
		"samsung,exynos4210-fimd"; /* for Exynos4 SoCs */
		"samsung,exynos4415-fimd"; /* for Exynos4415 SoC */
		"samsung,exynos5250-fimd"; /* for Exynos5 SoCs */

- reg: physical base address and length of the FIMD registers set.
+45 −87
Original line number Diff line number Diff line
@@ -30,12 +30,17 @@
#include <drm/drm_panel.h>
#include <drm/bridge/ptn3460.h>

#include "exynos_drm_drv.h"
#include "exynos_dp_core.h"

#define ctx_from_connector(c)	container_of(c, struct exynos_dp_device, \
					connector)

static inline struct exynos_dp_device *
display_to_dp(struct exynos_drm_display *d)
{
	return container_of(d, struct exynos_dp_device, display);
}

struct bridge_init {
	struct i2c_client *client;
	struct device_node *node;
@@ -882,7 +887,7 @@ static void exynos_dp_hotplug(struct work_struct *work)

static void exynos_dp_commit(struct exynos_drm_display *display)
{
	struct exynos_dp_device *dp = display->ctx;
	struct exynos_dp_device *dp = display_to_dp(display);
	int ret;

	/* Keep the panel disabled while we configure video */
@@ -1020,7 +1025,7 @@ static int exynos_drm_attach_lcd_bridge(struct drm_device *dev,
static int exynos_dp_create_connector(struct exynos_drm_display *display,
				struct drm_encoder *encoder)
{
	struct exynos_dp_device *dp = display->ctx;
	struct exynos_dp_device *dp = display_to_dp(display);
	struct drm_connector *connector = &dp->connector;
	int ret;

@@ -1052,33 +1057,19 @@ static int exynos_dp_create_connector(struct exynos_drm_display *display,

static void exynos_dp_phy_init(struct exynos_dp_device *dp)
{
	if (dp->phy) {
	if (dp->phy)
		phy_power_on(dp->phy);
	} else if (dp->phy_addr) {
		u32 reg;

		reg = __raw_readl(dp->phy_addr);
		reg |= dp->enable_mask;
		__raw_writel(reg, dp->phy_addr);
	}
}

static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
{
	if (dp->phy) {
	if (dp->phy)
		phy_power_off(dp->phy);
	} else if (dp->phy_addr) {
		u32 reg;

		reg = __raw_readl(dp->phy_addr);
		reg &= ~(dp->enable_mask);
		__raw_writel(reg, dp->phy_addr);
	}
}

static void exynos_dp_poweron(struct exynos_drm_display *display)
{
	struct exynos_dp_device *dp = display->ctx;
	struct exynos_dp_device *dp = display_to_dp(display);

	if (dp->dpms_mode == DRM_MODE_DPMS_ON)
		return;
@@ -1099,7 +1090,7 @@ static void exynos_dp_poweron(struct exynos_drm_display *display)

static void exynos_dp_poweroff(struct exynos_drm_display *display)
{
	struct exynos_dp_device *dp = display->ctx;
	struct exynos_dp_device *dp = display_to_dp(display);

	if (dp->dpms_mode != DRM_MODE_DPMS_ON)
		return;
@@ -1124,7 +1115,7 @@ static void exynos_dp_poweroff(struct exynos_drm_display *display)

static void exynos_dp_dpms(struct exynos_drm_display *display, int mode)
{
	struct exynos_dp_device *dp = display->ctx;
	struct exynos_dp_device *dp = display_to_dp(display);

	switch (mode) {
	case DRM_MODE_DPMS_ON:
@@ -1147,11 +1138,6 @@ static struct exynos_drm_display_ops exynos_dp_display_ops = {
	.commit = exynos_dp_commit,
};

static struct exynos_drm_display exynos_dp_display = {
	.type = EXYNOS_DISPLAY_TYPE_LCD,
	.ops = &exynos_dp_display_ops,
};

static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev)
{
	struct device_node *dp_node = dev->of_node;
@@ -1210,44 +1196,6 @@ static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev)
	return dp_video_config;
}

static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
{
	struct device_node *dp_phy_node = of_node_get(dp->dev->of_node);
	u32 phy_base;
	int ret = 0;

	dp_phy_node = of_find_node_by_name(dp_phy_node, "dptx-phy");
	if (!dp_phy_node) {
		dp->phy = devm_phy_get(dp->dev, "dp");
		return PTR_ERR_OR_ZERO(dp->phy);
	}

	if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
		dev_err(dp->dev, "failed to get reg for dptx-phy\n");
		ret = -EINVAL;
		goto err;
	}

	if (of_property_read_u32(dp_phy_node, "samsung,enable-mask",
				&dp->enable_mask)) {
		dev_err(dp->dev, "failed to get enable-mask for dptx-phy\n");
		ret = -EINVAL;
		goto err;
	}

	dp->phy_addr = ioremap(phy_base, SZ_4);
	if (!dp->phy_addr) {
		dev_err(dp->dev, "failed to ioremap dp-phy\n");
		ret = -ENOMEM;
		goto err;
	}

err:
	of_node_put(dp_phy_node);

	return ret;
}

static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp)
{
	int ret;
@@ -1263,10 +1211,10 @@ static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp)

static int exynos_dp_bind(struct device *dev, struct device *master, void *data)
{
	struct exynos_dp_device *dp = dev_get_drvdata(dev);
	struct platform_device *pdev = to_platform_device(dev);
	struct drm_device *drm_dev = data;
	struct resource *res;
	struct exynos_dp_device *dp = exynos_dp_display.ctx;
	unsigned int irq_flags;
	int ret = 0;

@@ -1277,9 +1225,21 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data)
	if (IS_ERR(dp->video_info))
		return PTR_ERR(dp->video_info);

	ret = exynos_dp_dt_parse_phydata(dp);
	if (ret)
	dp->phy = devm_phy_get(dp->dev, "dp");
	if (IS_ERR(dp->phy)) {
		dev_err(dp->dev, "no DP phy configured\n");
		ret = PTR_ERR(dp->phy);
		if (ret) {
			/*
			 * phy itself is not enabled, so we can move forward
			 * assigning NULL to phy pointer.
			 */
			if (ret == -ENOSYS || ret == -ENODEV)
				dp->phy = NULL;
			else
				return ret;
		}
	}

	if (!dp->panel) {
		ret = exynos_dp_dt_parse_panel(dp);
@@ -1346,17 +1306,15 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data)

	dp->drm_dev = drm_dev;

	platform_set_drvdata(pdev, &exynos_dp_display);

	return exynos_drm_create_enc_conn(drm_dev, &exynos_dp_display);
	return exynos_drm_create_enc_conn(drm_dev, &dp->display);
}

static void exynos_dp_unbind(struct device *dev, struct device *master,
				void *data)
{
	struct exynos_drm_display *display = dev_get_drvdata(dev);
	struct exynos_dp_device *dp = dev_get_drvdata(dev);

	exynos_dp_dpms(display, DRM_MODE_DPMS_OFF);
	exynos_dp_dpms(&dp->display, DRM_MODE_DPMS_OFF);
}

static const struct component_ops exynos_dp_ops = {
@@ -1371,16 +1329,20 @@ static int exynos_dp_probe(struct platform_device *pdev)
	struct exynos_dp_device *dp;
	int ret;

	ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR,
					exynos_dp_display.type);
	if (ret)
		return ret;

	dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
				GFP_KERNEL);
	if (!dp)
		return -ENOMEM;

	dp->display.type = EXYNOS_DISPLAY_TYPE_LCD;
	dp->display.ops = &exynos_dp_display_ops;
	platform_set_drvdata(pdev, dp);

	ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR,
					dp->display.type);
	if (ret)
		return ret;

	panel_node = of_parse_phandle(dev->of_node, "panel", 0);
	if (panel_node) {
		dp->panel = of_drm_find_panel(panel_node);
@@ -1389,8 +1351,6 @@ static int exynos_dp_probe(struct platform_device *pdev)
			return -EPROBE_DEFER;
	}

	exynos_dp_display.ctx = dp;

	ret = component_add(&pdev->dev, &exynos_dp_ops);
	if (ret)
		exynos_drm_component_del(&pdev->dev,
@@ -1410,19 +1370,17 @@ static int exynos_dp_remove(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP
static int exynos_dp_suspend(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct exynos_drm_display *display = platform_get_drvdata(pdev);
	struct exynos_dp_device *dp = dev_get_drvdata(dev);

	exynos_dp_dpms(display, DRM_MODE_DPMS_OFF);
	exynos_dp_dpms(&dp->display, DRM_MODE_DPMS_OFF);
	return 0;
}

static int exynos_dp_resume(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct exynos_drm_display *display = platform_get_drvdata(pdev);
	struct exynos_dp_device *dp = dev_get_drvdata(dev);

	exynos_dp_dpms(display, DRM_MODE_DPMS_ON);
	exynos_dp_dpms(&dp->display, DRM_MODE_DPMS_ON);
	return 0;
}
#endif
+3 −2
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
#include <drm/drm_dp_helper.h>
#include <drm/exynos_drm.h>

#include "exynos_drm_drv.h"

#define DP_TIMEOUT_LOOP_COUNT 100
#define MAX_CR_LOOP 5
#define MAX_EQ_LOOP 5
@@ -145,6 +147,7 @@ struct link_train {
};

struct exynos_dp_device {
	struct exynos_drm_display display;
	struct device		*dev;
	struct drm_device	*drm_dev;
	struct drm_connector	connector;
@@ -153,8 +156,6 @@ struct exynos_dp_device {
	struct clk		*clock;
	unsigned int		irq;
	void __iomem		*reg_base;
	void __iomem		*phy_addr;
	unsigned int		enable_mask;

	struct video_info	*video_info;
	struct link_train	link_train;
+1 −4
Original line number Diff line number Diff line
@@ -15,10 +15,7 @@
#ifndef _EXYNOS_DRM_CRTC_H_
#define _EXYNOS_DRM_CRTC_H_

struct drm_device;
struct drm_crtc;
struct exynos_drm_manager;
struct exynos_drm_overlay;
#include "exynos_drm_drv.h"

int exynos_drm_crtc_create(struct exynos_drm_manager *manager);
int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe);
Loading