Lines Matching full:lvds
25 /* LVDS Host registers */
46 /* LVDS Wrapper registers */
55 #define CR_LVDSEN BIT(0) /* LVDS PHY Enable */
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 */
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()
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()
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
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()
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()
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()
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()
783 drm_warn(drm, "No LVDS bus format reported\n"); 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()
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()
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()
940 struct stm_lvds *lvds = bridge_to_stm_lvds(bridge); in lvds_attach() local
941 struct drm_connector *connector = &lvds->connector; in lvds_attach()
957 if (lvds->next_bridge) in lvds_attach()
958 return drm_bridge_attach(bridge->encoder, lvds->next_bridge, in lvds_attach()
967 if (!lvds->panel) in lvds_attach()
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()
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()
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()
1058 lvds->dev = dev; 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()
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()
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()
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()
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",
1222 MODULE_DESCRIPTION("STMicroelectronics LVDS Display Interface Transmitter DRM driver");