diff options
author | Libin Yang <lbyang@marvell.com> | 2013-07-03 00:55:59 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2013-07-26 12:23:10 -0400 |
commit | 0e394f44fbd6d6bf87afd37cee74bc341019f86b (patch) | |
tree | 618b48ee1903aabf040751b50269ee906e9c904c /drivers/media/platform/marvell-ccic | |
parent | 05fed81625bf755cc67c5864cdfd18b69ea828d1 (diff) |
[media] marvell-ccic: add clock tree support for marvell-ccic driver
This patch adds the clock tree support for marvell-ccic.
Signed-off-by: Libin Yang <lbyang@marvell.com>
Signed-off-by: Albert Wang <twang13@marvell.com>
Acked-by: Jonathan Corbet <corbet@lwn.net>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/platform/marvell-ccic')
-rw-r--r-- | drivers/media/platform/marvell-ccic/mcam-core.h | 5 | ||||
-rw-r--r-- | drivers/media/platform/marvell-ccic/mmp-driver.c | 61 |
2 files changed, 66 insertions, 0 deletions
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h index 74394325dc4f..0de7e5fda836 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.h +++ b/drivers/media/platform/marvell-ccic/mcam-core.h | |||
@@ -88,6 +88,8 @@ struct mcam_frame_state { | |||
88 | unsigned int delivered; | 88 | unsigned int delivered; |
89 | }; | 89 | }; |
90 | 90 | ||
91 | #define NR_MCAM_CLK 3 | ||
92 | |||
91 | /* | 93 | /* |
92 | * A description of one of our devices. | 94 | * A description of one of our devices. |
93 | * Locking: controlled by s_mutex. Certain fields, however, require | 95 | * Locking: controlled by s_mutex. Certain fields, however, require |
@@ -124,6 +126,9 @@ struct mcam_camera { | |||
124 | bool mipi_enabled; /* flag whether mipi is enabled already */ | 126 | bool mipi_enabled; /* flag whether mipi is enabled already */ |
125 | int lane; /* lane number */ | 127 | int lane; /* lane number */ |
126 | 128 | ||
129 | /* clock tree support */ | ||
130 | struct clk *clk[NR_MCAM_CLK]; | ||
131 | |||
127 | /* | 132 | /* |
128 | * Callbacks from the core to the platform code. | 133 | * Callbacks from the core to the platform code. |
129 | */ | 134 | */ |
diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c index bd03668e7f0e..e7be4109797c 100644 --- a/drivers/media/platform/marvell-ccic/mmp-driver.c +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c | |||
@@ -34,6 +34,8 @@ MODULE_ALIAS("platform:mmp-camera"); | |||
34 | MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>"); | 34 | MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>"); |
35 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
36 | 36 | ||
37 | static char *mcam_clks[] = {"CCICAXICLK", "CCICFUNCLK", "CCICPHYCLK"}; | ||
38 | |||
37 | struct mmp_camera { | 39 | struct mmp_camera { |
38 | void *power_regs; | 40 | void *power_regs; |
39 | struct platform_device *pdev; | 41 | struct platform_device *pdev; |
@@ -104,6 +106,26 @@ static struct mmp_camera *mmpcam_find_device(struct platform_device *pdev) | |||
104 | #define REG_CCIC_DCGCR 0x28 /* CCIC dyn clock gate ctrl reg */ | 106 | #define REG_CCIC_DCGCR 0x28 /* CCIC dyn clock gate ctrl reg */ |
105 | #define REG_CCIC_CRCR 0x50 /* CCIC clk reset ctrl reg */ | 107 | #define REG_CCIC_CRCR 0x50 /* CCIC clk reset ctrl reg */ |
106 | 108 | ||
109 | static void mcam_clk_enable(struct mcam_camera *mcam) | ||
110 | { | ||
111 | unsigned int i; | ||
112 | |||
113 | for (i = 0; i < NR_MCAM_CLK; i++) { | ||
114 | if (!IS_ERR(mcam->clk[i])) | ||
115 | clk_prepare_enable(mcam->clk[i]); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | static void mcam_clk_disable(struct mcam_camera *mcam) | ||
120 | { | ||
121 | int i; | ||
122 | |||
123 | for (i = NR_MCAM_CLK - 1; i >= 0; i--) { | ||
124 | if (!IS_ERR(mcam->clk[i])) | ||
125 | clk_disable_unprepare(mcam->clk[i]); | ||
126 | } | ||
127 | } | ||
128 | |||
107 | /* | 129 | /* |
108 | * Power control. | 130 | * Power control. |
109 | */ | 131 | */ |
@@ -141,6 +163,9 @@ static int mmpcam_power_up(struct mcam_camera *mcam) | |||
141 | mdelay(5); | 163 | mdelay(5); |
142 | gpio_set_value(pdata->sensor_reset_gpio, 1); /* reset is active low */ | 164 | gpio_set_value(pdata->sensor_reset_gpio, 1); /* reset is active low */ |
143 | mdelay(5); | 165 | mdelay(5); |
166 | |||
167 | mcam_clk_enable(mcam); | ||
168 | |||
144 | return 0; | 169 | return 0; |
145 | } | 170 | } |
146 | 171 | ||
@@ -165,6 +190,8 @@ static void mmpcam_power_down(struct mcam_camera *mcam) | |||
165 | devm_clk_put(mcam->dev, cam->mipi_clk); | 190 | devm_clk_put(mcam->dev, cam->mipi_clk); |
166 | cam->mipi_clk = NULL; | 191 | cam->mipi_clk = NULL; |
167 | } | 192 | } |
193 | |||
194 | mcam_clk_disable(mcam); | ||
168 | } | 195 | } |
169 | 196 | ||
170 | /* | 197 | /* |
@@ -275,6 +302,35 @@ static irqreturn_t mmpcam_irq(int irq, void *data) | |||
275 | return IRQ_RETVAL(handled); | 302 | return IRQ_RETVAL(handled); |
276 | } | 303 | } |
277 | 304 | ||
305 | static void mcam_deinit_clk(struct mcam_camera *mcam) | ||
306 | { | ||
307 | unsigned int i; | ||
308 | |||
309 | for (i = 0; i < NR_MCAM_CLK; i++) { | ||
310 | if (!IS_ERR(mcam->clk[i])) { | ||
311 | if (mcam->clk[i]) | ||
312 | devm_clk_put(mcam->dev, mcam->clk[i]); | ||
313 | } | ||
314 | mcam->clk[i] = NULL; | ||
315 | } | ||
316 | } | ||
317 | |||
318 | static void mcam_init_clk(struct mcam_camera *mcam) | ||
319 | { | ||
320 | unsigned int i; | ||
321 | |||
322 | for (i = 0; i < NR_MCAM_CLK; i++) { | ||
323 | if (mcam_clks[i] != NULL) { | ||
324 | /* Some clks are not necessary on some boards | ||
325 | * We still try to run even it fails getting clk | ||
326 | */ | ||
327 | mcam->clk[i] = devm_clk_get(mcam->dev, mcam_clks[i]); | ||
328 | if (IS_ERR(mcam->clk[i])) | ||
329 | dev_warn(mcam->dev, "Could not get clk: %s\n", | ||
330 | mcam_clks[i]); | ||
331 | } | ||
332 | } | ||
333 | } | ||
278 | 334 | ||
279 | static int mmpcam_probe(struct platform_device *pdev) | 335 | static int mmpcam_probe(struct platform_device *pdev) |
280 | { | 336 | { |
@@ -370,6 +426,9 @@ static int mmpcam_probe(struct platform_device *pdev) | |||
370 | goto out_gpio; | 426 | goto out_gpio; |
371 | } | 427 | } |
372 | gpio_direction_output(pdata->sensor_reset_gpio, 0); | 428 | gpio_direction_output(pdata->sensor_reset_gpio, 0); |
429 | |||
430 | mcam_init_clk(mcam); | ||
431 | |||
373 | /* | 432 | /* |
374 | * Power the device up and hand it off to the core. | 433 | * Power the device up and hand it off to the core. |
375 | */ | 434 | */ |
@@ -401,6 +460,7 @@ out_unregister: | |||
401 | out_pwdn: | 460 | out_pwdn: |
402 | mmpcam_power_down(mcam); | 461 | mmpcam_power_down(mcam); |
403 | out_gpio2: | 462 | out_gpio2: |
463 | mcam_deinit_clk(mcam); | ||
404 | gpio_free(pdata->sensor_reset_gpio); | 464 | gpio_free(pdata->sensor_reset_gpio); |
405 | out_gpio: | 465 | out_gpio: |
406 | gpio_free(pdata->sensor_power_gpio); | 466 | gpio_free(pdata->sensor_power_gpio); |
@@ -426,6 +486,7 @@ static int mmpcam_remove(struct mmp_camera *cam) | |||
426 | pdata = cam->pdev->dev.platform_data; | 486 | pdata = cam->pdev->dev.platform_data; |
427 | gpio_free(pdata->sensor_reset_gpio); | 487 | gpio_free(pdata->sensor_reset_gpio); |
428 | gpio_free(pdata->sensor_power_gpio); | 488 | gpio_free(pdata->sensor_power_gpio); |
489 | mcam_deinit_clk(mcam); | ||
429 | iounmap(cam->power_regs); | 490 | iounmap(cam->power_regs); |
430 | iounmap(mcam->regs); | 491 | iounmap(mcam->regs); |
431 | kfree(cam); | 492 | kfree(cam); |