Lines Matching +full:lvds +full:- +full:encoder

1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2023, STMicroelectronics - All Rights Reserved
4 * Author(s): Raphaël GALLAIS-POU <raphael.gallais-pou@foss.st.com> for STMicroelectronics.
16 #include <linux/clk-provider.h>
19 #include <linux/media-bus-format.h>
25 /* LVDS Host registers */
46 /* LVDS Wrapper registers */
55 #define CR_LVDSEN BIT(0) /* LVDS PHY Enable */
62 #define CR_LK1POL GENMASK(20, 16) /* Link-1 output Polarity */
63 #define CR_LK2POL GENMASK(25, 21) /* Link-2 output Polarity */
82 #define PHY_GCR_RSTZ BIT(24) /* LVDS PHY digital reset */
94 #define PHY_CFGCR_EN_DIG_DL GENMASK(4, 0) /* LVDS PHY digital lane enable */
95 #define PHY_PLLCR1_PLL_EN BIT(0) /* LVDS PHY PLL enable */
96 #define PHY_PLLCR1_EN_SD BIT(1) /* LVDS PHY PLL sigma-delta signal enable */
97 #define PHY_PLLCR1_EN_TWG BIT(2) /* LVDS PHY PLL triangular wave generator enable */
98 #define PHY_PLLCR1_DIV_EN BIT(8) /* LVDS PHY PLL dividers enable */
101 #define PHY_PLLSR_PLL_LOCK BIT(0) /* LVDS PHY PLL lock status */
120 * ,--------. ,--------. ,--------. ,--------. ,---------.
123 * `--------' `--------' `--------' `--------' `---------'
127 * ,--------. ,--------. ,--------. ,--------. ,---------.
130 * `--------' `--------' `--------' `--------' `---------'
269 struct drm_encoder *encoder; member
282 #define lvds_is_dual_link(lvds) \ argument
284 typeof(lvds) __lvds = (lvds); \
289 static inline void lvds_write(struct stm_lvds *lvds, u32 reg, u32 val) in lvds_write() argument
291 writel(val, lvds->base + reg); in lvds_write()
294 static inline u32 lvds_read(struct stm_lvds *lvds, u32 reg) in lvds_read() argument
296 return readl(lvds->base + reg); in lvds_read()
299 static inline void lvds_set(struct stm_lvds *lvds, u32 reg, u32 mask) in lvds_set() argument
301 lvds_write(lvds, reg, lvds_read(lvds, reg) | mask); in lvds_set()
304 static inline void lvds_clear(struct stm_lvds *lvds, u32 reg, u32 mask) in lvds_clear() argument
306 lvds_write(lvds, reg, lvds_read(lvds, reg) & ~mask); in lvds_clear()
310 * Expected JEIDA-RGB888 data to be sent in LSB format
327 * Expected VESA-RGB888 data to be sent in LSB format
346 static int lvds_pll_enable(struct stm_lvds *lvds, struct lvds_phy_info *phy) in lvds_pll_enable() argument
348 struct drm_device *drm = lvds->lvds_bridge.dev; in lvds_pll_enable()
354 * Adjusted value so that the masking window is opened at start-up in lvds_pll_enable()
356 lvds_write(lvds, phy->base + phy->ofs.MPLCR, (0x200 - 0x160) << 16); in lvds_pll_enable()
359 lvds_write(lvds, phy->base + phy->ofs.BCR2, PHY_BCR2_BIAS_EN); in lvds_pll_enable()
363 lvds_set(lvds, phy->base + phy->ofs.GCR, lvds_gcr); in lvds_pll_enable()
366 lvds_set(lvds, phy->base + phy->ofs.PLLTESTCR, PHY_PLLTESTCR_EN); in lvds_pll_enable()
367 lvds_set(lvds, phy->base + phy->ofs.PLLCR1, PHY_PLLCR1_DIV_EN); in lvds_pll_enable()
370 lvds_set(lvds, phy->base + phy->ofs.SCR, PHY_SCR_TX_EN); in lvds_pll_enable()
372 /* Enable the LVDS PLL & wait for its lock */ in lvds_pll_enable()
373 lvds_set(lvds, phy->base + phy->ofs.PLLCR1, PHY_PLLCR1_PLL_EN); in lvds_pll_enable()
374 ret = readl_poll_timeout_atomic(lvds->base + phy->base + phy->ofs.PLLSR, in lvds_pll_enable()
381 lvds_write(lvds, LVDS_WCLKCR, WCLKCR_SECND_CLKPIX_SEL); in lvds_pll_enable()
383 lvds_set(lvds, phy->ofs.PLLTESTCR, PHY_PLLTESTCR_CLK_EN); in lvds_pll_enable()
407 static int lvds_pll_get_params(struct stm_lvds *lvds, in lvds_pll_get_params() argument
416 return -EINVAL; in lvds_pll_get_params()
427 delta = pll_get_clkout_khz(clkin_khz, i, n, o) - clkout_khz; in lvds_pll_get_params()
429 delta = -delta; in lvds_pll_get_params()
445 static void lvds_pll_config(struct stm_lvds *lvds, struct lvds_phy_info *phy) in lvds_pll_config() argument
452 * The LVDS PHY includes a low power low jitter high performance and in lvds_pll_config()
456 * made of a pre-divider NDIV, a feedback multiplier MDIV, followed by in lvds_pll_config()
457 * several post-dividers, each one with a specific application. in lvds_pll_config()
459 * ,------. ,-----. ,-----. in lvds_pll_config()
460 * Fref --> | NDIV | -Fpdf-> | PFD | --> | VCO | --------> Fvco in lvds_pll_config()
461 * `------' ,-> | | `-----' | in lvds_pll_config()
462 * | `-----' | in lvds_pll_config()
463 * | ,------. | in lvds_pll_config()
464 * `-------- | MDIV | <-----' in lvds_pll_config()
465 * `------' in lvds_pll_config()
469 * is passed through a programmable post-divider BDIV. Finally, the in lvds_pll_config()
472 * ,--------. in lvds_pll_config()
473 * ,-----> | DP div | ----------------> Fdp in lvds_pll_config()
474 * ,------. | `--------' in lvds_pll_config()
475 * Fvco --> | BDIV | ------------------------------------> Fbit in lvds_pll_config()
476 * | `------' ,------. | in lvds_pll_config()
477 * `-------------> | TDIV | --.---------------------> ClkObs in lvds_pll_config()
478 * '------' | ,--------. in lvds_pll_config()
479 * `--> | LS div | ------> Fls in lvds_pll_config()
480 * '--------' in lvds_pll_config()
489 hwclk = __clk_get_hw(lvds->pllref_clk); in lvds_pll_config()
495 if (lvds_is_dual_link(lvds->link_type)) in lvds_pll_config()
500 lvds_pll_get_params(lvds, pll_in_khz, in lvds_pll_config()
501 lvds->pixel_clock_rate * 7 / 1000 / multiplier, in lvds_pll_config()
505 lvds_write(lvds, phy->base + phy->ofs.PLLCR2, ndiv << 16); in lvds_pll_config()
506 lvds_set(lvds, phy->base + phy->ofs.PLLCR2, bdiv); in lvds_pll_config()
507 lvds_write(lvds, phy->base + phy->ofs.PLLSDCR1, mdiv); in lvds_pll_config()
510 lvds_write(lvds, phy->base + phy->ofs.PLLTESTCR, TDIV << 16); in lvds_pll_config()
517 * - PMRY_PLL_TWG_STEP = PMRY_PLL_SD_INT_RATIO in lvds_pll_config()
518 * - EN_TWG = 0 in lvds_pll_config()
519 * - EN_SD = 0 in lvds_pll_config()
520 * - DOWN_SPREAD = 0 in lvds_pll_config()
523 * - EN_TWG = 0 in lvds_pll_config()
524 * - EN_SD = 1 in lvds_pll_config()
525 * - DOWN_SPREAD = 0 in lvds_pll_config()
528 * - EN_TWG = 1 in lvds_pll_config()
529 * - EN_SD = 1 in lvds_pll_config()
533 lvds_clear(lvds, phy->base + phy->ofs.PLLCR1, PHY_PLLCR1_EN_TWG | PHY_PLLCR1_EN_SD); in lvds_pll_config()
536 lvds_set(lvds, phy->base + phy->ofs.DCR, PHY_DCR_POWER_OK); in lvds_pll_config()
537 lvds_set(lvds, phy->base + phy->ofs.CMCR1, PHY_CMCR_CM_EN_DL); in lvds_pll_config()
538 lvds_set(lvds, phy->base + phy->ofs.CMCR2, PHY_CMCR_CM_EN_DL4); in lvds_pll_config()
541 lvds_set(lvds, phy->base + phy->ofs.PLLCPCR, 0x1); in lvds_pll_config()
542 lvds_set(lvds, phy->base + phy->ofs.BCR3, PHY_BCR3_VM_EN_DL); in lvds_pll_config()
543 lvds_set(lvds, phy->base + phy->ofs.BCR1, PHY_BCR1_EN_BIAS_DL); in lvds_pll_config()
545 lvds_set(lvds, phy->base + phy->ofs.CFGCR, PHY_CFGCR_EN_DIG_DL); in lvds_pll_config()
550 struct stm_lvds *lvds = container_of(hw, struct stm_lvds, lvds_ck_px); in lvds_pixel_clk_enable() local
551 struct drm_device *drm = lvds->lvds_bridge.dev; in lvds_pixel_clk_enable()
555 ret = clk_prepare_enable(lvds->pclk); in lvds_pixel_clk_enable()
557 drm_err(drm, "Failed to enable lvds peripheral clk\n"); in lvds_pixel_clk_enable()
561 ret = clk_prepare_enable(lvds->pllref_clk); in lvds_pixel_clk_enable()
563 drm_err(drm, "Failed to enable lvds reference clk\n"); in lvds_pixel_clk_enable()
564 clk_disable_unprepare(lvds->pclk); in lvds_pixel_clk_enable()
569 if (lvds->secondary) { in lvds_pixel_clk_enable()
570 phy = lvds->secondary; in lvds_pixel_clk_enable()
572 /* Release LVDS PHY from reset mode */ in lvds_pixel_clk_enable()
573 lvds_set(lvds, phy->base + phy->ofs.GCR, PHY_GCR_DIV_RSTN | PHY_GCR_RSTZ); in lvds_pixel_clk_enable()
574 lvds_pll_config(lvds, phy); in lvds_pixel_clk_enable()
576 ret = lvds_pll_enable(lvds, phy); in lvds_pixel_clk_enable()
583 if (lvds->primary) { in lvds_pixel_clk_enable()
584 phy = lvds->primary; in lvds_pixel_clk_enable()
586 /* Release LVDS PHY from reset mode */ in lvds_pixel_clk_enable()
587 lvds_set(lvds, phy->base + phy->ofs.GCR, PHY_GCR_DIV_RSTN | PHY_GCR_RSTZ); in lvds_pixel_clk_enable()
588 lvds_pll_config(lvds, phy); in lvds_pixel_clk_enable()
590 ret = lvds_pll_enable(lvds, phy); in lvds_pixel_clk_enable()
602 struct stm_lvds *lvds = container_of(hw, struct stm_lvds, lvds_ck_px); in lvds_pixel_clk_disable() local
608 * Assert LVDS PHY in reset mode in lvds_pixel_clk_disable()
611 if (lvds->primary) { in lvds_pixel_clk_disable()
612 lvds_clear(lvds, lvds->primary->base + lvds->primary->ofs.GCR, in lvds_pixel_clk_disable()
614 lvds_clear(lvds, lvds->primary->base + lvds->primary->ofs.PLLCR1, in lvds_pixel_clk_disable()
616 lvds_clear(lvds, lvds->primary->base + lvds->primary->ofs.GCR, in lvds_pixel_clk_disable()
620 if (lvds->secondary) { in lvds_pixel_clk_disable()
621 lvds_clear(lvds, lvds->secondary->base + lvds->secondary->ofs.GCR, in lvds_pixel_clk_disable()
623 lvds_clear(lvds, lvds->secondary->base + lvds->secondary->ofs.PLLCR1, in lvds_pixel_clk_disable()
625 lvds_clear(lvds, lvds->secondary->base + lvds->secondary->ofs.GCR, in lvds_pixel_clk_disable()
629 clk_disable_unprepare(lvds->pllref_clk); in lvds_pixel_clk_disable()
630 clk_disable_unprepare(lvds->pclk); in lvds_pixel_clk_disable()
636 struct stm_lvds *lvds = container_of(hw, struct stm_lvds, lvds_ck_px); in lvds_pixel_clk_recalc_rate() local
637 struct drm_device *drm = lvds->lvds_bridge.dev; in lvds_pixel_clk_recalc_rate()
642 ret = clk_prepare_enable(lvds->pclk); in lvds_pixel_clk_recalc_rate()
644 drm_err(drm, "Failed to enable lvds peripheral clk\n"); in lvds_pixel_clk_recalc_rate()
648 if (lvds_is_dual_link(lvds->link_type)) in lvds_pixel_clk_recalc_rate()
653 val = lvds_read(lvds, lvds->primary->base + lvds->primary->ofs.PLLCR2); in lvds_pixel_clk_recalc_rate()
658 mdiv = (unsigned int)lvds_read(lvds, in lvds_pixel_clk_recalc_rate()
659 lvds->primary->base + lvds->primary->ofs.PLLSDCR1); in lvds_pixel_clk_recalc_rate()
665 lvds_pll_get_params(lvds, pll_in_khz, in lvds_pixel_clk_recalc_rate()
666 lvds->pixel_clock_rate * 7 / 1000 / multiplier, in lvds_pixel_clk_recalc_rate()
678 lvds->pixel_clock_rate = pll_out_khz * 1000 * multiplier / 7; in lvds_pixel_clk_recalc_rate()
680 clk_disable_unprepare(lvds->pclk); in lvds_pixel_clk_recalc_rate()
682 return (unsigned long)lvds->pixel_clock_rate; in lvds_pixel_clk_recalc_rate()
688 struct stm_lvds *lvds = container_of(hw, struct stm_lvds, lvds_ck_px); in lvds_pixel_clk_round_rate() local
694 connector = &lvds->connector; in lvds_pixel_clk_round_rate()
696 return -EINVAL; in lvds_pixel_clk_round_rate()
698 if (list_empty(&connector->modes)) { in lvds_pixel_clk_round_rate()
699 drm_dbg(connector->dev, "connector: empty modes list\n"); in lvds_pixel_clk_round_rate()
700 return -EINVAL; in lvds_pixel_clk_round_rate()
703 mode = list_first_entry(&connector->modes, in lvds_pixel_clk_round_rate()
708 if (lvds_is_dual_link(lvds->link_type)) in lvds_pixel_clk_round_rate()
713 lvds_pll_get_params(lvds, pll_in_khz, mode->clock * 7 / multiplier, &bdiv, &mdiv, &ndiv); in lvds_pixel_clk_round_rate()
719 lvds->pixel_clock_rate = (unsigned long)pll_get_clkout_khz(pll_in_khz, bdiv, mdiv, ndiv) in lvds_pixel_clk_round_rate()
722 return lvds->pixel_clock_rate; in lvds_pixel_clk_round_rate()
742 struct stm_lvds *lvds = data; in lvds_pixel_clk_unregister() local
744 of_clk_del_provider(lvds->dev->of_node); in lvds_pixel_clk_unregister()
745 clk_hw_unregister(&lvds->lvds_ck_px); in lvds_pixel_clk_unregister()
748 static int lvds_pixel_clk_register(struct stm_lvds *lvds) in lvds_pixel_clk_register() argument
750 struct device_node *node = lvds->dev->of_node; in lvds_pixel_clk_register()
753 lvds->lvds_ck_px.init = &clk_data; in lvds_pixel_clk_register()
756 lvds->pixel_clock_rate = 148500000; in lvds_pixel_clk_register()
758 ret = clk_hw_register(lvds->dev, &lvds->lvds_ck_px); in lvds_pixel_clk_register()
763 &lvds->lvds_ck_px); in lvds_pixel_clk_register()
765 clk_hw_unregister(&lvds->lvds_ck_px); in lvds_pixel_clk_register()
773 static void lvds_config_data_mapping(struct stm_lvds *lvds) in lvds_config_data_mapping() argument
775 struct drm_device *drm = lvds->lvds_bridge.dev; in lvds_config_data_mapping()
781 info = &(&lvds->connector)->display_info; in lvds_config_data_mapping()
782 if (!info->num_bus_formats || !info->bus_formats) { in lvds_config_data_mapping()
783 drm_warn(drm, "No LVDS bus format reported\n"); in lvds_config_data_mapping()
787 switch (info->bus_formats[0]) { in lvds_config_data_mapping()
788 case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: /* VESA-RGB666 */ in lvds_config_data_mapping()
791 case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: /* VESA-RGB888 */ in lvds_config_data_mapping()
794 case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: /* JEIDA-RGB888 */ in lvds_config_data_mapping()
798 drm_warn(drm, "Unsupported LVDS bus format 0x%04x\n", info->bus_formats[0]); in lvds_config_data_mapping()
812 lvds_write(lvds, LVDS_DMLCR(i), lvds_dmlcr); in lvds_config_data_mapping()
813 lvds_write(lvds, LVDS_DMMCR(i), lvds_dmmcr); in lvds_config_data_mapping()
817 static void lvds_config_mode(struct stm_lvds *lvds) in lvds_config_mode() argument
823 connector = &lvds->connector; in lvds_config_mode()
827 if (list_empty(&connector->modes)) { in lvds_config_mode()
828 drm_dbg(connector->dev, "connector: empty modes list\n"); in lvds_config_mode()
832 bus_flags = connector->display_info.bus_flags; in lvds_config_mode()
833 mode = list_first_entry(&connector->modes, in lvds_config_mode()
836 lvds_clear(lvds, LVDS_CR, CR_LKMOD); in lvds_config_mode()
837 lvds_clear(lvds, LVDS_CDL1CR, CDLCR_DISTR0 | CDLCR_DISTR1 | CDLCR_DISTR2 | in lvds_config_mode()
839 lvds_clear(lvds, LVDS_CDL2CR, CDLCR_DISTR0 | CDLCR_DISTR1 | CDLCR_DISTR2 | in lvds_config_mode()
843 if (lvds->primary) in lvds_config_mode()
846 if (lvds->secondary) { in lvds_config_mode()
855 if (mode->flags & DRM_MODE_FLAG_NHSYNC) in lvds_config_mode()
858 if (mode->flags & DRM_MODE_FLAG_NVSYNC) in lvds_config_mode()
861 switch (lvds->link_type) { in lvds_config_mode()
869 drm_notice(lvds->lvds_bridge.dev, "No phase precised, setting default\n"); in lvds_config_mode()
875 lvds_set(lvds, LVDS_CR, lvds_cr); in lvds_config_mode()
876 lvds_write(lvds, LVDS_CDL1CR, lvds_cdl1cr); in lvds_config_mode()
877 lvds_write(lvds, LVDS_CDL2CR, lvds_cdl2cr); in lvds_config_mode()
882 struct stm_lvds *lvds = connector_to_stm_lvds(connector); in lvds_connector_get_modes() local
884 return drm_panel_get_modes(lvds->panel, connector); in lvds_connector_get_modes()
896 return -EINVAL; in lvds_connector_atomic_check()
898 if (list_empty(&connector->modes)) { in lvds_connector_atomic_check()
899 drm_dbg(connector->dev, "connector: empty modes list\n"); in lvds_connector_atomic_check()
900 return -EINVAL; in lvds_connector_atomic_check()
903 if (!conn_state->crtc) in lvds_connector_atomic_check()
904 return -EINVAL; in lvds_connector_atomic_check()
906 panel_mode = list_first_entry(&connector->modes, in lvds_connector_atomic_check()
910 crtc_state = drm_atomic_get_crtc_state(state, conn_state->crtc); in lvds_connector_atomic_check()
914 if (crtc_state->mode.hdisplay != panel_mode->hdisplay || in lvds_connector_atomic_check()
915 crtc_state->mode.vdisplay != panel_mode->vdisplay) in lvds_connector_atomic_check()
916 return -EINVAL; in lvds_connector_atomic_check()
919 drm_mode_copy(&crtc_state->adjusted_mode, panel_mode); in lvds_connector_atomic_check()
940 struct stm_lvds *lvds = bridge_to_stm_lvds(bridge); in lvds_attach() local
941 struct drm_connector *connector = &lvds->connector; in lvds_attach()
942 struct drm_encoder *encoder = bridge->encoder; in lvds_attach() local
945 if (!bridge->encoder) { in lvds_attach()
946 drm_err(bridge->dev, "Parent encoder object not found\n"); in lvds_attach()
947 return -ENODEV; in lvds_attach()
950 /* Set the encoder type as caller does not know it */ in lvds_attach()
951 bridge->encoder->encoder_type = DRM_MODE_ENCODER_LVDS; in lvds_attach()
954 bridge->encoder->possible_clones = 0; in lvds_attach()
957 if (lvds->next_bridge) in lvds_attach()
958 return drm_bridge_attach(bridge->encoder, lvds->next_bridge, in lvds_attach()
962 drm_err(bridge->dev, "Fix bridge driver to make connector optional!"); in lvds_attach()
963 return -EINVAL; in lvds_attach()
967 if (!lvds->panel) in lvds_attach()
970 ret = drm_connector_init(bridge->dev, connector, in lvds_attach()
977 ret = drm_connector_attach_encoder(connector, encoder); in lvds_attach()
985 struct drm_atomic_state *state = old_bridge_state->base.state; in lvds_atomic_enable()
986 struct stm_lvds *lvds = bridge_to_stm_lvds(bridge); in lvds_atomic_enable() local
991 ret = clk_prepare_enable(lvds->pclk); in lvds_atomic_enable()
993 drm_err(bridge->dev, "Failed to enable lvds peripheral clk\n"); in lvds_atomic_enable()
997 connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); in lvds_atomic_enable()
1005 lvds_config_mode(lvds); in lvds_atomic_enable()
1008 lvds_config_data_mapping(lvds); in lvds_atomic_enable()
1011 lvds_set(lvds, LVDS_CR, CR_LVDSEN); in lvds_atomic_enable()
1013 if (lvds->panel) { in lvds_atomic_enable()
1014 drm_panel_prepare(lvds->panel); in lvds_atomic_enable()
1015 drm_panel_enable(lvds->panel); in lvds_atomic_enable()
1022 struct stm_lvds *lvds = bridge_to_stm_lvds(bridge); in lvds_atomic_disable() local
1024 if (lvds->panel) { in lvds_atomic_disable()
1025 drm_panel_disable(lvds->panel); in lvds_atomic_disable()
1026 drm_panel_unprepare(lvds->panel); in lvds_atomic_disable()
1029 /* Disable LVDS module */ in lvds_atomic_disable()
1030 lvds_clear(lvds, LVDS_CR, CR_LVDSEN); in lvds_atomic_disable()
1032 clk_disable_unprepare(lvds->pclk); in lvds_atomic_disable()
1047 struct device *dev = &pdev->dev; in lvds_probe()
1049 struct stm_lvds *lvds; in lvds_probe() local
1052 dev_dbg(dev, "Probing LVDS driver...\n"); in lvds_probe()
1054 lvds = devm_kzalloc(dev, sizeof(*lvds), GFP_KERNEL); in lvds_probe()
1055 if (!lvds) in lvds_probe()
1056 return -ENOMEM; in lvds_probe()
1058 lvds->dev = dev; in lvds_probe()
1060 ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, in lvds_probe()
1061 &lvds->panel, &lvds->next_bridge); in lvds_probe()
1067 lvds->base = devm_platform_ioremap_resource(pdev, 0); in lvds_probe()
1068 if (IS_ERR(lvds->base)) { in lvds_probe()
1069 ret = PTR_ERR(lvds->base); in lvds_probe()
1074 lvds->pclk = devm_clk_get(dev, "pclk"); in lvds_probe()
1075 if (IS_ERR(lvds->pclk)) { in lvds_probe()
1076 ret = PTR_ERR(lvds->pclk); in lvds_probe()
1081 ret = clk_prepare_enable(lvds->pclk); in lvds_probe()
1098 port1 = of_graph_get_port_by_id(dev->of_node, 1); in lvds_probe()
1099 port2 = of_graph_get_port_by_id(dev->of_node, 2); in lvds_probe()
1104 lvds->link_type = LVDS_DUAL_LINK_ODD_EVEN_PIXELS; in lvds_probe()
1105 lvds->primary = &lvds_phy_16ff_primary; in lvds_probe()
1106 lvds->secondary = &lvds_phy_16ff_secondary; in lvds_probe()
1109 lvds->link_type = LVDS_DUAL_LINK_EVEN_ODD_PIXELS; in lvds_probe()
1110 lvds->primary = &lvds_phy_16ff_primary; in lvds_probe()
1111 lvds->secondary = &lvds_phy_16ff_secondary; in lvds_probe()
1113 case -EINVAL: in lvds_probe()
1120 * In that case, the lvds panel can be a single link panel, or in lvds_probe()
1126 lvds->link_type = LVDS_SINGLE_LINK_PRIMARY; in lvds_probe()
1127 lvds->primary = &lvds_phy_16ff_primary; in lvds_probe()
1128 lvds->secondary = NULL; in lvds_probe()
1130 ret = -EINVAL; in lvds_probe()
1139 lvds->link_type = LVDS_SINGLE_LINK_SECONDARY; in lvds_probe()
1140 lvds->primary = NULL; in lvds_probe()
1141 lvds->secondary = &lvds_phy_16ff_secondary; in lvds_probe()
1143 ret = (ret == -EINVAL) ? -EINVAL : 0; in lvds_probe()
1150 ret = -EINVAL; in lvds_probe()
1156 lvds->pllref_clk = devm_clk_get(dev, "ref"); in lvds_probe()
1157 if (IS_ERR(lvds->pllref_clk)) { in lvds_probe()
1158 ret = PTR_ERR(lvds->pllref_clk); in lvds_probe()
1163 ret = lvds_pixel_clk_register(lvds); in lvds_probe()
1165 dev_err(dev, "Failed to register LVDS pixel clock: %d\n", ret); in lvds_probe()
1169 lvds->lvds_bridge.funcs = &lvds_bridge_funcs; in lvds_probe()
1170 lvds->lvds_bridge.of_node = dev->of_node; in lvds_probe()
1171 lvds->hw_version = lvds_read(lvds, LVDS_VERR); in lvds_probe()
1173 dev_info(dev, "version 0x%02x initialized\n", lvds->hw_version); in lvds_probe()
1175 drm_bridge_add(&lvds->lvds_bridge); in lvds_probe()
1177 platform_set_drvdata(pdev, lvds); in lvds_probe()
1179 clk_disable_unprepare(lvds->pclk); in lvds_probe()
1184 clk_disable_unprepare(lvds->pclk); in lvds_probe()
1191 struct stm_lvds *lvds = platform_get_drvdata(pdev); in lvds_remove() local
1193 lvds_pixel_clk_unregister(lvds); in lvds_remove()
1195 drm_bridge_remove(&lvds->lvds_bridge); in lvds_remove()
1200 .compatible = "st,stm32mp25-lvds",
1212 .name = "stm32-display-lvds",
1219 MODULE_AUTHOR("Raphaël Gallais-Pou <raphael.gallais-pou@foss.st.com>");
1222 MODULE_DESCRIPTION("STMicroelectronics LVDS Display Interface Transmitter DRM driver");