1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2014 Red Hat 4 * Author: Rob Clark <robdclark@gmail.com> 5 * Author: Vinay Simha <vinaysimha@inforcecomputing.com> 6 */ 7 8 #include <linux/delay.h> 9 10 #include <drm/drm_crtc.h> 11 #include <drm/drm_probe_helper.h> 12 13 #include "mdp4_kms.h" 14 15 struct mdp4_lcdc_encoder { 16 struct drm_encoder base; 17 struct device_node *panel_node; 18 struct drm_panel *panel; 19 struct clk *lcdc_clk; 20 unsigned long int pixclock; 21 struct regulator *regs[3]; 22 bool enabled; 23 uint32_t bsc; 24 }; 25 #define to_mdp4_lcdc_encoder(x) container_of(x, struct mdp4_lcdc_encoder, base) 26 27 static struct mdp4_kms *get_kms(struct drm_encoder *encoder) 28 { 29 struct msm_drm_private *priv = encoder->dev->dev_private; 30 return to_mdp4_kms(to_mdp_kms(priv->kms)); 31 } 32 33 static void mdp4_lcdc_encoder_destroy(struct drm_encoder *encoder) 34 { 35 struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = 36 to_mdp4_lcdc_encoder(encoder); 37 drm_encoder_cleanup(encoder); 38 kfree(mdp4_lcdc_encoder); 39 } 40 41 static const struct drm_encoder_funcs mdp4_lcdc_encoder_funcs = { 42 .destroy = mdp4_lcdc_encoder_destroy, 43 }; 44 45 /* this should probably be a helper: */ 46 static struct drm_connector *get_connector(struct drm_encoder *encoder) 47 { 48 struct drm_device *dev = encoder->dev; 49 struct drm_connector *connector; 50 51 list_for_each_entry(connector, &dev->mode_config.connector_list, head) 52 if (connector->encoder == encoder) 53 return connector; 54 55 return NULL; 56 } 57 58 static void setup_phy(struct drm_encoder *encoder) 59 { 60 struct drm_device *dev = encoder->dev; 61 struct drm_connector *connector = get_connector(encoder); 62 struct mdp4_kms *mdp4_kms = get_kms(encoder); 63 uint32_t lvds_intf = 0, lvds_phy_cfg0 = 0; 64 int bpp, nchan, swap; 65 66 if (!connector) 67 return; 68 69 bpp = 3 * connector->display_info.bpc; 70 71 if (!bpp) 72 bpp = 18; 73 74 /* TODO, these should come from panel somehow: */ 75 nchan = 1; 76 swap = 0; 77 78 switch (bpp) { 79 case 24: 80 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(0), 81 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x08) | 82 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x05) | 83 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x04) | 84 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x03)); 85 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(0), 86 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x02) | 87 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x01) | 88 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x00)); 89 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(1), 90 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x11) | 91 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x10) | 92 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x0d) | 93 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x0c)); 94 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(1), 95 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x0b) | 96 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x0a) | 97 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x09)); 98 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(2), 99 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x1a) | 100 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x19) | 101 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x18) | 102 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x15)); 103 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(2), 104 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x14) | 105 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x13) | 106 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x12)); 107 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(3), 108 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x1b) | 109 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x17) | 110 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x16) | 111 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x0f)); 112 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(3), 113 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x0e) | 114 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x07) | 115 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x06)); 116 if (nchan == 2) { 117 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE3_EN | 118 MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE2_EN | 119 MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE1_EN | 120 MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE0_EN | 121 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE3_EN | 122 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE2_EN | 123 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE1_EN | 124 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE0_EN; 125 } else { 126 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE3_EN | 127 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE2_EN | 128 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE1_EN | 129 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE0_EN; 130 } 131 break; 132 133 case 18: 134 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(0), 135 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x0a) | 136 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x07) | 137 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x06) | 138 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x05)); 139 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(0), 140 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x04) | 141 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x03) | 142 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x02)); 143 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(1), 144 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x13) | 145 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x12) | 146 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x0f) | 147 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x0e)); 148 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(1), 149 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x0d) | 150 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x0c) | 151 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x0b)); 152 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(2), 153 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x1a) | 154 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x19) | 155 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x18) | 156 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x17)); 157 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(2), 158 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x16) | 159 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x15) | 160 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x14)); 161 if (nchan == 2) { 162 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE2_EN | 163 MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE1_EN | 164 MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE0_EN | 165 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE2_EN | 166 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE1_EN | 167 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE0_EN; 168 } else { 169 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE2_EN | 170 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE1_EN | 171 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE0_EN; 172 } 173 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_RGB_OUT; 174 break; 175 176 default: 177 DRM_DEV_ERROR(dev->dev, "unknown bpp: %d\n", bpp); 178 return; 179 } 180 181 switch (nchan) { 182 case 1: 183 lvds_phy_cfg0 = MDP4_LVDS_PHY_CFG0_CHANNEL0; 184 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH1_CLK_LANE_EN | 185 MDP4_LCDC_LVDS_INTF_CTL_MODE_SEL; 186 break; 187 case 2: 188 lvds_phy_cfg0 = MDP4_LVDS_PHY_CFG0_CHANNEL0 | 189 MDP4_LVDS_PHY_CFG0_CHANNEL1; 190 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH2_CLK_LANE_EN | 191 MDP4_LCDC_LVDS_INTF_CTL_CH1_CLK_LANE_EN; 192 break; 193 default: 194 DRM_DEV_ERROR(dev->dev, "unknown # of channels: %d\n", nchan); 195 return; 196 } 197 198 if (swap) 199 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH_SWAP; 200 201 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_ENABLE; 202 203 mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_CFG0, lvds_phy_cfg0); 204 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_INTF_CTL, lvds_intf); 205 mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_CFG2, 0x30); 206 207 mb(); 208 udelay(1); 209 lvds_phy_cfg0 |= MDP4_LVDS_PHY_CFG0_SERIALIZATION_ENBLE; 210 mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_CFG0, lvds_phy_cfg0); 211 } 212 213 static void mdp4_lcdc_encoder_mode_set(struct drm_encoder *encoder, 214 struct drm_display_mode *mode, 215 struct drm_display_mode *adjusted_mode) 216 { 217 struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = 218 to_mdp4_lcdc_encoder(encoder); 219 struct mdp4_kms *mdp4_kms = get_kms(encoder); 220 uint32_t lcdc_hsync_skew, vsync_period, vsync_len, ctrl_pol; 221 uint32_t display_v_start, display_v_end; 222 uint32_t hsync_start_x, hsync_end_x; 223 224 mode = adjusted_mode; 225 226 DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode)); 227 228 mdp4_lcdc_encoder->pixclock = mode->clock * 1000; 229 230 DBG("pixclock=%lu", mdp4_lcdc_encoder->pixclock); 231 232 ctrl_pol = 0; 233 if (mode->flags & DRM_MODE_FLAG_NHSYNC) 234 ctrl_pol |= MDP4_LCDC_CTRL_POLARITY_HSYNC_LOW; 235 if (mode->flags & DRM_MODE_FLAG_NVSYNC) 236 ctrl_pol |= MDP4_LCDC_CTRL_POLARITY_VSYNC_LOW; 237 /* probably need to get DATA_EN polarity from panel.. */ 238 239 lcdc_hsync_skew = 0; /* get this from panel? */ 240 241 hsync_start_x = (mode->htotal - mode->hsync_start); 242 hsync_end_x = mode->htotal - (mode->hsync_start - mode->hdisplay) - 1; 243 244 vsync_period = mode->vtotal * mode->htotal; 245 vsync_len = (mode->vsync_end - mode->vsync_start) * mode->htotal; 246 display_v_start = (mode->vtotal - mode->vsync_start) * mode->htotal + lcdc_hsync_skew; 247 display_v_end = vsync_period - ((mode->vsync_start - mode->vdisplay) * mode->htotal) + lcdc_hsync_skew - 1; 248 249 mdp4_write(mdp4_kms, REG_MDP4_LCDC_HSYNC_CTRL, 250 MDP4_LCDC_HSYNC_CTRL_PULSEW(mode->hsync_end - mode->hsync_start) | 251 MDP4_LCDC_HSYNC_CTRL_PERIOD(mode->htotal)); 252 mdp4_write(mdp4_kms, REG_MDP4_LCDC_VSYNC_PERIOD, vsync_period); 253 mdp4_write(mdp4_kms, REG_MDP4_LCDC_VSYNC_LEN, vsync_len); 254 mdp4_write(mdp4_kms, REG_MDP4_LCDC_DISPLAY_HCTRL, 255 MDP4_LCDC_DISPLAY_HCTRL_START(hsync_start_x) | 256 MDP4_LCDC_DISPLAY_HCTRL_END(hsync_end_x)); 257 mdp4_write(mdp4_kms, REG_MDP4_LCDC_DISPLAY_VSTART, display_v_start); 258 mdp4_write(mdp4_kms, REG_MDP4_LCDC_DISPLAY_VEND, display_v_end); 259 mdp4_write(mdp4_kms, REG_MDP4_LCDC_BORDER_CLR, 0); 260 mdp4_write(mdp4_kms, REG_MDP4_LCDC_UNDERFLOW_CLR, 261 MDP4_LCDC_UNDERFLOW_CLR_ENABLE_RECOVERY | 262 MDP4_LCDC_UNDERFLOW_CLR_COLOR(0xff)); 263 mdp4_write(mdp4_kms, REG_MDP4_LCDC_HSYNC_SKEW, lcdc_hsync_skew); 264 mdp4_write(mdp4_kms, REG_MDP4_LCDC_CTRL_POLARITY, ctrl_pol); 265 mdp4_write(mdp4_kms, REG_MDP4_LCDC_ACTIVE_HCTL, 266 MDP4_LCDC_ACTIVE_HCTL_START(0) | 267 MDP4_LCDC_ACTIVE_HCTL_END(0)); 268 mdp4_write(mdp4_kms, REG_MDP4_LCDC_ACTIVE_VSTART, 0); 269 mdp4_write(mdp4_kms, REG_MDP4_LCDC_ACTIVE_VEND, 0); 270 } 271 272 static void mdp4_lcdc_encoder_disable(struct drm_encoder *encoder) 273 { 274 struct drm_device *dev = encoder->dev; 275 struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = 276 to_mdp4_lcdc_encoder(encoder); 277 struct mdp4_kms *mdp4_kms = get_kms(encoder); 278 struct drm_panel *panel; 279 int i, ret; 280 281 if (WARN_ON(!mdp4_lcdc_encoder->enabled)) 282 return; 283 284 mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 0); 285 286 panel = of_drm_find_panel(mdp4_lcdc_encoder->panel_node); 287 if (!IS_ERR(panel)) { 288 drm_panel_disable(panel); 289 drm_panel_unprepare(panel); 290 } 291 292 /* 293 * Wait for a vsync so we know the ENABLE=0 latched before 294 * the (connector) source of the vsync's gets disabled, 295 * otherwise we end up in a funny state if we re-enable 296 * before the disable latches, which results that some of 297 * the settings changes for the new modeset (like new 298 * scanout buffer) don't latch properly.. 299 */ 300 mdp_irq_wait(&mdp4_kms->base, MDP4_IRQ_PRIMARY_VSYNC); 301 302 clk_disable_unprepare(mdp4_lcdc_encoder->lcdc_clk); 303 304 for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) { 305 ret = regulator_disable(mdp4_lcdc_encoder->regs[i]); 306 if (ret) 307 DRM_DEV_ERROR(dev->dev, "failed to disable regulator: %d\n", ret); 308 } 309 310 mdp4_lcdc_encoder->enabled = false; 311 } 312 313 static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder) 314 { 315 struct drm_device *dev = encoder->dev; 316 struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = 317 to_mdp4_lcdc_encoder(encoder); 318 unsigned long pc = mdp4_lcdc_encoder->pixclock; 319 struct mdp4_kms *mdp4_kms = get_kms(encoder); 320 struct drm_panel *panel; 321 uint32_t config; 322 int i, ret; 323 324 if (WARN_ON(mdp4_lcdc_encoder->enabled)) 325 return; 326 327 /* TODO: hard-coded for 18bpp: */ 328 config = 329 MDP4_DMA_CONFIG_R_BPC(BPC6) | 330 MDP4_DMA_CONFIG_G_BPC(BPC6) | 331 MDP4_DMA_CONFIG_B_BPC(BPC6) | 332 MDP4_DMA_CONFIG_PACK(0x21) | 333 MDP4_DMA_CONFIG_DEFLKR_EN | 334 MDP4_DMA_CONFIG_DITHER_EN; 335 336 if (!of_property_read_bool(dev->dev->of_node, "qcom,lcdc-align-lsb")) 337 config |= MDP4_DMA_CONFIG_PACK_ALIGN_MSB; 338 339 mdp4_crtc_set_config(encoder->crtc, config); 340 mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 0); 341 342 for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) { 343 ret = regulator_enable(mdp4_lcdc_encoder->regs[i]); 344 if (ret) 345 DRM_DEV_ERROR(dev->dev, "failed to enable regulator: %d\n", ret); 346 } 347 348 DBG("setting lcdc_clk=%lu", pc); 349 ret = clk_set_rate(mdp4_lcdc_encoder->lcdc_clk, pc); 350 if (ret) 351 DRM_DEV_ERROR(dev->dev, "failed to configure lcdc_clk: %d\n", ret); 352 ret = clk_prepare_enable(mdp4_lcdc_encoder->lcdc_clk); 353 if (ret) 354 DRM_DEV_ERROR(dev->dev, "failed to enable lcdc_clk: %d\n", ret); 355 356 panel = of_drm_find_panel(mdp4_lcdc_encoder->panel_node); 357 if (!IS_ERR(panel)) { 358 drm_panel_prepare(panel); 359 drm_panel_enable(panel); 360 } 361 362 setup_phy(encoder); 363 364 mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 1); 365 366 mdp4_lcdc_encoder->enabled = true; 367 } 368 369 static const struct drm_encoder_helper_funcs mdp4_lcdc_encoder_helper_funcs = { 370 .mode_set = mdp4_lcdc_encoder_mode_set, 371 .disable = mdp4_lcdc_encoder_disable, 372 .enable = mdp4_lcdc_encoder_enable, 373 }; 374 375 long mdp4_lcdc_round_pixclk(struct drm_encoder *encoder, unsigned long rate) 376 { 377 struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = 378 to_mdp4_lcdc_encoder(encoder); 379 return clk_round_rate(mdp4_lcdc_encoder->lcdc_clk, rate); 380 } 381 382 /* initialize encoder */ 383 struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev, 384 struct device_node *panel_node) 385 { 386 struct drm_encoder *encoder = NULL; 387 struct mdp4_lcdc_encoder *mdp4_lcdc_encoder; 388 struct regulator *reg; 389 int ret; 390 391 mdp4_lcdc_encoder = kzalloc(sizeof(*mdp4_lcdc_encoder), GFP_KERNEL); 392 if (!mdp4_lcdc_encoder) { 393 ret = -ENOMEM; 394 goto fail; 395 } 396 397 mdp4_lcdc_encoder->panel_node = panel_node; 398 399 encoder = &mdp4_lcdc_encoder->base; 400 401 drm_encoder_init(dev, encoder, &mdp4_lcdc_encoder_funcs, 402 DRM_MODE_ENCODER_LVDS, NULL); 403 drm_encoder_helper_add(encoder, &mdp4_lcdc_encoder_helper_funcs); 404 405 /* TODO: do we need different pll in other cases? */ 406 mdp4_lcdc_encoder->lcdc_clk = mpd4_lvds_pll_init(dev); 407 if (IS_ERR(mdp4_lcdc_encoder->lcdc_clk)) { 408 DRM_DEV_ERROR(dev->dev, "failed to get lvds_clk\n"); 409 ret = PTR_ERR(mdp4_lcdc_encoder->lcdc_clk); 410 goto fail; 411 } 412 413 /* TODO: different regulators in other cases? */ 414 reg = devm_regulator_get(dev->dev, "lvds-vccs-3p3v"); 415 if (IS_ERR(reg)) { 416 ret = PTR_ERR(reg); 417 DRM_DEV_ERROR(dev->dev, "failed to get lvds-vccs-3p3v: %d\n", ret); 418 goto fail; 419 } 420 mdp4_lcdc_encoder->regs[0] = reg; 421 422 reg = devm_regulator_get(dev->dev, "lvds-pll-vdda"); 423 if (IS_ERR(reg)) { 424 ret = PTR_ERR(reg); 425 DRM_DEV_ERROR(dev->dev, "failed to get lvds-pll-vdda: %d\n", ret); 426 goto fail; 427 } 428 mdp4_lcdc_encoder->regs[1] = reg; 429 430 reg = devm_regulator_get(dev->dev, "lvds-vdda"); 431 if (IS_ERR(reg)) { 432 ret = PTR_ERR(reg); 433 DRM_DEV_ERROR(dev->dev, "failed to get lvds-vdda: %d\n", ret); 434 goto fail; 435 } 436 mdp4_lcdc_encoder->regs[2] = reg; 437 438 return encoder; 439 440 fail: 441 if (encoder) 442 mdp4_lcdc_encoder_destroy(encoder); 443 444 return ERR_PTR(ret); 445 } 446