Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) STMicroelectronics SA 2017
0004  *
0005  * Authors: Philippe Cornu <philippe.cornu@st.com>
0006  *          Yannick Fertre <yannick.fertre@st.com>
0007  */
0008 
0009 #include <linux/clk.h>
0010 #include <linux/iopoll.h>
0011 #include <linux/mod_devicetable.h>
0012 #include <linux/module.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/regulator/consumer.h>
0015 
0016 #include <video/mipi_display.h>
0017 
0018 #include <drm/bridge/dw_mipi_dsi.h>
0019 #include <drm/drm_mipi_dsi.h>
0020 #include <drm/drm_print.h>
0021 
0022 #define HWVER_130           0x31333000  /* IP version 1.30 */
0023 #define HWVER_131           0x31333100  /* IP version 1.31 */
0024 
0025 /* DSI digital registers & bit definitions */
0026 #define DSI_VERSION         0x00
0027 #define VERSION             GENMASK(31, 8)
0028 
0029 /* DSI wrapper registers & bit definitions */
0030 /* Note: registers are named as in the Reference Manual */
0031 #define DSI_WCFGR   0x0400      /* Wrapper ConFiGuration Reg */
0032 #define WCFGR_DSIM  BIT(0)      /* DSI Mode */
0033 #define WCFGR_COLMUX    GENMASK(3, 1)   /* COLor MUltipleXing */
0034 
0035 #define DSI_WCR     0x0404      /* Wrapper Control Reg */
0036 #define WCR_DSIEN   BIT(3)      /* DSI ENable */
0037 
0038 #define DSI_WISR    0x040C      /* Wrapper Interrupt and Status Reg */
0039 #define WISR_PLLLS  BIT(8)      /* PLL Lock Status */
0040 #define WISR_RRS    BIT(12)     /* Regulator Ready Status */
0041 
0042 #define DSI_WPCR0   0x0418      /* Wrapper Phy Conf Reg 0 */
0043 #define WPCR0_UIX4  GENMASK(5, 0)   /* Unit Interval X 4 */
0044 #define WPCR0_TDDL  BIT(16)     /* Turn Disable Data Lanes */
0045 
0046 #define DSI_WRPCR   0x0430      /* Wrapper Regulator & Pll Ctrl Reg */
0047 #define WRPCR_PLLEN BIT(0)      /* PLL ENable */
0048 #define WRPCR_NDIV  GENMASK(8, 2)   /* pll loop DIVision Factor */
0049 #define WRPCR_IDF   GENMASK(14, 11) /* pll Input Division Factor */
0050 #define WRPCR_ODF   GENMASK(17, 16) /* pll Output Division Factor */
0051 #define WRPCR_REGEN BIT(24)     /* REGulator ENable */
0052 #define WRPCR_BGREN BIT(28)     /* BandGap Reference ENable */
0053 #define IDF_MIN     1
0054 #define IDF_MAX     7
0055 #define NDIV_MIN    10
0056 #define NDIV_MAX    125
0057 #define ODF_MIN     1
0058 #define ODF_MAX     8
0059 
0060 /* dsi color format coding according to the datasheet */
0061 enum dsi_color {
0062     DSI_RGB565_CONF1,
0063     DSI_RGB565_CONF2,
0064     DSI_RGB565_CONF3,
0065     DSI_RGB666_CONF1,
0066     DSI_RGB666_CONF2,
0067     DSI_RGB888,
0068 };
0069 
0070 #define LANE_MIN_KBPS   31250
0071 #define LANE_MAX_KBPS   500000
0072 
0073 /* Sleep & timeout for regulator on/off, pll lock/unlock & fifo empty */
0074 #define SLEEP_US    1000
0075 #define TIMEOUT_US  200000
0076 
0077 struct dw_mipi_dsi_stm {
0078     void __iomem *base;
0079     struct clk *pllref_clk;
0080     struct dw_mipi_dsi *dsi;
0081     u32 hw_version;
0082     int lane_min_kbps;
0083     int lane_max_kbps;
0084     struct regulator *vdd_supply;
0085 };
0086 
0087 static inline void dsi_write(struct dw_mipi_dsi_stm *dsi, u32 reg, u32 val)
0088 {
0089     writel(val, dsi->base + reg);
0090 }
0091 
0092 static inline u32 dsi_read(struct dw_mipi_dsi_stm *dsi, u32 reg)
0093 {
0094     return readl(dsi->base + reg);
0095 }
0096 
0097 static inline void dsi_set(struct dw_mipi_dsi_stm *dsi, u32 reg, u32 mask)
0098 {
0099     dsi_write(dsi, reg, dsi_read(dsi, reg) | mask);
0100 }
0101 
0102 static inline void dsi_clear(struct dw_mipi_dsi_stm *dsi, u32 reg, u32 mask)
0103 {
0104     dsi_write(dsi, reg, dsi_read(dsi, reg) & ~mask);
0105 }
0106 
0107 static inline void dsi_update_bits(struct dw_mipi_dsi_stm *dsi, u32 reg,
0108                    u32 mask, u32 val)
0109 {
0110     dsi_write(dsi, reg, (dsi_read(dsi, reg) & ~mask) | val);
0111 }
0112 
0113 static enum dsi_color dsi_color_from_mipi(enum mipi_dsi_pixel_format fmt)
0114 {
0115     switch (fmt) {
0116     case MIPI_DSI_FMT_RGB888:
0117         return DSI_RGB888;
0118     case MIPI_DSI_FMT_RGB666:
0119         return DSI_RGB666_CONF2;
0120     case MIPI_DSI_FMT_RGB666_PACKED:
0121         return DSI_RGB666_CONF1;
0122     case MIPI_DSI_FMT_RGB565:
0123         return DSI_RGB565_CONF1;
0124     default:
0125         DRM_DEBUG_DRIVER("MIPI color invalid, so we use rgb888\n");
0126     }
0127     return DSI_RGB888;
0128 }
0129 
0130 static int dsi_pll_get_clkout_khz(int clkin_khz, int idf, int ndiv, int odf)
0131 {
0132     int divisor = idf * odf;
0133 
0134     /* prevent from division by 0 */
0135     if (!divisor)
0136         return 0;
0137 
0138     return DIV_ROUND_CLOSEST(clkin_khz * ndiv, divisor);
0139 }
0140 
0141 static int dsi_pll_get_params(struct dw_mipi_dsi_stm *dsi,
0142                   int clkin_khz, int clkout_khz,
0143                   int *idf, int *ndiv, int *odf)
0144 {
0145     int i, o, n, n_min, n_max;
0146     int fvco_min, fvco_max, delta, best_delta; /* all in khz */
0147 
0148     /* Early checks preventing division by 0 & odd results */
0149     if (clkin_khz <= 0 || clkout_khz <= 0)
0150         return -EINVAL;
0151 
0152     fvco_min = dsi->lane_min_kbps * 2 * ODF_MAX;
0153     fvco_max = dsi->lane_max_kbps * 2 * ODF_MIN;
0154 
0155     best_delta = 1000000; /* big started value (1000000khz) */
0156 
0157     for (i = IDF_MIN; i <= IDF_MAX; i++) {
0158         /* Compute ndiv range according to Fvco */
0159         n_min = ((fvco_min * i) / (2 * clkin_khz)) + 1;
0160         n_max = (fvco_max * i) / (2 * clkin_khz);
0161 
0162         /* No need to continue idf loop if we reach ndiv max */
0163         if (n_min >= NDIV_MAX)
0164             break;
0165 
0166         /* Clamp ndiv to valid values */
0167         if (n_min < NDIV_MIN)
0168             n_min = NDIV_MIN;
0169         if (n_max > NDIV_MAX)
0170             n_max = NDIV_MAX;
0171 
0172         for (o = ODF_MIN; o <= ODF_MAX; o *= 2) {
0173             n = DIV_ROUND_CLOSEST(i * o * clkout_khz, clkin_khz);
0174             /* Check ndiv according to vco range */
0175             if (n < n_min || n > n_max)
0176                 continue;
0177             /* Check if new delta is better & saves parameters */
0178             delta = dsi_pll_get_clkout_khz(clkin_khz, i, n, o) -
0179                 clkout_khz;
0180             if (delta < 0)
0181                 delta = -delta;
0182             if (delta < best_delta) {
0183                 *idf = i;
0184                 *ndiv = n;
0185                 *odf = o;
0186                 best_delta = delta;
0187             }
0188             /* fast return in case of "perfect result" */
0189             if (!delta)
0190                 return 0;
0191         }
0192     }
0193 
0194     return 0;
0195 }
0196 
0197 static int dw_mipi_dsi_phy_init(void *priv_data)
0198 {
0199     struct dw_mipi_dsi_stm *dsi = priv_data;
0200     u32 val;
0201     int ret;
0202 
0203     /* Enable the regulator */
0204     dsi_set(dsi, DSI_WRPCR, WRPCR_REGEN | WRPCR_BGREN);
0205     ret = readl_poll_timeout(dsi->base + DSI_WISR, val, val & WISR_RRS,
0206                  SLEEP_US, TIMEOUT_US);
0207     if (ret)
0208         DRM_DEBUG_DRIVER("!TIMEOUT! waiting REGU, let's continue\n");
0209 
0210     /* Enable the DSI PLL & wait for its lock */
0211     dsi_set(dsi, DSI_WRPCR, WRPCR_PLLEN);
0212     ret = readl_poll_timeout(dsi->base + DSI_WISR, val, val & WISR_PLLLS,
0213                  SLEEP_US, TIMEOUT_US);
0214     if (ret)
0215         DRM_DEBUG_DRIVER("!TIMEOUT! waiting PLL, let's continue\n");
0216 
0217     return 0;
0218 }
0219 
0220 static void dw_mipi_dsi_phy_power_on(void *priv_data)
0221 {
0222     struct dw_mipi_dsi_stm *dsi = priv_data;
0223 
0224     DRM_DEBUG_DRIVER("\n");
0225 
0226     /* Enable the DSI wrapper */
0227     dsi_set(dsi, DSI_WCR, WCR_DSIEN);
0228 }
0229 
0230 static void dw_mipi_dsi_phy_power_off(void *priv_data)
0231 {
0232     struct dw_mipi_dsi_stm *dsi = priv_data;
0233 
0234     DRM_DEBUG_DRIVER("\n");
0235 
0236     /* Disable the DSI wrapper */
0237     dsi_clear(dsi, DSI_WCR, WCR_DSIEN);
0238 }
0239 
0240 static int
0241 dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,
0242               unsigned long mode_flags, u32 lanes, u32 format,
0243               unsigned int *lane_mbps)
0244 {
0245     struct dw_mipi_dsi_stm *dsi = priv_data;
0246     unsigned int idf, ndiv, odf, pll_in_khz, pll_out_khz;
0247     int ret, bpp;
0248     u32 val;
0249 
0250     pll_in_khz = (unsigned int)(clk_get_rate(dsi->pllref_clk) / 1000);
0251 
0252     /* Compute requested pll out */
0253     bpp = mipi_dsi_pixel_format_to_bpp(format);
0254     pll_out_khz = mode->clock * bpp / lanes;
0255 
0256     /* Add 20% to pll out to be higher than pixel bw (burst mode only) */
0257     if (mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
0258         pll_out_khz = (pll_out_khz * 12) / 10;
0259 
0260     if (pll_out_khz > dsi->lane_max_kbps) {
0261         pll_out_khz = dsi->lane_max_kbps;
0262         DRM_WARN("Warning max phy mbps is used\n");
0263     }
0264     if (pll_out_khz < dsi->lane_min_kbps) {
0265         pll_out_khz = dsi->lane_min_kbps;
0266         DRM_WARN("Warning min phy mbps is used\n");
0267     }
0268 
0269     /* Compute best pll parameters */
0270     idf = 0;
0271     ndiv = 0;
0272     odf = 0;
0273     ret = dsi_pll_get_params(dsi, pll_in_khz, pll_out_khz,
0274                  &idf, &ndiv, &odf);
0275     if (ret)
0276         DRM_WARN("Warning dsi_pll_get_params(): bad params\n");
0277 
0278     /* Get the adjusted pll out value */
0279     pll_out_khz = dsi_pll_get_clkout_khz(pll_in_khz, idf, ndiv, odf);
0280 
0281     /* Set the PLL division factors */
0282     dsi_update_bits(dsi, DSI_WRPCR, WRPCR_NDIV | WRPCR_IDF | WRPCR_ODF,
0283             (ndiv << 2) | (idf << 11) | ((ffs(odf) - 1) << 16));
0284 
0285     /* Compute uix4 & set the bit period in high-speed mode */
0286     val = 4000000 / pll_out_khz;
0287     dsi_update_bits(dsi, DSI_WPCR0, WPCR0_UIX4, val);
0288 
0289     /* Select video mode by resetting DSIM bit */
0290     dsi_clear(dsi, DSI_WCFGR, WCFGR_DSIM);
0291 
0292     /* Select the color coding */
0293     dsi_update_bits(dsi, DSI_WCFGR, WCFGR_COLMUX,
0294             dsi_color_from_mipi(format) << 1);
0295 
0296     *lane_mbps = pll_out_khz / 1000;
0297 
0298     DRM_DEBUG_DRIVER("pll_in %ukHz pll_out %ukHz lane_mbps %uMHz\n",
0299              pll_in_khz, pll_out_khz, *lane_mbps);
0300 
0301     return 0;
0302 }
0303 
0304 #define DSI_PHY_DELAY(fp, vp, mbps) DIV_ROUND_UP((fp) * (mbps) + 1000 * (vp), 8000)
0305 
0306 static int
0307 dw_mipi_dsi_phy_get_timing(void *priv_data, unsigned int lane_mbps,
0308                struct dw_mipi_dsi_dphy_timing *timing)
0309 {
0310     /*
0311      * From STM32MP157 datasheet, valid for STM32F469, STM32F7x9, STM32H747
0312      * phy_clkhs2lp_time = (272+136*UI)/(8*UI)
0313      * phy_clklp2hs_time = (512+40*UI)/(8*UI)
0314      * phy_hs2lp_time = (192+64*UI)/(8*UI)
0315      * phy_lp2hs_time = (256+32*UI)/(8*UI)
0316      */
0317     timing->clk_hs2lp = DSI_PHY_DELAY(272, 136, lane_mbps);
0318     timing->clk_lp2hs = DSI_PHY_DELAY(512, 40, lane_mbps);
0319     timing->data_hs2lp = DSI_PHY_DELAY(192, 64, lane_mbps);
0320     timing->data_lp2hs = DSI_PHY_DELAY(256, 32, lane_mbps);
0321 
0322     return 0;
0323 }
0324 
0325 #define CLK_TOLERANCE_HZ 50
0326 
0327 static enum drm_mode_status
0328 dw_mipi_dsi_stm_mode_valid(void *priv_data,
0329                const struct drm_display_mode *mode,
0330                unsigned long mode_flags, u32 lanes, u32 format)
0331 {
0332     struct dw_mipi_dsi_stm *dsi = priv_data;
0333     unsigned int idf, ndiv, odf, pll_in_khz, pll_out_khz;
0334     int ret, bpp;
0335 
0336     bpp = mipi_dsi_pixel_format_to_bpp(format);
0337     if (bpp < 0)
0338         return MODE_BAD;
0339 
0340     /* Compute requested pll out */
0341     pll_out_khz = mode->clock * bpp / lanes;
0342 
0343     if (pll_out_khz > dsi->lane_max_kbps)
0344         return MODE_CLOCK_HIGH;
0345 
0346     if (mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {
0347         /* Add 20% to pll out to be higher than pixel bw */
0348         pll_out_khz = (pll_out_khz * 12) / 10;
0349     } else {
0350         if (pll_out_khz < dsi->lane_min_kbps)
0351             return MODE_CLOCK_LOW;
0352     }
0353 
0354     /* Compute best pll parameters */
0355     idf = 0;
0356     ndiv = 0;
0357     odf = 0;
0358     pll_in_khz = clk_get_rate(dsi->pllref_clk) / 1000;
0359     ret = dsi_pll_get_params(dsi, pll_in_khz, pll_out_khz, &idf, &ndiv, &odf);
0360     if (ret) {
0361         DRM_WARN("Warning dsi_pll_get_params(): bad params\n");
0362         return MODE_ERROR;
0363     }
0364 
0365     if (!(mode_flags & MIPI_DSI_MODE_VIDEO_BURST)) {
0366         unsigned int px_clock_hz, target_px_clock_hz, lane_mbps;
0367         int dsi_short_packet_size_px, hfp, hsync, hbp, delay_to_lp;
0368         struct dw_mipi_dsi_dphy_timing dphy_timing;
0369 
0370         /* Get the adjusted pll out value */
0371         pll_out_khz = dsi_pll_get_clkout_khz(pll_in_khz, idf, ndiv, odf);
0372 
0373         px_clock_hz = DIV_ROUND_CLOSEST_ULL(1000ULL * pll_out_khz * lanes, bpp);
0374         target_px_clock_hz = mode->clock * 1000;
0375         /*
0376          * Filter modes according to the clock value, particularly useful for
0377          * hdmi modes that require precise pixel clocks.
0378          */
0379         if (px_clock_hz < target_px_clock_hz - CLK_TOLERANCE_HZ ||
0380             px_clock_hz > target_px_clock_hz + CLK_TOLERANCE_HZ)
0381             return MODE_CLOCK_RANGE;
0382 
0383         /* sync packets are codes as DSI short packets (4 bytes) */
0384         dsi_short_packet_size_px = DIV_ROUND_UP(4 * BITS_PER_BYTE, bpp);
0385 
0386         hfp = mode->hsync_start - mode->hdisplay;
0387         hsync = mode->hsync_end - mode->hsync_start;
0388         hbp = mode->htotal - mode->hsync_end;
0389 
0390         /* hsync must be longer than 4 bytes HSS packets */
0391         if (hsync < dsi_short_packet_size_px)
0392             return MODE_HSYNC_NARROW;
0393 
0394         if (mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
0395             /* HBP must be longer than 4 bytes HSE packets */
0396             if (hbp < dsi_short_packet_size_px)
0397                 return MODE_HSYNC_NARROW;
0398             hbp -= dsi_short_packet_size_px;
0399         } else {
0400             /* With sync events HBP extends in the hsync */
0401             hbp += hsync - dsi_short_packet_size_px;
0402         }
0403 
0404         lane_mbps = pll_out_khz / 1000;
0405         ret = dw_mipi_dsi_phy_get_timing(priv_data, lane_mbps, &dphy_timing);
0406         if (ret)
0407             return MODE_ERROR;
0408         /*
0409          * In non-burst mode DSI has to enter in LP during HFP
0410          * (horizontal front porch) or HBP (horizontal back porch) to
0411          * resync with LTDC pixel clock.
0412          */
0413         delay_to_lp = DIV_ROUND_UP((dphy_timing.data_hs2lp + dphy_timing.data_lp2hs) *
0414                        lanes * BITS_PER_BYTE, bpp);
0415         if (hfp < delay_to_lp && hbp < delay_to_lp)
0416             return MODE_HSYNC;
0417     }
0418 
0419     return MODE_OK;
0420 }
0421 
0422 static const struct dw_mipi_dsi_phy_ops dw_mipi_dsi_stm_phy_ops = {
0423     .init = dw_mipi_dsi_phy_init,
0424     .power_on = dw_mipi_dsi_phy_power_on,
0425     .power_off = dw_mipi_dsi_phy_power_off,
0426     .get_lane_mbps = dw_mipi_dsi_get_lane_mbps,
0427     .get_timing = dw_mipi_dsi_phy_get_timing,
0428 };
0429 
0430 static struct dw_mipi_dsi_plat_data dw_mipi_dsi_stm_plat_data = {
0431     .max_data_lanes = 2,
0432     .mode_valid = dw_mipi_dsi_stm_mode_valid,
0433     .phy_ops = &dw_mipi_dsi_stm_phy_ops,
0434 };
0435 
0436 static const struct of_device_id dw_mipi_dsi_stm_dt_ids[] = {
0437     { .compatible = "st,stm32-dsi", .data = &dw_mipi_dsi_stm_plat_data, },
0438     { },
0439 };
0440 MODULE_DEVICE_TABLE(of, dw_mipi_dsi_stm_dt_ids);
0441 
0442 static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
0443 {
0444     struct device *dev = &pdev->dev;
0445     struct dw_mipi_dsi_stm *dsi;
0446     struct clk *pclk;
0447     struct resource *res;
0448     int ret;
0449 
0450     dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
0451     if (!dsi)
0452         return -ENOMEM;
0453 
0454     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0455     dsi->base = devm_ioremap_resource(dev, res);
0456     if (IS_ERR(dsi->base)) {
0457         ret = PTR_ERR(dsi->base);
0458         DRM_ERROR("Unable to get dsi registers %d\n", ret);
0459         return ret;
0460     }
0461 
0462     dsi->vdd_supply = devm_regulator_get(dev, "phy-dsi");
0463     if (IS_ERR(dsi->vdd_supply)) {
0464         ret = PTR_ERR(dsi->vdd_supply);
0465         dev_err_probe(dev, ret, "Failed to request regulator\n");
0466         return ret;
0467     }
0468 
0469     ret = regulator_enable(dsi->vdd_supply);
0470     if (ret) {
0471         DRM_ERROR("Failed to enable regulator: %d\n", ret);
0472         return ret;
0473     }
0474 
0475     dsi->pllref_clk = devm_clk_get(dev, "ref");
0476     if (IS_ERR(dsi->pllref_clk)) {
0477         ret = PTR_ERR(dsi->pllref_clk);
0478         dev_err_probe(dev, ret, "Unable to get pll reference clock\n");
0479         goto err_clk_get;
0480     }
0481 
0482     ret = clk_prepare_enable(dsi->pllref_clk);
0483     if (ret) {
0484         DRM_ERROR("Failed to enable pllref_clk: %d\n", ret);
0485         goto err_clk_get;
0486     }
0487 
0488     pclk = devm_clk_get(dev, "pclk");
0489     if (IS_ERR(pclk)) {
0490         ret = PTR_ERR(pclk);
0491         DRM_ERROR("Unable to get peripheral clock: %d\n", ret);
0492         goto err_dsi_probe;
0493     }
0494 
0495     ret = clk_prepare_enable(pclk);
0496     if (ret) {
0497         DRM_ERROR("%s: Failed to enable peripheral clk\n", __func__);
0498         goto err_dsi_probe;
0499     }
0500 
0501     dsi->hw_version = dsi_read(dsi, DSI_VERSION) & VERSION;
0502     clk_disable_unprepare(pclk);
0503 
0504     if (dsi->hw_version != HWVER_130 && dsi->hw_version != HWVER_131) {
0505         ret = -ENODEV;
0506         DRM_ERROR("bad dsi hardware version\n");
0507         goto err_dsi_probe;
0508     }
0509 
0510     /* set lane capabilities according to hw version */
0511     dsi->lane_min_kbps = LANE_MIN_KBPS;
0512     dsi->lane_max_kbps = LANE_MAX_KBPS;
0513     if (dsi->hw_version == HWVER_131) {
0514         dsi->lane_min_kbps *= 2;
0515         dsi->lane_max_kbps *= 2;
0516     }
0517 
0518     dw_mipi_dsi_stm_plat_data.base = dsi->base;
0519     dw_mipi_dsi_stm_plat_data.priv_data = dsi;
0520 
0521     platform_set_drvdata(pdev, dsi);
0522 
0523     dsi->dsi = dw_mipi_dsi_probe(pdev, &dw_mipi_dsi_stm_plat_data);
0524     if (IS_ERR(dsi->dsi)) {
0525         ret = PTR_ERR(dsi->dsi);
0526         dev_err_probe(dev, ret, "Failed to initialize mipi dsi host\n");
0527         goto err_dsi_probe;
0528     }
0529 
0530     return 0;
0531 
0532 err_dsi_probe:
0533     clk_disable_unprepare(dsi->pllref_clk);
0534 err_clk_get:
0535     regulator_disable(dsi->vdd_supply);
0536 
0537     return ret;
0538 }
0539 
0540 static int dw_mipi_dsi_stm_remove(struct platform_device *pdev)
0541 {
0542     struct dw_mipi_dsi_stm *dsi = platform_get_drvdata(pdev);
0543 
0544     dw_mipi_dsi_remove(dsi->dsi);
0545     clk_disable_unprepare(dsi->pllref_clk);
0546     regulator_disable(dsi->vdd_supply);
0547 
0548     return 0;
0549 }
0550 
0551 static int __maybe_unused dw_mipi_dsi_stm_suspend(struct device *dev)
0552 {
0553     struct dw_mipi_dsi_stm *dsi = dw_mipi_dsi_stm_plat_data.priv_data;
0554 
0555     DRM_DEBUG_DRIVER("\n");
0556 
0557     clk_disable_unprepare(dsi->pllref_clk);
0558     regulator_disable(dsi->vdd_supply);
0559 
0560     return 0;
0561 }
0562 
0563 static int __maybe_unused dw_mipi_dsi_stm_resume(struct device *dev)
0564 {
0565     struct dw_mipi_dsi_stm *dsi = dw_mipi_dsi_stm_plat_data.priv_data;
0566     int ret;
0567 
0568     DRM_DEBUG_DRIVER("\n");
0569 
0570     ret = regulator_enable(dsi->vdd_supply);
0571     if (ret) {
0572         DRM_ERROR("Failed to enable regulator: %d\n", ret);
0573         return ret;
0574     }
0575 
0576     ret = clk_prepare_enable(dsi->pllref_clk);
0577     if (ret) {
0578         regulator_disable(dsi->vdd_supply);
0579         DRM_ERROR("Failed to enable pllref_clk: %d\n", ret);
0580         return ret;
0581     }
0582 
0583     return 0;
0584 }
0585 
0586 static const struct dev_pm_ops dw_mipi_dsi_stm_pm_ops = {
0587     SET_SYSTEM_SLEEP_PM_OPS(dw_mipi_dsi_stm_suspend,
0588                 dw_mipi_dsi_stm_resume)
0589 };
0590 
0591 static struct platform_driver dw_mipi_dsi_stm_driver = {
0592     .probe      = dw_mipi_dsi_stm_probe,
0593     .remove     = dw_mipi_dsi_stm_remove,
0594     .driver     = {
0595         .of_match_table = dw_mipi_dsi_stm_dt_ids,
0596         .name   = "stm32-display-dsi",
0597         .pm = &dw_mipi_dsi_stm_pm_ops,
0598     },
0599 };
0600 
0601 module_platform_driver(dw_mipi_dsi_stm_driver);
0602 
0603 MODULE_AUTHOR("Philippe Cornu <philippe.cornu@st.com>");
0604 MODULE_AUTHOR("Yannick Fertre <yannick.fertre@st.com>");
0605 MODULE_DESCRIPTION("STMicroelectronics DW MIPI DSI host controller driver");
0606 MODULE_LICENSE("GPL v2");