This patch set adds device tree support for DRM-FIMD for Samsung's Exynos5250. It includes parsing platform data from dts file. Also, adds the driver data for exynos4 and exynos5 devices.
This patchset is based and tested on top of v3.6-rc4 on smdk5250 board Also depends on below patchset http://lists.freedesktop.org/archives/dri-devel/2012-August/026076.html
Changes since V4: - Changed the compatible string from "samsung,exynos4-fb" to "samsung,exynos4-fimd".
Changes since V3: - Removed the fimd version from driver data and using timing base address instead - Removed the drm_ prefixes to the structures and fucntions
Changes since V2: - Added driver data to exynos5-drm-fimd as per Marek Szyprowski suggestion
Changes since V1: - Corrected typo errors and changed compatibility string
Leela Krishna Amudala (2): drm/exynos: add platform_device_id table and driver data for drm fimd video: drm: exynos: Add device tree support
Documentation/devicetree/bindings/fb/drm-fimd.txt | 80 ++++++++++++ drivers/gpu/drm/exynos/exynos_drm_fimd.c | 138 ++++++++++++++++++++- 2 files changed, 212 insertions(+), 6 deletions(-) create mode 100644 Documentation/devicetree/bindings/fb/drm-fimd.txt
Applied.
Thanks. Inki Dae
2012/9/7 Leela Krishna Amudala l.krishna@samsung.com:
This patch set adds device tree support for DRM-FIMD for Samsung's Exynos5250. It includes parsing platform data from dts file. Also, adds the driver data for exynos4 and exynos5 devices.
This patchset is based and tested on top of v3.6-rc4 on smdk5250 board Also depends on below patchset http://lists.freedesktop.org/archives/dri-devel/2012-August/026076.html
Changes since V4: - Changed the compatible string from "samsung,exynos4-fb" to "samsung,exynos4-fimd".
Changes since V3: - Removed the fimd version from driver data and using timing base address instead - Removed the drm_ prefixes to the structures and fucntions
Changes since V2: - Added driver data to exynos5-drm-fimd as per Marek Szyprowski suggestion
Changes since V1: - Corrected typo errors and changed compatibility string
Leela Krishna Amudala (2): drm/exynos: add platform_device_id table and driver data for drm fimd video: drm: exynos: Add device tree support
Documentation/devicetree/bindings/fb/drm-fimd.txt | 80 ++++++++++++ drivers/gpu/drm/exynos/exynos_drm_fimd.c | 138 ++++++++++++++++++++- 2 files changed, 212 insertions(+), 6 deletions(-) create mode 100644 Documentation/devicetree/bindings/fb/drm-fimd.txt
linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Two device ids are created for exynos4-fb and exynos5-fb. Also, added driver data for exynos4 and exynos5 to pick the timing base address at runtime to write data into appropriate register address.
Signed-off-by: Leela Krishna Amudala l.krishna@samsung.com --- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 43 +++++++++++++++++++++++++++--- 1 files changed, 39 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 24c0bd4..65e927b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -57,6 +57,18 @@
#define get_fimd_context(dev) platform_get_drvdata(to_platform_device(dev))
+struct fimd_driver_data { + unsigned int timing_base; +}; + +struct fimd_driver_data exynos4_fimd_driver_data = { + .timing_base = 0x0, +}; + +struct fimd_driver_data exynos5_fimd_driver_data = { + .timing_base = 0x20000, +}; + struct fimd_win_data { unsigned int offset_x; unsigned int offset_y; @@ -91,6 +103,13 @@ struct fimd_context { struct exynos_drm_panel_info *panel; };
+static inline struct fimd_driver_data *drm_fimd_get_driver_data( + struct platform_device *pdev) +{ + return (struct fimd_driver_data *) + platform_get_device_id(pdev)->driver_data; +} + static bool fimd_display_is_connected(struct device *dev) { DRM_DEBUG_KMS("%s\n", __FILE__); @@ -194,32 +213,35 @@ static void fimd_commit(struct device *dev) struct fimd_context *ctx = get_fimd_context(dev); struct exynos_drm_panel_info *panel = ctx->panel; struct fb_videomode *timing = &panel->timing; + struct fimd_driver_data *driver_data; + struct platform_device *pdev = to_platform_device(dev); u32 val;
+ driver_data = drm_fimd_get_driver_data(pdev); if (ctx->suspended) return;
DRM_DEBUG_KMS("%s\n", __FILE__);
/* setup polarity values from machine code. */ - writel(ctx->vidcon1, ctx->regs + VIDCON1); + writel(ctx->vidcon1, ctx->regs + driver_data->timing_base + VIDCON1);
/* setup vertical timing values. */ val = VIDTCON0_VBPD(timing->upper_margin - 1) | VIDTCON0_VFPD(timing->lower_margin - 1) | VIDTCON0_VSPW(timing->vsync_len - 1); - writel(val, ctx->regs + VIDTCON0); + writel(val, ctx->regs + driver_data->timing_base + VIDTCON0);
/* setup horizontal timing values. */ val = VIDTCON1_HBPD(timing->left_margin - 1) | VIDTCON1_HFPD(timing->right_margin - 1) | VIDTCON1_HSPW(timing->hsync_len - 1); - writel(val, ctx->regs + VIDTCON1); + writel(val, ctx->regs + driver_data->timing_base + VIDTCON1);
/* setup horizontal and vertical display size. */ val = VIDTCON2_LINEVAL(timing->yres - 1) | VIDTCON2_HOZVAL(timing->xres - 1); - writel(val, ctx->regs + VIDTCON2); + writel(val, ctx->regs + driver_data->timing_base + VIDTCON2);
/* setup clock source, clock divider, enable dma. */ val = ctx->vidcon0; @@ -982,6 +1004,18 @@ static int fimd_runtime_resume(struct device *dev) } #endif
+static struct platform_device_id fimd_driver_ids[] = { + { + .name = "exynos4-fb", + .driver_data = (unsigned long)&exynos4_fimd_driver_data, + }, { + .name = "exynos5-fb", + .driver_data = (unsigned long)&exynos5_fimd_driver_data, + }, + {}, +}; +MODULE_DEVICE_TABLE(platform, fimd_driver_ids); + static const struct dev_pm_ops fimd_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(fimd_suspend, fimd_resume) SET_RUNTIME_PM_OPS(fimd_runtime_suspend, fimd_runtime_resume, NULL) @@ -990,6 +1024,7 @@ static const struct dev_pm_ops fimd_pm_ops = { struct platform_driver fimd_driver = { .probe = fimd_probe, .remove = __devexit_p(fimd_remove), + .id_table = fimd_driver_ids, .driver = { .name = "exynos4-fb", .owner = THIS_MODULE,
Add device tree based discovery support for DRM-FIMD driver.
Signed-off-by: Leela Krishna Amudala l.krishna@samsung.com --- Documentation/devicetree/bindings/fb/drm-fimd.txt | 80 +++++++++++++++++ drivers/gpu/drm/exynos/exynos_drm_fimd.c | 95 ++++++++++++++++++++- 2 files changed, 173 insertions(+), 2 deletions(-) create mode 100644 Documentation/devicetree/bindings/fb/drm-fimd.txt
diff --git a/Documentation/devicetree/bindings/fb/drm-fimd.txt b/Documentation/devicetree/bindings/fb/drm-fimd.txt new file mode 100644 index 0000000..bf94cd6 --- /dev/null +++ b/Documentation/devicetree/bindings/fb/drm-fimd.txt @@ -0,0 +1,80 @@ +* Samsung Display Controller using DRM frame work + +The display controller is used to transfer image data from memory to an +external LCD driver interface. It supports various color formats such as +rgb and yuv. + +Required properties: + - compatible: Should be "samsung,exynos5-fimd" or "samsung,exynos4-fimd" for + fimd using DRM frame work. + - reg: physical base address of the controller and length of memory + mapped region. + - interrupts: Three interrupts should be specified. The interrupts should be + specified in the following order. + - VSYNC interrupt + - FIFO level interrupt + - FIMD System Interrupt + + - samsung,fimd-display: This property should specify the phandle of the + display device node which holds the video interface timing with the + below mentioned properties. + + - lcd-htiming: Specifies the horizontal timing for the overlay. The + horizontal timing includes four parameters in the following order. + + - horizontal back porch (in number of lcd clocks) + - horizontal front porch (in number of lcd clocks) + - hsync pulse width (in number of lcd clocks) + - Display panels X resolution. + + - lcd-vtiming: Specifies the vertical timing for the overlay. The + vertical timing includes four parameters in the following order. + + - vertical back porch (in number of lcd lines) + - vertical front porch (in number of lcd lines) + - vsync pulse width (in number of lcd clocks) + - Display panels Y resolution. + + + - samsung,default-window: Specifies the default window number of the fimd controller. + + - samsung,fimd-win-bpp: Specifies the bits per pixel. + +Optional properties: + - samsung,fimd-vidout-rgb: Video output format is RGB. + - samsung,fimd-inv-vclk: invert video clock polarity. + - samsung,fimd-frame-rate: Number of video frames per second. + +Example: + + The following is an example for the fimd controller is split into + two portions. The SoC specific portion can be specified in the SoC + specific dts file. The board specific portion can be specified in the + board specific dts file. + + - SoC Specific portion + + fimd { + compatible = "samsung,exynos5-fimd"; + interrupt-parent = <&combiner>; + reg = <0x14400000 0x40000>; + interrupts = <18 5>, <18 4>, <18 6>; + }; + + - Board Specific portion + + lcd_fimd0: lcd_panel0 { + lcd-htiming = <4 4 4 480>; + lcd-vtiming = <4 4 4 320>; + supports-mipi-panel; + }; + + fimd { + samsung,fimd-display = <&lcd_fimd0>; + samsung,fimd-vidout-rgb; + samsung,fimd-inv-vclk; + samsung,fimd-frame-rate = <60>; + samsung,default-window = <0>; + samsung,fimd-win-bpp = <32>; + }; + diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 65e927b..cd1b841 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -18,6 +18,7 @@ #include <linux/platform_device.h> #include <linux/clk.h> #include <linux/pm_runtime.h> +#include <linux/of.h>
#include <video/samsung_fimd.h> #include <drm/exynos_drm.h> @@ -103,9 +104,18 @@ struct fimd_context { struct exynos_drm_panel_info *panel; };
+static const struct of_device_id fimd_dt_match[]; + static inline struct fimd_driver_data *drm_fimd_get_driver_data( struct platform_device *pdev) { +#ifdef CONFIG_OF + if (pdev->dev.of_node) { + const struct of_device_id *match; + match = of_match_ptr(fimd_dt_match); + return (struct fimd_driver_data *)match->data; + } +#endif return (struct fimd_driver_data *) platform_get_device_id(pdev)->driver_data; } @@ -809,12 +819,77 @@ static int fimd_power_on(struct fimd_context *ctx, bool enable) return 0; }
+#ifdef CONFIG_OF +static struct exynos_drm_fimd_pdata *drm_fimd_dt_parse_pdata(struct device *dev) +{ + struct device_node *np = dev->of_node; + struct device_node *disp_np; + struct exynos_drm_fimd_pdata *pd; + u32 data[4]; + + pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); + if (!pd) { + dev_err(dev, "memory allocation for pdata failed\n"); + return ERR_PTR(-ENOMEM); + } + + if (of_get_property(np, "samsung,fimd-vidout-rgb", NULL)) + pd->vidcon0 |= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB; + if (of_get_property(np, "samsung,fimd-inv-hsync", NULL)) + pd->vidcon1 |= VIDCON1_INV_HSYNC; + if (of_get_property(np, "samsung,fimd-inv-vsync", NULL)) + pd->vidcon1 |= VIDCON1_INV_VSYNC; + if (of_get_property(np, "samsung,fimd-inv-vclk", NULL)) + pd->vidcon1 |= VIDCON1_INV_VCLK; + if (of_get_property(np, "samsung,fimd-inv-vden", NULL)) + pd->vidcon1 |= VIDCON1_INV_VDEN; + + disp_np = of_parse_phandle(np, "samsung,fimd-display", 0); + if (!disp_np) { + dev_err(dev, "unable to find display panel info\n"); + return ERR_PTR(-EINVAL); + } + + if (of_property_read_u32_array(disp_np, "lcd-htiming", data, 4)) { + dev_err(dev, "invalid horizontal timing\n"); + return ERR_PTR(-EINVAL); + } + pd->panel.timing.left_margin = data[0]; + pd->panel.timing.right_margin = data[1]; + pd->panel.timing.hsync_len = data[2]; + pd->panel.timing.xres = data[3]; + + if (of_property_read_u32_array(disp_np, "lcd-vtiming", data, 4)) { + dev_err(dev, "invalid vertical timing\n"); + return ERR_PTR(-EINVAL); + } + pd->panel.timing.upper_margin = data[0]; + pd->panel.timing.lower_margin = data[1]; + pd->panel.timing.vsync_len = data[2]; + pd->panel.timing.yres = data[3]; + + of_property_read_u32(np, "samsung,fimd-frame-rate", + &pd->panel.timing.refresh); + + of_property_read_u32(np, "samsung,default-window", &pd->default_win); + + of_property_read_u32(np, "samsung,fimd-win-bpp", &pd->bpp); + + return pd; +} +#else +static struct exynos_drm_fimd_pdata *drm_fimd_dt_parse_pdata(struct device *dev) +{ + return NULL; +} +#endif /* CONFIG_OF */ + static int __devinit fimd_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct fimd_context *ctx; struct exynos_drm_subdrv *subdrv; - struct exynos_drm_fimd_pdata *pdata; + struct exynos_drm_fimd_pdata *pdata = pdev->dev.platform_data; struct exynos_drm_panel_info *panel; struct resource *res; int win; @@ -822,7 +897,11 @@ static int __devinit fimd_probe(struct platform_device *pdev)
DRM_DEBUG_KMS("%s\n", __FILE__);
- pdata = pdev->dev.platform_data; + if (pdev->dev.of_node) { + pdata = drm_fimd_dt_parse_pdata(&pdev->dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + } if (!pdata) { dev_err(dev, "no platform data specified\n"); return -EINVAL; @@ -1016,6 +1095,17 @@ static struct platform_device_id fimd_driver_ids[] = { }; MODULE_DEVICE_TABLE(platform, fimd_driver_ids);
+#ifdef CONFIG_OF +static const struct of_device_id fimd_dt_match[] = { + { .compatible = "samsung,exynos5-fimd", + .data = &exynos5_fimd_driver_data }, + { .compatible = "samsung,exynos4-fimd", + .data = &exynos4_fimd_driver_data }, + {}, +}; +MODULE_DEVICE_TABLE(of, fimd_dt_match); +#endif + static const struct dev_pm_ops fimd_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(fimd_suspend, fimd_resume) SET_RUNTIME_PM_OPS(fimd_runtime_suspend, fimd_runtime_resume, NULL) @@ -1029,5 +1119,6 @@ struct platform_driver fimd_driver = { .name = "exynos4-fb", .owner = THIS_MODULE, .pm = &fimd_pm_ops, + .of_match_table = of_match_ptr(fimd_dt_match), }, };
dri-devel@lists.freedesktop.org