800 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) STMicroelectronics SA 20174 *5 * Authors: Philippe Cornu <philippe.cornu@st.com>6 * Yannick Fertre <yannick.fertre@st.com>7 */8 9#include <linux/clk.h>10#include <linux/clk-provider.h>11#include <linux/iopoll.h>12#include <linux/kernel.h>13#include <linux/mod_devicetable.h>14#include <linux/module.h>15#include <linux/platform_device.h>16#include <linux/pm_runtime.h>17#include <linux/regulator/consumer.h>18 19#include <video/mipi_display.h>20 21#include <drm/bridge/dw_mipi_dsi.h>22#include <drm/drm_mipi_dsi.h>23#include <drm/drm_print.h>24 25#define HWVER_130 0x31333000 /* IP version 1.30 */26#define HWVER_131 0x31333100 /* IP version 1.31 */27 28/* DSI digital registers & bit definitions */29#define DSI_VERSION 0x0030#define VERSION GENMASK(31, 8)31 32/* DSI wrapper registers & bit definitions */33/* Note: registers are named as in the Reference Manual */34#define DSI_WCFGR 0x0400 /* Wrapper ConFiGuration Reg */35#define WCFGR_DSIM BIT(0) /* DSI Mode */36#define WCFGR_COLMUX GENMASK(3, 1) /* COLor MUltipleXing */37 38#define DSI_WCR 0x0404 /* Wrapper Control Reg */39#define WCR_DSIEN BIT(3) /* DSI ENable */40 41#define DSI_WISR 0x040C /* Wrapper Interrupt and Status Reg */42#define WISR_PLLLS BIT(8) /* PLL Lock Status */43#define WISR_RRS BIT(12) /* Regulator Ready Status */44 45#define DSI_WPCR0 0x0418 /* Wrapper Phy Conf Reg 0 */46#define WPCR0_UIX4 GENMASK(5, 0) /* Unit Interval X 4 */47#define WPCR0_TDDL BIT(16) /* Turn Disable Data Lanes */48 49#define DSI_WRPCR 0x0430 /* Wrapper Regulator & Pll Ctrl Reg */50#define WRPCR_PLLEN BIT(0) /* PLL ENable */51#define WRPCR_NDIV GENMASK(8, 2) /* pll loop DIVision Factor */52#define WRPCR_IDF GENMASK(14, 11) /* pll Input Division Factor */53#define WRPCR_ODF GENMASK(17, 16) /* pll Output Division Factor */54#define WRPCR_REGEN BIT(24) /* REGulator ENable */55#define WRPCR_BGREN BIT(28) /* BandGap Reference ENable */56#define IDF_MIN 157#define IDF_MAX 758#define NDIV_MIN 1059#define NDIV_MAX 12560#define ODF_MIN 161#define ODF_MAX 862 63/* dsi color format coding according to the datasheet */64enum dsi_color {65 DSI_RGB565_CONF1,66 DSI_RGB565_CONF2,67 DSI_RGB565_CONF3,68 DSI_RGB666_CONF1,69 DSI_RGB666_CONF2,70 DSI_RGB888,71};72 73#define LANE_MIN_KBPS 3125074#define LANE_MAX_KBPS 50000075 76/* Sleep & timeout for regulator on/off, pll lock/unlock & fifo empty */77#define SLEEP_US 100078#define TIMEOUT_US 20000079 80struct dw_mipi_dsi_stm {81 void __iomem *base;82 struct device *dev;83 struct clk *pllref_clk;84 struct clk *pclk;85 struct clk_hw txbyte_clk;86 struct dw_mipi_dsi *dsi;87 struct dw_mipi_dsi_plat_data pdata;88 u32 hw_version;89 int lane_min_kbps;90 int lane_max_kbps;91 struct regulator *vdd_supply;92};93 94static inline void dsi_write(struct dw_mipi_dsi_stm *dsi, u32 reg, u32 val)95{96 writel(val, dsi->base + reg);97}98 99static inline u32 dsi_read(struct dw_mipi_dsi_stm *dsi, u32 reg)100{101 return readl(dsi->base + reg);102}103 104static inline void dsi_set(struct dw_mipi_dsi_stm *dsi, u32 reg, u32 mask)105{106 dsi_write(dsi, reg, dsi_read(dsi, reg) | mask);107}108 109static inline void dsi_clear(struct dw_mipi_dsi_stm *dsi, u32 reg, u32 mask)110{111 dsi_write(dsi, reg, dsi_read(dsi, reg) & ~mask);112}113 114static inline void dsi_update_bits(struct dw_mipi_dsi_stm *dsi, u32 reg,115 u32 mask, u32 val)116{117 dsi_write(dsi, reg, (dsi_read(dsi, reg) & ~mask) | val);118}119 120static enum dsi_color dsi_color_from_mipi(enum mipi_dsi_pixel_format fmt)121{122 switch (fmt) {123 case MIPI_DSI_FMT_RGB888:124 return DSI_RGB888;125 case MIPI_DSI_FMT_RGB666:126 return DSI_RGB666_CONF2;127 case MIPI_DSI_FMT_RGB666_PACKED:128 return DSI_RGB666_CONF1;129 case MIPI_DSI_FMT_RGB565:130 return DSI_RGB565_CONF1;131 default:132 DRM_DEBUG_DRIVER("MIPI color invalid, so we use rgb888\n");133 }134 return DSI_RGB888;135}136 137static int dsi_pll_get_clkout_khz(int clkin_khz, int idf, int ndiv, int odf)138{139 int divisor = idf * odf;140 141 /* prevent from division by 0 */142 if (!divisor)143 return 0;144 145 return DIV_ROUND_CLOSEST(clkin_khz * ndiv, divisor);146}147 148static int dsi_pll_get_params(struct dw_mipi_dsi_stm *dsi,149 int clkin_khz, int clkout_khz,150 int *idf, int *ndiv, int *odf)151{152 int i, o, n, n_min, n_max;153 int fvco_min, fvco_max, delta, best_delta; /* all in khz */154 155 /* Early checks preventing division by 0 & odd results */156 if (clkin_khz <= 0 || clkout_khz <= 0)157 return -EINVAL;158 159 fvco_min = dsi->lane_min_kbps * 2 * ODF_MAX;160 fvco_max = dsi->lane_max_kbps * 2 * ODF_MIN;161 162 best_delta = 1000000; /* big started value (1000000khz) */163 164 for (i = IDF_MIN; i <= IDF_MAX; i++) {165 /* Compute ndiv range according to Fvco */166 n_min = ((fvco_min * i) / (2 * clkin_khz)) + 1;167 n_max = (fvco_max * i) / (2 * clkin_khz);168 169 /* No need to continue idf loop if we reach ndiv max */170 if (n_min >= NDIV_MAX)171 break;172 173 /* Clamp ndiv to valid values */174 if (n_min < NDIV_MIN)175 n_min = NDIV_MIN;176 if (n_max > NDIV_MAX)177 n_max = NDIV_MAX;178 179 for (o = ODF_MIN; o <= ODF_MAX; o *= 2) {180 n = DIV_ROUND_CLOSEST(i * o * clkout_khz, clkin_khz);181 /* Check ndiv according to vco range */182 if (n < n_min || n > n_max)183 continue;184 /* Check if new delta is better & saves parameters */185 delta = dsi_pll_get_clkout_khz(clkin_khz, i, n, o) -186 clkout_khz;187 if (delta < 0)188 delta = -delta;189 if (delta < best_delta) {190 *idf = i;191 *ndiv = n;192 *odf = o;193 best_delta = delta;194 }195 /* fast return in case of "perfect result" */196 if (!delta)197 return 0;198 }199 }200 201 return 0;202}203 204#define clk_to_dw_mipi_dsi_stm(clk) \205 container_of(clk, struct dw_mipi_dsi_stm, txbyte_clk)206 207static void dw_mipi_dsi_clk_disable(struct clk_hw *clk)208{209 struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(clk);210 211 DRM_DEBUG_DRIVER("\n");212 213 /* Disable the DSI PLL */214 dsi_clear(dsi, DSI_WRPCR, WRPCR_PLLEN);215 216 /* Disable the regulator */217 dsi_clear(dsi, DSI_WRPCR, WRPCR_REGEN | WRPCR_BGREN);218}219 220static int dw_mipi_dsi_clk_enable(struct clk_hw *clk)221{222 struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(clk);223 u32 val;224 int ret;225 226 DRM_DEBUG_DRIVER("\n");227 228 /* Enable the regulator */229 dsi_set(dsi, DSI_WRPCR, WRPCR_REGEN | WRPCR_BGREN);230 ret = readl_poll_timeout_atomic(dsi->base + DSI_WISR, val, val & WISR_RRS,231 SLEEP_US, TIMEOUT_US);232 if (ret)233 DRM_DEBUG_DRIVER("!TIMEOUT! waiting REGU, let's continue\n");234 235 /* Enable the DSI PLL & wait for its lock */236 dsi_set(dsi, DSI_WRPCR, WRPCR_PLLEN);237 ret = readl_poll_timeout_atomic(dsi->base + DSI_WISR, val, val & WISR_PLLLS,238 SLEEP_US, TIMEOUT_US);239 if (ret)240 DRM_DEBUG_DRIVER("!TIMEOUT! waiting PLL, let's continue\n");241 242 return 0;243}244 245static int dw_mipi_dsi_clk_is_enabled(struct clk_hw *hw)246{247 struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(hw);248 249 return dsi_read(dsi, DSI_WRPCR) & WRPCR_PLLEN;250}251 252static unsigned long dw_mipi_dsi_clk_recalc_rate(struct clk_hw *hw,253 unsigned long parent_rate)254{255 struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(hw);256 unsigned int idf, ndiv, odf, pll_in_khz, pll_out_khz;257 u32 val;258 259 DRM_DEBUG_DRIVER("\n");260 261 pll_in_khz = (unsigned int)(parent_rate / 1000);262 263 val = dsi_read(dsi, DSI_WRPCR);264 265 idf = (val & WRPCR_IDF) >> 11;266 if (!idf)267 idf = 1;268 ndiv = (val & WRPCR_NDIV) >> 2;269 odf = int_pow(2, (val & WRPCR_ODF) >> 16);270 271 /* Get the adjusted pll out value */272 pll_out_khz = dsi_pll_get_clkout_khz(pll_in_khz, idf, ndiv, odf);273 274 return (unsigned long)pll_out_khz * 1000;275}276 277static long dw_mipi_dsi_clk_round_rate(struct clk_hw *hw, unsigned long rate,278 unsigned long *parent_rate)279{280 struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(hw);281 unsigned int idf, ndiv, odf, pll_in_khz, pll_out_khz;282 int ret;283 284 DRM_DEBUG_DRIVER("\n");285 286 pll_in_khz = (unsigned int)(*parent_rate / 1000);287 288 /* Compute best pll parameters */289 idf = 0;290 ndiv = 0;291 odf = 0;292 293 ret = dsi_pll_get_params(dsi, pll_in_khz, rate / 1000,294 &idf, &ndiv, &odf);295 if (ret)296 DRM_WARN("Warning dsi_pll_get_params(): bad params\n");297 298 /* Get the adjusted pll out value */299 pll_out_khz = dsi_pll_get_clkout_khz(pll_in_khz, idf, ndiv, odf);300 301 return pll_out_khz * 1000;302}303 304static int dw_mipi_dsi_clk_set_rate(struct clk_hw *hw, unsigned long rate,305 unsigned long parent_rate)306{307 struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(hw);308 unsigned int idf, ndiv, odf, pll_in_khz, pll_out_khz;309 int ret;310 u32 val;311 312 DRM_DEBUG_DRIVER("\n");313 314 pll_in_khz = (unsigned int)(parent_rate / 1000);315 316 /* Compute best pll parameters */317 idf = 0;318 ndiv = 0;319 odf = 0;320 321 ret = dsi_pll_get_params(dsi, pll_in_khz, rate / 1000, &idf, &ndiv, &odf);322 if (ret)323 DRM_WARN("Warning dsi_pll_get_params(): bad params\n");324 325 /* Get the adjusted pll out value */326 pll_out_khz = dsi_pll_get_clkout_khz(pll_in_khz, idf, ndiv, odf);327 328 /* Set the PLL division factors */329 dsi_update_bits(dsi, DSI_WRPCR, WRPCR_NDIV | WRPCR_IDF | WRPCR_ODF,330 (ndiv << 2) | (idf << 11) | ((ffs(odf) - 1) << 16));331 332 /* Compute uix4 & set the bit period in high-speed mode */333 val = 4000000 / pll_out_khz;334 dsi_update_bits(dsi, DSI_WPCR0, WPCR0_UIX4, val);335 336 return 0;337}338 339static void dw_mipi_dsi_clk_unregister(void *data)340{341 struct dw_mipi_dsi_stm *dsi = data;342 343 DRM_DEBUG_DRIVER("\n");344 345 of_clk_del_provider(dsi->dev->of_node);346 clk_hw_unregister(&dsi->txbyte_clk);347}348 349static const struct clk_ops dw_mipi_dsi_stm_clk_ops = {350 .enable = dw_mipi_dsi_clk_enable,351 .disable = dw_mipi_dsi_clk_disable,352 .is_enabled = dw_mipi_dsi_clk_is_enabled,353 .recalc_rate = dw_mipi_dsi_clk_recalc_rate,354 .round_rate = dw_mipi_dsi_clk_round_rate,355 .set_rate = dw_mipi_dsi_clk_set_rate,356};357 358static struct clk_init_data cdata_init = {359 .name = "ck_dsi_phy",360 .ops = &dw_mipi_dsi_stm_clk_ops,361 .parent_names = (const char * []) {"ck_hse"},362 .num_parents = 1,363};364 365static int dw_mipi_dsi_clk_register(struct dw_mipi_dsi_stm *dsi,366 struct device *dev)367{368 struct device_node *node = dev->of_node;369 int ret;370 371 DRM_DEBUG_DRIVER("Registering clk\n");372 373 dsi->txbyte_clk.init = &cdata_init;374 375 ret = clk_hw_register(dev, &dsi->txbyte_clk);376 if (ret)377 return ret;378 379 ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get,380 &dsi->txbyte_clk);381 if (ret)382 clk_hw_unregister(&dsi->txbyte_clk);383 384 return ret;385}386 387static int dw_mipi_dsi_phy_init(void *priv_data)388{389 struct dw_mipi_dsi_stm *dsi = priv_data;390 int ret;391 392 ret = clk_prepare_enable(dsi->txbyte_clk.clk);393 return ret;394}395 396static void dw_mipi_dsi_phy_power_on(void *priv_data)397{398 struct dw_mipi_dsi_stm *dsi = priv_data;399 400 DRM_DEBUG_DRIVER("\n");401 402 /* Enable the DSI wrapper */403 dsi_set(dsi, DSI_WCR, WCR_DSIEN);404}405 406static void dw_mipi_dsi_phy_power_off(void *priv_data)407{408 struct dw_mipi_dsi_stm *dsi = priv_data;409 410 DRM_DEBUG_DRIVER("\n");411 412 clk_disable_unprepare(dsi->txbyte_clk.clk);413 414 /* Disable the DSI wrapper */415 dsi_clear(dsi, DSI_WCR, WCR_DSIEN);416}417 418static int419dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,420 unsigned long mode_flags, u32 lanes, u32 format,421 unsigned int *lane_mbps)422{423 struct dw_mipi_dsi_stm *dsi = priv_data;424 unsigned int pll_in_khz, pll_out_khz;425 int ret, bpp;426 427 pll_in_khz = (unsigned int)(clk_get_rate(dsi->pllref_clk) / 1000);428 429 /* Compute requested pll out */430 bpp = mipi_dsi_pixel_format_to_bpp(format);431 pll_out_khz = mode->clock * bpp / lanes;432 433 /* Add 20% to pll out to be higher than pixel bw (burst mode only) */434 if (mode_flags & MIPI_DSI_MODE_VIDEO_BURST)435 pll_out_khz = (pll_out_khz * 12) / 10;436 437 if (pll_out_khz > dsi->lane_max_kbps) {438 pll_out_khz = dsi->lane_max_kbps;439 DRM_WARN("Warning max phy mbps is used\n");440 }441 if (pll_out_khz < dsi->lane_min_kbps) {442 pll_out_khz = dsi->lane_min_kbps;443 DRM_WARN("Warning min phy mbps is used\n");444 }445 446 ret = clk_set_rate((dsi->txbyte_clk.clk), pll_out_khz * 1000);447 if (ret)448 DRM_DEBUG_DRIVER("ERROR Could not set rate of %d to %s clk->name",449 pll_out_khz, clk_hw_get_name(&dsi->txbyte_clk));450 451 /* Select video mode by resetting DSIM bit */452 dsi_clear(dsi, DSI_WCFGR, WCFGR_DSIM);453 454 /* Select the color coding */455 dsi_update_bits(dsi, DSI_WCFGR, WCFGR_COLMUX,456 dsi_color_from_mipi(format) << 1);457 458 *lane_mbps = pll_out_khz / 1000;459 460 DRM_DEBUG_DRIVER("pll_in %ukHz pll_out %ukHz lane_mbps %uMHz\n",461 pll_in_khz, pll_out_khz, *lane_mbps);462 463 return 0;464}465 466#define DSI_PHY_DELAY(fp, vp, mbps) DIV_ROUND_UP((fp) * (mbps) + 1000 * (vp), 8000)467 468static int469dw_mipi_dsi_phy_get_timing(void *priv_data, unsigned int lane_mbps,470 struct dw_mipi_dsi_dphy_timing *timing)471{472 /*473 * From STM32MP157 datasheet, valid for STM32F469, STM32F7x9, STM32H747474 * phy_clkhs2lp_time = (272+136*UI)/(8*UI)475 * phy_clklp2hs_time = (512+40*UI)/(8*UI)476 * phy_hs2lp_time = (192+64*UI)/(8*UI)477 * phy_lp2hs_time = (256+32*UI)/(8*UI)478 */479 timing->clk_hs2lp = DSI_PHY_DELAY(272, 136, lane_mbps);480 timing->clk_lp2hs = DSI_PHY_DELAY(512, 40, lane_mbps);481 timing->data_hs2lp = DSI_PHY_DELAY(192, 64, lane_mbps);482 timing->data_lp2hs = DSI_PHY_DELAY(256, 32, lane_mbps);483 484 return 0;485}486 487#define CLK_TOLERANCE_HZ 50488 489static enum drm_mode_status490dw_mipi_dsi_stm_mode_valid(void *priv_data,491 const struct drm_display_mode *mode,492 unsigned long mode_flags, u32 lanes, u32 format)493{494 struct dw_mipi_dsi_stm *dsi = priv_data;495 unsigned int idf, ndiv, odf, pll_in_khz, pll_out_khz;496 int ret, bpp;497 498 bpp = mipi_dsi_pixel_format_to_bpp(format);499 if (bpp < 0)500 return MODE_BAD;501 502 /* Compute requested pll out */503 pll_out_khz = mode->clock * bpp / lanes;504 505 if (pll_out_khz > dsi->lane_max_kbps)506 return MODE_CLOCK_HIGH;507 508 if (mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {509 /* Add 20% to pll out to be higher than pixel bw */510 pll_out_khz = (pll_out_khz * 12) / 10;511 } else {512 if (pll_out_khz < dsi->lane_min_kbps)513 return MODE_CLOCK_LOW;514 }515 516 /* Compute best pll parameters */517 idf = 0;518 ndiv = 0;519 odf = 0;520 pll_in_khz = clk_get_rate(dsi->pllref_clk) / 1000;521 ret = dsi_pll_get_params(dsi, pll_in_khz, pll_out_khz, &idf, &ndiv, &odf);522 if (ret) {523 DRM_WARN("Warning dsi_pll_get_params(): bad params\n");524 return MODE_ERROR;525 }526 527 if (!(mode_flags & MIPI_DSI_MODE_VIDEO_BURST)) {528 unsigned int px_clock_hz, target_px_clock_hz, lane_mbps;529 int dsi_short_packet_size_px, hfp, hsync, hbp, delay_to_lp;530 struct dw_mipi_dsi_dphy_timing dphy_timing;531 532 /* Get the adjusted pll out value */533 pll_out_khz = dsi_pll_get_clkout_khz(pll_in_khz, idf, ndiv, odf);534 535 px_clock_hz = DIV_ROUND_CLOSEST_ULL(1000ULL * pll_out_khz * lanes, bpp);536 target_px_clock_hz = mode->clock * 1000;537 /*538 * Filter modes according to the clock value, particularly useful for539 * hdmi modes that require precise pixel clocks.540 */541 if (px_clock_hz < target_px_clock_hz - CLK_TOLERANCE_HZ ||542 px_clock_hz > target_px_clock_hz + CLK_TOLERANCE_HZ)543 return MODE_CLOCK_RANGE;544 545 /* sync packets are codes as DSI short packets (4 bytes) */546 dsi_short_packet_size_px = DIV_ROUND_UP(4 * BITS_PER_BYTE, bpp);547 548 hfp = mode->hsync_start - mode->hdisplay;549 hsync = mode->hsync_end - mode->hsync_start;550 hbp = mode->htotal - mode->hsync_end;551 552 /* hsync must be longer than 4 bytes HSS packets */553 if (hsync < dsi_short_packet_size_px)554 return MODE_HSYNC_NARROW;555 556 if (mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {557 /* HBP must be longer than 4 bytes HSE packets */558 if (hbp < dsi_short_packet_size_px)559 return MODE_HSYNC_NARROW;560 hbp -= dsi_short_packet_size_px;561 } else {562 /* With sync events HBP extends in the hsync */563 hbp += hsync - dsi_short_packet_size_px;564 }565 566 lane_mbps = pll_out_khz / 1000;567 ret = dw_mipi_dsi_phy_get_timing(priv_data, lane_mbps, &dphy_timing);568 if (ret)569 return MODE_ERROR;570 /*571 * In non-burst mode DSI has to enter in LP during HFP572 * (horizontal front porch) or HBP (horizontal back porch) to573 * resync with LTDC pixel clock.574 */575 delay_to_lp = DIV_ROUND_UP((dphy_timing.data_hs2lp + dphy_timing.data_lp2hs) *576 lanes * BITS_PER_BYTE, bpp);577 if (hfp < delay_to_lp && hbp < delay_to_lp)578 return MODE_HSYNC;579 }580 581 return MODE_OK;582}583 584static const struct dw_mipi_dsi_phy_ops dw_mipi_dsi_stm_phy_ops = {585 .init = dw_mipi_dsi_phy_init,586 .power_on = dw_mipi_dsi_phy_power_on,587 .power_off = dw_mipi_dsi_phy_power_off,588 .get_lane_mbps = dw_mipi_dsi_get_lane_mbps,589 .get_timing = dw_mipi_dsi_phy_get_timing,590};591 592static struct dw_mipi_dsi_plat_data dw_mipi_dsi_stm_plat_data = {593 .max_data_lanes = 2,594 .mode_valid = dw_mipi_dsi_stm_mode_valid,595 .phy_ops = &dw_mipi_dsi_stm_phy_ops,596};597 598static const struct of_device_id dw_mipi_dsi_stm_dt_ids[] = {599 { .compatible = "st,stm32-dsi", .data = &dw_mipi_dsi_stm_plat_data, },600 { },601};602MODULE_DEVICE_TABLE(of, dw_mipi_dsi_stm_dt_ids);603 604static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)605{606 struct device *dev = &pdev->dev;607 struct dw_mipi_dsi_stm *dsi;608 const struct dw_mipi_dsi_plat_data *pdata = of_device_get_match_data(dev);609 int ret;610 611 dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);612 if (!dsi)613 return -ENOMEM;614 615 dsi->base = devm_platform_ioremap_resource(pdev, 0);616 if (IS_ERR(dsi->base)) {617 ret = PTR_ERR(dsi->base);618 DRM_ERROR("Unable to get dsi registers %d\n", ret);619 return ret;620 }621 622 dsi->vdd_supply = devm_regulator_get(dev, "phy-dsi");623 if (IS_ERR(dsi->vdd_supply)) {624 ret = PTR_ERR(dsi->vdd_supply);625 dev_err_probe(dev, ret, "Failed to request regulator\n");626 return ret;627 }628 629 ret = regulator_enable(dsi->vdd_supply);630 if (ret) {631 DRM_ERROR("Failed to enable regulator: %d\n", ret);632 return ret;633 }634 635 dsi->pllref_clk = devm_clk_get(dev, "ref");636 if (IS_ERR(dsi->pllref_clk)) {637 ret = PTR_ERR(dsi->pllref_clk);638 dev_err_probe(dev, ret, "Unable to get pll reference clock\n");639 goto err_clk_get;640 }641 642 ret = clk_prepare_enable(dsi->pllref_clk);643 if (ret) {644 DRM_ERROR("Failed to enable pllref_clk: %d\n", ret);645 goto err_clk_get;646 }647 648 dsi->pclk = devm_clk_get(dev, "pclk");649 if (IS_ERR(dsi->pclk)) {650 ret = PTR_ERR(dsi->pclk);651 DRM_ERROR("Unable to get peripheral clock: %d\n", ret);652 goto err_dsi_probe;653 }654 655 ret = clk_prepare_enable(dsi->pclk);656 if (ret) {657 DRM_ERROR("%s: Failed to enable peripheral clk\n", __func__);658 goto err_dsi_probe;659 }660 661 dsi->hw_version = dsi_read(dsi, DSI_VERSION) & VERSION;662 clk_disable_unprepare(dsi->pclk);663 664 if (dsi->hw_version != HWVER_130 && dsi->hw_version != HWVER_131) {665 ret = -ENODEV;666 DRM_ERROR("bad dsi hardware version\n");667 goto err_dsi_probe;668 }669 670 /* set lane capabilities according to hw version */671 dsi->lane_min_kbps = LANE_MIN_KBPS;672 dsi->lane_max_kbps = LANE_MAX_KBPS;673 if (dsi->hw_version == HWVER_131) {674 dsi->lane_min_kbps *= 2;675 dsi->lane_max_kbps *= 2;676 }677 678 dsi->pdata = *pdata;679 dsi->pdata.base = dsi->base;680 dsi->pdata.priv_data = dsi;681 682 dsi->pdata.max_data_lanes = 2;683 dsi->pdata.phy_ops = &dw_mipi_dsi_stm_phy_ops;684 685 platform_set_drvdata(pdev, dsi);686 687 dsi->dsi = dw_mipi_dsi_probe(pdev, &dsi->pdata);688 if (IS_ERR(dsi->dsi)) {689 ret = PTR_ERR(dsi->dsi);690 dev_err_probe(dev, ret, "Failed to initialize mipi dsi host\n");691 goto err_dsi_probe;692 }693 694 /*695 * We need to wait for the generic bridge to probe before enabling and696 * register the internal pixel clock.697 */698 ret = clk_prepare_enable(dsi->pclk);699 if (ret) {700 DRM_ERROR("%s: Failed to enable peripheral clk\n", __func__);701 goto err_dsi_probe;702 }703 704 ret = dw_mipi_dsi_clk_register(dsi, dev);705 if (ret) {706 DRM_ERROR("Failed to register DSI pixel clock: %d\n", ret);707 clk_disable_unprepare(dsi->pclk);708 goto err_dsi_probe;709 }710 711 clk_disable_unprepare(dsi->pclk);712 713 return 0;714 715err_dsi_probe:716 clk_disable_unprepare(dsi->pllref_clk);717err_clk_get:718 regulator_disable(dsi->vdd_supply);719 720 return ret;721}722 723static void dw_mipi_dsi_stm_remove(struct platform_device *pdev)724{725 struct dw_mipi_dsi_stm *dsi = platform_get_drvdata(pdev);726 727 dw_mipi_dsi_remove(dsi->dsi);728 clk_disable_unprepare(dsi->pllref_clk);729 dw_mipi_dsi_clk_unregister(dsi);730 regulator_disable(dsi->vdd_supply);731}732 733static int dw_mipi_dsi_stm_suspend(struct device *dev)734{735 struct dw_mipi_dsi_stm *dsi = dev_get_drvdata(dev);736 737 DRM_DEBUG_DRIVER("\n");738 739 clk_disable_unprepare(dsi->pllref_clk);740 clk_disable_unprepare(dsi->pclk);741 regulator_disable(dsi->vdd_supply);742 743 return 0;744}745 746static int dw_mipi_dsi_stm_resume(struct device *dev)747{748 struct dw_mipi_dsi_stm *dsi = dev_get_drvdata(dev);749 int ret;750 751 DRM_DEBUG_DRIVER("\n");752 753 ret = regulator_enable(dsi->vdd_supply);754 if (ret) {755 DRM_ERROR("Failed to enable regulator: %d\n", ret);756 return ret;757 }758 759 ret = clk_prepare_enable(dsi->pclk);760 if (ret) {761 regulator_disable(dsi->vdd_supply);762 DRM_ERROR("Failed to enable pclk: %d\n", ret);763 return ret;764 }765 766 ret = clk_prepare_enable(dsi->pllref_clk);767 if (ret) {768 clk_disable_unprepare(dsi->pclk);769 regulator_disable(dsi->vdd_supply);770 DRM_ERROR("Failed to enable pllref_clk: %d\n", ret);771 return ret;772 }773 774 return 0;775}776 777static const struct dev_pm_ops dw_mipi_dsi_stm_pm_ops = {778 SYSTEM_SLEEP_PM_OPS(dw_mipi_dsi_stm_suspend,779 dw_mipi_dsi_stm_resume)780 RUNTIME_PM_OPS(dw_mipi_dsi_stm_suspend,781 dw_mipi_dsi_stm_resume, NULL)782};783 784static struct platform_driver dw_mipi_dsi_stm_driver = {785 .probe = dw_mipi_dsi_stm_probe,786 .remove_new = dw_mipi_dsi_stm_remove,787 .driver = {788 .of_match_table = dw_mipi_dsi_stm_dt_ids,789 .name = "stm32-display-dsi",790 .pm = &dw_mipi_dsi_stm_pm_ops,791 },792};793 794module_platform_driver(dw_mipi_dsi_stm_driver);795 796MODULE_AUTHOR("Philippe Cornu <philippe.cornu@st.com>");797MODULE_AUTHOR("Yannick Fertre <yannick.fertre@st.com>");798MODULE_DESCRIPTION("STMicroelectronics DW MIPI DSI host controller driver");799MODULE_LICENSE("GPL v2");800