From baa88c8313bfdb5086220cbd962a93617ee85a91 Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Thu, 25 Apr 2013 19:21:42 +0900 Subject: Revert "drm/exynos: prepare FIMD clocks" This reverts commit b4e3a3e844a0e33cf106a1c9f27ff93340c37640. diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 15e58f5..4073430 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -949,16 +949,6 @@ static int fimd_probe(struct platform_device *pdev) return ret; } - ret = clk_prepare(ctx->bus_clk); - if (ret < 0) - return ret; - - ret = clk_prepare(ctx->lcd_clk); - if (ret < 0) { - clk_unprepare(ctx->bus_clk); - return ret; - } - ctx->vidcon0 = pdata->vidcon0; ctx->vidcon1 = pdata->vidcon1; ctx->default_win = pdata->default_win; @@ -1006,8 +996,8 @@ static int fimd_remove(struct platform_device *pdev) if (ctx->suspended) goto out; - clk_unprepare(ctx->lcd_clk); - clk_unprepare(ctx->bus_clk); + clk_disable(ctx->lcd_clk); + clk_disable(ctx->bus_clk); pm_runtime_set_suspended(dev); pm_runtime_put_sync(dev); -- cgit v0.10.2 From 11963a638f7ac30f926f4358f7f699828408bb96 Mon Sep 17 00:00:00 2001 From: Vikas Sajjan Date: Tue, 23 Apr 2013 17:19:50 +0530 Subject: drm/exynos: enable FIMD clocks Common Clock Framework introduced the need to prepare clocks before enabling them, otherwise clk_enable() fails. This patch adds clk_prepare_enable and clk_disable_unprepare() calls to the driver. This patch also removes clk_disable() from fimd_remove() as it will be done by pm_runtime_put_sync. Signed-off-by: Vikas Sajjan Signed-off-by: Inki Dae diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 4073430..746b282 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -801,18 +801,18 @@ static int fimd_clock(struct fimd_context *ctx, bool enable) if (enable) { int ret; - ret = clk_enable(ctx->bus_clk); + ret = clk_prepare_enable(ctx->bus_clk); if (ret < 0) return ret; - ret = clk_enable(ctx->lcd_clk); + ret = clk_prepare_enable(ctx->lcd_clk); if (ret < 0) { - clk_disable(ctx->bus_clk); + clk_disable_unprepare(ctx->bus_clk); return ret; } } else { - clk_disable(ctx->lcd_clk); - clk_disable(ctx->bus_clk); + clk_disable_unprepare(ctx->lcd_clk); + clk_disable_unprepare(ctx->bus_clk); } return 0; @@ -996,9 +996,6 @@ static int fimd_remove(struct platform_device *pdev) if (ctx->suspended) goto out; - clk_disable(ctx->lcd_clk); - clk_disable(ctx->bus_clk); - pm_runtime_set_suspended(dev); pm_runtime_put_sync(dev); -- cgit v0.10.2 From 4c30cbc0b9c89d90c5a0d08bfb62d7a6b6c88d33 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 23 Apr 2013 13:34:36 +0200 Subject: drm/exynos: remove redundant devm_kfree() There is no need for explicit calls of devm_kfree(), as the allocated memory will be freed during driver's detach. Remove the redundant devm_kfree() calls from probe() and remove() callbacks. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Inki Dae diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c index 411f69b7..d812c57 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c @@ -1843,7 +1843,6 @@ static int fimc_probe(struct platform_device *pdev) return 0; err_ippdrv_register: - devm_kfree(dev, ippdrv->prop_list); pm_runtime_disable(dev); err_get_irq: free_irq(ctx->irq, ctx); @@ -1857,7 +1856,6 @@ static int fimc_remove(struct platform_device *pdev) struct fimc_context *ctx = get_fimc_context(dev); struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - devm_kfree(dev, ippdrv->prop_list); exynos_drm_ippdrv_unregister(ippdrv); mutex_destroy(&ctx->lock); -- cgit v0.10.2 From e5f8683923af2fd2bb0c5a7c0a66597cc6b50ef3 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 23 Apr 2013 13:34:37 +0200 Subject: drm/exynos: rework fimc clocks handling The clocks handling is refactored and a "mux" clock handling is added to account for changes in the clocks driver. After switching to the common clock framework the sclk_fimc clock is now split into two clocks: a gate and a mux clock. In order to retain the exisiting functionality two additional consumer clocks are passed to the driver from device tree: "mux" and "parent". Then the driver sets "parent" clock as a parent clock of the "mux" clock. These two additional clocks are optional, and should go away when there is a standard way of setting up parent clocks on DT platforms. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Inki Dae diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c index d812c57..2cce97d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c @@ -76,6 +76,27 @@ enum fimc_wb { FIMC_WB_B, }; +enum { + FIMC_CLK_LCLK, + FIMC_CLK_GATE, + FIMC_CLK_WB_A, + FIMC_CLK_WB_B, + FIMC_CLK_MUX, + FIMC_CLK_PARENT, + FIMC_CLKS_MAX +}; + +static const char * const fimc_clock_names[] = { + [FIMC_CLK_LCLK] = "sclk_fimc", + [FIMC_CLK_GATE] = "fimc", + [FIMC_CLK_WB_A] = "pxl_async0", + [FIMC_CLK_WB_B] = "pxl_async1", + [FIMC_CLK_MUX] = "mux", + [FIMC_CLK_PARENT] = "parent", +}; + +#define FIMC_DEFAULT_LCLK_FREQUENCY 133000000UL + /* * A structure of scaler. * @@ -134,13 +155,9 @@ struct fimc_driverdata { * @regs_res: register resources. * @regs: memory mapped io registers. * @lock: locking of operations. - * @sclk_fimc_clk: fimc source clock. - * @fimc_clk: fimc clock. - * @wb_clk: writeback a clock. - * @wb_b_clk: writeback b clock. + * @clocks: fimc clocks. + * @clk_frequency: LCLK clock frequency. * @sc: scaler infomations. - * @odr: ordering of YUV. - * @ver: fimc version. * @pol: porarity of writeback. * @id: fimc id. * @irq: irq number. @@ -151,10 +168,8 @@ struct fimc_context { struct resource *regs_res; void __iomem *regs; struct mutex lock; - struct clk *sclk_fimc_clk; - struct clk *fimc_clk; - struct clk *wb_clk; - struct clk *wb_b_clk; + struct clk *clocks[FIMC_CLKS_MAX]; + u32 clk_frequency; struct fimc_scaler sc; struct fimc_driverdata *ddata; struct exynos_drm_ipp_pol pol; @@ -1301,14 +1316,12 @@ static int fimc_clk_ctrl(struct fimc_context *ctx, bool enable) DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable); if (enable) { - clk_enable(ctx->sclk_fimc_clk); - clk_enable(ctx->fimc_clk); - clk_enable(ctx->wb_clk); + clk_prepare_enable(ctx->clocks[FIMC_CLK_GATE]); + clk_prepare_enable(ctx->clocks[FIMC_CLK_WB_A]); ctx->suspended = false; } else { - clk_disable(ctx->sclk_fimc_clk); - clk_disable(ctx->fimc_clk); - clk_disable(ctx->wb_clk); + clk_disable_unprepare(ctx->clocks[FIMC_CLK_GATE]); + clk_disable_unprepare(ctx->clocks[FIMC_CLK_WB_A]); ctx->suspended = true; } @@ -1713,11 +1726,70 @@ static void fimc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd) fimc_write(cfg, EXYNOS_CIGCTRL); } +static void fimc_put_clocks(struct fimc_context *ctx) +{ + int i; + + for (i = 0; i < FIMC_CLKS_MAX; i++) { + if (IS_ERR(ctx->clocks[i])) + continue; + clk_put(ctx->clocks[i]); + ctx->clocks[i] = ERR_PTR(-EINVAL); + } +} + +static int fimc_setup_clocks(struct fimc_context *ctx) +{ + struct device *fimc_dev = ctx->ippdrv.dev; + struct device *dev; + int ret, i; + + for (i = 0; i < FIMC_CLKS_MAX; i++) + ctx->clocks[i] = ERR_PTR(-EINVAL); + + for (i = 0; i < FIMC_CLKS_MAX; i++) { + if (i == FIMC_CLK_WB_A || i == FIMC_CLK_WB_B) + dev = fimc_dev->parent; + else + dev = fimc_dev; + + ctx->clocks[i] = clk_get(dev, fimc_clock_names[i]); + if (IS_ERR(ctx->clocks[i])) { + if (i >= FIMC_CLK_MUX) + break; + ret = PTR_ERR(ctx->clocks[i]); + dev_err(fimc_dev, "failed to get clock: %s\n", + fimc_clock_names[i]); + goto e_clk_free; + } + } + + /* Optional FIMC LCLK parent clock setting */ + if (!IS_ERR(ctx->clocks[FIMC_CLK_PARENT])) { + ret = clk_set_parent(ctx->clocks[FIMC_CLK_MUX], + ctx->clocks[FIMC_CLK_PARENT]); + if (ret < 0) { + dev_err(fimc_dev, "failed to set parent.\n"); + goto e_clk_free; + } + } + + ret = clk_set_rate(ctx->clocks[FIMC_CLK_LCLK], ctx->clk_frequency); + if (ret < 0) + goto e_clk_free; + + ret = clk_prepare_enable(ctx->clocks[FIMC_CLK_LCLK]); + if (!ret) + return ret; +e_clk_free: + fimc_put_clocks(ctx); + return ret; +} + static int fimc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct fimc_context *ctx; - struct clk *parent_clk; struct resource *res; struct exynos_drm_ippdrv *ippdrv; struct exynos_drm_fimc_pdata *pdata; @@ -1734,55 +1806,6 @@ static int fimc_probe(struct platform_device *pdev) if (!ctx) return -ENOMEM; - ddata = (struct fimc_driverdata *) - platform_get_device_id(pdev)->driver_data; - - /* clock control */ - ctx->sclk_fimc_clk = devm_clk_get(dev, "sclk_fimc"); - if (IS_ERR(ctx->sclk_fimc_clk)) { - dev_err(dev, "failed to get src fimc clock.\n"); - return PTR_ERR(ctx->sclk_fimc_clk); - } - clk_enable(ctx->sclk_fimc_clk); - - ctx->fimc_clk = devm_clk_get(dev, "fimc"); - if (IS_ERR(ctx->fimc_clk)) { - dev_err(dev, "failed to get fimc clock.\n"); - clk_disable(ctx->sclk_fimc_clk); - return PTR_ERR(ctx->fimc_clk); - } - - ctx->wb_clk = devm_clk_get(dev, "pxl_async0"); - if (IS_ERR(ctx->wb_clk)) { - dev_err(dev, "failed to get writeback a clock.\n"); - clk_disable(ctx->sclk_fimc_clk); - return PTR_ERR(ctx->wb_clk); - } - - ctx->wb_b_clk = devm_clk_get(dev, "pxl_async1"); - if (IS_ERR(ctx->wb_b_clk)) { - dev_err(dev, "failed to get writeback b clock.\n"); - clk_disable(ctx->sclk_fimc_clk); - return PTR_ERR(ctx->wb_b_clk); - } - - parent_clk = devm_clk_get(dev, ddata->parent_clk); - - if (IS_ERR(parent_clk)) { - dev_err(dev, "failed to get parent clock.\n"); - clk_disable(ctx->sclk_fimc_clk); - return PTR_ERR(parent_clk); - } - - if (clk_set_parent(ctx->sclk_fimc_clk, parent_clk)) { - dev_err(dev, "failed to set parent.\n"); - clk_disable(ctx->sclk_fimc_clk); - return -EINVAL; - } - - devm_clk_put(dev, parent_clk); - clk_set_rate(ctx->sclk_fimc_clk, pdata->clk_rate); - /* resource memory */ ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ctx->regs = devm_ioremap_resource(dev, ctx->regs_res); @@ -1804,6 +1827,9 @@ static int fimc_probe(struct platform_device *pdev) return ret; } + ret = fimc_setup_clocks(ctx); + if (ret < 0) + goto err_free_irq; /* context initailization */ ctx->id = pdev->id; ctx->pol = pdata->pol; @@ -1820,7 +1846,7 @@ static int fimc_probe(struct platform_device *pdev) ret = fimc_init_prop_list(ippdrv); if (ret < 0) { dev_err(dev, "failed to init property list.\n"); - goto err_get_irq; + goto err_put_clk; } DRM_DEBUG_KMS("%s:id[%d]ippdrv[0x%x]\n", __func__, ctx->id, @@ -1835,16 +1861,18 @@ static int fimc_probe(struct platform_device *pdev) ret = exynos_drm_ippdrv_register(ippdrv); if (ret < 0) { dev_err(dev, "failed to register drm fimc device.\n"); - goto err_ippdrv_register; + goto err_pm_dis; } dev_info(&pdev->dev, "drm fimc registered successfully.\n"); return 0; -err_ippdrv_register: +err_pm_dis: pm_runtime_disable(dev); -err_get_irq: +err_put_clk: + fimc_put_clocks(ctx); +err_free_irq: free_irq(ctx->irq, ctx); return ret; @@ -1859,6 +1887,7 @@ static int fimc_remove(struct platform_device *pdev) exynos_drm_ippdrv_unregister(ippdrv); mutex_destroy(&ctx->lock); + fimc_put_clocks(ctx); pm_runtime_set_suspended(dev); pm_runtime_disable(dev); -- cgit v0.10.2 From 5186fc5e8eda184935467aa84295b2897166fecd Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 23 Apr 2013 13:34:38 +0200 Subject: drm/exynos: add device tree support for fimc ipp driver This patch adds OF initialization support for the FIMC driver. The binding documentation can be found at Documentation/devicetree/ bindings/media/samsung-fimc.txt. The syscon regmap interface is used to serialize access to the shared CAMBLK registers from within the V4L2 FIMC-IS and the DRM FIMC drivers. The DRM driver uses this interface for setting up the FIFO data link between FIMD and FIMC IP blocks, while the V4L2 one for setting up a data link between the camera ISP and FIMC for camera capture. The CAMBLK registers are not accessed any more through a statically mapped IO. Synchronized access to these registers is required for simultaneous operation of the camera ISP and the DRM IPP on Exynos4x12. The driver data and driver_ids static data structures are removed since Exynos4 is going to be a dt-only platform and there is currently no board file in mainline that defines platform data for the FIMC IPP, i.e. uses it. Camera input signal polarities are not currently parsed from the device tree. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Inki Dae diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 406f32a..5c4be2a 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -56,7 +56,7 @@ config DRM_EXYNOS_IPP config DRM_EXYNOS_FIMC bool "Exynos DRM FIMC" - depends on DRM_EXYNOS_IPP + depends on DRM_EXYNOS_IPP && MFD_SYSCON && OF help Choose this option if you want to use Exynos FIMC for DRM. diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c index 2cce97d..773f583 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c @@ -12,11 +12,12 @@ * */ #include +#include #include #include +#include #include #include -#include #include #include @@ -140,15 +141,6 @@ struct fimc_capability { }; /* - * A structure of fimc driver data. - * - * @parent_clk: name of parent clock. - */ -struct fimc_driverdata { - char *parent_clk; -}; - -/* * A structure of fimc context. * * @ippdrv: prepare initialization using ippdrv. @@ -157,6 +149,7 @@ struct fimc_driverdata { * @lock: locking of operations. * @clocks: fimc clocks. * @clk_frequency: LCLK clock frequency. + * @sysreg: handle to SYSREG block regmap. * @sc: scaler infomations. * @pol: porarity of writeback. * @id: fimc id. @@ -170,8 +163,8 @@ struct fimc_context { struct mutex lock; struct clk *clocks[FIMC_CLKS_MAX]; u32 clk_frequency; + struct regmap *sysreg; struct fimc_scaler sc; - struct fimc_driverdata *ddata; struct exynos_drm_ipp_pol pol; int id; int irq; @@ -215,17 +208,13 @@ static void fimc_sw_reset(struct fimc_context *ctx) fimc_write(0x0, EXYNOS_CIFCNTSEQ); } -static void fimc_set_camblk_fimd0_wb(struct fimc_context *ctx) +static int fimc_set_camblk_fimd0_wb(struct fimc_context *ctx) { - u32 camblk_cfg; - DRM_DEBUG_KMS("%s\n", __func__); - camblk_cfg = readl(SYSREG_CAMERA_BLK); - camblk_cfg &= ~(SYSREG_FIMD0WB_DEST_MASK); - camblk_cfg |= ctx->id << (SYSREG_FIMD0WB_DEST_SHIFT); - - writel(camblk_cfg, SYSREG_CAMERA_BLK); + return regmap_update_bits(ctx->sysreg, SYSREG_CAMERA_BLK, + SYSREG_FIMD0WB_DEST_MASK, + ctx->id << SYSREG_FIMD0WB_DEST_SHIFT); } static void fimc_set_type_ctrl(struct fimc_context *ctx, enum fimc_wb wb) @@ -1626,7 +1615,11 @@ static int fimc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd) fimc_handle_lastend(ctx, true); /* setup FIMD */ - fimc_set_camblk_fimd0_wb(ctx); + ret = fimc_set_camblk_fimd0_wb(ctx); + if (ret < 0) { + dev_err(dev, "camblk setup failed.\n"); + return ret; + } set_wb.enable = 1; set_wb.refresh = property->refresh_rate; @@ -1786,26 +1779,58 @@ e_clk_free: return ret; } +static int fimc_parse_dt(struct fimc_context *ctx) +{ + struct device_node *node = ctx->ippdrv.dev->of_node; + + /* Handle only devices that support the LCD Writeback data path */ + if (!of_property_read_bool(node, "samsung,lcd-wb")) + return -ENODEV; + + if (of_property_read_u32(node, "clock-frequency", + &ctx->clk_frequency)) + ctx->clk_frequency = FIMC_DEFAULT_LCLK_FREQUENCY; + + ctx->id = of_alias_get_id(node, "fimc"); + + if (ctx->id < 0) { + dev_err(ctx->ippdrv.dev, "failed to get node alias id.\n"); + return -EINVAL; + } + + return 0; +} + static int fimc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct fimc_context *ctx; struct resource *res; struct exynos_drm_ippdrv *ippdrv; - struct exynos_drm_fimc_pdata *pdata; - struct fimc_driverdata *ddata; int ret; - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_err(dev, "no platform data specified.\n"); - return -EINVAL; + if (!dev->of_node) { + dev_err(dev, "device tree node not found.\n"); + return -ENODEV; } ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; + ctx->ippdrv.dev = dev; + + ret = fimc_parse_dt(ctx); + if (ret < 0) + return ret; + + ctx->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node, + "samsung,sysreg"); + if (IS_ERR(ctx->sysreg)) { + dev_err(dev, "syscon regmap lookup failed.\n"); + return PTR_ERR(ctx->sysreg); + } + /* resource memory */ ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ctx->regs = devm_ioremap_resource(dev, ctx->regs_res); @@ -1830,13 +1855,8 @@ static int fimc_probe(struct platform_device *pdev) ret = fimc_setup_clocks(ctx); if (ret < 0) goto err_free_irq; - /* context initailization */ - ctx->id = pdev->id; - ctx->pol = pdata->pol; - ctx->ddata = ddata; ippdrv = &ctx->ippdrv; - ippdrv->dev = dev; ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &fimc_src_ops; ippdrv->ops[EXYNOS_DRM_OPS_DST] = &fimc_dst_ops; ippdrv->check_property = fimc_ippdrv_check_property; @@ -1942,36 +1962,22 @@ static int fimc_runtime_resume(struct device *dev) } #endif -static struct fimc_driverdata exynos4210_fimc_data = { - .parent_clk = "mout_mpll", -}; - -static struct fimc_driverdata exynos4410_fimc_data = { - .parent_clk = "mout_mpll_user", -}; - -static struct platform_device_id fimc_driver_ids[] = { - { - .name = "exynos4210-fimc", - .driver_data = (unsigned long)&exynos4210_fimc_data, - }, { - .name = "exynos4412-fimc", - .driver_data = (unsigned long)&exynos4410_fimc_data, - }, - {}, -}; -MODULE_DEVICE_TABLE(platform, fimc_driver_ids); - static const struct dev_pm_ops fimc_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend, fimc_resume) SET_RUNTIME_PM_OPS(fimc_runtime_suspend, fimc_runtime_resume, NULL) }; +static const struct of_device_id fimc_of_match[] = { + { .compatible = "samsung,exynos4210-fimc" }, + { .compatible = "samsung,exynos4212-fimc" }, + { }, +}; + struct platform_driver fimc_driver = { .probe = fimc_probe, .remove = fimc_remove, - .id_table = fimc_driver_ids, .driver = { + .of_match_table = fimc_of_match, .name = "exynos-drm-fimc", .owner = THIS_MODULE, .pm = &fimc_pm_ops, diff --git a/drivers/gpu/drm/exynos/regs-fimc.h b/drivers/gpu/drm/exynos/regs-fimc.h index b4f9ca1..3049613 100644 --- a/drivers/gpu/drm/exynos/regs-fimc.h +++ b/drivers/gpu/drm/exynos/regs-fimc.h @@ -661,9 +661,8 @@ #define EXYNOS_CLKSRC_SCLK (1 << 1) /* SYSREG for FIMC writeback */ -#define SYSREG_CAMERA_BLK (S3C_VA_SYS + 0x0218) -#define SYSREG_ISP_BLK (S3C_VA_SYS + 0x020c) -#define SYSREG_FIMD0WB_DEST_MASK (0x3 << 23) -#define SYSREG_FIMD0WB_DEST_SHIFT 23 +#define SYSREG_CAMERA_BLK (0x0218) +#define SYSREG_FIMD0WB_DEST_MASK (0x3 << 23) +#define SYSREG_FIMD0WB_DEST_SHIFT 23 #endif /* EXYNOS_REGS_FIMC_H */ -- cgit v0.10.2 From 1055f49e9953e5a55e8b7d54db19c4b8c1108eec Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Mon, 22 Apr 2013 17:13:13 +0900 Subject: drm/exynos: fix wrong return check for platform_device_register_simple platform_device_register_simple() never returns NULL, but IS_ERR_OR_NULL macro is used for checking return value in exynos drm driver. Signed-off-by: Seung-Woo Kim Signed-off-by: Inki Dae diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 3da5c2d..488278c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -388,7 +388,7 @@ static int __init exynos_drm_init(void) exynos_drm_pdev = platform_device_register_simple("exynos-drm", -1, NULL, 0); - if (IS_ERR_OR_NULL(exynos_drm_pdev)) { + if (IS_ERR(exynos_drm_pdev)) { ret = PTR_ERR(exynos_drm_pdev); goto out; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index 5285509..6986a1b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c @@ -56,7 +56,7 @@ int exynos_platform_device_hdmi_register(void) exynos_drm_hdmi_pdev = platform_device_register_simple( "exynos-drm-hdmi", -1, NULL, 0); - if (IS_ERR_OR_NULL(exynos_drm_hdmi_pdev)) + if (IS_ERR(exynos_drm_hdmi_pdev)) return PTR_ERR(exynos_drm_hdmi_pdev); return 0; -- cgit v0.10.2 From 0f6f95922e4def60b9e55cecc1fdbaacda9c426d Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Mon, 22 Apr 2013 18:40:34 +0900 Subject: exynos/drm: hdmi: cleanup for hdmi common device registration The hdmi common device registration function does not need extern definition and for error case and unregister case, exynos_drm_hdmi_pdev should be cleared. Signed-off-by: Seung-Woo Kim Signed-off-by: Inki Dae diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 4606fac..635d4c5 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -322,7 +322,7 @@ void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file); * this function registers exynos drm hdmi platform device. It ensures only one * instance of the device is created. */ -extern int exynos_platform_device_hdmi_register(void); +int exynos_platform_device_hdmi_register(void); /* * this function unregisters exynos drm hdmi platform device if it exists. diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index 6986a1b..ba2f0f1 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c @@ -51,21 +51,27 @@ struct drm_hdmi_context { int exynos_platform_device_hdmi_register(void) { + struct platform_device *pdev; + if (exynos_drm_hdmi_pdev) return -EEXIST; - exynos_drm_hdmi_pdev = platform_device_register_simple( + pdev = platform_device_register_simple( "exynos-drm-hdmi", -1, NULL, 0); - if (IS_ERR(exynos_drm_hdmi_pdev)) - return PTR_ERR(exynos_drm_hdmi_pdev); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); + + exynos_drm_hdmi_pdev = pdev; return 0; } void exynos_platform_device_hdmi_unregister(void) { - if (exynos_drm_hdmi_pdev) + if (exynos_drm_hdmi_pdev) { platform_device_unregister(exynos_drm_hdmi_pdev); + exynos_drm_hdmi_pdev = NULL; + } } void exynos_hdmi_drv_attach(struct exynos_drm_hdmi_context *ctx) -- cgit v0.10.2 From 43f4190047a088d2f1ce7fe5c5ae6485f943edc6 Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Tue, 23 Apr 2013 14:02:53 +0900 Subject: drm/exynos: added ipp device registration to drm driver This patch added exynos-drm-ipp platform device registration to the exynos drm driver. When DT is enabled, platform devices need to be registered within the driver code. This patch fits the requirement of both DT and Non DT based drm drivers. Signed-off-by: Seung-Woo Kim Signed-off-by: Donghwa Lee Signed-off-by: Inki Dae diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 488278c..ba6d995 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -380,6 +380,10 @@ static int __init exynos_drm_init(void) ret = platform_driver_register(&ipp_driver); if (ret < 0) goto out_ipp; + + ret = exynos_platform_device_ipp_register(); + if (ret < 0) + goto out_ipp_dev; #endif ret = platform_driver_register(&exynos_drm_platform_driver); @@ -400,6 +404,8 @@ out: out_drm: #ifdef CONFIG_DRM_EXYNOS_IPP + exynos_platform_device_ipp_unregister(); +out_ipp_dev: platform_driver_unregister(&ipp_driver); out_ipp: #endif @@ -456,6 +462,7 @@ static void __exit exynos_drm_exit(void) platform_driver_unregister(&exynos_drm_platform_driver); #ifdef CONFIG_DRM_EXYNOS_IPP + exynos_platform_device_ipp_unregister(); platform_driver_unregister(&ipp_driver); #endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 635d4c5..680a7c1 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -329,6 +329,16 @@ int exynos_platform_device_hdmi_register(void); */ void exynos_platform_device_hdmi_unregister(void); +/* + * this function registers exynos drm ipp platform device. + */ +int exynos_platform_device_ipp_register(void); + +/* + * this function unregisters exynos drm ipp platform device if it exists. + */ +void exynos_platform_device_ipp_unregister(void); + 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_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index 1adce07..29d2ad3 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c @@ -47,6 +47,9 @@ #define get_ipp_context(dev) platform_get_drvdata(to_platform_device(dev)) #define ipp_is_m2m_cmd(c) (c == IPP_CMD_M2M) +/* platform device pointer for ipp device. */ +static struct platform_device *exynos_drm_ipp_pdev; + /* * A structure of event. * @@ -102,6 +105,30 @@ static LIST_HEAD(exynos_drm_ippdrv_list); static DEFINE_MUTEX(exynos_drm_ippdrv_lock); static BLOCKING_NOTIFIER_HEAD(exynos_drm_ippnb_list); +int exynos_platform_device_ipp_register(void) +{ + struct platform_device *pdev; + + if (exynos_drm_ipp_pdev) + return -EEXIST; + + pdev = platform_device_register_simple("exynos-drm-ipp", -1, NULL, 0); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); + + exynos_drm_ipp_pdev = pdev; + + return 0; +} + +void exynos_platform_device_ipp_unregister(void) +{ + if (exynos_drm_ipp_pdev) { + platform_device_unregister(exynos_drm_ipp_pdev); + exynos_drm_ipp_pdev = NULL; + } +} + int exynos_drm_ippdrv_register(struct exynos_drm_ippdrv *ippdrv) { DRM_DEBUG_KMS("%s\n", __func__); -- cgit v0.10.2 From 69961d8f2d6f30733ac85b95542ce05e796eecd7 Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Thu, 18 Apr 2013 14:04:17 +0900 Subject: drm/exynos: do not use generic flags to dumb This patch removes the use of dumb flags from driver. As Dave pointed out, the dumb flags are not driver specific so this should be removed from driver. Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index 0e6fe00..cf4543f 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -682,7 +682,8 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv, args->pitch = args->width * ((args->bpp + 7) / 8); args->size = args->pitch * args->height; - exynos_gem_obj = exynos_drm_gem_create(dev, args->flags, args->size); + exynos_gem_obj = exynos_drm_gem_create(dev, EXYNOS_BO_CONTIG | + EXYNOS_BO_WC, args->size); if (IS_ERR(exynos_gem_obj)) return PTR_ERR(exynos_gem_obj); -- cgit v0.10.2 From b9047b8d2e4863749934fef6e8809d71b6c540c2 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Apr 2013 17:06:06 +0530 Subject: drm/exynos: Select VIDEOMODE_HELPERS for FIMD FIMD also requires video mode helper APIs. Without this patch we get the following build error: drivers/gpu/drm/exynos/exynos_drm_fimd.c:895: undefined reference to `of_get_fb_videomode' make: *** [vmlinux] Error 1 Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 5c4be2a..772c62a 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -25,8 +25,8 @@ config DRM_EXYNOS_DMABUF config DRM_EXYNOS_FIMD bool "Exynos DRM FIMD" depends on OF && DRM_EXYNOS && !FB_S3C && !ARCH_MULTIPLATFORM - select OF_VIDEOMODE select FB_MODE_HELPERS + select VIDEOMODE_HELPERS help Choose this option if you want to use Exynos FIMD for DRM. -- cgit v0.10.2 From 5f46c333f9522938ed3c54fe9d7ee2b61e41ad2f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 26 Apr 2013 11:29:00 +0530 Subject: drm/exynos: Remove unnecessary braces in exynos_hdmi.c Silences the following checkpatch warning: WARNING: braces {} are not necessary for any arm of this statement Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 93b70e9..bbfc384 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -1373,11 +1373,10 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata) return; } - if (hdata->type == HDMI_TYPE13) { + if (hdata->type == HDMI_TYPE13) hdmiphy_data = hdmiphy_v13_configs[i].conf; - } else { + else hdmiphy_data = hdmiphy_v14_configs[i].conf; - } memcpy(buffer, hdmiphy_data, 32); ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32); @@ -1653,11 +1652,10 @@ static void hdmi_mode_set(void *ctx, void *mode) m->vrefresh, (m->flags & DRM_MODE_FLAG_INTERLACE) ? "INTERLACED" : "PROGERESSIVE"); - if (hdata->type == HDMI_TYPE13) { + if (hdata->type == HDMI_TYPE13) hdmi_v13_mode_set(hdata, mode); - } else { + else hdmi_v14_mode_set(hdata, mode); - } } static void hdmi_get_max_resol(void *ctx, unsigned int *width, -- cgit v0.10.2 From 0377f4ed9f1aed30292c4e3c87f24e028ae26f36 Mon Sep 17 00:00:00 2001 From: Sean Paul Date: Thu, 25 Apr 2013 15:13:26 -0400 Subject: drm/exynos: Don't blend mixer layer 0 This patch disables blending the mixer's layer 0 onto the background (solid color). It doesn't make sense to blend this layer by default, and causes color distortion if the layer is used for arbitrary content. Signed-off-by: Sean Paul Signed-off-by: Inki Dae diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index f08e251..ec3e376 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -643,12 +643,14 @@ static void mixer_win_reset(struct mixer_context *ctx) /* setting graphical layers */ val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */ val |= MXR_GRP_CFG_WIN_BLEND_EN; - val |= MXR_GRP_CFG_BLEND_PRE_MUL; - val |= MXR_GRP_CFG_PIXEL_BLEND_EN; val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */ - /* the same configuration for both layers */ + /* Don't blend layer 0 onto the mixer background */ mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val); + + /* Blend layer 1 into layer 0 */ + val |= MXR_GRP_CFG_BLEND_PRE_MUL; + val |= MXR_GRP_CFG_PIXEL_BLEND_EN; mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val); /* setting video layers */ -- cgit v0.10.2