diff options
author | Stefan Agner <stefan.agner@toradex.com> | 2016-03-28 11:04:53 -0700 |
---|---|---|
committer | Stefan Agner <stefan.agner@toradex.com> | 2016-03-28 11:04:53 -0700 |
commit | 9b8284b6d0351d5fd5f9d8c526de185edd066689 (patch) | |
tree | 9331b4efc858546f9b16a39ad0b8f4872e151d15 | |
parent | 2ec8b7f8a380a92b8e2d60a9a074326fed138f55 (diff) | |
parent | b976c5f1d8be3905d3d91d8598ab1b9e97b10b22 (diff) |
Merge branch 'vf610-dcu-drm-4.4' into toradex_vf_4.4-next
-rw-r--r-- | Documentation/devicetree/bindings/display/fsl,dcu.txt | 2 | ||||
-rw-r--r-- | arch/arm/boot/dts/vfxxx.dtsi | 5 | ||||
-rw-r--r-- | drivers/clk/imx/clk-vf610.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c | 72 | ||||
-rw-r--r-- | drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/fsl-dcu/fsl_tcon.c | 48 | ||||
-rw-r--r-- | drivers/gpu/drm/fsl-dcu/fsl_tcon.h | 8 |
9 files changed, 75 insertions, 76 deletions
diff --git a/Documentation/devicetree/bindings/display/fsl,dcu.txt b/Documentation/devicetree/bindings/display/fsl,dcu.txt index 8153c9a564b1..62c167e3da21 100644 --- a/Documentation/devicetree/bindings/display/fsl,dcu.txt +++ b/Documentation/devicetree/bindings/display/fsl,dcu.txt @@ -13,6 +13,8 @@ Required properties: Optional properties: - fsl,tcon: The phandle to the timing controller node. +- clocks: Second handle for pixel clock. +- clock-names: Second name "pix" for pixel clock. Examples: dcu: dcu@2ce0000 { diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi index 98666b403546..11a15f0affe6 100644 --- a/arch/arm/boot/dts/vfxxx.dtsi +++ b/arch/arm/boot/dts/vfxxx.dtsi @@ -455,8 +455,9 @@ compatible = "fsl,vf610-dcu"; reg = <0x40058000 0x1200>; interrupts = <30 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks VF610_CLK_DCU0>; - clock-names = "dcu"; + clocks = <&clks VF610_CLK_DCU0>, + <&clks VF610_CLK_DCU0_DIV>; + clock-names = "dcu", "pix"; fsl,tcon = <&tcon0>; status = "disabled"; }; diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c index 9627f426b1d7..f3b891999f41 100644 --- a/drivers/clk/imx/clk-vf610.c +++ b/drivers/clk/imx/clk-vf610.c @@ -392,11 +392,11 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) clk[VF610_CLK_DCU0_SEL] = imx_clk_mux("dcu0_sel", CCM_CSCMR1, 28, 1, dcu_sels, 2); clk[VF610_CLK_DCU0_EN] = imx_clk_gate("dcu0_en", "dcu0_sel", CCM_CSCDR3, 19); clk[VF610_CLK_DCU0_DIV] = imx_clk_divider("dcu0_div", "dcu0_en", CCM_CSCDR3, 16, 3); - clk[VF610_CLK_DCU0] = imx_clk_gate2("dcu0", "dcu0_div", CCM_CCGR3, CCM_CCGRx_CGn(8)); + clk[VF610_CLK_DCU0] = imx_clk_gate2("dcu0", "ipg_bus", CCM_CCGR3, CCM_CCGRx_CGn(8)); clk[VF610_CLK_DCU1_SEL] = imx_clk_mux("dcu1_sel", CCM_CSCMR1, 29, 1, dcu_sels, 2); clk[VF610_CLK_DCU1_EN] = imx_clk_gate("dcu1_en", "dcu1_sel", CCM_CSCDR3, 23); clk[VF610_CLK_DCU1_DIV] = imx_clk_divider("dcu1_div", "dcu1_en", CCM_CSCDR3, 20, 3); - clk[VF610_CLK_DCU1] = imx_clk_gate2("dcu1", "dcu1_div", CCM_CCGR9, CCM_CCGRx_CGn(8)); + clk[VF610_CLK_DCU1] = imx_clk_gate2("dcu1", "ipg_bus", CCM_CCGR9, CCM_CCGRx_CGn(8)); clk[VF610_CLK_TCON0] = imx_clk_gate2("tcon0", "platform_bus", CCM_CCGR1, CCM_CCGRx_CGn(13)); clk[VF610_CLK_TCON1] = imx_clk_gate2("tcon1", "platform_bus", CCM_CCGR7, CCM_CCGRx_CGn(13)); 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 afb303680f18..503bebb3097e 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c @@ -139,12 +139,10 @@ static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; struct drm_display_mode *mode = &crtc->state->mode; - unsigned int hbp, hfp, hsw, vbp, vfp, vsw, div, index, pol = 0; - unsigned long dcuclk; + unsigned int hbp, hfp, hsw, vbp, vfp, vsw, index, pol = 0; index = drm_crtc_index(crtc); - dcuclk = clk_get_rate(fsl_dev->clk); - div = dcuclk / mode->clock / 1000; + clk_set_rate(fsl_dev->pix_clk, mode->clock * 1000); /* Configure timings: */ hbp = mode->htotal - mode->hsync_end; @@ -174,7 +172,6 @@ static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) regmap_write(fsl_dev->regmap, DCU_DISP_SIZE, DCU_DISP_SIZE_DELTA_Y(mode->vdisplay) | DCU_DISP_SIZE_DELTA_X(mode->hdisplay)); - regmap_write(fsl_dev->regmap, DCU_DIV_RATIO, div); regmap_write(fsl_dev->regmap, DCU_SYN_POL, pol); regmap_write(fsl_dev->regmap, DCU_BGND, DCU_BGND_R(0) | 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 cdefadbba9e2..84b8d7265087 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c @@ -251,7 +251,6 @@ static int fsl_dcu_drm_pm_suspend(struct device *dev) return PTR_ERR(fsl_dev->state); } - fsl_tcon_suspend(fsl_dev->tcon); clk_disable_unprepare(fsl_dev->clk); return 0; @@ -271,7 +270,6 @@ static int fsl_dcu_drm_pm_resume(struct device *dev) return ret; } - fsl_tcon_resume(fsl_dev->tcon); fsl_dcu_drm_init_planes(fsl_dev->drm); drm_atomic_helper_resume(fsl_dev->drm, fsl_dev->state); @@ -324,6 +322,9 @@ static int fsl_dcu_drm_probe(struct platform_device *pdev) struct resource *res; void __iomem *base; struct drm_driver *driver = &fsl_dcu_drm_driver; + struct clk *pix_clk_in; + char pix_clk_name[32]; + const char *pix_clk_in_name; const struct of_device_id *id; int ret; @@ -331,6 +332,11 @@ static int fsl_dcu_drm_probe(struct platform_device *pdev) if (!fsl_dev) return -ENOMEM; + id = of_match_node(fsl_dcu_of_match, pdev->dev.of_node); + if (!id) + return -ENODEV; + fsl_dev->soc = id->data; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "could not get memory IO resource\n"); @@ -349,39 +355,52 @@ static int fsl_dcu_drm_probe(struct platform_device *pdev) return -ENXIO; } + fsl_dev->regmap = devm_regmap_init_mmio(dev, base, + &fsl_dcu_regmap_config); + if (IS_ERR(fsl_dev->regmap)) { + dev_err(dev, "regmap init failed\n"); + return PTR_ERR(fsl_dev->regmap); + } + fsl_dev->clk = devm_clk_get(dev, "dcu"); if (IS_ERR(fsl_dev->clk)) { - ret = PTR_ERR(fsl_dev->clk); dev_err(dev, "failed to get dcu clock\n"); - return ret; + return PTR_ERR(fsl_dev->clk); } - ret = clk_prepare(fsl_dev->clk); - if (ret < 0) { - dev_err(dev, "failed to prepare dcu clk\n"); - return ret; - } - ret = clk_enable(fsl_dev->clk); + ret = clk_prepare_enable(fsl_dev->clk); if (ret < 0) { dev_err(dev, "failed to enable dcu clk\n"); - clk_unprepare(fsl_dev->clk); return ret; } - fsl_dev->regmap = devm_regmap_init_mmio(dev, base, - &fsl_dcu_regmap_config); - if (IS_ERR(fsl_dev->regmap)) { - dev_err(dev, "regmap init failed\n"); - return PTR_ERR(fsl_dev->regmap); + pix_clk_in = devm_clk_get(dev, "pix"); + if (IS_ERR(pix_clk_in)) { + /* legancy binding, use dcu clock as pixel clock input */ + pix_clk_in = fsl_dev->clk; } - id = of_match_node(fsl_dcu_of_match, pdev->dev.of_node); - if (!id) - return -ENODEV; - fsl_dev->soc = id->data; + pix_clk_in_name = __clk_get_name(pix_clk_in); + snprintf(pix_clk_name, sizeof(pix_clk_name), "%s_pix", pix_clk_in_name); + fsl_dev->pix_clk = clk_register_divider(dev, pix_clk_name, + pix_clk_in_name, 0, base + DCU_DIV_RATIO, + 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL); + if (IS_ERR(fsl_dev->pix_clk)) { + dev_err(dev, "failed to register pix clk\n"); + ret = PTR_ERR(fsl_dev->pix_clk); + goto disable_clk; + } + + ret = clk_prepare_enable(fsl_dev->pix_clk); + if (ret < 0) { + dev_err(dev, "failed to enable pix clk\n"); + goto unregister_pix_clk; + } drm = drm_dev_alloc(driver, dev); - if (!drm) - return -ENOMEM; + if (!drm) { + ret = -ENOMEM; + goto disable_pix_clk; + } fsl_dev->tcon = fsl_tcon_init(dev); fsl_dev->dev = dev; @@ -403,6 +422,12 @@ static int fsl_dcu_drm_probe(struct platform_device *pdev) unref: drm_dev_unref(drm); +disable_pix_clk: + clk_disable_unprepare(fsl_dev->pix_clk); +unregister_pix_clk: + clk_unregister(fsl_dev->pix_clk); +disable_clk: + clk_disable_unprepare(fsl_dev->clk); return ret; } @@ -410,6 +435,9 @@ static int fsl_dcu_drm_remove(struct platform_device *pdev) { struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev); + clk_disable_unprepare(fsl_dev->clk); + clk_disable_unprepare(fsl_dev->pix_clk); + clk_unregister(fsl_dev->pix_clk); drm_put_dev(fsl_dev->drm); return 0; diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h index e1ee6efe5dc6..feef220a257c 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h @@ -185,6 +185,7 @@ struct fsl_dcu_drm_device { struct regmap *regmap; int irq; struct clk *clk; + struct clk *pix_clk; struct fsl_tcon *tcon; /*protects hardware register*/ spinlock_t irq_lock; diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c index 9081086d8f21..f64a0723bda3 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c @@ -34,7 +34,7 @@ static void fsl_dcu_drm_encoder_disable(struct drm_encoder *encoder) struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; if (fsl_dev->tcon) - fsl_tcon_disable(fsl_dev->tcon); + fsl_tcon_bypass_disable(fsl_dev->tcon); } static void fsl_dcu_drm_encoder_enable(struct drm_encoder *encoder) @@ -43,7 +43,7 @@ static void fsl_dcu_drm_encoder_enable(struct drm_encoder *encoder) struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; if (fsl_dev->tcon) - fsl_tcon_enable(fsl_dev->tcon); + fsl_tcon_bypass_enable(fsl_dev->tcon); } static const struct drm_encoder_helper_funcs encoder_helper_funcs = { diff --git a/drivers/gpu/drm/fsl-dcu/fsl_tcon.c b/drivers/gpu/drm/fsl-dcu/fsl_tcon.c index de3c58b59ba5..e5001a186850 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_tcon.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_tcon.c @@ -20,38 +20,14 @@ #include "fsl_tcon.h" -void fsl_tcon_disable(struct fsl_tcon *tcon) +void fsl_tcon_bypass_disable(struct fsl_tcon *tcon) { regmap_update_bits(tcon->regs, FSL_TCON_CTRL1, FSL_TCON_CTRL1_TCON_BYPASS, 0); - - tcon->enabled = false; -} - -void fsl_tcon_enable(struct fsl_tcon *tcon) -{ - regmap_update_bits(tcon->regs, FSL_TCON_CTRL1, - FSL_TCON_CTRL1_TCON_BYPASS, - FSL_TCON_CTRL1_TCON_BYPASS); - - tcon->enabled = true; -} - -void fsl_tcon_suspend(struct fsl_tcon *tcon) -{ - regmap_update_bits(tcon->regs, FSL_TCON_CTRL1, - FSL_TCON_CTRL1_TCON_BYPASS, 0); - - clk_disable_unprepare(tcon->ipg_clk); } -void fsl_tcon_resume(struct fsl_tcon *tcon) +void fsl_tcon_bypass_enable(struct fsl_tcon *tcon) { - clk_prepare_enable(tcon->ipg_clk); - - if (!tcon->enabled) - return; - regmap_update_bits(tcon->regs, FSL_TCON_CTRL1, FSL_TCON_CTRL1_TCON_BYPASS, FSL_TCON_CTRL1_TCON_BYPASS); @@ -71,21 +47,18 @@ static int fsl_tcon_init_regmap(struct device *dev, { struct resource res; void __iomem *regs; - int ret; - ret = of_address_to_resource(np, 0, &res); + if (of_address_to_resource(np, 0, &res)) + return -EINVAL; + regs = devm_ioremap_resource(dev, &res); - if (IS_ERR(regs)) { - dev_err(dev, "Couldn't map the TCON registers\n"); + if (IS_ERR(regs)) return PTR_ERR(regs); - } tcon->regs = devm_regmap_init_mmio(dev, regs, &fsl_tcon_regmap_config); - if (IS_ERR(tcon->regs)) { - dev_err(dev, "Couldn't create the TCON regmap\n"); + if (IS_ERR(tcon->regs)) return PTR_ERR(tcon->regs); - } return 0; } @@ -107,20 +80,21 @@ struct fsl_tcon *fsl_tcon_init(struct device *dev) } ret = fsl_tcon_init_regmap(dev, tcon, np); - if (ret) + if (ret) { + dev_err(dev, "Couldn't create the TCON regmap\n"); goto err_node_put; + } tcon->ipg_clk = of_clk_get_by_name(np, "ipg"); if (IS_ERR(tcon->ipg_clk)) { dev_err(dev, "Couldn't get the TCON bus clock\n"); - goto err_free_regmap; + goto err_node_put; } clk_prepare_enable(tcon->ipg_clk); return tcon; -err_free_regmap: err_node_put: of_node_put(np); return NULL; diff --git a/drivers/gpu/drm/fsl-dcu/fsl_tcon.h b/drivers/gpu/drm/fsl-dcu/fsl_tcon.h index 199e6a1f0d69..80a7617de58f 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_tcon.h +++ b/drivers/gpu/drm/fsl-dcu/fsl_tcon.h @@ -22,16 +22,12 @@ struct fsl_tcon { struct regmap *regs; struct clk *ipg_clk; - - bool enabled; }; struct fsl_tcon *fsl_tcon_init(struct device *dev); void fsl_tcon_free(struct fsl_tcon *tcon); -void fsl_tcon_disable(struct fsl_tcon *tcon); -void fsl_tcon_enable(struct fsl_tcon *tcon); -void fsl_tcon_suspend(struct fsl_tcon *tcon); -void fsl_tcon_resume(struct fsl_tcon *tcon); +void fsl_tcon_bypass_disable(struct fsl_tcon *tcon); +void fsl_tcon_bypass_enable(struct fsl_tcon *tcon); #endif /* __FSL_TCON_H__ */ |