aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/exynos/exynos_drm_fimc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_fimc.c')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimc.c169
1 files changed, 99 insertions, 70 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
index d812c5743eaf..2cce97d42ece 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 {
76 FIMC_WB_B, 76 FIMC_WB_B,
77}; 77};
78 78
79enum {
80 FIMC_CLK_LCLK,
81 FIMC_CLK_GATE,
82 FIMC_CLK_WB_A,
83 FIMC_CLK_WB_B,
84 FIMC_CLK_MUX,
85 FIMC_CLK_PARENT,
86 FIMC_CLKS_MAX
87};
88
89static const char * const fimc_clock_names[] = {
90 [FIMC_CLK_LCLK] = "sclk_fimc",
91 [FIMC_CLK_GATE] = "fimc",
92 [FIMC_CLK_WB_A] = "pxl_async0",
93 [FIMC_CLK_WB_B] = "pxl_async1",
94 [FIMC_CLK_MUX] = "mux",
95 [FIMC_CLK_PARENT] = "parent",
96};
97
98#define FIMC_DEFAULT_LCLK_FREQUENCY 133000000UL
99
79/* 100/*
80 * A structure of scaler. 101 * A structure of scaler.
81 * 102 *
@@ -134,13 +155,9 @@ struct fimc_driverdata {
134 * @regs_res: register resources. 155 * @regs_res: register resources.
135 * @regs: memory mapped io registers. 156 * @regs: memory mapped io registers.
136 * @lock: locking of operations. 157 * @lock: locking of operations.
137 * @sclk_fimc_clk: fimc source clock. 158 * @clocks: fimc clocks.
138 * @fimc_clk: fimc clock. 159 * @clk_frequency: LCLK clock frequency.
139 * @wb_clk: writeback a clock.
140 * @wb_b_clk: writeback b clock.
141 * @sc: scaler infomations. 160 * @sc: scaler infomations.
142 * @odr: ordering of YUV.
143 * @ver: fimc version.
144 * @pol: porarity of writeback. 161 * @pol: porarity of writeback.
145 * @id: fimc id. 162 * @id: fimc id.
146 * @irq: irq number. 163 * @irq: irq number.
@@ -151,10 +168,8 @@ struct fimc_context {
151 struct resource *regs_res; 168 struct resource *regs_res;
152 void __iomem *regs; 169 void __iomem *regs;
153 struct mutex lock; 170 struct mutex lock;
154 struct clk *sclk_fimc_clk; 171 struct clk *clocks[FIMC_CLKS_MAX];
155 struct clk *fimc_clk; 172 u32 clk_frequency;
156 struct clk *wb_clk;
157 struct clk *wb_b_clk;
158 struct fimc_scaler sc; 173 struct fimc_scaler sc;
159 struct fimc_driverdata *ddata; 174 struct fimc_driverdata *ddata;
160 struct exynos_drm_ipp_pol pol; 175 struct exynos_drm_ipp_pol pol;
@@ -1301,14 +1316,12 @@ static int fimc_clk_ctrl(struct fimc_context *ctx, bool enable)
1301 DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable); 1316 DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
1302 1317
1303 if (enable) { 1318 if (enable) {
1304 clk_enable(ctx->sclk_fimc_clk); 1319 clk_prepare_enable(ctx->clocks[FIMC_CLK_GATE]);
1305 clk_enable(ctx->fimc_clk); 1320 clk_prepare_enable(ctx->clocks[FIMC_CLK_WB_A]);
1306 clk_enable(ctx->wb_clk);
1307 ctx->suspended = false; 1321 ctx->suspended = false;
1308 } else { 1322 } else {
1309 clk_disable(ctx->sclk_fimc_clk); 1323 clk_disable_unprepare(ctx->clocks[FIMC_CLK_GATE]);
1310 clk_disable(ctx->fimc_clk); 1324 clk_disable_unprepare(ctx->clocks[FIMC_CLK_WB_A]);
1311 clk_disable(ctx->wb_clk);
1312 ctx->suspended = true; 1325 ctx->suspended = true;
1313 } 1326 }
1314 1327
@@ -1713,11 +1726,70 @@ static void fimc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd)
1713 fimc_write(cfg, EXYNOS_CIGCTRL); 1726 fimc_write(cfg, EXYNOS_CIGCTRL);
1714} 1727}
1715 1728
1729static void fimc_put_clocks(struct fimc_context *ctx)
1730{
1731 int i;
1732
1733 for (i = 0; i < FIMC_CLKS_MAX; i++) {
1734 if (IS_ERR(ctx->clocks[i]))
1735 continue;
1736 clk_put(ctx->clocks[i]);
1737 ctx->clocks[i] = ERR_PTR(-EINVAL);
1738 }
1739}
1740
1741static int fimc_setup_clocks(struct fimc_context *ctx)
1742{
1743 struct device *fimc_dev = ctx->ippdrv.dev;
1744 struct device *dev;
1745 int ret, i;
1746
1747 for (i = 0; i < FIMC_CLKS_MAX; i++)
1748 ctx->clocks[i] = ERR_PTR(-EINVAL);
1749
1750 for (i = 0; i < FIMC_CLKS_MAX; i++) {
1751 if (i == FIMC_CLK_WB_A || i == FIMC_CLK_WB_B)
1752 dev = fimc_dev->parent;
1753 else
1754 dev = fimc_dev;
1755
1756 ctx->clocks[i] = clk_get(dev, fimc_clock_names[i]);
1757 if (IS_ERR(ctx->clocks[i])) {
1758 if (i >= FIMC_CLK_MUX)
1759 break;
1760 ret = PTR_ERR(ctx->clocks[i]);
1761 dev_err(fimc_dev, "failed to get clock: %s\n",
1762 fimc_clock_names[i]);
1763 goto e_clk_free;
1764 }
1765 }
1766
1767 /* Optional FIMC LCLK parent clock setting */
1768 if (!IS_ERR(ctx->clocks[FIMC_CLK_PARENT])) {
1769 ret = clk_set_parent(ctx->clocks[FIMC_CLK_MUX],
1770 ctx->clocks[FIMC_CLK_PARENT]);
1771 if (ret < 0) {
1772 dev_err(fimc_dev, "failed to set parent.\n");
1773 goto e_clk_free;
1774 }
1775 }
1776
1777 ret = clk_set_rate(ctx->clocks[FIMC_CLK_LCLK], ctx->clk_frequency);
1778 if (ret < 0)
1779 goto e_clk_free;
1780
1781 ret = clk_prepare_enable(ctx->clocks[FIMC_CLK_LCLK]);
1782 if (!ret)
1783 return ret;
1784e_clk_free:
1785 fimc_put_clocks(ctx);
1786 return ret;
1787}
1788
1716static int fimc_probe(struct platform_device *pdev) 1789static int fimc_probe(struct platform_device *pdev)
1717{ 1790{
1718 struct device *dev = &pdev->dev; 1791 struct device *dev = &pdev->dev;
1719 struct fimc_context *ctx; 1792 struct fimc_context *ctx;
1720 struct clk *parent_clk;
1721 struct resource *res; 1793 struct resource *res;
1722 struct exynos_drm_ippdrv *ippdrv; 1794 struct exynos_drm_ippdrv *ippdrv;
1723 struct exynos_drm_fimc_pdata *pdata; 1795 struct exynos_drm_fimc_pdata *pdata;
@@ -1734,55 +1806,6 @@ static int fimc_probe(struct platform_device *pdev)
1734 if (!ctx) 1806 if (!ctx)
1735 return -ENOMEM; 1807 return -ENOMEM;
1736 1808
1737 ddata = (struct fimc_driverdata *)
1738 platform_get_device_id(pdev)->driver_data;
1739
1740 /* clock control */
1741 ctx->sclk_fimc_clk = devm_clk_get(dev, "sclk_fimc");
1742 if (IS_ERR(ctx->sclk_fimc_clk)) {
1743 dev_err(dev, "failed to get src fimc clock.\n");
1744 return PTR_ERR(ctx->sclk_fimc_clk);
1745 }
1746 clk_enable(ctx->sclk_fimc_clk);
1747
1748 ctx->fimc_clk = devm_clk_get(dev, "fimc");
1749 if (IS_ERR(ctx->fimc_clk)) {
1750 dev_err(dev, "failed to get fimc clock.\n");
1751 clk_disable(ctx->sclk_fimc_clk);
1752 return PTR_ERR(ctx->fimc_clk);
1753 }
1754
1755 ctx->wb_clk = devm_clk_get(dev, "pxl_async0");
1756 if (IS_ERR(ctx->wb_clk)) {
1757 dev_err(dev, "failed to get writeback a clock.\n");
1758 clk_disable(ctx->sclk_fimc_clk);
1759 return PTR_ERR(ctx->wb_clk);
1760 }
1761
1762 ctx->wb_b_clk = devm_clk_get(dev, "pxl_async1");
1763 if (IS_ERR(ctx->wb_b_clk)) {
1764 dev_err(dev, "failed to get writeback b clock.\n");
1765 clk_disable(ctx->sclk_fimc_clk);
1766 return PTR_ERR(ctx->wb_b_clk);
1767 }
1768
1769 parent_clk = devm_clk_get(dev, ddata->parent_clk);
1770
1771 if (IS_ERR(parent_clk)) {
1772 dev_err(dev, "failed to get parent clock.\n");
1773 clk_disable(ctx->sclk_fimc_clk);
1774 return PTR_ERR(parent_clk);
1775 }
1776
1777 if (clk_set_parent(ctx->sclk_fimc_clk, parent_clk)) {
1778 dev_err(dev, "failed to set parent.\n");
1779 clk_disable(ctx->sclk_fimc_clk);
1780 return -EINVAL;
1781 }
1782
1783 devm_clk_put(dev, parent_clk);
1784 clk_set_rate(ctx->sclk_fimc_clk, pdata->clk_rate);
1785
1786 /* resource memory */ 1809 /* resource memory */
1787 ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1810 ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1788 ctx->regs = devm_ioremap_resource(dev, ctx->regs_res); 1811 ctx->regs = devm_ioremap_resource(dev, ctx->regs_res);
@@ -1804,6 +1827,9 @@ static int fimc_probe(struct platform_device *pdev)
1804 return ret; 1827 return ret;
1805 } 1828 }
1806 1829
1830 ret = fimc_setup_clocks(ctx);
1831 if (ret < 0)
1832 goto err_free_irq;
1807 /* context initailization */ 1833 /* context initailization */
1808 ctx->id = pdev->id; 1834 ctx->id = pdev->id;
1809 ctx->pol = pdata->pol; 1835 ctx->pol = pdata->pol;
@@ -1820,7 +1846,7 @@ static int fimc_probe(struct platform_device *pdev)
1820 ret = fimc_init_prop_list(ippdrv); 1846 ret = fimc_init_prop_list(ippdrv);
1821 if (ret < 0) { 1847 if (ret < 0) {
1822 dev_err(dev, "failed to init property list.\n"); 1848 dev_err(dev, "failed to init property list.\n");
1823 goto err_get_irq; 1849 goto err_put_clk;
1824 } 1850 }
1825 1851
1826 DRM_DEBUG_KMS("%s:id[%d]ippdrv[0x%x]\n", __func__, ctx->id, 1852 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)
1835 ret = exynos_drm_ippdrv_register(ippdrv); 1861 ret = exynos_drm_ippdrv_register(ippdrv);
1836 if (ret < 0) { 1862 if (ret < 0) {
1837 dev_err(dev, "failed to register drm fimc device.\n"); 1863 dev_err(dev, "failed to register drm fimc device.\n");
1838 goto err_ippdrv_register; 1864 goto err_pm_dis;
1839 } 1865 }
1840 1866
1841 dev_info(&pdev->dev, "drm fimc registered successfully.\n"); 1867 dev_info(&pdev->dev, "drm fimc registered successfully.\n");
1842 1868
1843 return 0; 1869 return 0;
1844 1870
1845err_ippdrv_register: 1871err_pm_dis:
1846 pm_runtime_disable(dev); 1872 pm_runtime_disable(dev);
1847err_get_irq: 1873err_put_clk:
1874 fimc_put_clocks(ctx);
1875err_free_irq:
1848 free_irq(ctx->irq, ctx); 1876 free_irq(ctx->irq, ctx);
1849 1877
1850 return ret; 1878 return ret;
@@ -1859,6 +1887,7 @@ static int fimc_remove(struct platform_device *pdev)
1859 exynos_drm_ippdrv_unregister(ippdrv); 1887 exynos_drm_ippdrv_unregister(ippdrv);
1860 mutex_destroy(&ctx->lock); 1888 mutex_destroy(&ctx->lock);
1861 1889
1890 fimc_put_clocks(ctx);
1862 pm_runtime_set_suspended(dev); 1891 pm_runtime_set_suspended(dev);
1863 pm_runtime_disable(dev); 1892 pm_runtime_disable(dev);
1864 1893