Skip to content

Commit

Permalink
[media] s5p-mfc: Rework clock handling
Browse files Browse the repository at this point in the history
This patch changes the code for handling clocks. Now clocks are defined
per each device variant, what is a preparation for adding support for
Exynos 5433 MFC V8, which has more clocks than all previous versions.
Also use devm_clk_get() to simplify cleanup path.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
  • Loading branch information
Marek Szyprowski authored and Mauro Carvalho Chehab committed Nov 30, 2016
1 parent 741f433 commit 1bce6fb
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 59 deletions.
8 changes: 8 additions & 0 deletions drivers/media/platform/s5p-mfc/s5p_mfc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1434,6 +1434,8 @@ static struct s5p_mfc_variant mfc_drvdata_v5 = {
.buf_size = &buf_size_v5,
.buf_align = &mfc_buf_align_v5,
.fw_name[0] = "s5p-mfc.fw",
.clk_names = {"mfc", "sclk_mfc"},
.num_clocks = 2,
.use_clock_gating = true,
};

Expand Down Expand Up @@ -1467,6 +1469,8 @@ static struct s5p_mfc_variant mfc_drvdata_v6 = {
* for init buffer command
*/
.fw_name[1] = "s5p-mfc-v6-v2.fw",
.clk_names = {"mfc"},
.num_clocks = 1,
};

static struct s5p_mfc_buf_size_v6 mfc_buf_size_v7 = {
Expand Down Expand Up @@ -1494,6 +1498,8 @@ static struct s5p_mfc_variant mfc_drvdata_v7 = {
.buf_size = &buf_size_v7,
.buf_align = &mfc_buf_align_v7,
.fw_name[0] = "s5p-mfc-v7.fw",
.clk_names = {"mfc", "sclk_mfc"},
.num_clocks = 2,
};

static struct s5p_mfc_buf_size_v6 mfc_buf_size_v8 = {
Expand Down Expand Up @@ -1521,6 +1527,8 @@ static struct s5p_mfc_variant mfc_drvdata_v8 = {
.buf_size = &buf_size_v8,
.buf_align = &mfc_buf_align_v8,
.fw_name[0] = "s5p-mfc-v8.fw",
.clk_names = {"mfc"},
.num_clocks = 1,
};

static const struct of_device_id exynos_mfc_match[] = {
Expand Down
9 changes: 8 additions & 1 deletion drivers/media/platform/s5p-mfc/s5p_mfc_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b)
#define S5P_MFC_R2H_CMD_ENC_BUFFER_FUL_RET 16
#define S5P_MFC_R2H_CMD_ERR_RET 32

#define MFC_MAX_CLOCKS 4

#define mfc_read(dev, offset) readl(dev->regs_base + (offset))
#define mfc_write(dev, data, offset) writel((data), dev->regs_base + \
(offset))
Expand Down Expand Up @@ -197,9 +199,12 @@ struct s5p_mfc_buf {
* struct s5p_mfc_pm - power management data structure
*/
struct s5p_mfc_pm {
struct clk *clock;
struct clk *clock_gate;
const char **clk_names;
struct clk *clocks[MFC_MAX_CLOCKS];
int num_clocks;
bool use_clock_gating;

struct device *device;
};

Expand Down Expand Up @@ -235,6 +240,8 @@ struct s5p_mfc_variant {
struct s5p_mfc_buf_size *buf_size;
struct s5p_mfc_buf_align *buf_align;
char *fw_name[MFC_FW_MAX_VERSIONS];
const char *clk_names[MFC_MAX_CLOCKS];
int num_clocks;
bool use_clock_gating;
};

Expand Down
98 changes: 40 additions & 58 deletions drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,56 +18,42 @@
#include "s5p_mfc_debug.h"
#include "s5p_mfc_pm.h"

#define MFC_GATE_CLK_NAME "mfc"
#define MFC_SCLK_NAME "sclk_mfc"

static struct s5p_mfc_pm *pm;
static struct s5p_mfc_dev *p_dev;
static atomic_t clk_ref;

int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
{
int ret = 0;
int i;

pm = &dev->pm;
p_dev = dev;
pm->use_clock_gating = dev->variant->use_clock_gating;
pm->clock_gate = clk_get(&dev->plat_dev->dev, MFC_GATE_CLK_NAME);
if (IS_ERR(pm->clock_gate)) {
mfc_err("Failed to get clock-gating control\n");
ret = PTR_ERR(pm->clock_gate);
goto err_g_ip_clk;
}

if (dev->variant->version != MFC_VERSION_V6) {
pm->clock = clk_get(&dev->plat_dev->dev, MFC_SCLK_NAME);
if (IS_ERR(pm->clock)) {
mfc_info("Failed to get MFC special clock control\n");
pm->clock = NULL;
pm->num_clocks = dev->variant->num_clocks;
pm->clk_names = dev->variant->clk_names;
pm->device = &dev->plat_dev->dev;
pm->clock_gate = NULL;

/* clock control */
for (i = 0; i < pm->num_clocks; i++) {
pm->clocks[i] = devm_clk_get(pm->device, pm->clk_names[i]);
if (IS_ERR(pm->clocks[i])) {
mfc_err("Failed to get clock: %s\n",
pm->clk_names[i]);
return PTR_ERR(pm->clocks[i]);
}
}

pm->device = &dev->plat_dev->dev;
if (dev->variant->use_clock_gating)
pm->clock_gate = pm->clocks[0];

pm_runtime_enable(pm->device);
atomic_set(&clk_ref, 0);

return 0;

clk_put(pm->clock_gate);
pm->clock_gate = NULL;
err_g_ip_clk:
return ret;
}

void s5p_mfc_final_pm(struct s5p_mfc_dev *dev)
{
if (dev->variant->version != MFC_VERSION_V6 &&
pm->clock) {
clk_put(pm->clock);
pm->clock = NULL;
}
clk_put(pm->clock_gate);
pm->clock_gate = NULL;
pm_runtime_disable(pm->device);
}

Expand All @@ -76,8 +62,6 @@ int s5p_mfc_clock_on(void)
atomic_inc(&clk_ref);
mfc_debug(3, "+ %d\n", atomic_read(&clk_ref));

if (!pm->use_clock_gating)
return 0;
return clk_enable(pm->clock_gate);
}

Expand All @@ -86,50 +70,48 @@ void s5p_mfc_clock_off(void)
atomic_dec(&clk_ref);
mfc_debug(3, "- %d\n", atomic_read(&clk_ref));

if (!pm->use_clock_gating)
return;
clk_disable(pm->clock_gate);
}

int s5p_mfc_power_on(void)
{
int ret;
int i, ret = 0;

ret = pm_runtime_get_sync(pm->device);
if (ret)
if (ret < 0)
return ret;

ret = clk_prepare_enable(pm->clock_gate);
if (ret)
goto err_pm;

if (pm->clock) {
ret = clk_prepare_enable(pm->clock);
if (ret)
goto err_gate;
/* clock control */
for (i = 0; i < pm->num_clocks; i++) {
ret = clk_prepare_enable(pm->clocks[i]);
if (ret < 0) {
mfc_err("clock prepare failed for clock: %s\n",
pm->clk_names[i]);
i++;
goto err;
}
}

if (pm->use_clock_gating)
clk_disable(pm->clock_gate);
return 0;
/* prepare for software clock gating */
clk_disable(pm->clock_gate);

err_gate:
clk_disable_unprepare(pm->clock_gate);
err_pm:
pm_runtime_put_sync(pm->device);
return 0;
err:
while (--i > 0)
clk_disable_unprepare(pm->clocks[i]);
pm_runtime_put(pm->device);
return ret;

}

int s5p_mfc_power_off(void)
{
if (pm->clock)
clk_disable_unprepare(pm->clock);
int i;

/* finish software clock gating */
clk_enable(pm->clock_gate);

if (pm->use_clock_gating)
clk_unprepare(pm->clock_gate);
else
clk_disable_unprepare(pm->clock_gate);
for (i = 0; i < pm->num_clocks; i++)
clk_disable_unprepare(pm->clocks[i]);

return pm_runtime_put_sync(pm->device);
}
Expand Down

0 comments on commit 1bce6fb

Please sign in to comment.