Skip to content

Commit

Permalink
Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…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
  ...
  • Loading branch information
Dave Airlie committed Nov 25, 2014
2 parents 955289c + 5baf5d4 commit 0364d4f
Show file tree
Hide file tree
Showing 17 changed files with 609 additions and 666 deletions.
1 change: 1 addition & 0 deletions Documentation/devicetree/bindings/video/exynos_dsim.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions Documentation/devicetree/bindings/video/samsung-fimd.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
132 changes: 45 additions & 87 deletions drivers/gpu/drm/exynos/exynos_dp_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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:
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -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)
return 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);
Expand Down Expand Up @@ -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 = {
Expand All @@ -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);
Expand All @@ -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,
Expand All @@ -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
Expand Down
5 changes: 3 additions & 2 deletions drivers/gpu/drm/exynos/exynos_dp_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
5 changes: 1 addition & 4 deletions drivers/gpu/drm/exynos/exynos_drm_crtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 0364d4f

Please sign in to comment.