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 Changes in v3: None Changes in v4: - Changed _ to - in dts documentation .../devicetree/bindings/video/exynos_dp.txt | 17 ++++ .../devicetree/bindings/video/samsung-fimd.txt | 2 + drivers/gpu/drm/exynos/exynos_dp_core.c | 100 +++++++++++++++++---- drivers/gpu/drm/exynos/exynos_dp_core.h | 4 + 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 | 79 +++------------- 7 files changed, 131 insertions(+), 86 deletions(-) diff --git a/Documentation/devicetree/bindings/video/exynos_dp.txt b/Documentation/devicetree/bindings/video/exynos_dp.txt index 3289d76..57ccdde 100644 --- a/Documentation/devicetree/bindings/video/exynos_dp.txt +++ b/Documentation/devicetree/bindings/video/exynos_dp.txt @@ -49,6 +49,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: @@ -84,4 +86,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..36b7895 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 b3af496..5c26161 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.c +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c @@ -19,7 +19,12 @@ #include <linux/delay.h> #include <linux/of.h> #include <linux/phy/phy.h> +#include <video/of_display_timing.h> +#include <video/of_videomode.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) @@ -892,6 +897,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, +}; + static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev) { struct device_node *dp_node = dev->of_node; @@ -993,6 +1027,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) { if (dp->phy) { @@ -1019,6 +1066,28 @@ static void exynos_dp_phy_exit(struct exynos_dp_device *dp) } } +void exynos_dp_poweron(struct exynos_dp_device *dp) +{ + exynos_dp_phy_init(dp); + + clk_prepare_enable(dp->clock); + + exynos_dp_init_dp(dp); + + enable_irq(dp->irq); +} + +void exynos_dp_poweroff(struct exynos_dp_device *dp) +{ + disable_irq(dp->irq); + + flush_work(&dp->hotplug_work); + + exynos_dp_phy_exit(dp); + + clk_disable_unprepare(dp->clock); +} + static int exynos_dp_probe(struct platform_device *pdev) { struct resource *res; @@ -1043,6 +1112,10 @@ static int exynos_dp_probe(struct platform_device *pdev) if (ret) return ret; + ret = exynos_dp_dt_parse_panel(dp); + if (ret) + return ret; + dp->clock = devm_clk_get(&pdev->dev, "dp"); if (IS_ERR(dp->clock)) { dev_err(&pdev->dev, "failed to get clock\n"); @@ -1078,6 +1151,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; } @@ -1085,6 +1161,8 @@ static int exynos_dp_remove(struct platform_device *pdev) { struct exynos_dp_device *dp = platform_get_drvdata(pdev); + exynos_drm_display_unregister(&exynos_dp_display); + flush_work(&dp->hotplug_work); exynos_dp_phy_exit(dp); @@ -1100,14 +1178,7 @@ static int exynos_dp_suspend(struct device *dev) { struct exynos_dp_device *dp = dev_get_drvdata(dev); - disable_irq(dp->irq); - - flush_work(&dp->hotplug_work); - - exynos_dp_phy_exit(dp); - - clk_disable_unprepare(dp->clock); - + exynos_dp_poweroff(dp); return 0; } @@ -1115,14 +1186,7 @@ static int exynos_dp_resume(struct device *dev) { struct exynos_dp_device *dp = dev_get_drvdata(dev); - exynos_dp_phy_init(dp); - - clk_prepare_enable(dp->clock); - - exynos_dp_init_dp(dp); - - enable_irq(dp->irq); - + exynos_dp_poweron(dp); return 0; } #endif @@ -1137,7 +1201,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 = { @@ -1148,8 +1212,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 607e36d..4f14141 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.h +++ b/drivers/gpu/drm/exynos/exynos_dp_core.h @@ -13,6 +13,8 @@ #ifndef _EXYNOS_DP_CORE_H #define _EXYNOS_DP_CORE_H +#include <drm/exynos_drm.h> + #define DP_TIMEOUT_LOOP_COUNT 100 #define MAX_CR_LOOP 5 #define MAX_EQ_LOOP 5 @@ -152,6 +154,8 @@ struct exynos_dp_device { struct link_train link_train; struct work_struct hotplug_work; struct phy *phy; + + 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 6143742..87ac369 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -353,6 +353,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) @@ -468,6 +474,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; } @@ -510,6 +520,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 81f7de4..09c158a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -370,6 +370,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 9419513..6eb0008 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -144,39 +144,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 int fimd_mgr_initialize(struct exynos_drm_manager *mgr, struct drm_device *drm_dev, int pipe) { @@ -253,7 +220,7 @@ static void fimd_commit(struct exynos_drm_manager *mgr) struct fimd_context *ctx = mgr->ctx; struct drm_display_mode *mode = &ctx->mode; struct fimd_driver_data *driver_data; - u32 val, clkdiv; + u32 val, clkdiv, vidcon1; int hblank, vblank, vsync_len, vbpd, vfpd, hsync_len, hbpd, hfpd; driver_data = ctx->driver_data; @@ -264,8 +231,13 @@ static void fimd_commit(struct exynos_drm_manager *mgr) if (mode->htotal == 0 || mode->vtotal == 0) return; - /* setup polarity values from machine code. */ - writel(ctx->vidcon1, ctx->regs + driver_data->timing_base + VIDCON1); + /* setup polarity values */ + vidcon1 = ctx->vidcon1; + if (mode->flags & DRM_MODE_FLAG_NVSYNC) + vidcon1 |= VIDCON1_INV_VSYNC; + if (mode->flags & DRM_MODE_FLAG_NHSYNC) + vidcon1 |= VIDCON1_INV_HSYNC; + writel(vidcon1, ctx->regs + driver_data->timing_base + VIDCON1); /* setup vertical timing values. */ vblank = mode->crtc_vblank_end - mode->crtc_vblank_start; @@ -871,30 +843,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; @@ -912,9 +860,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)) { @@ -956,9 +905,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); @@ -974,7 +920,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.5.1 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel