Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 371615
b: refs/heads/master
c: e5f8683
h: refs/heads/master
i:
  371613: fa7db11
  371611: 971dfbb
  371607: 3d59d00
  371599: a6df0ed
  371583: af447ba
v: v3
  • Loading branch information
Sylwester Nawrocki authored and Inki Dae committed Apr 29, 2013
1 parent cbe59c5 commit 87644be
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 71 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 4c30cbc0b9c89d90c5a0d08bfb62d7a6b6c88d33
refs/heads/master: e5f8683923af2fd2bb0c5a7c0a66597cc6b50ef3
169 changes: 99 additions & 70 deletions trunk/drivers/gpu/drm/exynos/exynos_drm_fimc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down Expand Up @@ -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.
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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,
Expand All @@ -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;
Expand All @@ -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);

Expand Down

0 comments on commit 87644be

Please sign in to comment.