Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Sylwester Nawrocki and committed by
Inki Dae
5186fc5e e5f86839

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