summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/display/fsl,dcu.txt2
-rw-r--r--arch/arm/boot/dts/vfxxx.dtsi5
-rw-r--r--drivers/clk/imx/clk-vf610.c4
-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.c72
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h1
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c4
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_tcon.c48
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_tcon.h8
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__ */