diff options
author | Robby Cai <R63905@freescale.com> | 2014-02-18 22:37:33 -0500 |
---|---|---|
committer | Nitin Garg <nitin.garg@freescale.com> | 2014-04-16 09:57:38 -0400 |
commit | 5a062b2edf4e91b91bf282ab1c9fca28d9a68d3f (patch) | |
tree | 96039eb0959d136ab6054b340af068d5f67ec0c9 /drivers/video | |
parent | a5f76c96ceb4e6faa3ff6c9aec6a50ef3fde708f (diff) |
ENGR00299746-3 imx: lcdif: add disp_axi clock handling for imx6sx
The display axi clock is a clock gating newly added on imx6sx.
It need to be enabled for lcdif/pxp/csi/pcie to work.
It should be set as a placeholder on other SoCs.
This patch also simplifies the sanity check for axi and pixel clock.
Signed-off-by: Sandor Yu <R01008@freescale.com>
Signed-off-by: Robby Cai <R63905@freescale.com>
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/mxsfb.c | 43 |
1 files changed, 39 insertions, 4 deletions
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index 7b0304af8665..cbca5c65d2e4 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c | |||
@@ -187,7 +187,9 @@ struct mxsfb_info { | |||
187 | struct platform_device *pdev; | 187 | struct platform_device *pdev; |
188 | struct clk *clk_pix; | 188 | struct clk *clk_pix; |
189 | struct clk *clk_axi; | 189 | struct clk *clk_axi; |
190 | struct clk *clk_disp_axi; | ||
190 | bool clk_axi_enabled; | 191 | bool clk_axi_enabled; |
192 | bool clk_disp_axi_enabled; | ||
191 | void __iomem *base; /* registers */ | 193 | void __iomem *base; /* registers */ |
192 | unsigned allocated_size; | 194 | unsigned allocated_size; |
193 | int enabled; | 195 | int enabled; |
@@ -234,8 +236,7 @@ static int mxsfb_unmap_videomem(struct fb_info *info); | |||
234 | /* enable lcdif axi clock */ | 236 | /* enable lcdif axi clock */ |
235 | static inline void clk_enable_axi(struct mxsfb_info *host) | 237 | static inline void clk_enable_axi(struct mxsfb_info *host) |
236 | { | 238 | { |
237 | if (!host->clk_axi_enabled && host && | 239 | if (!host->clk_axi_enabled && (host->clk_axi != NULL)) { |
238 | host->clk_axi && !IS_ERR(host->clk_axi)) { | ||
239 | clk_prepare_enable(host->clk_axi); | 240 | clk_prepare_enable(host->clk_axi); |
240 | host->clk_axi_enabled = true; | 241 | host->clk_axi_enabled = true; |
241 | } | 242 | } |
@@ -244,13 +245,30 @@ static inline void clk_enable_axi(struct mxsfb_info *host) | |||
244 | /* disable lcdif axi clock */ | 245 | /* disable lcdif axi clock */ |
245 | static inline void clk_disable_axi(struct mxsfb_info *host) | 246 | static inline void clk_disable_axi(struct mxsfb_info *host) |
246 | { | 247 | { |
247 | if (host->clk_axi_enabled && host && | 248 | if (host->clk_axi_enabled && (host->clk_axi != NULL)) { |
248 | host->clk_axi && !IS_ERR(host->clk_axi)) { | ||
249 | clk_disable_unprepare(host->clk_axi); | 249 | clk_disable_unprepare(host->clk_axi); |
250 | host->clk_axi_enabled = false; | 250 | host->clk_axi_enabled = false; |
251 | } | 251 | } |
252 | } | 252 | } |
253 | 253 | ||
254 | /* enable DISP axi clock */ | ||
255 | static inline void clk_enable_disp_axi(struct mxsfb_info *host) | ||
256 | { | ||
257 | if (!host->clk_disp_axi_enabled && (host->clk_disp_axi != NULL)) { | ||
258 | clk_prepare_enable(host->clk_disp_axi); | ||
259 | host->clk_disp_axi_enabled = true; | ||
260 | } | ||
261 | } | ||
262 | |||
263 | /* disable DISP axi clock */ | ||
264 | static inline void clk_disable_disp_axi(struct mxsfb_info *host) | ||
265 | { | ||
266 | if (host->clk_disp_axi_enabled && (host->clk_disp_axi != NULL)) { | ||
267 | clk_disable_unprepare(host->clk_disp_axi); | ||
268 | host->clk_disp_axi_enabled = false; | ||
269 | } | ||
270 | } | ||
271 | |||
254 | /* mask and shift depends on architecture */ | 272 | /* mask and shift depends on architecture */ |
255 | static inline u32 set_hsync_pulse_width(struct mxsfb_info *host, unsigned val) | 273 | static inline u32 set_hsync_pulse_width(struct mxsfb_info *host, unsigned val) |
256 | { | 274 | { |
@@ -430,6 +448,7 @@ static void mxsfb_enable_controller(struct fb_info *fb_info) | |||
430 | pm_runtime_get_sync(&host->pdev->dev); | 448 | pm_runtime_get_sync(&host->pdev->dev); |
431 | 449 | ||
432 | clk_enable_axi(host); | 450 | clk_enable_axi(host); |
451 | clk_enable_disp_axi(host); | ||
433 | 452 | ||
434 | clk_prepare_enable(host->clk_pix); | 453 | clk_prepare_enable(host->clk_pix); |
435 | clk_set_rate(host->clk_pix, PICOS2KHZ(fb_info->var.pixclock) * 1000U); | 454 | clk_set_rate(host->clk_pix, PICOS2KHZ(fb_info->var.pixclock) * 1000U); |
@@ -464,6 +483,7 @@ static void mxsfb_disable_controller(struct fb_info *fb_info) | |||
464 | dev_dbg(&host->pdev->dev, "%s\n", __func__); | 483 | dev_dbg(&host->pdev->dev, "%s\n", __func__); |
465 | 484 | ||
466 | clk_enable_axi(host); | 485 | clk_enable_axi(host); |
486 | clk_enable_disp_axi(host); | ||
467 | /* | 487 | /* |
468 | * Even if we disable the controller here, it will still continue | 488 | * Even if we disable the controller here, it will still continue |
469 | * until its FIFOs are running out of data | 489 | * until its FIFOs are running out of data |
@@ -505,6 +525,7 @@ static int mxsfb_set_par(struct fb_info *fb_info) | |||
505 | int reenable = 0; | 525 | int reenable = 0; |
506 | 526 | ||
507 | clk_enable_axi(host); | 527 | clk_enable_axi(host); |
528 | clk_enable_disp_axi(host); | ||
508 | 529 | ||
509 | dev_dbg(&host->pdev->dev, "%s\n", __func__); | 530 | dev_dbg(&host->pdev->dev, "%s\n", __func__); |
510 | /* | 531 | /* |
@@ -726,6 +747,7 @@ static int mxsfb_blank(int blank, struct fb_info *fb_info) | |||
726 | if (host->enabled) | 747 | if (host->enabled) |
727 | mxsfb_disable_controller(fb_info); | 748 | mxsfb_disable_controller(fb_info); |
728 | 749 | ||
750 | clk_disable_disp_axi(host); | ||
729 | clk_disable_axi(host); | 751 | clk_disable_axi(host); |
730 | break; | 752 | break; |
731 | 753 | ||
@@ -761,6 +783,7 @@ static int mxsfb_pan_display(struct fb_var_screeninfo *var, | |||
761 | } | 783 | } |
762 | 784 | ||
763 | clk_enable_axi(host); | 785 | clk_enable_axi(host); |
786 | clk_enable_disp_axi(host); | ||
764 | 787 | ||
765 | offset = fb_info->fix.line_length * var->yoffset; | 788 | offset = fb_info->fix.line_length * var->yoffset; |
766 | 789 | ||
@@ -834,6 +857,7 @@ static int mxsfb_restore_mode(struct mxsfb_info *host) | |||
834 | struct fb_videomode vmode; | 857 | struct fb_videomode vmode; |
835 | 858 | ||
836 | clk_enable_axi(host); | 859 | clk_enable_axi(host); |
860 | clk_enable_disp_axi(host); | ||
837 | 861 | ||
838 | /* Only restore the mode when the controller is running */ | 862 | /* Only restore the mode when the controller is running */ |
839 | ctrl = readl(host->base + LCDC_CTRL); | 863 | ctrl = readl(host->base + LCDC_CTRL); |
@@ -1190,16 +1214,25 @@ static int mxsfb_probe(struct platform_device *pdev) | |||
1190 | 1214 | ||
1191 | host->clk_pix = devm_clk_get(&host->pdev->dev, "pix"); | 1215 | host->clk_pix = devm_clk_get(&host->pdev->dev, "pix"); |
1192 | if (IS_ERR(host->clk_pix)) { | 1216 | if (IS_ERR(host->clk_pix)) { |
1217 | host->clk_pix = NULL; | ||
1193 | ret = PTR_ERR(host->clk_pix); | 1218 | ret = PTR_ERR(host->clk_pix); |
1194 | goto fb_release; | 1219 | goto fb_release; |
1195 | } | 1220 | } |
1196 | 1221 | ||
1197 | host->clk_axi = devm_clk_get(&host->pdev->dev, "axi"); | 1222 | host->clk_axi = devm_clk_get(&host->pdev->dev, "axi"); |
1198 | if (IS_ERR(host->clk_axi)) { | 1223 | if (IS_ERR(host->clk_axi)) { |
1224 | host->clk_axi = NULL; | ||
1199 | ret = PTR_ERR(host->clk_axi); | 1225 | ret = PTR_ERR(host->clk_axi); |
1200 | goto fb_release; | 1226 | goto fb_release; |
1201 | } | 1227 | } |
1202 | 1228 | ||
1229 | host->clk_disp_axi = devm_clk_get(&host->pdev->dev, "disp_axi"); | ||
1230 | if (IS_ERR(host->clk_disp_axi)) { | ||
1231 | host->clk_disp_axi = NULL; | ||
1232 | ret = PTR_ERR(host->clk_disp_axi); | ||
1233 | goto fb_release; | ||
1234 | } | ||
1235 | |||
1203 | host->reg_lcd = devm_regulator_get(&pdev->dev, "lcd"); | 1236 | host->reg_lcd = devm_regulator_get(&pdev->dev, "lcd"); |
1204 | if (IS_ERR(host->reg_lcd)) | 1237 | if (IS_ERR(host->reg_lcd)) |
1205 | host->reg_lcd = NULL; | 1238 | host->reg_lcd = NULL; |
@@ -1274,12 +1307,14 @@ static void mxsfb_shutdown(struct platform_device *pdev) | |||
1274 | struct mxsfb_info *host = to_imxfb_host(fb_info); | 1307 | struct mxsfb_info *host = to_imxfb_host(fb_info); |
1275 | 1308 | ||
1276 | clk_enable_axi(host); | 1309 | clk_enable_axi(host); |
1310 | clk_enable_disp_axi(host); | ||
1277 | /* | 1311 | /* |
1278 | * Force stop the LCD controller as keeping it running during reboot | 1312 | * Force stop the LCD controller as keeping it running during reboot |
1279 | * might interfere with the BootROM's boot mode pads sampling. | 1313 | * might interfere with the BootROM's boot mode pads sampling. |
1280 | */ | 1314 | */ |
1281 | writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR); | 1315 | writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR); |
1282 | writel(CTRL_MASTER, host->base + LCDC_CTRL + REG_CLR); | 1316 | writel(CTRL_MASTER, host->base + LCDC_CTRL + REG_CLR); |
1317 | clk_disable_disp_axi(host); | ||
1283 | clk_disable_axi(host); | 1318 | clk_disable_axi(host); |
1284 | } | 1319 | } |
1285 | 1320 | ||