aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_lvds.c359
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_lvds_regs.h43
2 files changed, 355 insertions, 47 deletions
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c
index ce0eb68c3416..173d7ad0b991 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
@@ -24,6 +24,8 @@
24 24
25#include "rcar_lvds_regs.h" 25#include "rcar_lvds_regs.h"
26 26
27struct rcar_lvds;
28
27/* Keep in sync with the LVDCR0.LVMD hardware register values. */ 29/* Keep in sync with the LVDCR0.LVMD hardware register values. */
28enum rcar_lvds_mode { 30enum rcar_lvds_mode {
29 RCAR_LVDS_MODE_JEIDA = 0, 31 RCAR_LVDS_MODE_JEIDA = 0,
@@ -31,14 +33,16 @@ enum rcar_lvds_mode {
31 RCAR_LVDS_MODE_VESA = 4, 33 RCAR_LVDS_MODE_VESA = 4,
32}; 34};
33 35
34#define RCAR_LVDS_QUIRK_LANES (1 << 0) /* LVDS lanes 1 and 3 inverted */ 36#define RCAR_LVDS_QUIRK_LANES BIT(0) /* LVDS lanes 1 and 3 inverted */
35#define RCAR_LVDS_QUIRK_GEN2_PLLCR (1 << 1) /* LVDPLLCR has gen2 layout */ 37#define RCAR_LVDS_QUIRK_GEN3_LVEN BIT(1) /* LVEN bit needs to be set on R8A77970/R8A7799x */
36#define RCAR_LVDS_QUIRK_GEN3_LVEN (1 << 2) /* LVEN bit needs to be set */ 38#define RCAR_LVDS_QUIRK_PWD BIT(2) /* PWD bit available (all of Gen3 but E3) */
37 /* on R8A77970/R8A7799x */ 39#define RCAR_LVDS_QUIRK_EXT_PLL BIT(3) /* Has extended PLL */
40#define RCAR_LVDS_QUIRK_DUAL_LINK BIT(4) /* Supports dual-link operation */
38 41
39struct rcar_lvds_device_info { 42struct rcar_lvds_device_info {
40 unsigned int gen; 43 unsigned int gen;
41 unsigned int quirks; 44 unsigned int quirks;
45 void (*pll_setup)(struct rcar_lvds *lvds, unsigned int freq);
42}; 46};
43 47
44struct rcar_lvds { 48struct rcar_lvds {
@@ -52,7 +56,11 @@ struct rcar_lvds {
52 struct drm_panel *panel; 56 struct drm_panel *panel;
53 57
54 void __iomem *mmio; 58 void __iomem *mmio;
55 struct clk *clock; 59 struct {
60 struct clk *mod; /* CPG module clock */
61 struct clk *extal; /* External clock */
62 struct clk *dotclkin[2]; /* External DU clocks */
63 } clocks;
56 bool enabled; 64 bool enabled;
57 65
58 struct drm_display_mode display_mode; 66 struct drm_display_mode display_mode;
@@ -128,33 +136,216 @@ static const struct drm_connector_funcs rcar_lvds_conn_funcs = {
128}; 136};
129 137
130/* ----------------------------------------------------------------------------- 138/* -----------------------------------------------------------------------------
131 * Bridge 139 * PLL Setup
132 */ 140 */
133 141
134static u32 rcar_lvds_lvdpllcr_gen2(unsigned int freq) 142static void rcar_lvds_pll_setup_gen2(struct rcar_lvds *lvds, unsigned int freq)
135{ 143{
136 if (freq < 39000) 144 u32 val;
137 return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M; 145
138 else if (freq < 61000) 146 if (freq < 39000000)
139 return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M; 147 val = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M;
140 else if (freq < 121000) 148 else if (freq < 61000000)
141 return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M; 149 val = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M;
150 else if (freq < 121000000)
151 val = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M;
142 else 152 else
143 return LVDPLLCR_PLLDLYCNT_150M; 153 val = LVDPLLCR_PLLDLYCNT_150M;
154
155 rcar_lvds_write(lvds, LVDPLLCR, val);
144} 156}
145 157
146static u32 rcar_lvds_lvdpllcr_gen3(unsigned int freq) 158static void rcar_lvds_pll_setup_gen3(struct rcar_lvds *lvds, unsigned int freq)
147{ 159{
148 if (freq < 42000) 160 u32 val;
149 return LVDPLLCR_PLLDIVCNT_42M; 161
150 else if (freq < 85000) 162 if (freq < 42000000)
151 return LVDPLLCR_PLLDIVCNT_85M; 163 val = LVDPLLCR_PLLDIVCNT_42M;
152 else if (freq < 128000) 164 else if (freq < 85000000)
153 return LVDPLLCR_PLLDIVCNT_128M; 165 val = LVDPLLCR_PLLDIVCNT_85M;
166 else if (freq < 128000000)
167 val = LVDPLLCR_PLLDIVCNT_128M;
154 else 168 else
155 return LVDPLLCR_PLLDIVCNT_148M; 169 val = LVDPLLCR_PLLDIVCNT_148M;
170
171 rcar_lvds_write(lvds, LVDPLLCR, val);
156} 172}
157 173
174struct pll_info {
175 unsigned long diff;
176 unsigned int pll_m;
177 unsigned int pll_n;
178 unsigned int pll_e;
179 unsigned int div;
180 u32 clksel;
181};
182
183static void rcar_lvds_d3_e3_pll_calc(struct rcar_lvds *lvds, struct clk *clk,
184 unsigned long target, struct pll_info *pll,
185 u32 clksel)
186{
187 unsigned long output;
188 unsigned long fin;
189 unsigned int m_min;
190 unsigned int m_max;
191 unsigned int m;
192 int error;
193
194 if (!clk)
195 return;
196
197 /*
198 * The LVDS PLL is made of a pre-divider and a multiplier (strangely
199 * enough called M and N respectively), followed by a post-divider E.
200 *
201 * ,-----. ,-----. ,-----. ,-----.
202 * Fin --> | 1/M | -Fpdf-> | PFD | --> | VCO | -Fvco-> | 1/E | --> Fout
203 * `-----' ,-> | | `-----' | `-----'
204 * | `-----' |
205 * | ,-----. |
206 * `-------- | 1/N | <-------'
207 * `-----'
208 *
209 * The clock output by the PLL is then further divided by a programmable
210 * divider DIV to achieve the desired target frequency. Finally, an
211 * optional fixed /7 divider is used to convert the bit clock to a pixel
212 * clock (as LVDS transmits 7 bits per lane per clock sample).
213 *
214 * ,-------. ,-----. |\
215 * Fout --> | 1/DIV | --> | 1/7 | --> | |
216 * `-------' | `-----' | | --> dot clock
217 * `------------> | |
218 * |/
219 *
220 * The /7 divider is optional when the LVDS PLL is used to generate a
221 * dot clock for the DU RGB output, without using the LVDS encoder. We
222 * don't support this configuration yet.
223 *
224 * The PLL allowed input frequency range is 12 MHz to 192 MHz.
225 */
226
227 fin = clk_get_rate(clk);
228 if (fin < 12000000 || fin > 192000000)
229 return;
230
231 /*
232 * The comparison frequency range is 12 MHz to 24 MHz, which limits the
233 * allowed values for the pre-divider M (normal range 1-8).
234 *
235 * Fpfd = Fin / M
236 */
237 m_min = max_t(unsigned int, 1, DIV_ROUND_UP(fin, 24000000));
238 m_max = min_t(unsigned int, 8, fin / 12000000);
239
240 for (m = m_min; m <= m_max; ++m) {
241 unsigned long fpfd;
242 unsigned int n_min;
243 unsigned int n_max;
244 unsigned int n;
245
246 /*
247 * The VCO operating range is 900 Mhz to 1800 MHz, which limits
248 * the allowed values for the multiplier N (normal range
249 * 60-120).
250 *
251 * Fvco = Fin * N / M
252 */
253 fpfd = fin / m;
254 n_min = max_t(unsigned int, 60, DIV_ROUND_UP(900000000, fpfd));
255 n_max = min_t(unsigned int, 120, 1800000000 / fpfd);
256
257 for (n = n_min; n < n_max; ++n) {
258 unsigned long fvco;
259 unsigned int e_min;
260 unsigned int e;
261
262 /*
263 * The output frequency is limited to 1039.5 MHz,
264 * limiting again the allowed values for the
265 * post-divider E (normal value 1, 2 or 4).
266 *
267 * Fout = Fvco / E
268 */
269 fvco = fpfd * n;
270 e_min = fvco > 1039500000 ? 1 : 0;
271
272 for (e = e_min; e < 3; ++e) {
273 unsigned long fout;
274 unsigned long diff;
275 unsigned int div;
276
277 /*
278 * Finally we have a programable divider after
279 * the PLL, followed by a an optional fixed /7
280 * divider.
281 */
282 fout = fvco / (1 << e) / 7;
283 div = DIV_ROUND_CLOSEST(fout, target);
284 diff = abs(fout / div - target);
285
286 if (diff < pll->diff) {
287 pll->diff = diff;
288 pll->pll_m = m;
289 pll->pll_n = n;
290 pll->pll_e = e;
291 pll->div = div;
292 pll->clksel = clksel;
293
294 if (diff == 0)
295 goto done;
296 }
297 }
298 }
299 }
300
301done:
302 output = fin * pll->pll_n / pll->pll_m / (1 << pll->pll_e)
303 / 7 / pll->div;
304 error = (long)(output - target) * 10000 / (long)target;
305
306 dev_dbg(lvds->dev,
307 "%pC %lu Hz -> Fout %lu Hz (target %lu Hz, error %d.%02u%%), PLL M/N/E/DIV %u/%u/%u/%u\n",
308 clk, fin, output, target, error / 100,
309 error < 0 ? -error % 100 : error % 100,
310 pll->pll_m, pll->pll_n, pll->pll_e, pll->div);
311}
312
313static void rcar_lvds_pll_setup_d3_e3(struct rcar_lvds *lvds, unsigned int freq)
314{
315 struct pll_info pll = { .diff = (unsigned long)-1 };
316 u32 lvdpllcr;
317
318 rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.dotclkin[0], freq, &pll,
319 LVDPLLCR_CKSEL_DU_DOTCLKIN(0));
320 rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.dotclkin[1], freq, &pll,
321 LVDPLLCR_CKSEL_DU_DOTCLKIN(1));
322 rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.extal, freq, &pll,
323 LVDPLLCR_CKSEL_EXTAL);
324
325 lvdpllcr = LVDPLLCR_PLLON | pll.clksel | LVDPLLCR_CLKOUT
326 | LVDPLLCR_PLLN(pll.pll_n - 1) | LVDPLLCR_PLLM(pll.pll_m - 1);
327
328 if (pll.pll_e > 0)
329 lvdpllcr |= LVDPLLCR_STP_CLKOUTE | LVDPLLCR_OUTCLKSEL
330 | LVDPLLCR_PLLE(pll.pll_e - 1);
331
332 rcar_lvds_write(lvds, LVDPLLCR, lvdpllcr);
333
334 if (pll.div > 1)
335 /*
336 * The DIVRESET bit is a misnomer, setting it to 1 deasserts the
337 * divisor reset.
338 */
339 rcar_lvds_write(lvds, LVDDIV, LVDDIV_DIVSEL |
340 LVDDIV_DIVRESET | LVDDIV_DIV(pll.div - 1));
341 else
342 rcar_lvds_write(lvds, LVDDIV, 0);
343}
344
345/* -----------------------------------------------------------------------------
346 * Bridge
347 */
348
158static void rcar_lvds_enable(struct drm_bridge *bridge) 349static void rcar_lvds_enable(struct drm_bridge *bridge)
159{ 350{
160 struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge); 351 struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
@@ -164,14 +355,13 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
164 * do we get a state pointer? 355 * do we get a state pointer?
165 */ 356 */
166 struct drm_crtc *crtc = lvds->bridge.encoder->crtc; 357 struct drm_crtc *crtc = lvds->bridge.encoder->crtc;
167 u32 lvdpllcr;
168 u32 lvdhcr; 358 u32 lvdhcr;
169 u32 lvdcr0; 359 u32 lvdcr0;
170 int ret; 360 int ret;
171 361
172 WARN_ON(lvds->enabled); 362 WARN_ON(lvds->enabled);
173 363
174 ret = clk_prepare_enable(lvds->clock); 364 ret = clk_prepare_enable(lvds->clocks.mod);
175 if (ret < 0) 365 if (ret < 0)
176 return; 366 return;
177 367
@@ -196,12 +386,13 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
196 386
197 rcar_lvds_write(lvds, LVDCHCR, lvdhcr); 387 rcar_lvds_write(lvds, LVDCHCR, lvdhcr);
198 388
389 if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK) {
390 /* Disable dual-link mode. */
391 rcar_lvds_write(lvds, LVDSTRIPE, 0);
392 }
393
199 /* PLL clock configuration. */ 394 /* PLL clock configuration. */
200 if (lvds->info->quirks & RCAR_LVDS_QUIRK_GEN2_PLLCR) 395 lvds->info->pll_setup(lvds, mode->clock * 1000);
201 lvdpllcr = rcar_lvds_lvdpllcr_gen2(mode->clock);
202 else
203 lvdpllcr = rcar_lvds_lvdpllcr_gen3(mode->clock);
204 rcar_lvds_write(lvds, LVDPLLCR, lvdpllcr);
205 396
206 /* Set the LVDS mode and select the input. */ 397 /* Set the LVDS mode and select the input. */
207 lvdcr0 = lvds->mode << LVDCR0_LVMD_SHIFT; 398 lvdcr0 = lvds->mode << LVDCR0_LVMD_SHIFT;
@@ -220,11 +411,16 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
220 rcar_lvds_write(lvds, LVDCR0, lvdcr0); 411 rcar_lvds_write(lvds, LVDCR0, lvdcr0);
221 } 412 }
222 413
223 /* Turn the PLL on. */ 414 if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)) {
224 lvdcr0 |= LVDCR0_PLLON; 415 /*
225 rcar_lvds_write(lvds, LVDCR0, lvdcr0); 416 * Turn the PLL on (simple PLL only, extended PLL is fully
417 * controlled through LVDPLLCR).
418 */
419 lvdcr0 |= LVDCR0_PLLON;
420 rcar_lvds_write(lvds, LVDCR0, lvdcr0);
421 }
226 422
227 if (lvds->info->gen > 2) { 423 if (lvds->info->quirks & RCAR_LVDS_QUIRK_PWD) {
228 /* Set LVDS normal mode. */ 424 /* Set LVDS normal mode. */
229 lvdcr0 |= LVDCR0_PWD; 425 lvdcr0 |= LVDCR0_PWD;
230 rcar_lvds_write(lvds, LVDCR0, lvdcr0); 426 rcar_lvds_write(lvds, LVDCR0, lvdcr0);
@@ -236,8 +432,10 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
236 rcar_lvds_write(lvds, LVDCR0, lvdcr0); 432 rcar_lvds_write(lvds, LVDCR0, lvdcr0);
237 } 433 }
238 434
239 /* Wait for the startup delay. */ 435 if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)) {
240 usleep_range(100, 150); 436 /* Wait for the PLL startup delay (simple PLL only). */
437 usleep_range(100, 150);
438 }
241 439
242 /* Turn the output on. */ 440 /* Turn the output on. */
243 lvdcr0 |= LVDCR0_LVRES; 441 lvdcr0 |= LVDCR0_LVRES;
@@ -264,8 +462,9 @@ static void rcar_lvds_disable(struct drm_bridge *bridge)
264 462
265 rcar_lvds_write(lvds, LVDCR0, 0); 463 rcar_lvds_write(lvds, LVDCR0, 0);
266 rcar_lvds_write(lvds, LVDCR1, 0); 464 rcar_lvds_write(lvds, LVDCR1, 0);
465 rcar_lvds_write(lvds, LVDPLLCR, 0);
267 466
268 clk_disable_unprepare(lvds->clock); 467 clk_disable_unprepare(lvds->clocks.mod);
269 468
270 lvds->enabled = false; 469 lvds->enabled = false;
271} 470}
@@ -446,6 +645,60 @@ done:
446 return ret; 645 return ret;
447} 646}
448 647
648static struct clk *rcar_lvds_get_clock(struct rcar_lvds *lvds, const char *name,
649 bool optional)
650{
651 struct clk *clk;
652
653 clk = devm_clk_get(lvds->dev, name);
654 if (!IS_ERR(clk))
655 return clk;
656
657 if (PTR_ERR(clk) == -ENOENT && optional)
658 return NULL;
659
660 if (PTR_ERR(clk) != -EPROBE_DEFER)
661 dev_err(lvds->dev, "failed to get %s clock\n",
662 name ? name : "module");
663
664 return clk;
665}
666
667static int rcar_lvds_get_clocks(struct rcar_lvds *lvds)
668{
669 lvds->clocks.mod = rcar_lvds_get_clock(lvds, NULL, false);
670 if (IS_ERR(lvds->clocks.mod))
671 return PTR_ERR(lvds->clocks.mod);
672
673 /*
674 * LVDS encoders without an extended PLL have no external clock inputs.
675 */
676 if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL))
677 return 0;
678
679 lvds->clocks.extal = rcar_lvds_get_clock(lvds, "extal", true);
680 if (IS_ERR(lvds->clocks.extal))
681 return PTR_ERR(lvds->clocks.extal);
682
683 lvds->clocks.dotclkin[0] = rcar_lvds_get_clock(lvds, "dclkin.0", true);
684 if (IS_ERR(lvds->clocks.dotclkin[0]))
685 return PTR_ERR(lvds->clocks.dotclkin[0]);
686
687 lvds->clocks.dotclkin[1] = rcar_lvds_get_clock(lvds, "dclkin.1", true);
688 if (IS_ERR(lvds->clocks.dotclkin[1]))
689 return PTR_ERR(lvds->clocks.dotclkin[1]);
690
691 /* At least one input to the PLL must be available. */
692 if (!lvds->clocks.extal && !lvds->clocks.dotclkin[0] &&
693 !lvds->clocks.dotclkin[1]) {
694 dev_err(lvds->dev,
695 "no input clock (extal, dclkin.0 or dclkin.1)\n");
696 return -EINVAL;
697 }
698
699 return 0;
700}
701
449static int rcar_lvds_probe(struct platform_device *pdev) 702static int rcar_lvds_probe(struct platform_device *pdev)
450{ 703{
451 struct rcar_lvds *lvds; 704 struct rcar_lvds *lvds;
@@ -475,11 +728,9 @@ static int rcar_lvds_probe(struct platform_device *pdev)
475 if (IS_ERR(lvds->mmio)) 728 if (IS_ERR(lvds->mmio))
476 return PTR_ERR(lvds->mmio); 729 return PTR_ERR(lvds->mmio);
477 730
478 lvds->clock = devm_clk_get(&pdev->dev, NULL); 731 ret = rcar_lvds_get_clocks(lvds);
479 if (IS_ERR(lvds->clock)) { 732 if (ret < 0)
480 dev_err(&pdev->dev, "failed to get clock\n"); 733 return ret;
481 return PTR_ERR(lvds->clock);
482 }
483 734
484 drm_bridge_add(&lvds->bridge); 735 drm_bridge_add(&lvds->bridge);
485 736
@@ -497,21 +748,39 @@ static int rcar_lvds_remove(struct platform_device *pdev)
497 748
498static const struct rcar_lvds_device_info rcar_lvds_gen2_info = { 749static const struct rcar_lvds_device_info rcar_lvds_gen2_info = {
499 .gen = 2, 750 .gen = 2,
500 .quirks = RCAR_LVDS_QUIRK_GEN2_PLLCR, 751 .pll_setup = rcar_lvds_pll_setup_gen2,
501}; 752};
502 753
503static const struct rcar_lvds_device_info rcar_lvds_r8a7790_info = { 754static const struct rcar_lvds_device_info rcar_lvds_r8a7790_info = {
504 .gen = 2, 755 .gen = 2,
505 .quirks = RCAR_LVDS_QUIRK_GEN2_PLLCR | RCAR_LVDS_QUIRK_LANES, 756 .quirks = RCAR_LVDS_QUIRK_LANES,
757 .pll_setup = rcar_lvds_pll_setup_gen2,
506}; 758};
507 759
508static const struct rcar_lvds_device_info rcar_lvds_gen3_info = { 760static const struct rcar_lvds_device_info rcar_lvds_gen3_info = {
509 .gen = 3, 761 .gen = 3,
762 .quirks = RCAR_LVDS_QUIRK_PWD,
763 .pll_setup = rcar_lvds_pll_setup_gen3,
510}; 764};
511 765
512static const struct rcar_lvds_device_info rcar_lvds_r8a77970_info = { 766static const struct rcar_lvds_device_info rcar_lvds_r8a77970_info = {
513 .gen = 3, 767 .gen = 3,
514 .quirks = RCAR_LVDS_QUIRK_GEN2_PLLCR | RCAR_LVDS_QUIRK_GEN3_LVEN, 768 .quirks = RCAR_LVDS_QUIRK_PWD | RCAR_LVDS_QUIRK_GEN3_LVEN,
769 .pll_setup = rcar_lvds_pll_setup_gen2,
770};
771
772static const struct rcar_lvds_device_info rcar_lvds_r8a77990_info = {
773 .gen = 3,
774 .quirks = RCAR_LVDS_QUIRK_GEN3_LVEN | RCAR_LVDS_QUIRK_EXT_PLL
775 | RCAR_LVDS_QUIRK_DUAL_LINK,
776 .pll_setup = rcar_lvds_pll_setup_d3_e3,
777};
778
779static const struct rcar_lvds_device_info rcar_lvds_r8a77995_info = {
780 .gen = 3,
781 .quirks = RCAR_LVDS_QUIRK_GEN3_LVEN | RCAR_LVDS_QUIRK_PWD
782 | RCAR_LVDS_QUIRK_EXT_PLL | RCAR_LVDS_QUIRK_DUAL_LINK,
783 .pll_setup = rcar_lvds_pll_setup_d3_e3,
515}; 784};
516 785
517static const struct of_device_id rcar_lvds_of_table[] = { 786static const struct of_device_id rcar_lvds_of_table[] = {
@@ -523,6 +792,8 @@ static const struct of_device_id rcar_lvds_of_table[] = {
523 { .compatible = "renesas,r8a7796-lvds", .data = &rcar_lvds_gen3_info }, 792 { .compatible = "renesas,r8a7796-lvds", .data = &rcar_lvds_gen3_info },
524 { .compatible = "renesas,r8a77970-lvds", .data = &rcar_lvds_r8a77970_info }, 793 { .compatible = "renesas,r8a77970-lvds", .data = &rcar_lvds_r8a77970_info },
525 { .compatible = "renesas,r8a77980-lvds", .data = &rcar_lvds_gen3_info }, 794 { .compatible = "renesas,r8a77980-lvds", .data = &rcar_lvds_gen3_info },
795 { .compatible = "renesas,r8a77990-lvds", .data = &rcar_lvds_r8a77990_info },
796 { .compatible = "renesas,r8a77995-lvds", .data = &rcar_lvds_r8a77995_info },
526 { } 797 { }
527}; 798};
528 799
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
index 4870f50d9bec..87149f2f8056 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
@@ -18,7 +18,7 @@
18#define LVDCR0_PLLON (1 << 4) 18#define LVDCR0_PLLON (1 << 4)
19#define LVDCR0_PWD (1 << 2) /* Gen3 only */ 19#define LVDCR0_PWD (1 << 2) /* Gen3 only */
20#define LVDCR0_BEN (1 << 2) /* Gen2 only */ 20#define LVDCR0_BEN (1 << 2) /* Gen2 only */
21#define LVDCR0_LVEN (1 << 1) /* Gen2 only */ 21#define LVDCR0_LVEN (1 << 1)
22#define LVDCR0_LVRES (1 << 0) 22#define LVDCR0_LVRES (1 << 0)
23 23
24#define LVDCR1 0x0004 24#define LVDCR1 0x0004
@@ -27,21 +27,36 @@
27#define LVDCR1_CLKSTBY (3 << 0) 27#define LVDCR1_CLKSTBY (3 << 0)
28 28
29#define LVDPLLCR 0x0008 29#define LVDPLLCR 0x0008
30/* Gen2 & V3M */
30#define LVDPLLCR_CEEN (1 << 14) 31#define LVDPLLCR_CEEN (1 << 14)
31#define LVDPLLCR_FBEN (1 << 13) 32#define LVDPLLCR_FBEN (1 << 13)
32#define LVDPLLCR_COSEL (1 << 12) 33#define LVDPLLCR_COSEL (1 << 12)
33/* Gen2 */
34#define LVDPLLCR_PLLDLYCNT_150M (0x1bf << 0) 34#define LVDPLLCR_PLLDLYCNT_150M (0x1bf << 0)
35#define LVDPLLCR_PLLDLYCNT_121M (0x22c << 0) 35#define LVDPLLCR_PLLDLYCNT_121M (0x22c << 0)
36#define LVDPLLCR_PLLDLYCNT_60M (0x77b << 0) 36#define LVDPLLCR_PLLDLYCNT_60M (0x77b << 0)
37#define LVDPLLCR_PLLDLYCNT_38M (0x69a << 0) 37#define LVDPLLCR_PLLDLYCNT_38M (0x69a << 0)
38#define LVDPLLCR_PLLDLYCNT_MASK (0x7ff << 0) 38#define LVDPLLCR_PLLDLYCNT_MASK (0x7ff << 0)
39/* Gen3 */ 39/* Gen3 but V3M,D3 and E3 */
40#define LVDPLLCR_PLLDIVCNT_42M (0x014cb << 0) 40#define LVDPLLCR_PLLDIVCNT_42M (0x014cb << 0)
41#define LVDPLLCR_PLLDIVCNT_85M (0x00a45 << 0) 41#define LVDPLLCR_PLLDIVCNT_85M (0x00a45 << 0)
42#define LVDPLLCR_PLLDIVCNT_128M (0x006c3 << 0) 42#define LVDPLLCR_PLLDIVCNT_128M (0x006c3 << 0)
43#define LVDPLLCR_PLLDIVCNT_148M (0x046c1 << 0) 43#define LVDPLLCR_PLLDIVCNT_148M (0x046c1 << 0)
44#define LVDPLLCR_PLLDIVCNT_MASK (0x7ffff << 0) 44#define LVDPLLCR_PLLDIVCNT_MASK (0x7ffff << 0)
45/* D3 and E3 */
46#define LVDPLLCR_PLLON (1 << 22)
47#define LVDPLLCR_PLLSEL_PLL0 (0 << 20)
48#define LVDPLLCR_PLLSEL_LVX (1 << 20)
49#define LVDPLLCR_PLLSEL_PLL1 (2 << 20)
50#define LVDPLLCR_CKSEL_LVX (1 << 17)
51#define LVDPLLCR_CKSEL_EXTAL (3 << 17)
52#define LVDPLLCR_CKSEL_DU_DOTCLKIN(n) ((5 + (n) * 2) << 17)
53#define LVDPLLCR_OCKSEL (1 << 16)
54#define LVDPLLCR_STP_CLKOUTE (1 << 14)
55#define LVDPLLCR_OUTCLKSEL (1 << 12)
56#define LVDPLLCR_CLKOUT (1 << 11)
57#define LVDPLLCR_PLLE(n) ((n) << 10)
58#define LVDPLLCR_PLLN(n) ((n) << 3)
59#define LVDPLLCR_PLLM(n) ((n) << 0)
45 60
46#define LVDCTRCR 0x000c 61#define LVDCTRCR 0x000c
47#define LVDCTRCR_CTR3SEL_ZERO (0 << 12) 62#define LVDCTRCR_CTR3SEL_ZERO (0 << 12)
@@ -71,4 +86,26 @@
71#define LVDCHCR_CHSEL_CH(n, c) ((((c) - (n)) & 3) << ((n) * 4)) 86#define LVDCHCR_CHSEL_CH(n, c) ((((c) - (n)) & 3) << ((n) * 4))
72#define LVDCHCR_CHSEL_MASK(n) (3 << ((n) * 4)) 87#define LVDCHCR_CHSEL_MASK(n) (3 << ((n) * 4))
73 88
89/* All registers below are specific to D3 and E3 */
90#define LVDSTRIPE 0x0014
91#define LVDSTRIPE_ST_TRGSEL_DISP (0 << 2)
92#define LVDSTRIPE_ST_TRGSEL_HSYNC_R (1 << 2)
93#define LVDSTRIPE_ST_TRGSEL_HSYNC_F (2 << 2)
94#define LVDSTRIPE_ST_SWAP (1 << 1)
95#define LVDSTRIPE_ST_ON (1 << 0)
96
97#define LVDSCR 0x0018
98#define LVDSCR_DEPTH(n) (((n) - 1) << 29)
99#define LVDSCR_BANDSET (1 << 28)
100#define LVDSCR_TWGCNT(n) ((((n) - 256) / 16) << 24)
101#define LVDSCR_SDIV(n) ((n) << 22)
102#define LVDSCR_MODE (1 << 21)
103#define LVDSCR_RSTN (1 << 20)
104
105#define LVDDIV 0x001c
106#define LVDDIV_DIVSEL (1 << 8)
107#define LVDDIV_DIVRESET (1 << 7)
108#define LVDDIV_DIVSTP (1 << 6)
109#define LVDDIV_DIV(n) ((n) << 0)
110
74#endif /* __RCAR_LVDS_REGS_H__ */ 111#endif /* __RCAR_LVDS_REGS_H__ */