This patch moves the exynos_drm_display implementation from fimd into the dp driver. This will allow for tighter integration of the dp driver into the exynos drm driver. Signed-off-by: Sean Paul <seanpaul@xxxxxxxxxxxx> --- Changes in v2: None .../devicetree/bindings/video/exynos_dp.txt | 17 +++ .../devicetree/bindings/video/samsung-fimd.txt | 2 + drivers/gpu/drm/exynos/exynos_dp_core.c | 137 ++++++++++++++++----- drivers/gpu/drm/exynos/exynos_dp_core.h | 5 + drivers/gpu/drm/exynos/exynos_drm_drv.c | 14 +++ drivers/gpu/drm/exynos/exynos_drm_drv.h | 1 + drivers/gpu/drm/exynos/exynos_drm_fimd.c | 78 +++--------- 7 files changed, 156 insertions(+), 98 deletions(-) diff --git a/Documentation/devicetree/bindings/video/exynos_dp.txt b/Documentation/devicetree/bindings/video/exynos_dp.txt index 84f10c1..a073e15 100644 --- a/Documentation/devicetree/bindings/video/exynos_dp.txt +++ b/Documentation/devicetree/bindings/video/exynos_dp.txt @@ -45,6 +45,8 @@ Required properties for dp-controller: -samsung,lane-count: number of lanes supported by the panel. LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4 + - display-timings: timings for the connected panel as described by + Documentation/devicetree/bindings/video/display-timing.txt Optional properties for dp-controller: -interlaced: @@ -83,4 +85,19 @@ Board Specific portion: samsung,color-depth = <1>; samsung,link-rate = <0x0a>; samsung,lane-count = <4>; + + display-timings { + native-mode = <&lcd_timing>; + lcd_timing: 1366x768 { + clock-frequency = <70589280>; + hactive = <1366>; + vactive = <768>; + hfront-porch = <40>; + hback-porch = <40>; + hsync-len = <32>; + vback-porch = <10>; + vfront-porch = <12>; + vsync-len = <6>; + }; + }; }; diff --git a/Documentation/devicetree/bindings/video/samsung-fimd.txt b/Documentation/devicetree/bindings/video/samsung-fimd.txt index 778838a..fa465c3 100644 --- a/Documentation/devicetree/bindings/video/samsung-fimd.txt +++ b/Documentation/devicetree/bindings/video/samsung-fimd.txt @@ -39,6 +39,8 @@ Required properties: Optional Properties: - samsung,power-domain: a phandle to FIMD power domain node. +- samsung,invert-vden: video enable signal is inverted +- samsung,invert_vclk: video clock signal is inverted Example: diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c index 089ae22..13ea8b7 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.c +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c @@ -18,9 +18,12 @@ #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/of.h> +#include <video/of_display_timing.h> +#include <video/of_videomode.h> -#include <video/exynos_dp.h> +#include <drm/drmP.h> +#include "exynos_drm_drv.h" #include "exynos_dp_core.h" static int exynos_dp_init_dp(struct exynos_dp_device *dp) @@ -893,6 +896,35 @@ static void exynos_dp_hotplug(struct work_struct *work) dev_err(dp->dev, "unable to config video\n"); } +static bool exynos_dp_display_is_connected(struct exynos_drm_display *display) +{ + return true; +} + +static void *exynos_dp_get_panel(struct exynos_drm_display *display) +{ + struct exynos_dp_device *dp = display->ctx; + + return &dp->panel; +} + +static int exynos_dp_check_mode(struct exynos_drm_display *display, + struct drm_display_mode *mode) +{ + return 0; +} + +static struct exynos_drm_display_ops exynos_dp_display_ops = { + .is_connected = exynos_dp_display_is_connected, + .get_panel = exynos_dp_get_panel, + .check_mode = exynos_dp_check_mode, +}; + +static struct exynos_drm_display exynos_dp_display = { + .type = EXYNOS_DISPLAY_TYPE_LCD, + .ops = &exynos_dp_display_ops, +}; + #ifdef CONFIG_OF static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev) { @@ -1000,6 +1032,19 @@ err: return ret; } +static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp) +{ + int ret; + + ret = of_get_videomode(dp->dev->of_node, &dp->panel.vm, + OF_USE_NATIVE_MODE); + if (ret) { + DRM_ERROR("failed: of_get_videomode() : %d\n", ret); + return ret; + } + return 0; +} + static void exynos_dp_phy_init(struct exynos_dp_device *dp) { u32 reg; @@ -1028,6 +1073,11 @@ static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp) return -EINVAL; } +static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp) +{ + return -EINVAL; +} + static void exynos_dp_phy_init(struct exynos_dp_device *dp) { return; @@ -1039,6 +1089,46 @@ static void exynos_dp_phy_exit(struct exynos_dp_device *dp) } #endif /* CONFIG_OF */ +void exynos_dp_poweron(struct exynos_dp_device *dp) +{ + struct device *dev = dp->dev; + struct exynos_dp_platdata *pdata = dev->platform_data; + + if (dev->of_node) { + if (dp->phy_addr) + exynos_dp_phy_init(dp); + } else { + if (pdata->phy_init) + pdata->phy_init(); + } + + clk_prepare_enable(dp->clock); + + exynos_dp_init_dp(dp); + + enable_irq(dp->irq); +} + +void exynos_dp_poweroff(struct exynos_dp_device *dp) +{ + struct device *dev = dp->dev; + struct exynos_dp_platdata *pdata = dev->platform_data; + + disable_irq(dp->irq); + + flush_work(&dp->hotplug_work); + + if (dev->of_node) { + if (dp->phy_addr) + exynos_dp_phy_exit(dp); + } else { + if (pdata->phy_exit) + pdata->phy_exit(); + } + + clk_disable_unprepare(dp->clock); +} + static int exynos_dp_probe(struct platform_device *pdev) { struct resource *res; @@ -1064,6 +1154,10 @@ static int exynos_dp_probe(struct platform_device *pdev) ret = exynos_dp_dt_parse_phydata(dp); if (ret) return ret; + + ret = exynos_dp_dt_parse_panel(dp); + if (ret) + return ret; } else { pdata = pdev->dev.platform_data; if (!pdata) { @@ -1115,6 +1209,9 @@ static int exynos_dp_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dp); + exynos_dp_display.ctx = dp; + exynos_drm_display_register(&exynos_dp_display); + return 0; } @@ -1123,6 +1220,8 @@ static int exynos_dp_remove(struct platform_device *pdev) struct exynos_dp_platdata *pdata = pdev->dev.platform_data; struct exynos_dp_device *dp = platform_get_drvdata(pdev); + exynos_drm_display_unregister(&exynos_dp_display); + flush_work(&dp->hotplug_work); if (pdev->dev.of_node) { @@ -1142,45 +1241,17 @@ static int exynos_dp_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int exynos_dp_suspend(struct device *dev) { - struct exynos_dp_platdata *pdata = dev->platform_data; struct exynos_dp_device *dp = dev_get_drvdata(dev); - disable_irq(dp->irq); - - flush_work(&dp->hotplug_work); - - if (dev->of_node) { - if (dp->phy_addr) - exynos_dp_phy_exit(dp); - } else { - if (pdata->phy_exit) - pdata->phy_exit(); - } - - clk_disable_unprepare(dp->clock); - + exynos_dp_poweroff(dp); return 0; } static int exynos_dp_resume(struct device *dev) { - struct exynos_dp_platdata *pdata = dev->platform_data; struct exynos_dp_device *dp = dev_get_drvdata(dev); - if (dev->of_node) { - if (dp->phy_addr) - exynos_dp_phy_init(dp); - } else { - if (pdata->phy_init) - pdata->phy_init(); - } - - clk_prepare_enable(dp->clock); - - exynos_dp_init_dp(dp); - - enable_irq(dp->irq); - + exynos_dp_poweron(dp); return 0; } #endif @@ -1195,7 +1266,7 @@ static const struct of_device_id exynos_dp_match[] = { }; MODULE_DEVICE_TABLE(of, exynos_dp_match); -static struct platform_driver exynos_dp_driver = { +struct platform_driver dp_driver = { .probe = exynos_dp_probe, .remove = exynos_dp_remove, .driver = { @@ -1206,8 +1277,6 @@ static struct platform_driver exynos_dp_driver = { }, }; -module_platform_driver(exynos_dp_driver); - MODULE_AUTHOR("Jingoo Han <jg1.han@xxxxxxxxxxx>"); MODULE_DESCRIPTION("Samsung SoC DP Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.h b/drivers/gpu/drm/exynos/exynos_dp_core.h index 6c567bbf..a5e9145 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.h +++ b/drivers/gpu/drm/exynos/exynos_dp_core.h @@ -13,6 +13,9 @@ #ifndef _EXYNOS_DP_CORE_H #define _EXYNOS_DP_CORE_H +#include <drm/exynos_drm.h> +#include <video/exynos_dp.h> + enum dp_irq_type { DP_IRQ_TYPE_HP_CABLE_IN, DP_IRQ_TYPE_HP_CABLE_OUT, @@ -42,6 +45,8 @@ struct exynos_dp_device { struct video_info *video_info; struct link_train link_train; struct work_struct hotplug_work; + + struct exynos_drm_panel_info panel; }; /* exynos_dp_reg.c */ diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 4b265bf..03caa3a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -316,6 +316,12 @@ static int __init exynos_drm_init(void) { int ret; +#ifdef CONFIG_DRM_EXYNOS_DP + ret = platform_driver_register(&dp_driver); + if (ret < 0) + goto out_dp; +#endif + #ifdef CONFIG_DRM_EXYNOS_FIMD ret = platform_driver_register(&fimd_driver); if (ret < 0) @@ -431,6 +437,10 @@ out_hdmi: platform_driver_unregister(&fimd_driver); out_fimd: #endif +#ifdef CONFIG_DRM_EXYNOS_DP + platform_driver_unregister(&dp_driver); +out_dp: +#endif return ret; } @@ -473,6 +483,10 @@ static void __exit exynos_drm_exit(void) #ifdef CONFIG_DRM_EXYNOS_FIMD platform_driver_unregister(&fimd_driver); #endif + +#ifdef CONFIG_DRM_EXYNOS_DP + platform_driver_unregister(&dp_driver); +#endif } module_init(exynos_drm_init); diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 97bdfcc..f3e18d1 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -369,6 +369,7 @@ int exynos_platform_device_ipp_register(void); */ void exynos_platform_device_ipp_unregister(void); +extern struct platform_driver dp_driver; extern struct platform_driver fimd_driver; extern struct platform_driver hdmi_driver; extern struct platform_driver mixer_driver; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 61124ca..c6a05f6 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -158,39 +158,6 @@ static inline struct fimd_driver_data *drm_fimd_get_driver_data( return (struct fimd_driver_data *)of_id->data; } -static bool fimd_display_is_connected(struct exynos_drm_display *display) -{ - /* TODO. */ - - return true; -} - -static void *fimd_get_panel(struct exynos_drm_display *display) -{ - struct fimd_context *ctx = display->ctx; - - return &ctx->panel; -} - -static int fimd_check_mode(struct exynos_drm_display *display, - struct drm_display_mode *mode) -{ - /* TODO. */ - - return 0; -} - -static struct exynos_drm_display_ops fimd_display_ops = { - .is_connected = fimd_display_is_connected, - .get_panel = fimd_get_panel, - .check_mode = fimd_check_mode, -}; - -static struct exynos_drm_display fimd_display = { - .type = EXYNOS_DISPLAY_TYPE_LCD, - .ops = &fimd_display_ops, -}; - static void fimd_win_mode_set(struct exynos_drm_manager *mgr, struct exynos_drm_overlay *overlay) { @@ -611,6 +578,16 @@ static void fimd_mode_set(struct exynos_drm_manager *mgr, mode->hfpd = hblank - mode->hsync_len - mode->hbpd; mode->clkdiv = fimd_calc_clkdiv(ctx, in_mode); + + if (in_mode->flags & DRM_MODE_FLAG_NVSYNC) + ctx->vidcon1 |= VIDCON1_INV_VSYNC; + else + ctx->vidcon1 &= ~VIDCON1_INV_VSYNC; + + if (in_mode->flags & DRM_MODE_FLAG_NHSYNC) + ctx->vidcon1 |= VIDCON1_INV_HSYNC; + else + ctx->vidcon1 &= ~VIDCON1_INV_HSYNC; } static void fimd_commit(struct exynos_drm_manager *mgr) @@ -888,30 +865,6 @@ static int fimd_activate(struct exynos_drm_manager *mgr, bool enable) return 0; } -static int fimd_get_platform_data(struct fimd_context *ctx, struct device *dev) -{ - struct videomode *vm; - int ret; - - vm = &ctx->panel.vm; - ret = of_get_videomode(dev->of_node, vm, OF_USE_NATIVE_MODE); - if (ret) { - DRM_ERROR("failed: of_get_videomode() : %d\n", ret); - return ret; - } - - if (vm->flags & DISPLAY_FLAGS_VSYNC_LOW) - ctx->vidcon1 |= VIDCON1_INV_VSYNC; - if (vm->flags & DISPLAY_FLAGS_HSYNC_LOW) - ctx->vidcon1 |= VIDCON1_INV_HSYNC; - if (vm->flags & DISPLAY_FLAGS_DE_LOW) - ctx->vidcon1 |= VIDCON1_INV_VDEN; - if (vm->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE) - ctx->vidcon1 |= VIDCON1_INV_VCLK; - - return 0; -} - static int fimd_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -929,9 +882,10 @@ static int fimd_probe(struct platform_device *pdev) ctx->dev = dev; - ret = fimd_get_platform_data(ctx, dev); - if (ret) - return ret; + if (of_property_read_bool(dev->of_node, "samsung,invert-vden")) + ctx->vidcon1 |= VIDCON1_INV_VDEN; + if (of_property_read_bool(dev->of_node, "samsung,invert-vclk")) + ctx->vidcon1 |= VIDCON1_INV_VCLK; ctx->bus_clk = devm_clk_get(dev, "fimd"); if (IS_ERR(ctx->bus_clk)) { @@ -973,9 +927,6 @@ static int fimd_probe(struct platform_device *pdev) fimd_manager.ctx = ctx; exynos_drm_manager_register(&fimd_manager); - fimd_display.ctx = ctx; - exynos_drm_display_register(&fimd_display); - pm_runtime_enable(dev); pm_runtime_get_sync(dev); @@ -991,7 +942,6 @@ static int fimd_remove(struct platform_device *pdev) struct exynos_drm_manager *mgr = platform_get_drvdata(pdev); struct fimd_context *ctx = mgr->ctx; - exynos_drm_display_unregister(&fimd_display); exynos_drm_manager_unregister(&fimd_manager); if (ctx->suspended) -- 1.8.4 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel