diff options
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_hdmi.c')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_hdmi.c | 121 |
1 files changed, 38 insertions, 83 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 41ff79d8ac8e..fbab3c468603 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/regulator/consumer.h> | 34 | #include <linux/regulator/consumer.h> |
35 | #include <linux/io.h> | 35 | #include <linux/io.h> |
36 | #include <linux/of_gpio.h> | 36 | #include <linux/of_gpio.h> |
37 | #include <plat/gpio-cfg.h> | ||
38 | 37 | ||
39 | #include <drm/exynos_drm.h> | 38 | #include <drm/exynos_drm.h> |
40 | 39 | ||
@@ -98,8 +97,7 @@ struct hdmi_context { | |||
98 | 97 | ||
99 | void __iomem *regs; | 98 | void __iomem *regs; |
100 | void *parent_ctx; | 99 | void *parent_ctx; |
101 | int external_irq; | 100 | int irq; |
102 | int internal_irq; | ||
103 | 101 | ||
104 | struct i2c_client *ddc_port; | 102 | struct i2c_client *ddc_port; |
105 | struct i2c_client *hdmiphy_port; | 103 | struct i2c_client *hdmiphy_port; |
@@ -1391,8 +1389,7 @@ static bool hdmi_is_connected(void *ctx) | |||
1391 | return hdata->hpd; | 1389 | return hdata->hpd; |
1392 | } | 1390 | } |
1393 | 1391 | ||
1394 | static int hdmi_get_edid(void *ctx, struct drm_connector *connector, | 1392 | static struct edid *hdmi_get_edid(void *ctx, struct drm_connector *connector) |
1395 | u8 *edid, int len) | ||
1396 | { | 1393 | { |
1397 | struct edid *raw_edid; | 1394 | struct edid *raw_edid; |
1398 | struct hdmi_context *hdata = ctx; | 1395 | struct hdmi_context *hdata = ctx; |
@@ -1400,22 +1397,18 @@ static int hdmi_get_edid(void *ctx, struct drm_connector *connector, | |||
1400 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); | 1397 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); |
1401 | 1398 | ||
1402 | if (!hdata->ddc_port) | 1399 | if (!hdata->ddc_port) |
1403 | return -ENODEV; | 1400 | return ERR_PTR(-ENODEV); |
1404 | 1401 | ||
1405 | raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter); | 1402 | raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter); |
1406 | if (raw_edid) { | 1403 | if (!raw_edid) |
1407 | hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid); | 1404 | return ERR_PTR(-ENODEV); |
1408 | memcpy(edid, raw_edid, min((1 + raw_edid->extensions) | ||
1409 | * EDID_LENGTH, len)); | ||
1410 | DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n", | ||
1411 | (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"), | ||
1412 | raw_edid->width_cm, raw_edid->height_cm); | ||
1413 | kfree(raw_edid); | ||
1414 | } else { | ||
1415 | return -ENODEV; | ||
1416 | } | ||
1417 | 1405 | ||
1418 | return 0; | 1406 | hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid); |
1407 | DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n", | ||
1408 | (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"), | ||
1409 | raw_edid->width_cm, raw_edid->height_cm); | ||
1410 | |||
1411 | return raw_edid; | ||
1419 | } | 1412 | } |
1420 | 1413 | ||
1421 | static int hdmi_v13_check_timing(struct fb_videomode *check_timing) | 1414 | static int hdmi_v13_check_timing(struct fb_videomode *check_timing) |
@@ -1652,16 +1645,16 @@ static void hdmi_conf_reset(struct hdmi_context *hdata) | |||
1652 | 1645 | ||
1653 | /* resetting HDMI core */ | 1646 | /* resetting HDMI core */ |
1654 | hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT); | 1647 | hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT); |
1655 | mdelay(10); | 1648 | usleep_range(10000, 12000); |
1656 | hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT); | 1649 | hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT); |
1657 | mdelay(10); | 1650 | usleep_range(10000, 12000); |
1658 | } | 1651 | } |
1659 | 1652 | ||
1660 | static void hdmi_conf_init(struct hdmi_context *hdata) | 1653 | static void hdmi_conf_init(struct hdmi_context *hdata) |
1661 | { | 1654 | { |
1662 | struct hdmi_infoframe infoframe; | 1655 | struct hdmi_infoframe infoframe; |
1663 | 1656 | ||
1664 | /* disable HPD interrupts */ | 1657 | /* disable HPD interrupts from HDMI IP block, use GPIO instead */ |
1665 | hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL | | 1658 | hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL | |
1666 | HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG); | 1659 | HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG); |
1667 | 1660 | ||
@@ -1779,7 +1772,7 @@ static void hdmi_v13_timing_apply(struct hdmi_context *hdata) | |||
1779 | u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS); | 1772 | u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS); |
1780 | if (val & HDMI_PHY_STATUS_READY) | 1773 | if (val & HDMI_PHY_STATUS_READY) |
1781 | break; | 1774 | break; |
1782 | mdelay(1); | 1775 | usleep_range(1000, 2000); |
1783 | } | 1776 | } |
1784 | /* steady state not achieved */ | 1777 | /* steady state not achieved */ |
1785 | if (tries == 0) { | 1778 | if (tries == 0) { |
@@ -1946,7 +1939,7 @@ static void hdmi_v14_timing_apply(struct hdmi_context *hdata) | |||
1946 | u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0); | 1939 | u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0); |
1947 | if (val & HDMI_PHY_STATUS_READY) | 1940 | if (val & HDMI_PHY_STATUS_READY) |
1948 | break; | 1941 | break; |
1949 | mdelay(1); | 1942 | usleep_range(1000, 2000); |
1950 | } | 1943 | } |
1951 | /* steady state not achieved */ | 1944 | /* steady state not achieved */ |
1952 | if (tries == 0) { | 1945 | if (tries == 0) { |
@@ -1998,9 +1991,9 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata) | |||
1998 | 1991 | ||
1999 | /* reset hdmiphy */ | 1992 | /* reset hdmiphy */ |
2000 | hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT); | 1993 | hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT); |
2001 | mdelay(10); | 1994 | usleep_range(10000, 12000); |
2002 | hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT); | 1995 | hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT); |
2003 | mdelay(10); | 1996 | usleep_range(10000, 12000); |
2004 | } | 1997 | } |
2005 | 1998 | ||
2006 | static void hdmiphy_poweron(struct hdmi_context *hdata) | 1999 | static void hdmiphy_poweron(struct hdmi_context *hdata) |
@@ -2048,7 +2041,7 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata) | |||
2048 | return; | 2041 | return; |
2049 | } | 2042 | } |
2050 | 2043 | ||
2051 | mdelay(10); | 2044 | usleep_range(10000, 12000); |
2052 | 2045 | ||
2053 | /* operation mode */ | 2046 | /* operation mode */ |
2054 | operation[0] = 0x1f; | 2047 | operation[0] = 0x1f; |
@@ -2170,6 +2163,13 @@ static void hdmi_commit(void *ctx) | |||
2170 | 2163 | ||
2171 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); | 2164 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); |
2172 | 2165 | ||
2166 | mutex_lock(&hdata->hdmi_mutex); | ||
2167 | if (!hdata->powered) { | ||
2168 | mutex_unlock(&hdata->hdmi_mutex); | ||
2169 | return; | ||
2170 | } | ||
2171 | mutex_unlock(&hdata->hdmi_mutex); | ||
2172 | |||
2173 | hdmi_conf_apply(hdata); | 2173 | hdmi_conf_apply(hdata); |
2174 | } | 2174 | } |
2175 | 2175 | ||
@@ -2265,7 +2265,7 @@ static struct exynos_hdmi_ops hdmi_ops = { | |||
2265 | .dpms = hdmi_dpms, | 2265 | .dpms = hdmi_dpms, |
2266 | }; | 2266 | }; |
2267 | 2267 | ||
2268 | static irqreturn_t hdmi_external_irq_thread(int irq, void *arg) | 2268 | static irqreturn_t hdmi_irq_thread(int irq, void *arg) |
2269 | { | 2269 | { |
2270 | struct exynos_drm_hdmi_context *ctx = arg; | 2270 | struct exynos_drm_hdmi_context *ctx = arg; |
2271 | struct hdmi_context *hdata = ctx->ctx; | 2271 | struct hdmi_context *hdata = ctx->ctx; |
@@ -2280,31 +2280,6 @@ static irqreturn_t hdmi_external_irq_thread(int irq, void *arg) | |||
2280 | return IRQ_HANDLED; | 2280 | return IRQ_HANDLED; |
2281 | } | 2281 | } |
2282 | 2282 | ||
2283 | static irqreturn_t hdmi_internal_irq_thread(int irq, void *arg) | ||
2284 | { | ||
2285 | struct exynos_drm_hdmi_context *ctx = arg; | ||
2286 | struct hdmi_context *hdata = ctx->ctx; | ||
2287 | u32 intc_flag; | ||
2288 | |||
2289 | intc_flag = hdmi_reg_read(hdata, HDMI_INTC_FLAG); | ||
2290 | /* clearing flags for HPD plug/unplug */ | ||
2291 | if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) { | ||
2292 | DRM_DEBUG_KMS("unplugged\n"); | ||
2293 | hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0, | ||
2294 | HDMI_INTC_FLAG_HPD_UNPLUG); | ||
2295 | } | ||
2296 | if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) { | ||
2297 | DRM_DEBUG_KMS("plugged\n"); | ||
2298 | hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0, | ||
2299 | HDMI_INTC_FLAG_HPD_PLUG); | ||
2300 | } | ||
2301 | |||
2302 | if (ctx->drm_dev) | ||
2303 | drm_helper_hpd_irq_event(ctx->drm_dev); | ||
2304 | |||
2305 | return IRQ_HANDLED; | ||
2306 | } | ||
2307 | |||
2308 | static int hdmi_resources_init(struct hdmi_context *hdata) | 2283 | static int hdmi_resources_init(struct hdmi_context *hdata) |
2309 | { | 2284 | { |
2310 | struct device *dev = hdata->dev; | 2285 | struct device *dev = hdata->dev; |
@@ -2555,39 +2530,24 @@ static int hdmi_probe(struct platform_device *pdev) | |||
2555 | 2530 | ||
2556 | hdata->hdmiphy_port = hdmi_hdmiphy; | 2531 | hdata->hdmiphy_port = hdmi_hdmiphy; |
2557 | 2532 | ||
2558 | hdata->external_irq = gpio_to_irq(hdata->hpd_gpio); | 2533 | hdata->irq = gpio_to_irq(hdata->hpd_gpio); |
2559 | if (hdata->external_irq < 0) { | 2534 | if (hdata->irq < 0) { |
2560 | DRM_ERROR("failed to get GPIO external irq\n"); | 2535 | DRM_ERROR("failed to get GPIO irq\n"); |
2561 | ret = hdata->external_irq; | 2536 | ret = hdata->irq; |
2562 | goto err_hdmiphy; | ||
2563 | } | ||
2564 | |||
2565 | hdata->internal_irq = platform_get_irq(pdev, 0); | ||
2566 | if (hdata->internal_irq < 0) { | ||
2567 | DRM_ERROR("failed to get platform internal irq\n"); | ||
2568 | ret = hdata->internal_irq; | ||
2569 | goto err_hdmiphy; | 2537 | goto err_hdmiphy; |
2570 | } | 2538 | } |
2571 | 2539 | ||
2572 | hdata->hpd = gpio_get_value(hdata->hpd_gpio); | 2540 | hdata->hpd = gpio_get_value(hdata->hpd_gpio); |
2573 | 2541 | ||
2574 | ret = request_threaded_irq(hdata->external_irq, NULL, | 2542 | ret = request_threaded_irq(hdata->irq, NULL, |
2575 | hdmi_external_irq_thread, IRQF_TRIGGER_RISING | | 2543 | hdmi_irq_thread, IRQF_TRIGGER_RISING | |
2576 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | 2544 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, |
2577 | "hdmi_external", drm_hdmi_ctx); | 2545 | "hdmi", drm_hdmi_ctx); |
2578 | if (ret) { | 2546 | if (ret) { |
2579 | DRM_ERROR("failed to register hdmi external interrupt\n"); | 2547 | DRM_ERROR("failed to register hdmi interrupt\n"); |
2580 | goto err_hdmiphy; | 2548 | goto err_hdmiphy; |
2581 | } | 2549 | } |
2582 | 2550 | ||
2583 | ret = request_threaded_irq(hdata->internal_irq, NULL, | ||
2584 | hdmi_internal_irq_thread, IRQF_ONESHOT, | ||
2585 | "hdmi_internal", drm_hdmi_ctx); | ||
2586 | if (ret) { | ||
2587 | DRM_ERROR("failed to register hdmi internal interrupt\n"); | ||
2588 | goto err_free_irq; | ||
2589 | } | ||
2590 | |||
2591 | /* Attach HDMI Driver to common hdmi. */ | 2551 | /* Attach HDMI Driver to common hdmi. */ |
2592 | exynos_hdmi_drv_attach(drm_hdmi_ctx); | 2552 | exynos_hdmi_drv_attach(drm_hdmi_ctx); |
2593 | 2553 | ||
@@ -2598,8 +2558,6 @@ static int hdmi_probe(struct platform_device *pdev) | |||
2598 | 2558 | ||
2599 | return 0; | 2559 | return 0; |
2600 | 2560 | ||
2601 | err_free_irq: | ||
2602 | free_irq(hdata->external_irq, drm_hdmi_ctx); | ||
2603 | err_hdmiphy: | 2561 | err_hdmiphy: |
2604 | i2c_del_driver(&hdmiphy_driver); | 2562 | i2c_del_driver(&hdmiphy_driver); |
2605 | err_ddc: | 2563 | err_ddc: |
@@ -2617,8 +2575,7 @@ static int hdmi_remove(struct platform_device *pdev) | |||
2617 | 2575 | ||
2618 | pm_runtime_disable(dev); | 2576 | pm_runtime_disable(dev); |
2619 | 2577 | ||
2620 | free_irq(hdata->internal_irq, hdata); | 2578 | free_irq(hdata->irq, hdata); |
2621 | free_irq(hdata->external_irq, hdata); | ||
2622 | 2579 | ||
2623 | 2580 | ||
2624 | /* hdmiphy i2c driver */ | 2581 | /* hdmiphy i2c driver */ |
@@ -2637,8 +2594,7 @@ static int hdmi_suspend(struct device *dev) | |||
2637 | 2594 | ||
2638 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); | 2595 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); |
2639 | 2596 | ||
2640 | disable_irq(hdata->internal_irq); | 2597 | disable_irq(hdata->irq); |
2641 | disable_irq(hdata->external_irq); | ||
2642 | 2598 | ||
2643 | hdata->hpd = false; | 2599 | hdata->hpd = false; |
2644 | if (ctx->drm_dev) | 2600 | if (ctx->drm_dev) |
@@ -2663,8 +2619,7 @@ static int hdmi_resume(struct device *dev) | |||
2663 | 2619 | ||
2664 | hdata->hpd = gpio_get_value(hdata->hpd_gpio); | 2620 | hdata->hpd = gpio_get_value(hdata->hpd_gpio); |
2665 | 2621 | ||
2666 | enable_irq(hdata->external_irq); | 2622 | enable_irq(hdata->irq); |
2667 | enable_irq(hdata->internal_irq); | ||
2668 | 2623 | ||
2669 | if (!pm_runtime_suspended(dev)) { | 2624 | if (!pm_runtime_suspended(dev)) { |
2670 | DRM_DEBUG_KMS("%s : Already resumed\n", __func__); | 2625 | DRM_DEBUG_KMS("%s : Already resumed\n", __func__); |