drm/exynos: do not start enabling DP at bind() phase

The DP device will be properly enabled at the enable() call just
after the bind call finishes.

Changelog v2:
- no change

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
This commit is contained in:
Gustavo Padovan 2015-11-02 20:00:03 +09:00 committed by Inki Dae
parent 663a233eef
commit 07c4270302
2 changed files with 78 additions and 30 deletions

View File

@ -1009,9 +1009,9 @@ static int exynos_drm_attach_lcd_bridge(struct exynos_dp_device *dp,
{
int ret;
encoder->bridge = dp->bridge;
dp->bridge->encoder = encoder;
ret = drm_bridge_attach(encoder->dev, dp->bridge);
encoder->bridge->next = dp->ptn_bridge;
dp->ptn_bridge->encoder = encoder;
ret = drm_bridge_attach(encoder->dev, dp->ptn_bridge);
if (ret) {
DRM_ERROR("Failed to attach bridge to drm\n");
return ret;
@ -1020,14 +1020,15 @@ static int exynos_drm_attach_lcd_bridge(struct exynos_dp_device *dp,
return 0;
}
static int exynos_dp_create_connector(struct drm_encoder *encoder)
static int exynos_dp_bridge_attach(struct drm_bridge *bridge)
{
struct exynos_dp_device *dp = encoder_to_dp(encoder);
struct exynos_dp_device *dp = bridge->driver_private;
struct drm_encoder *encoder = &dp->encoder;
struct drm_connector *connector = &dp->connector;
int ret;
/* Pre-empt DP connector creation if there's a bridge */
if (dp->bridge) {
if (dp->ptn_bridge) {
ret = exynos_drm_attach_lcd_bridge(dp, encoder);
if (!ret)
return 0;
@ -1052,22 +1053,9 @@ static int exynos_dp_create_connector(struct drm_encoder *encoder)
return ret;
}
static bool exynos_dp_mode_fixup(struct drm_encoder *encoder,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
static void exynos_dp_bridge_enable(struct drm_bridge *bridge)
{
return true;
}
static void exynos_dp_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
}
static void exynos_dp_enable(struct drm_encoder *encoder)
{
struct exynos_dp_device *dp = encoder_to_dp(encoder);
struct exynos_dp_device *dp = bridge->driver_private;
struct exynos_drm_crtc *crtc = dp_to_crtc(dp);
if (dp->dpms_mode == DRM_MODE_DPMS_ON)
@ -1092,9 +1080,9 @@ static void exynos_dp_enable(struct drm_encoder *encoder)
dp->dpms_mode = DRM_MODE_DPMS_ON;
}
static void exynos_dp_disable(struct drm_encoder *encoder)
static void exynos_dp_bridge_disable(struct drm_bridge *bridge)
{
struct exynos_dp_device *dp = encoder_to_dp(encoder);
struct exynos_dp_device *dp = bridge->driver_private;
struct exynos_drm_crtc *crtc = dp_to_crtc(dp);
if (dp->dpms_mode != DRM_MODE_DPMS_ON)
@ -1123,6 +1111,69 @@ static void exynos_dp_disable(struct drm_encoder *encoder)
dp->dpms_mode = DRM_MODE_DPMS_OFF;
}
static void exynos_dp_bridge_nop(struct drm_bridge *bridge)
{
/* do nothing */
}
static const struct drm_bridge_funcs exynos_dp_bridge_funcs = {
.enable = exynos_dp_bridge_enable,
.disable = exynos_dp_bridge_disable,
.pre_enable = exynos_dp_bridge_nop,
.post_disable = exynos_dp_bridge_nop,
.attach = exynos_dp_bridge_attach,
};
static int exynos_dp_create_connector(struct drm_encoder *encoder)
{
struct exynos_dp_device *dp = encoder_to_dp(encoder);
struct drm_device *drm_dev = dp->drm_dev;
struct drm_bridge *bridge;
int ret;
bridge = devm_kzalloc(drm_dev->dev, sizeof(*bridge), GFP_KERNEL);
if (!bridge) {
DRM_ERROR("failed to allocate for drm bridge\n");
return -ENOMEM;
}
dp->bridge = bridge;
encoder->bridge = bridge;
bridge->driver_private = dp;
bridge->encoder = encoder;
bridge->funcs = &exynos_dp_bridge_funcs;
ret = drm_bridge_attach(drm_dev, bridge);
if (ret) {
DRM_ERROR("failed to attach drm bridge\n");
return -EINVAL;
}
return 0;
}
static bool exynos_dp_mode_fixup(struct drm_encoder *encoder,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
return true;
}
static void exynos_dp_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
}
static void exynos_dp_enable(struct drm_encoder *encoder)
{
}
static void exynos_dp_disable(struct drm_encoder *encoder)
{
}
static struct drm_encoder_helper_funcs exynos_dp_encoder_helper_funcs = {
.mode_fixup = exynos_dp_mode_fixup,
.mode_set = exynos_dp_mode_set,
@ -1238,7 +1289,7 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data)
}
}
if (!dp->panel && !dp->bridge) {
if (!dp->panel && !dp->ptn_bridge) {
ret = exynos_dp_dt_parse_panel(dp);
if (ret)
return ret;
@ -1289,10 +1340,6 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data)
INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug);
phy_power_on(dp->phy);
exynos_dp_init_dp(dp);
ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler,
irq_flags, "exynos-dp", dp);
if (ret) {
@ -1365,9 +1412,9 @@ static int exynos_dp_probe(struct platform_device *pdev)
if (endpoint) {
bridge_node = of_graph_get_remote_port_parent(endpoint);
if (bridge_node) {
dp->bridge = of_drm_find_bridge(bridge_node);
dp->ptn_bridge = of_drm_find_bridge(bridge_node);
of_node_put(bridge_node);
if (!dp->bridge)
if (!dp->ptn_bridge)
return -EPROBE_DEFER;
} else
return -EPROBE_DEFER;

View File

@ -153,6 +153,7 @@ struct exynos_dp_device {
struct drm_connector connector;
struct drm_panel *panel;
struct drm_bridge *bridge;
struct drm_bridge *ptn_bridge;
struct clk *clock;
unsigned int irq;
void __iomem *reg_base;