aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Agner <stefan@agner.ch>2016-03-22 21:06:08 -0400
committerStefan Agner <stefan@agner.ch>2016-04-25 23:27:18 -0400
commit2d701449bce1b7ddb0a7d85de7479c7422ee0e42 (patch)
tree74607f258876165b8d90e77c0ac1ddcdcc2ec769
parentf93500f430733178dfd8f9c80e52b13d0f273dd3 (diff)
drm/fsl-dcu: use common clock framework for pixel clock divider
Use the common clock framework to calculate the pixel clock dividier. The previous implementation rounded down the calculated factor. Thanks to the CLK_DIVIDER_ROUND_CLOSEST flag using the common clock framework divider implementation improves the pixel clock accuracy in some cases. Ontop of that it also allows to see the actual pixel clock in the sysfs clock summary. Signed-off-by: Stefan Agner <stefan@agner.ch>
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c7
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c26
2 files changed, 24 insertions, 9 deletions
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
index 87d85faaac6a..365809edf29a 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
@@ -67,12 +67,10 @@ static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
67 struct drm_device *dev = crtc->dev; 67 struct drm_device *dev = crtc->dev;
68 struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; 68 struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
69 struct drm_display_mode *mode = &crtc->state->mode; 69 struct drm_display_mode *mode = &crtc->state->mode;
70 unsigned int hbp, hfp, hsw, vbp, vfp, vsw, div, index, pol = 0; 70 unsigned int hbp, hfp, hsw, vbp, vfp, vsw, index, pol = 0;
71 unsigned long dcuclk;
72 71
73 index = drm_crtc_index(crtc); 72 index = drm_crtc_index(crtc);
74 dcuclk = clk_get_rate(fsl_dev->pix_clk); 73 clk_set_rate(fsl_dev->pix_clk, mode->clock * 1000);
75 div = dcuclk / mode->clock / 1000;
76 74
77 /* Configure timings: */ 75 /* Configure timings: */
78 hbp = mode->htotal - mode->hsync_end; 76 hbp = mode->htotal - mode->hsync_end;
@@ -99,7 +97,6 @@ static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
99 regmap_write(fsl_dev->regmap, DCU_DISP_SIZE, 97 regmap_write(fsl_dev->regmap, DCU_DISP_SIZE,
100 DCU_DISP_SIZE_DELTA_Y(mode->vdisplay) | 98 DCU_DISP_SIZE_DELTA_Y(mode->vdisplay) |
101 DCU_DISP_SIZE_DELTA_X(mode->hdisplay)); 99 DCU_DISP_SIZE_DELTA_X(mode->hdisplay));
102 regmap_write(fsl_dev->regmap, DCU_DIV_RATIO, div);
103 regmap_write(fsl_dev->regmap, DCU_SYN_POL, pol); 100 regmap_write(fsl_dev->regmap, DCU_SYN_POL, pol);
104 regmap_write(fsl_dev->regmap, DCU_BGND, DCU_BGND_R(0) | 101 regmap_write(fsl_dev->regmap, DCU_BGND, DCU_BGND_R(0) |
105 DCU_BGND_G(0) | DCU_BGND_B(0)); 102 DCU_BGND_G(0) | DCU_BGND_B(0));
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
index f80c116018b5..093a60b5d2d3 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
@@ -283,6 +283,9 @@ static int fsl_dcu_drm_probe(struct platform_device *pdev)
283 struct resource *res; 283 struct resource *res;
284 void __iomem *base; 284 void __iomem *base;
285 struct drm_driver *driver = &fsl_dcu_drm_driver; 285 struct drm_driver *driver = &fsl_dcu_drm_driver;
286 struct clk *pix_clk_in;
287 char pix_clk_name[32];
288 const char *pix_clk_in_name;
286 const struct of_device_id *id; 289 const struct of_device_id *id;
287 int ret; 290 int ret;
288 291
@@ -331,15 +334,27 @@ static int fsl_dcu_drm_probe(struct platform_device *pdev)
331 return ret; 334 return ret;
332 } 335 }
333 336
334 fsl_dev->pix_clk = devm_clk_get(dev, "pix"); 337 pix_clk_in = devm_clk_get(dev, "pix");
338 if (IS_ERR(pix_clk_in)) {
339 /* legancy binding, use dcu clock as pixel clock input */
340 pix_clk_in = fsl_dev->clk;
341 }
342
343 pix_clk_in_name = __clk_get_name(pix_clk_in);
344 snprintf(pix_clk_name, sizeof(pix_clk_name), "%s_pix", pix_clk_in_name);
345 fsl_dev->pix_clk = clk_register_divider(dev, pix_clk_name,
346 pix_clk_in_name, 0, base + DCU_DIV_RATIO,
347 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL);
335 if (IS_ERR(fsl_dev->pix_clk)) { 348 if (IS_ERR(fsl_dev->pix_clk)) {
336 /* legancy binding, use dcu clock as pixel clock */ 349 dev_err(dev, "failed to register pix clk\n");
337 fsl_dev->pix_clk = fsl_dev->clk; 350 ret = PTR_ERR(fsl_dev->pix_clk);
351 goto disable_clk;
338 } 352 }
353
339 ret = clk_prepare_enable(fsl_dev->pix_clk); 354 ret = clk_prepare_enable(fsl_dev->pix_clk);
340 if (ret < 0) { 355 if (ret < 0) {
341 dev_err(dev, "failed to enable pix clk\n"); 356 dev_err(dev, "failed to enable pix clk\n");
342 goto disable_clk; 357 goto unregister_pix_clk;
343 } 358 }
344 359
345 drm = drm_dev_alloc(driver, dev); 360 drm = drm_dev_alloc(driver, dev);
@@ -368,6 +383,8 @@ unref:
368 drm_dev_unref(drm); 383 drm_dev_unref(drm);
369disable_pix_clk: 384disable_pix_clk:
370 clk_disable_unprepare(fsl_dev->pix_clk); 385 clk_disable_unprepare(fsl_dev->pix_clk);
386unregister_pix_clk:
387 clk_unregister(fsl_dev->pix_clk);
371disable_clk: 388disable_clk:
372 clk_disable_unprepare(fsl_dev->clk); 389 clk_disable_unprepare(fsl_dev->clk);
373 return ret; 390 return ret;
@@ -379,6 +396,7 @@ static int fsl_dcu_drm_remove(struct platform_device *pdev)
379 396
380 clk_disable_unprepare(fsl_dev->clk); 397 clk_disable_unprepare(fsl_dev->clk);
381 clk_disable_unprepare(fsl_dev->pix_clk); 398 clk_disable_unprepare(fsl_dev->pix_clk);
399 clk_unregister(fsl_dev->pix_clk);
382 drm_put_dev(fsl_dev->drm); 400 drm_put_dev(fsl_dev->drm);
383 401
384 return 0; 402 return 0;