aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorSylwester Nawrocki <s.nawrocki@samsung.com>2013-04-23 07:34:38 -0400
committerInki Dae <inki.dae@samsung.com>2013-04-29 01:35:32 -0400
commit5186fc5e8eda184935467aa84295b2897166fecd (patch)
tree98df35e733476b5775a4cc91c3d0706328580a4e /drivers/gpu
parente5f8683923af2fd2bb0c5a7c0a66597cc6b50ef3 (diff)
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 <s.nawrocki@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Inki Dae <inki.dae@samsung.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/exynos/Kconfig2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimc.c110
-rw-r--r--drivers/gpu/drm/exynos/regs-fimc.h7
3 files changed, 62 insertions, 57 deletions
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 406f32af8266..5c4be2a0472d 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -56,7 +56,7 @@ config DRM_EXYNOS_IPP
56 56
57config DRM_EXYNOS_FIMC 57config DRM_EXYNOS_FIMC
58 bool "Exynos DRM FIMC" 58 bool "Exynos DRM FIMC"
59 depends on DRM_EXYNOS_IPP 59 depends on DRM_EXYNOS_IPP && MFD_SYSCON && OF
60 help 60 help
61 Choose this option if you want to use Exynos FIMC for DRM. 61 Choose this option if you want to use Exynos FIMC for DRM.
62 62
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
index 2cce97d42ece..773f583fa964 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
@@ -12,11 +12,12 @@
12 * 12 *
13 */ 13 */
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/mfd/syscon.h>
15#include <linux/module.h> 16#include <linux/module.h>
16#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/regmap.h>
17#include <linux/clk.h> 19#include <linux/clk.h>
18#include <linux/pm_runtime.h> 20#include <linux/pm_runtime.h>
19#include <plat/map-base.h>
20 21
21#include <drm/drmP.h> 22#include <drm/drmP.h>
22#include <drm/exynos_drm.h> 23#include <drm/exynos_drm.h>
@@ -140,15 +141,6 @@ struct fimc_capability {
140}; 141};
141 142
142/* 143/*
143 * A structure of fimc driver data.
144 *
145 * @parent_clk: name of parent clock.
146 */
147struct fimc_driverdata {
148 char *parent_clk;
149};
150
151/*
152 * A structure of fimc context. 144 * A structure of fimc context.
153 * 145 *
154 * @ippdrv: prepare initialization using ippdrv. 146 * @ippdrv: prepare initialization using ippdrv.
@@ -157,6 +149,7 @@ struct fimc_driverdata {
157 * @lock: locking of operations. 149 * @lock: locking of operations.
158 * @clocks: fimc clocks. 150 * @clocks: fimc clocks.
159 * @clk_frequency: LCLK clock frequency. 151 * @clk_frequency: LCLK clock frequency.
152 * @sysreg: handle to SYSREG block regmap.
160 * @sc: scaler infomations. 153 * @sc: scaler infomations.
161 * @pol: porarity of writeback. 154 * @pol: porarity of writeback.
162 * @id: fimc id. 155 * @id: fimc id.
@@ -170,8 +163,8 @@ struct fimc_context {
170 struct mutex lock; 163 struct mutex lock;
171 struct clk *clocks[FIMC_CLKS_MAX]; 164 struct clk *clocks[FIMC_CLKS_MAX];
172 u32 clk_frequency; 165 u32 clk_frequency;
166 struct regmap *sysreg;
173 struct fimc_scaler sc; 167 struct fimc_scaler sc;
174 struct fimc_driverdata *ddata;
175 struct exynos_drm_ipp_pol pol; 168 struct exynos_drm_ipp_pol pol;
176 int id; 169 int id;
177 int irq; 170 int irq;
@@ -215,17 +208,13 @@ static void fimc_sw_reset(struct fimc_context *ctx)
215 fimc_write(0x0, EXYNOS_CIFCNTSEQ); 208 fimc_write(0x0, EXYNOS_CIFCNTSEQ);
216} 209}
217 210
218static void fimc_set_camblk_fimd0_wb(struct fimc_context *ctx) 211static int fimc_set_camblk_fimd0_wb(struct fimc_context *ctx)
219{ 212{
220 u32 camblk_cfg;
221
222 DRM_DEBUG_KMS("%s\n", __func__); 213 DRM_DEBUG_KMS("%s\n", __func__);
223 214
224 camblk_cfg = readl(SYSREG_CAMERA_BLK); 215 return regmap_update_bits(ctx->sysreg, SYSREG_CAMERA_BLK,
225 camblk_cfg &= ~(SYSREG_FIMD0WB_DEST_MASK); 216 SYSREG_FIMD0WB_DEST_MASK,
226 camblk_cfg |= ctx->id << (SYSREG_FIMD0WB_DEST_SHIFT); 217 ctx->id << SYSREG_FIMD0WB_DEST_SHIFT);
227
228 writel(camblk_cfg, SYSREG_CAMERA_BLK);
229} 218}
230 219
231static void fimc_set_type_ctrl(struct fimc_context *ctx, enum fimc_wb wb) 220static 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)
1626 fimc_handle_lastend(ctx, true); 1615 fimc_handle_lastend(ctx, true);
1627 1616
1628 /* setup FIMD */ 1617 /* setup FIMD */
1629 fimc_set_camblk_fimd0_wb(ctx); 1618 ret = fimc_set_camblk_fimd0_wb(ctx);
1619 if (ret < 0) {
1620 dev_err(dev, "camblk setup failed.\n");
1621 return ret;
1622 }
1630 1623
1631 set_wb.enable = 1; 1624 set_wb.enable = 1;
1632 set_wb.refresh = property->refresh_rate; 1625 set_wb.refresh = property->refresh_rate;
@@ -1786,26 +1779,58 @@ e_clk_free:
1786 return ret; 1779 return ret;
1787} 1780}
1788 1781
1782static int fimc_parse_dt(struct fimc_context *ctx)
1783{
1784 struct device_node *node = ctx->ippdrv.dev->of_node;
1785
1786 /* Handle only devices that support the LCD Writeback data path */
1787 if (!of_property_read_bool(node, "samsung,lcd-wb"))
1788 return -ENODEV;
1789
1790 if (of_property_read_u32(node, "clock-frequency",
1791 &ctx->clk_frequency))
1792 ctx->clk_frequency = FIMC_DEFAULT_LCLK_FREQUENCY;
1793
1794 ctx->id = of_alias_get_id(node, "fimc");
1795
1796 if (ctx->id < 0) {
1797 dev_err(ctx->ippdrv.dev, "failed to get node alias id.\n");
1798 return -EINVAL;
1799 }
1800
1801 return 0;
1802}
1803
1789static int fimc_probe(struct platform_device *pdev) 1804static int fimc_probe(struct platform_device *pdev)
1790{ 1805{
1791 struct device *dev = &pdev->dev; 1806 struct device *dev = &pdev->dev;
1792 struct fimc_context *ctx; 1807 struct fimc_context *ctx;
1793 struct resource *res; 1808 struct resource *res;
1794 struct exynos_drm_ippdrv *ippdrv; 1809 struct exynos_drm_ippdrv *ippdrv;
1795 struct exynos_drm_fimc_pdata *pdata;
1796 struct fimc_driverdata *ddata;
1797 int ret; 1810 int ret;
1798 1811
1799 pdata = pdev->dev.platform_data; 1812 if (!dev->of_node) {
1800 if (!pdata) { 1813 dev_err(dev, "device tree node not found.\n");
1801 dev_err(dev, "no platform data specified.\n"); 1814 return -ENODEV;
1802 return -EINVAL;
1803 } 1815 }
1804 1816
1805 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 1817 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
1806 if (!ctx) 1818 if (!ctx)
1807 return -ENOMEM; 1819 return -ENOMEM;
1808 1820
1821 ctx->ippdrv.dev = dev;
1822
1823 ret = fimc_parse_dt(ctx);
1824 if (ret < 0)
1825 return ret;
1826
1827 ctx->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
1828 "samsung,sysreg");
1829 if (IS_ERR(ctx->sysreg)) {
1830 dev_err(dev, "syscon regmap lookup failed.\n");
1831 return PTR_ERR(ctx->sysreg);
1832 }
1833
1809 /* resource memory */ 1834 /* resource memory */
1810 ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1835 ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1811 ctx->regs = devm_ioremap_resource(dev, ctx->regs_res); 1836 ctx->regs = devm_ioremap_resource(dev, ctx->regs_res);
@@ -1830,13 +1855,8 @@ static int fimc_probe(struct platform_device *pdev)
1830 ret = fimc_setup_clocks(ctx); 1855 ret = fimc_setup_clocks(ctx);
1831 if (ret < 0) 1856 if (ret < 0)
1832 goto err_free_irq; 1857 goto err_free_irq;
1833 /* context initailization */
1834 ctx->id = pdev->id;
1835 ctx->pol = pdata->pol;
1836 ctx->ddata = ddata;
1837 1858
1838 ippdrv = &ctx->ippdrv; 1859 ippdrv = &ctx->ippdrv;
1839 ippdrv->dev = dev;
1840 ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &fimc_src_ops; 1860 ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &fimc_src_ops;
1841 ippdrv->ops[EXYNOS_DRM_OPS_DST] = &fimc_dst_ops; 1861 ippdrv->ops[EXYNOS_DRM_OPS_DST] = &fimc_dst_ops;
1842 ippdrv->check_property = fimc_ippdrv_check_property; 1862 ippdrv->check_property = fimc_ippdrv_check_property;
@@ -1942,36 +1962,22 @@ static int fimc_runtime_resume(struct device *dev)
1942} 1962}
1943#endif 1963#endif
1944 1964
1945static struct fimc_driverdata exynos4210_fimc_data = {
1946 .parent_clk = "mout_mpll",
1947};
1948
1949static struct fimc_driverdata exynos4410_fimc_data = {
1950 .parent_clk = "mout_mpll_user",
1951};
1952
1953static struct platform_device_id fimc_driver_ids[] = {
1954 {
1955 .name = "exynos4210-fimc",
1956 .driver_data = (unsigned long)&exynos4210_fimc_data,
1957 }, {
1958 .name = "exynos4412-fimc",
1959 .driver_data = (unsigned long)&exynos4410_fimc_data,
1960 },
1961 {},
1962};
1963MODULE_DEVICE_TABLE(platform, fimc_driver_ids);
1964
1965static const struct dev_pm_ops fimc_pm_ops = { 1965static const struct dev_pm_ops fimc_pm_ops = {
1966 SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend, fimc_resume) 1966 SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend, fimc_resume)
1967 SET_RUNTIME_PM_OPS(fimc_runtime_suspend, fimc_runtime_resume, NULL) 1967 SET_RUNTIME_PM_OPS(fimc_runtime_suspend, fimc_runtime_resume, NULL)
1968}; 1968};
1969 1969
1970static const struct of_device_id fimc_of_match[] = {
1971 { .compatible = "samsung,exynos4210-fimc" },
1972 { .compatible = "samsung,exynos4212-fimc" },
1973 { },
1974};
1975
1970struct platform_driver fimc_driver = { 1976struct platform_driver fimc_driver = {
1971 .probe = fimc_probe, 1977 .probe = fimc_probe,
1972 .remove = fimc_remove, 1978 .remove = fimc_remove,
1973 .id_table = fimc_driver_ids,
1974 .driver = { 1979 .driver = {
1980 .of_match_table = fimc_of_match,
1975 .name = "exynos-drm-fimc", 1981 .name = "exynos-drm-fimc",
1976 .owner = THIS_MODULE, 1982 .owner = THIS_MODULE,
1977 .pm = &fimc_pm_ops, 1983 .pm = &fimc_pm_ops,
diff --git a/drivers/gpu/drm/exynos/regs-fimc.h b/drivers/gpu/drm/exynos/regs-fimc.h
index b4f9ca1fd851..30496134a3d0 100644
--- a/drivers/gpu/drm/exynos/regs-fimc.h
+++ b/drivers/gpu/drm/exynos/regs-fimc.h
@@ -661,9 +661,8 @@
661#define EXYNOS_CLKSRC_SCLK (1 << 1) 661#define EXYNOS_CLKSRC_SCLK (1 << 1)
662 662
663/* SYSREG for FIMC writeback */ 663/* SYSREG for FIMC writeback */
664#define SYSREG_CAMERA_BLK (S3C_VA_SYS + 0x0218) 664#define SYSREG_CAMERA_BLK (0x0218)
665#define SYSREG_ISP_BLK (S3C_VA_SYS + 0x020c) 665#define SYSREG_FIMD0WB_DEST_MASK (0x3 << 23)
666#define SYSREG_FIMD0WB_DEST_MASK (0x3 << 23) 666#define SYSREG_FIMD0WB_DEST_SHIFT 23
667#define SYSREG_FIMD0WB_DEST_SHIFT 23
668 667
669#endif /* EXYNOS_REGS_FIMC_H */ 668#endif /* EXYNOS_REGS_FIMC_H */