0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/clk.h>
0011 #include <linux/delay.h>
0012 #include <linux/io.h>
0013 #include <linux/media-bus-format.h>
0014 #include <linux/module.h>
0015 #include <linux/of.h>
0016 #include <linux/of_device.h>
0017 #include <linux/of_graph.h>
0018 #include <linux/platform_device.h>
0019 #include <linux/slab.h>
0020 #include <linux/sys_soc.h>
0021
0022 #include <drm/drm_atomic.h>
0023 #include <drm/drm_atomic_helper.h>
0024 #include <drm/drm_bridge.h>
0025 #include <drm/drm_of.h>
0026 #include <drm/drm_panel.h>
0027 #include <drm/drm_print.h>
0028 #include <drm/drm_probe_helper.h>
0029
0030 #include "rcar_lvds.h"
0031 #include "rcar_lvds_regs.h"
0032
0033 struct rcar_lvds;
0034
0035
0036 enum rcar_lvds_mode {
0037 RCAR_LVDS_MODE_JEIDA = 0,
0038 RCAR_LVDS_MODE_MIRROR = 1,
0039 RCAR_LVDS_MODE_VESA = 4,
0040 };
0041
0042 enum rcar_lvds_link_type {
0043 RCAR_LVDS_SINGLE_LINK = 0,
0044 RCAR_LVDS_DUAL_LINK_EVEN_ODD_PIXELS = 1,
0045 RCAR_LVDS_DUAL_LINK_ODD_EVEN_PIXELS = 2,
0046 };
0047
0048 #define RCAR_LVDS_QUIRK_LANES BIT(0)
0049 #define RCAR_LVDS_QUIRK_GEN3_LVEN BIT(1)
0050 #define RCAR_LVDS_QUIRK_PWD BIT(2)
0051 #define RCAR_LVDS_QUIRK_EXT_PLL BIT(3)
0052 #define RCAR_LVDS_QUIRK_DUAL_LINK BIT(4)
0053
0054 struct rcar_lvds_device_info {
0055 unsigned int gen;
0056 unsigned int quirks;
0057 void (*pll_setup)(struct rcar_lvds *lvds, unsigned int freq);
0058 };
0059
0060 struct rcar_lvds {
0061 struct device *dev;
0062 const struct rcar_lvds_device_info *info;
0063
0064 struct drm_bridge bridge;
0065
0066 struct drm_bridge *next_bridge;
0067 struct drm_panel *panel;
0068
0069 void __iomem *mmio;
0070 struct {
0071 struct clk *mod;
0072 struct clk *extal;
0073 struct clk *dotclkin[2];
0074 } clocks;
0075
0076 struct drm_bridge *companion;
0077 enum rcar_lvds_link_type link_type;
0078 };
0079
0080 #define bridge_to_rcar_lvds(b) \
0081 container_of(b, struct rcar_lvds, bridge)
0082
0083 static void rcar_lvds_write(struct rcar_lvds *lvds, u32 reg, u32 data)
0084 {
0085 iowrite32(data, lvds->mmio + reg);
0086 }
0087
0088
0089
0090
0091
0092 static void rcar_lvds_pll_setup_gen2(struct rcar_lvds *lvds, unsigned int freq)
0093 {
0094 u32 val;
0095
0096 if (freq < 39000000)
0097 val = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M;
0098 else if (freq < 61000000)
0099 val = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M;
0100 else if (freq < 121000000)
0101 val = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M;
0102 else
0103 val = LVDPLLCR_PLLDLYCNT_150M;
0104
0105 rcar_lvds_write(lvds, LVDPLLCR, val);
0106 }
0107
0108 static void rcar_lvds_pll_setup_gen3(struct rcar_lvds *lvds, unsigned int freq)
0109 {
0110 u32 val;
0111
0112 if (freq < 42000000)
0113 val = LVDPLLCR_PLLDIVCNT_42M;
0114 else if (freq < 85000000)
0115 val = LVDPLLCR_PLLDIVCNT_85M;
0116 else if (freq < 128000000)
0117 val = LVDPLLCR_PLLDIVCNT_128M;
0118 else
0119 val = LVDPLLCR_PLLDIVCNT_148M;
0120
0121 rcar_lvds_write(lvds, LVDPLLCR, val);
0122 }
0123
0124 struct pll_info {
0125 unsigned long diff;
0126 unsigned int pll_m;
0127 unsigned int pll_n;
0128 unsigned int pll_e;
0129 unsigned int div;
0130 u32 clksel;
0131 };
0132
0133 static void rcar_lvds_d3_e3_pll_calc(struct rcar_lvds *lvds, struct clk *clk,
0134 unsigned long target, struct pll_info *pll,
0135 u32 clksel, bool dot_clock_only)
0136 {
0137 unsigned int div7 = dot_clock_only ? 1 : 7;
0138 unsigned long output;
0139 unsigned long fin;
0140 unsigned int m_min;
0141 unsigned int m_max;
0142 unsigned int m;
0143 int error;
0144
0145 if (!clk)
0146 return;
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178 fin = clk_get_rate(clk);
0179 if (fin < 12000000 || fin > 192000000)
0180 return;
0181
0182
0183
0184
0185
0186
0187
0188 m_min = max_t(unsigned int, 1, DIV_ROUND_UP(fin, 24000000));
0189 m_max = min_t(unsigned int, 8, fin / 12000000);
0190
0191 for (m = m_min; m <= m_max; ++m) {
0192 unsigned long fpfd;
0193 unsigned int n_min;
0194 unsigned int n_max;
0195 unsigned int n;
0196
0197
0198
0199
0200
0201
0202
0203
0204 fpfd = fin / m;
0205 n_min = max_t(unsigned int, 60, DIV_ROUND_UP(900000000, fpfd));
0206 n_max = min_t(unsigned int, 120, 1800000000 / fpfd);
0207
0208 for (n = n_min; n < n_max; ++n) {
0209 unsigned long fvco;
0210 unsigned int e_min;
0211 unsigned int e;
0212
0213
0214
0215
0216
0217
0218
0219
0220 fvco = fpfd * n;
0221 e_min = fvco > 1039500000 ? 1 : 0;
0222
0223 for (e = e_min; e < 3; ++e) {
0224 unsigned long fout;
0225 unsigned long diff;
0226 unsigned int div;
0227
0228
0229
0230
0231
0232
0233 fout = fvco / (1 << e) / div7;
0234 div = max(1UL, DIV_ROUND_CLOSEST(fout, target));
0235 diff = abs(fout / div - target);
0236
0237 if (diff < pll->diff) {
0238 pll->diff = diff;
0239 pll->pll_m = m;
0240 pll->pll_n = n;
0241 pll->pll_e = e;
0242 pll->div = div;
0243 pll->clksel = clksel;
0244
0245 if (diff == 0)
0246 goto done;
0247 }
0248 }
0249 }
0250 }
0251
0252 done:
0253 output = fin * pll->pll_n / pll->pll_m / (1 << pll->pll_e)
0254 / div7 / pll->div;
0255 error = (long)(output - target) * 10000 / (long)target;
0256
0257 dev_dbg(lvds->dev,
0258 "%pC %lu Hz -> Fout %lu Hz (target %lu Hz, error %d.%02u%%), PLL M/N/E/DIV %u/%u/%u/%u\n",
0259 clk, fin, output, target, error / 100,
0260 error < 0 ? -error % 100 : error % 100,
0261 pll->pll_m, pll->pll_n, pll->pll_e, pll->div);
0262 }
0263
0264 static void __rcar_lvds_pll_setup_d3_e3(struct rcar_lvds *lvds,
0265 unsigned int freq, bool dot_clock_only)
0266 {
0267 struct pll_info pll = { .diff = (unsigned long)-1 };
0268 u32 lvdpllcr;
0269
0270 rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.dotclkin[0], freq, &pll,
0271 LVDPLLCR_CKSEL_DU_DOTCLKIN(0), dot_clock_only);
0272 rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.dotclkin[1], freq, &pll,
0273 LVDPLLCR_CKSEL_DU_DOTCLKIN(1), dot_clock_only);
0274 rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.extal, freq, &pll,
0275 LVDPLLCR_CKSEL_EXTAL, dot_clock_only);
0276
0277 lvdpllcr = LVDPLLCR_PLLON | pll.clksel | LVDPLLCR_CLKOUT
0278 | LVDPLLCR_PLLN(pll.pll_n - 1) | LVDPLLCR_PLLM(pll.pll_m - 1);
0279
0280 if (pll.pll_e > 0)
0281 lvdpllcr |= LVDPLLCR_STP_CLKOUTE | LVDPLLCR_OUTCLKSEL
0282 | LVDPLLCR_PLLE(pll.pll_e - 1);
0283
0284 if (dot_clock_only)
0285 lvdpllcr |= LVDPLLCR_OCKSEL;
0286
0287 rcar_lvds_write(lvds, LVDPLLCR, lvdpllcr);
0288
0289 if (pll.div > 1)
0290
0291
0292
0293
0294 rcar_lvds_write(lvds, LVDDIV, LVDDIV_DIVSEL |
0295 LVDDIV_DIVRESET | LVDDIV_DIV(pll.div - 1));
0296 else
0297 rcar_lvds_write(lvds, LVDDIV, 0);
0298 }
0299
0300 static void rcar_lvds_pll_setup_d3_e3(struct rcar_lvds *lvds, unsigned int freq)
0301 {
0302 __rcar_lvds_pll_setup_d3_e3(lvds, freq, false);
0303 }
0304
0305
0306
0307
0308
0309 int rcar_lvds_clk_enable(struct drm_bridge *bridge, unsigned long freq)
0310 {
0311 struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
0312 int ret;
0313
0314 if (WARN_ON(!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)))
0315 return -ENODEV;
0316
0317 dev_dbg(lvds->dev, "enabling LVDS PLL, freq=%luHz\n", freq);
0318
0319 ret = clk_prepare_enable(lvds->clocks.mod);
0320 if (ret < 0)
0321 return ret;
0322
0323 __rcar_lvds_pll_setup_d3_e3(lvds, freq, true);
0324
0325 return 0;
0326 }
0327 EXPORT_SYMBOL_GPL(rcar_lvds_clk_enable);
0328
0329 void rcar_lvds_clk_disable(struct drm_bridge *bridge)
0330 {
0331 struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
0332
0333 if (WARN_ON(!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)))
0334 return;
0335
0336 dev_dbg(lvds->dev, "disabling LVDS PLL\n");
0337
0338 rcar_lvds_write(lvds, LVDPLLCR, 0);
0339
0340 clk_disable_unprepare(lvds->clocks.mod);
0341 }
0342 EXPORT_SYMBOL_GPL(rcar_lvds_clk_disable);
0343
0344
0345
0346
0347
0348 static enum rcar_lvds_mode rcar_lvds_get_lvds_mode(struct rcar_lvds *lvds,
0349 const struct drm_connector *connector)
0350 {
0351 const struct drm_display_info *info;
0352 enum rcar_lvds_mode mode;
0353
0354
0355
0356
0357
0358 if (!lvds->panel)
0359 return RCAR_LVDS_MODE_JEIDA;
0360
0361 info = &connector->display_info;
0362 if (!info->num_bus_formats || !info->bus_formats) {
0363 dev_warn(lvds->dev,
0364 "no LVDS bus format reported, using JEIDA\n");
0365 return RCAR_LVDS_MODE_JEIDA;
0366 }
0367
0368 switch (info->bus_formats[0]) {
0369 case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
0370 case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
0371 mode = RCAR_LVDS_MODE_JEIDA;
0372 break;
0373 case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
0374 mode = RCAR_LVDS_MODE_VESA;
0375 break;
0376 default:
0377 dev_warn(lvds->dev,
0378 "unsupported LVDS bus format 0x%04x, using JEIDA\n",
0379 info->bus_formats[0]);
0380 return RCAR_LVDS_MODE_JEIDA;
0381 }
0382
0383 if (info->bus_flags & DRM_BUS_FLAG_DATA_LSB_TO_MSB)
0384 mode |= RCAR_LVDS_MODE_MIRROR;
0385
0386 return mode;
0387 }
0388
0389 static void __rcar_lvds_atomic_enable(struct drm_bridge *bridge,
0390 struct drm_atomic_state *state,
0391 struct drm_crtc *crtc,
0392 struct drm_connector *connector)
0393 {
0394 struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
0395 u32 lvdhcr;
0396 u32 lvdcr0;
0397 int ret;
0398
0399 ret = clk_prepare_enable(lvds->clocks.mod);
0400 if (ret < 0)
0401 return;
0402
0403
0404 if (lvds->link_type != RCAR_LVDS_SINGLE_LINK && lvds->companion)
0405 __rcar_lvds_atomic_enable(lvds->companion, state, crtc,
0406 connector);
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416 rcar_lvds_write(lvds, LVDCTRCR, LVDCTRCR_CTR3SEL_ZERO |
0417 LVDCTRCR_CTR2SEL_DISP | LVDCTRCR_CTR1SEL_VSYNC |
0418 LVDCTRCR_CTR0SEL_HSYNC);
0419
0420 if (lvds->info->quirks & RCAR_LVDS_QUIRK_LANES)
0421 lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 3)
0422 | LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 1);
0423 else
0424 lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 1)
0425 | LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 3);
0426
0427 rcar_lvds_write(lvds, LVDCHCR, lvdhcr);
0428
0429 if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK) {
0430 u32 lvdstripe = 0;
0431
0432 if (lvds->link_type != RCAR_LVDS_SINGLE_LINK) {
0433
0434
0435
0436
0437
0438
0439
0440 bool swap_pixels = lvds->link_type ==
0441 RCAR_LVDS_DUAL_LINK_ODD_EVEN_PIXELS;
0442
0443
0444
0445
0446
0447
0448
0449
0450 lvdstripe = LVDSTRIPE_ST_ON
0451 | (lvds->companion && swap_pixels ?
0452 LVDSTRIPE_ST_SWAP : 0);
0453 }
0454 rcar_lvds_write(lvds, LVDSTRIPE, lvdstripe);
0455 }
0456
0457
0458
0459
0460
0461 if (lvds->link_type == RCAR_LVDS_SINGLE_LINK || lvds->companion) {
0462 const struct drm_crtc_state *crtc_state =
0463 drm_atomic_get_new_crtc_state(state, crtc);
0464 const struct drm_display_mode *mode =
0465 &crtc_state->adjusted_mode;
0466
0467 lvds->info->pll_setup(lvds, mode->clock * 1000);
0468 }
0469
0470
0471 lvdcr0 = rcar_lvds_get_lvds_mode(lvds, connector) << LVDCR0_LVMD_SHIFT;
0472
0473 if (lvds->bridge.encoder) {
0474 if (drm_crtc_index(crtc) == 2)
0475 lvdcr0 |= LVDCR0_DUSEL;
0476 }
0477
0478 rcar_lvds_write(lvds, LVDCR0, lvdcr0);
0479
0480
0481 rcar_lvds_write(lvds, LVDCR1,
0482 LVDCR1_CHSTBY(3) | LVDCR1_CHSTBY(2) |
0483 LVDCR1_CHSTBY(1) | LVDCR1_CHSTBY(0) | LVDCR1_CLKSTBY);
0484
0485 if (lvds->info->gen < 3) {
0486
0487 lvdcr0 |= LVDCR0_BEN | LVDCR0_LVEN;
0488 rcar_lvds_write(lvds, LVDCR0, lvdcr0);
0489 }
0490
0491 if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)) {
0492
0493
0494
0495
0496 lvdcr0 |= LVDCR0_PLLON;
0497 rcar_lvds_write(lvds, LVDCR0, lvdcr0);
0498 }
0499
0500 if (lvds->info->quirks & RCAR_LVDS_QUIRK_PWD) {
0501
0502 lvdcr0 |= LVDCR0_PWD;
0503 rcar_lvds_write(lvds, LVDCR0, lvdcr0);
0504 }
0505
0506 if (lvds->info->quirks & RCAR_LVDS_QUIRK_GEN3_LVEN) {
0507
0508
0509
0510
0511 lvdcr0 |= LVDCR0_LVEN;
0512 if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_PWD))
0513 rcar_lvds_write(lvds, LVDCR0, lvdcr0);
0514 }
0515
0516 if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)) {
0517
0518 usleep_range(100, 150);
0519 }
0520
0521
0522 lvdcr0 |= LVDCR0_LVRES;
0523 rcar_lvds_write(lvds, LVDCR0, lvdcr0);
0524 }
0525
0526 static void rcar_lvds_atomic_enable(struct drm_bridge *bridge,
0527 struct drm_bridge_state *old_bridge_state)
0528 {
0529 struct drm_atomic_state *state = old_bridge_state->base.state;
0530 struct drm_connector *connector;
0531 struct drm_crtc *crtc;
0532
0533 connector = drm_atomic_get_new_connector_for_encoder(state,
0534 bridge->encoder);
0535 crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
0536
0537 __rcar_lvds_atomic_enable(bridge, state, crtc, connector);
0538 }
0539
0540 static void rcar_lvds_atomic_disable(struct drm_bridge *bridge,
0541 struct drm_bridge_state *old_bridge_state)
0542 {
0543 struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
0544
0545 rcar_lvds_write(lvds, LVDCR0, 0);
0546 rcar_lvds_write(lvds, LVDCR1, 0);
0547 rcar_lvds_write(lvds, LVDPLLCR, 0);
0548
0549
0550 if (lvds->link_type != RCAR_LVDS_SINGLE_LINK && lvds->companion)
0551 lvds->companion->funcs->atomic_disable(lvds->companion,
0552 old_bridge_state);
0553
0554 clk_disable_unprepare(lvds->clocks.mod);
0555 }
0556
0557 static bool rcar_lvds_mode_fixup(struct drm_bridge *bridge,
0558 const struct drm_display_mode *mode,
0559 struct drm_display_mode *adjusted_mode)
0560 {
0561 struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
0562 int min_freq;
0563
0564
0565
0566
0567
0568
0569 min_freq = lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL ? 5000 : 31000;
0570 adjusted_mode->clock = clamp(adjusted_mode->clock, min_freq, 148500);
0571
0572 return true;
0573 }
0574
0575 static int rcar_lvds_attach(struct drm_bridge *bridge,
0576 enum drm_bridge_attach_flags flags)
0577 {
0578 struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
0579
0580 if (!lvds->next_bridge)
0581 return 0;
0582
0583 return drm_bridge_attach(bridge->encoder, lvds->next_bridge, bridge,
0584 flags);
0585 }
0586
0587 static const struct drm_bridge_funcs rcar_lvds_bridge_ops = {
0588 .attach = rcar_lvds_attach,
0589 .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
0590 .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
0591 .atomic_reset = drm_atomic_helper_bridge_reset,
0592 .atomic_enable = rcar_lvds_atomic_enable,
0593 .atomic_disable = rcar_lvds_atomic_disable,
0594 .mode_fixup = rcar_lvds_mode_fixup,
0595 };
0596
0597 bool rcar_lvds_dual_link(struct drm_bridge *bridge)
0598 {
0599 struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
0600
0601 return lvds->link_type != RCAR_LVDS_SINGLE_LINK;
0602 }
0603 EXPORT_SYMBOL_GPL(rcar_lvds_dual_link);
0604
0605 bool rcar_lvds_is_connected(struct drm_bridge *bridge)
0606 {
0607 struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
0608
0609 return lvds->next_bridge != NULL;
0610 }
0611 EXPORT_SYMBOL_GPL(rcar_lvds_is_connected);
0612
0613
0614
0615
0616
0617 static int rcar_lvds_parse_dt_companion(struct rcar_lvds *lvds)
0618 {
0619 const struct of_device_id *match;
0620 struct device_node *companion;
0621 struct device_node *port0, *port1;
0622 struct rcar_lvds *companion_lvds;
0623 struct device *dev = lvds->dev;
0624 int dual_link;
0625 int ret = 0;
0626
0627
0628 companion = of_parse_phandle(dev->of_node, "renesas,companion", 0);
0629 if (!companion)
0630 return 0;
0631
0632
0633
0634
0635
0636 match = of_match_device(dev->driver->of_match_table, dev);
0637 if (!of_device_is_compatible(companion, match->compatible)) {
0638 dev_err(dev, "Companion LVDS encoder is invalid\n");
0639 ret = -ENXIO;
0640 goto done;
0641 }
0642
0643
0644
0645
0646
0647
0648
0649 port0 = of_graph_get_port_by_id(dev->of_node, 1);
0650 port1 = of_graph_get_port_by_id(companion, 1);
0651 dual_link = drm_of_lvds_get_dual_link_pixel_order(port0, port1);
0652 of_node_put(port0);
0653 of_node_put(port1);
0654
0655 switch (dual_link) {
0656 case DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS:
0657 lvds->link_type = RCAR_LVDS_DUAL_LINK_ODD_EVEN_PIXELS;
0658 break;
0659 case DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS:
0660 lvds->link_type = RCAR_LVDS_DUAL_LINK_EVEN_ODD_PIXELS;
0661 break;
0662 default:
0663
0664
0665
0666
0667
0668
0669 if (lvds->next_bridge->timings &&
0670 lvds->next_bridge->timings->dual_link)
0671 lvds->link_type = RCAR_LVDS_DUAL_LINK_EVEN_ODD_PIXELS;
0672 else
0673 lvds->link_type = RCAR_LVDS_SINGLE_LINK;
0674 }
0675
0676 if (lvds->link_type == RCAR_LVDS_SINGLE_LINK) {
0677 dev_dbg(dev, "Single-link configuration detected\n");
0678 goto done;
0679 }
0680
0681 lvds->companion = of_drm_find_bridge(companion);
0682 if (!lvds->companion) {
0683 ret = -EPROBE_DEFER;
0684 goto done;
0685 }
0686
0687 dev_dbg(dev,
0688 "Dual-link configuration detected (companion encoder %pOF)\n",
0689 companion);
0690
0691 if (lvds->link_type == RCAR_LVDS_DUAL_LINK_ODD_EVEN_PIXELS)
0692 dev_dbg(dev, "Data swapping required\n");
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703 companion_lvds = bridge_to_rcar_lvds(lvds->companion);
0704 companion_lvds->link_type = lvds->link_type;
0705
0706 done:
0707 of_node_put(companion);
0708
0709 return ret;
0710 }
0711
0712 static int rcar_lvds_parse_dt(struct rcar_lvds *lvds)
0713 {
0714 int ret;
0715
0716 ret = drm_of_find_panel_or_bridge(lvds->dev->of_node, 1, 0,
0717 &lvds->panel, &lvds->next_bridge);
0718 if (ret)
0719 goto done;
0720
0721 if (lvds->panel) {
0722 lvds->next_bridge = devm_drm_panel_bridge_add(lvds->dev,
0723 lvds->panel);
0724 if (IS_ERR_OR_NULL(lvds->next_bridge)) {
0725 ret = -EINVAL;
0726 goto done;
0727 }
0728 }
0729
0730 if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK)
0731 ret = rcar_lvds_parse_dt_companion(lvds);
0732
0733 done:
0734
0735
0736
0737
0738
0739
0740 if (lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)
0741 return ret == -ENODEV ? 0 : ret;
0742
0743 return ret;
0744 }
0745
0746 static struct clk *rcar_lvds_get_clock(struct rcar_lvds *lvds, const char *name,
0747 bool optional)
0748 {
0749 struct clk *clk;
0750
0751 clk = devm_clk_get(lvds->dev, name);
0752 if (!IS_ERR(clk))
0753 return clk;
0754
0755 if (PTR_ERR(clk) == -ENOENT && optional)
0756 return NULL;
0757
0758 dev_err_probe(lvds->dev, PTR_ERR(clk), "failed to get %s clock\n",
0759 name ? name : "module");
0760
0761 return clk;
0762 }
0763
0764 static int rcar_lvds_get_clocks(struct rcar_lvds *lvds)
0765 {
0766 lvds->clocks.mod = rcar_lvds_get_clock(lvds, NULL, false);
0767 if (IS_ERR(lvds->clocks.mod))
0768 return PTR_ERR(lvds->clocks.mod);
0769
0770
0771
0772
0773 if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL))
0774 return 0;
0775
0776 lvds->clocks.extal = rcar_lvds_get_clock(lvds, "extal", true);
0777 if (IS_ERR(lvds->clocks.extal))
0778 return PTR_ERR(lvds->clocks.extal);
0779
0780 lvds->clocks.dotclkin[0] = rcar_lvds_get_clock(lvds, "dclkin.0", true);
0781 if (IS_ERR(lvds->clocks.dotclkin[0]))
0782 return PTR_ERR(lvds->clocks.dotclkin[0]);
0783
0784 lvds->clocks.dotclkin[1] = rcar_lvds_get_clock(lvds, "dclkin.1", true);
0785 if (IS_ERR(lvds->clocks.dotclkin[1]))
0786 return PTR_ERR(lvds->clocks.dotclkin[1]);
0787
0788
0789 if (!lvds->clocks.extal && !lvds->clocks.dotclkin[0] &&
0790 !lvds->clocks.dotclkin[1]) {
0791 dev_err(lvds->dev,
0792 "no input clock (extal, dclkin.0 or dclkin.1)\n");
0793 return -EINVAL;
0794 }
0795
0796 return 0;
0797 }
0798
0799 static const struct rcar_lvds_device_info rcar_lvds_r8a7790es1_info = {
0800 .gen = 2,
0801 .quirks = RCAR_LVDS_QUIRK_LANES,
0802 .pll_setup = rcar_lvds_pll_setup_gen2,
0803 };
0804
0805 static const struct soc_device_attribute lvds_quirk_matches[] = {
0806 {
0807 .soc_id = "r8a7790", .revision = "ES1.*",
0808 .data = &rcar_lvds_r8a7790es1_info,
0809 },
0810 { }
0811 };
0812
0813 static int rcar_lvds_probe(struct platform_device *pdev)
0814 {
0815 const struct soc_device_attribute *attr;
0816 struct rcar_lvds *lvds;
0817 int ret;
0818
0819 lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL);
0820 if (lvds == NULL)
0821 return -ENOMEM;
0822
0823 platform_set_drvdata(pdev, lvds);
0824
0825 lvds->dev = &pdev->dev;
0826 lvds->info = of_device_get_match_data(&pdev->dev);
0827
0828 attr = soc_device_match(lvds_quirk_matches);
0829 if (attr)
0830 lvds->info = attr->data;
0831
0832 ret = rcar_lvds_parse_dt(lvds);
0833 if (ret < 0)
0834 return ret;
0835
0836 lvds->bridge.funcs = &rcar_lvds_bridge_ops;
0837 lvds->bridge.of_node = pdev->dev.of_node;
0838
0839 lvds->mmio = devm_platform_ioremap_resource(pdev, 0);
0840 if (IS_ERR(lvds->mmio))
0841 return PTR_ERR(lvds->mmio);
0842
0843 ret = rcar_lvds_get_clocks(lvds);
0844 if (ret < 0)
0845 return ret;
0846
0847 drm_bridge_add(&lvds->bridge);
0848
0849 return 0;
0850 }
0851
0852 static int rcar_lvds_remove(struct platform_device *pdev)
0853 {
0854 struct rcar_lvds *lvds = platform_get_drvdata(pdev);
0855
0856 drm_bridge_remove(&lvds->bridge);
0857
0858 return 0;
0859 }
0860
0861 static const struct rcar_lvds_device_info rcar_lvds_gen2_info = {
0862 .gen = 2,
0863 .pll_setup = rcar_lvds_pll_setup_gen2,
0864 };
0865
0866 static const struct rcar_lvds_device_info rcar_lvds_gen3_info = {
0867 .gen = 3,
0868 .quirks = RCAR_LVDS_QUIRK_PWD,
0869 .pll_setup = rcar_lvds_pll_setup_gen3,
0870 };
0871
0872 static const struct rcar_lvds_device_info rcar_lvds_r8a77970_info = {
0873 .gen = 3,
0874 .quirks = RCAR_LVDS_QUIRK_PWD | RCAR_LVDS_QUIRK_GEN3_LVEN,
0875 .pll_setup = rcar_lvds_pll_setup_gen2,
0876 };
0877
0878 static const struct rcar_lvds_device_info rcar_lvds_r8a77990_info = {
0879 .gen = 3,
0880 .quirks = RCAR_LVDS_QUIRK_GEN3_LVEN | RCAR_LVDS_QUIRK_EXT_PLL
0881 | RCAR_LVDS_QUIRK_DUAL_LINK,
0882 .pll_setup = rcar_lvds_pll_setup_d3_e3,
0883 };
0884
0885 static const struct rcar_lvds_device_info rcar_lvds_r8a77995_info = {
0886 .gen = 3,
0887 .quirks = RCAR_LVDS_QUIRK_GEN3_LVEN | RCAR_LVDS_QUIRK_PWD
0888 | RCAR_LVDS_QUIRK_EXT_PLL | RCAR_LVDS_QUIRK_DUAL_LINK,
0889 .pll_setup = rcar_lvds_pll_setup_d3_e3,
0890 };
0891
0892 static const struct of_device_id rcar_lvds_of_table[] = {
0893 { .compatible = "renesas,r8a7742-lvds", .data = &rcar_lvds_gen2_info },
0894 { .compatible = "renesas,r8a7743-lvds", .data = &rcar_lvds_gen2_info },
0895 { .compatible = "renesas,r8a7744-lvds", .data = &rcar_lvds_gen2_info },
0896 { .compatible = "renesas,r8a774a1-lvds", .data = &rcar_lvds_gen3_info },
0897 { .compatible = "renesas,r8a774b1-lvds", .data = &rcar_lvds_gen3_info },
0898 { .compatible = "renesas,r8a774c0-lvds", .data = &rcar_lvds_r8a77990_info },
0899 { .compatible = "renesas,r8a774e1-lvds", .data = &rcar_lvds_gen3_info },
0900 { .compatible = "renesas,r8a7790-lvds", .data = &rcar_lvds_gen2_info },
0901 { .compatible = "renesas,r8a7791-lvds", .data = &rcar_lvds_gen2_info },
0902 { .compatible = "renesas,r8a7793-lvds", .data = &rcar_lvds_gen2_info },
0903 { .compatible = "renesas,r8a7795-lvds", .data = &rcar_lvds_gen3_info },
0904 { .compatible = "renesas,r8a7796-lvds", .data = &rcar_lvds_gen3_info },
0905 { .compatible = "renesas,r8a77961-lvds", .data = &rcar_lvds_gen3_info },
0906 { .compatible = "renesas,r8a77965-lvds", .data = &rcar_lvds_gen3_info },
0907 { .compatible = "renesas,r8a77970-lvds", .data = &rcar_lvds_r8a77970_info },
0908 { .compatible = "renesas,r8a77980-lvds", .data = &rcar_lvds_gen3_info },
0909 { .compatible = "renesas,r8a77990-lvds", .data = &rcar_lvds_r8a77990_info },
0910 { .compatible = "renesas,r8a77995-lvds", .data = &rcar_lvds_r8a77995_info },
0911 { }
0912 };
0913
0914 MODULE_DEVICE_TABLE(of, rcar_lvds_of_table);
0915
0916 static struct platform_driver rcar_lvds_platform_driver = {
0917 .probe = rcar_lvds_probe,
0918 .remove = rcar_lvds_remove,
0919 .driver = {
0920 .name = "rcar-lvds",
0921 .of_match_table = rcar_lvds_of_table,
0922 },
0923 };
0924
0925 module_platform_driver(rcar_lvds_platform_driver);
0926
0927 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
0928 MODULE_DESCRIPTION("Renesas R-Car LVDS Encoder Driver");
0929 MODULE_LICENSE("GPL");