2 * Copyright (C) 2012 Russell King
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * Armada 510 (aka Dove) variant support
10 #include <linux/clk.h>
12 #include <drm/drm_probe_helper.h>
13 #include "armada_crtc.h"
14 #include "armada_drm.h"
15 #include "armada_hw.h"
17 static int armada510_crtc_init(struct armada_crtc
*dcrtc
, struct device
*dev
)
21 clk
= devm_clk_get(dev
, "ext_ref_clk1");
23 return PTR_ERR(clk
) == -ENOENT
? -EPROBE_DEFER
: PTR_ERR(clk
);
25 dcrtc
->extclk
[0] = clk
;
27 /* Lower the watermark so to eliminate jitter at higher bandwidths */
28 armada_updatel(0x20, (1 << 11) | 0xff, dcrtc
->base
+ LCD_CFG_RDREG4F
);
30 /* Initialise SPU register */
31 writel_relaxed(ADV_HWC32ENABLE
| ADV_HWC32ARGB
| ADV_HWC32BLEND
,
32 dcrtc
->base
+ LCD_SPU_ADV_REG
);
38 * Armada510 specific SCLK register selection.
39 * This gets called with sclk = NULL to test whether the mode is
40 * supportable, and again with sclk != NULL to set the clocks up for
41 * that. The former can return an error, but the latter is expected
44 * We currently are pretty rudimentary here, always selecting
45 * EXT_REF_CLK_1 for LCD0 and erroring LCD1. This needs improvement!
47 static int armada510_crtc_compute_clock(struct armada_crtc
*dcrtc
,
48 const struct drm_display_mode
*mode
, uint32_t *sclk
)
50 struct clk
*clk
= dcrtc
->extclk
[0];
59 if (dcrtc
->clk
!= clk
) {
60 ret
= clk_prepare_enable(clk
);
67 uint32_t rate
, ref
, div
;
69 rate
= mode
->clock
* 1000;
70 ref
= clk_round_rate(clk
, rate
);
71 div
= DIV_ROUND_UP(ref
, rate
);
75 clk_set_rate(clk
, ref
);
76 *sclk
= div
| SCLK_510_EXTCLK1
;
82 static void armada510_crtc_disable(struct armada_crtc
*dcrtc
)
84 if (!IS_ERR(dcrtc
->clk
)) {
85 clk_disable_unprepare(dcrtc
->clk
);
86 dcrtc
->clk
= ERR_PTR(-EINVAL
);
90 static void armada510_crtc_enable(struct armada_crtc
*dcrtc
,
91 const struct drm_display_mode
*mode
)
93 if (IS_ERR(dcrtc
->clk
)) {
94 dcrtc
->clk
= dcrtc
->extclk
[0];
95 WARN_ON(clk_prepare_enable(dcrtc
->clk
));
99 const struct armada_variant armada510_ops
= {
100 .has_spu_adv_reg
= true,
101 .init
= armada510_crtc_init
,
102 .compute_clock
= armada510_crtc_compute_clock
,
103 .disable
= armada510_crtc_disable
,
104 .enable
= armada510_crtc_enable
,