Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2014 Red Hat
0004  * Author: Rob Clark <robdclark@gmail.com>
0005  * Author: Vinay Simha <vinaysimha@inforcecomputing.com>
0006  */
0007 
0008 #include <linux/delay.h>
0009 
0010 #include <drm/drm_crtc.h>
0011 #include <drm/drm_probe_helper.h>
0012 
0013 #include "mdp4_kms.h"
0014 
0015 struct mdp4_lcdc_encoder {
0016     struct drm_encoder base;
0017     struct device_node *panel_node;
0018     struct drm_panel *panel;
0019     struct clk *lcdc_clk;
0020     unsigned long int pixclock;
0021     struct regulator *regs[3];
0022     bool enabled;
0023     uint32_t bsc;
0024 };
0025 #define to_mdp4_lcdc_encoder(x) container_of(x, struct mdp4_lcdc_encoder, base)
0026 
0027 static struct mdp4_kms *get_kms(struct drm_encoder *encoder)
0028 {
0029     struct msm_drm_private *priv = encoder->dev->dev_private;
0030     return to_mdp4_kms(to_mdp_kms(priv->kms));
0031 }
0032 
0033 static void mdp4_lcdc_encoder_destroy(struct drm_encoder *encoder)
0034 {
0035     struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
0036             to_mdp4_lcdc_encoder(encoder);
0037     drm_encoder_cleanup(encoder);
0038     kfree(mdp4_lcdc_encoder);
0039 }
0040 
0041 static const struct drm_encoder_funcs mdp4_lcdc_encoder_funcs = {
0042     .destroy = mdp4_lcdc_encoder_destroy,
0043 };
0044 
0045 /* this should probably be a helper: */
0046 static struct drm_connector *get_connector(struct drm_encoder *encoder)
0047 {
0048     struct drm_device *dev = encoder->dev;
0049     struct drm_connector *connector;
0050 
0051     list_for_each_entry(connector, &dev->mode_config.connector_list, head)
0052         if (connector->encoder == encoder)
0053             return connector;
0054 
0055     return NULL;
0056 }
0057 
0058 static void setup_phy(struct drm_encoder *encoder)
0059 {
0060     struct drm_device *dev = encoder->dev;
0061     struct drm_connector *connector = get_connector(encoder);
0062     struct mdp4_kms *mdp4_kms = get_kms(encoder);
0063     uint32_t lvds_intf = 0, lvds_phy_cfg0 = 0;
0064     int bpp, nchan, swap;
0065 
0066     if (!connector)
0067         return;
0068 
0069     bpp = 3 * connector->display_info.bpc;
0070 
0071     if (!bpp)
0072         bpp = 18;
0073 
0074     /* TODO, these should come from panel somehow: */
0075     nchan = 1;
0076     swap = 0;
0077 
0078     switch (bpp) {
0079     case 24:
0080         mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(0),
0081                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x08) |
0082                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x05) |
0083                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x04) |
0084                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x03));
0085         mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(0),
0086                 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x02) |
0087                 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x01) |
0088                 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x00));
0089         mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(1),
0090                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x11) |
0091                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x10) |
0092                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x0d) |
0093                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x0c));
0094         mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(1),
0095                 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x0b) |
0096                 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x0a) |
0097                 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x09));
0098         mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(2),
0099                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x1a) |
0100                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x19) |
0101                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x18) |
0102                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x15));
0103         mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(2),
0104                 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x14) |
0105                 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x13) |
0106                 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x12));
0107         mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(3),
0108                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x1b) |
0109                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x17) |
0110                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x16) |
0111                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x0f));
0112         mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(3),
0113                 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x0e) |
0114                 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x07) |
0115                 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x06));
0116         if (nchan == 2) {
0117             lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE3_EN |
0118                     MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE2_EN |
0119                     MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE1_EN |
0120                     MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE0_EN |
0121                     MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE3_EN |
0122                     MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE2_EN |
0123                     MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE1_EN |
0124                     MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE0_EN;
0125         } else {
0126             lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE3_EN |
0127                     MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE2_EN |
0128                     MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE1_EN |
0129                     MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE0_EN;
0130         }
0131         break;
0132 
0133     case 18:
0134         mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(0),
0135                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x0a) |
0136                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x07) |
0137                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x06) |
0138                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x05));
0139         mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(0),
0140                 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x04) |
0141                 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x03) |
0142                 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x02));
0143         mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(1),
0144                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x13) |
0145                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x12) |
0146                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x0f) |
0147                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x0e));
0148         mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(1),
0149                 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x0d) |
0150                 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x0c) |
0151                 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x0b));
0152         mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(2),
0153                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x1a) |
0154                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x19) |
0155                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x18) |
0156                 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x17));
0157         mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(2),
0158                 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x16) |
0159                 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x15) |
0160                 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x14));
0161         if (nchan == 2) {
0162             lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE2_EN |
0163                     MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE1_EN |
0164                     MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE0_EN |
0165                     MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE2_EN |
0166                     MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE1_EN |
0167                     MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE0_EN;
0168         } else {
0169             lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE2_EN |
0170                     MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE1_EN |
0171                     MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE0_EN;
0172         }
0173         lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_RGB_OUT;
0174         break;
0175 
0176     default:
0177         DRM_DEV_ERROR(dev->dev, "unknown bpp: %d\n", bpp);
0178         return;
0179     }
0180 
0181     switch (nchan) {
0182     case 1:
0183         lvds_phy_cfg0 = MDP4_LVDS_PHY_CFG0_CHANNEL0;
0184         lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH1_CLK_LANE_EN |
0185                 MDP4_LCDC_LVDS_INTF_CTL_MODE_SEL;
0186         break;
0187     case 2:
0188         lvds_phy_cfg0 = MDP4_LVDS_PHY_CFG0_CHANNEL0 |
0189                 MDP4_LVDS_PHY_CFG0_CHANNEL1;
0190         lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH2_CLK_LANE_EN |
0191                 MDP4_LCDC_LVDS_INTF_CTL_CH1_CLK_LANE_EN;
0192         break;
0193     default:
0194         DRM_DEV_ERROR(dev->dev, "unknown # of channels: %d\n", nchan);
0195         return;
0196     }
0197 
0198     if (swap)
0199         lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH_SWAP;
0200 
0201     lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_ENABLE;
0202 
0203     mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_CFG0, lvds_phy_cfg0);
0204     mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_INTF_CTL, lvds_intf);
0205     mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_CFG2, 0x30);
0206 
0207     mb();
0208     udelay(1);
0209     lvds_phy_cfg0 |= MDP4_LVDS_PHY_CFG0_SERIALIZATION_ENBLE;
0210     mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_CFG0, lvds_phy_cfg0);
0211 }
0212 
0213 static void mdp4_lcdc_encoder_mode_set(struct drm_encoder *encoder,
0214         struct drm_display_mode *mode,
0215         struct drm_display_mode *adjusted_mode)
0216 {
0217     struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
0218             to_mdp4_lcdc_encoder(encoder);
0219     struct mdp4_kms *mdp4_kms = get_kms(encoder);
0220     uint32_t lcdc_hsync_skew, vsync_period, vsync_len, ctrl_pol;
0221     uint32_t display_v_start, display_v_end;
0222     uint32_t hsync_start_x, hsync_end_x;
0223 
0224     mode = adjusted_mode;
0225 
0226     DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode));
0227 
0228     mdp4_lcdc_encoder->pixclock = mode->clock * 1000;
0229 
0230     DBG("pixclock=%lu", mdp4_lcdc_encoder->pixclock);
0231 
0232     ctrl_pol = 0;
0233     if (mode->flags & DRM_MODE_FLAG_NHSYNC)
0234         ctrl_pol |= MDP4_LCDC_CTRL_POLARITY_HSYNC_LOW;
0235     if (mode->flags & DRM_MODE_FLAG_NVSYNC)
0236         ctrl_pol |= MDP4_LCDC_CTRL_POLARITY_VSYNC_LOW;
0237     /* probably need to get DATA_EN polarity from panel.. */
0238 
0239     lcdc_hsync_skew = 0;  /* get this from panel? */
0240 
0241     hsync_start_x = (mode->htotal - mode->hsync_start);
0242     hsync_end_x = mode->htotal - (mode->hsync_start - mode->hdisplay) - 1;
0243 
0244     vsync_period = mode->vtotal * mode->htotal;
0245     vsync_len = (mode->vsync_end - mode->vsync_start) * mode->htotal;
0246     display_v_start = (mode->vtotal - mode->vsync_start) * mode->htotal + lcdc_hsync_skew;
0247     display_v_end = vsync_period - ((mode->vsync_start - mode->vdisplay) * mode->htotal) + lcdc_hsync_skew - 1;
0248 
0249     mdp4_write(mdp4_kms, REG_MDP4_LCDC_HSYNC_CTRL,
0250             MDP4_LCDC_HSYNC_CTRL_PULSEW(mode->hsync_end - mode->hsync_start) |
0251             MDP4_LCDC_HSYNC_CTRL_PERIOD(mode->htotal));
0252     mdp4_write(mdp4_kms, REG_MDP4_LCDC_VSYNC_PERIOD, vsync_period);
0253     mdp4_write(mdp4_kms, REG_MDP4_LCDC_VSYNC_LEN, vsync_len);
0254     mdp4_write(mdp4_kms, REG_MDP4_LCDC_DISPLAY_HCTRL,
0255             MDP4_LCDC_DISPLAY_HCTRL_START(hsync_start_x) |
0256             MDP4_LCDC_DISPLAY_HCTRL_END(hsync_end_x));
0257     mdp4_write(mdp4_kms, REG_MDP4_LCDC_DISPLAY_VSTART, display_v_start);
0258     mdp4_write(mdp4_kms, REG_MDP4_LCDC_DISPLAY_VEND, display_v_end);
0259     mdp4_write(mdp4_kms, REG_MDP4_LCDC_BORDER_CLR, 0);
0260     mdp4_write(mdp4_kms, REG_MDP4_LCDC_UNDERFLOW_CLR,
0261             MDP4_LCDC_UNDERFLOW_CLR_ENABLE_RECOVERY |
0262             MDP4_LCDC_UNDERFLOW_CLR_COLOR(0xff));
0263     mdp4_write(mdp4_kms, REG_MDP4_LCDC_HSYNC_SKEW, lcdc_hsync_skew);
0264     mdp4_write(mdp4_kms, REG_MDP4_LCDC_CTRL_POLARITY, ctrl_pol);
0265     mdp4_write(mdp4_kms, REG_MDP4_LCDC_ACTIVE_HCTL,
0266             MDP4_LCDC_ACTIVE_HCTL_START(0) |
0267             MDP4_LCDC_ACTIVE_HCTL_END(0));
0268     mdp4_write(mdp4_kms, REG_MDP4_LCDC_ACTIVE_VSTART, 0);
0269     mdp4_write(mdp4_kms, REG_MDP4_LCDC_ACTIVE_VEND, 0);
0270 }
0271 
0272 static void mdp4_lcdc_encoder_disable(struct drm_encoder *encoder)
0273 {
0274     struct drm_device *dev = encoder->dev;
0275     struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
0276             to_mdp4_lcdc_encoder(encoder);
0277     struct mdp4_kms *mdp4_kms = get_kms(encoder);
0278     struct drm_panel *panel;
0279     int i, ret;
0280 
0281     if (WARN_ON(!mdp4_lcdc_encoder->enabled))
0282         return;
0283 
0284     mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 0);
0285 
0286     panel = of_drm_find_panel(mdp4_lcdc_encoder->panel_node);
0287     if (!IS_ERR(panel)) {
0288         drm_panel_disable(panel);
0289         drm_panel_unprepare(panel);
0290     }
0291 
0292     /*
0293      * Wait for a vsync so we know the ENABLE=0 latched before
0294      * the (connector) source of the vsync's gets disabled,
0295      * otherwise we end up in a funny state if we re-enable
0296      * before the disable latches, which results that some of
0297      * the settings changes for the new modeset (like new
0298      * scanout buffer) don't latch properly..
0299      */
0300     mdp_irq_wait(&mdp4_kms->base, MDP4_IRQ_PRIMARY_VSYNC);
0301 
0302     clk_disable_unprepare(mdp4_lcdc_encoder->lcdc_clk);
0303 
0304     for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) {
0305         ret = regulator_disable(mdp4_lcdc_encoder->regs[i]);
0306         if (ret)
0307             DRM_DEV_ERROR(dev->dev, "failed to disable regulator: %d\n", ret);
0308     }
0309 
0310     mdp4_lcdc_encoder->enabled = false;
0311 }
0312 
0313 static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder)
0314 {
0315     struct drm_device *dev = encoder->dev;
0316     struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
0317             to_mdp4_lcdc_encoder(encoder);
0318     unsigned long pc = mdp4_lcdc_encoder->pixclock;
0319     struct mdp4_kms *mdp4_kms = get_kms(encoder);
0320     struct drm_panel *panel;
0321     uint32_t config;
0322     int i, ret;
0323 
0324     if (WARN_ON(mdp4_lcdc_encoder->enabled))
0325         return;
0326 
0327     /* TODO: hard-coded for 18bpp: */
0328     config =
0329         MDP4_DMA_CONFIG_R_BPC(BPC6) |
0330         MDP4_DMA_CONFIG_G_BPC(BPC6) |
0331         MDP4_DMA_CONFIG_B_BPC(BPC6) |
0332         MDP4_DMA_CONFIG_PACK(0x21) |
0333         MDP4_DMA_CONFIG_DEFLKR_EN |
0334         MDP4_DMA_CONFIG_DITHER_EN;
0335 
0336     if (!of_property_read_bool(dev->dev->of_node, "qcom,lcdc-align-lsb"))
0337         config |= MDP4_DMA_CONFIG_PACK_ALIGN_MSB;
0338 
0339     mdp4_crtc_set_config(encoder->crtc, config);
0340     mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 0);
0341 
0342     for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) {
0343         ret = regulator_enable(mdp4_lcdc_encoder->regs[i]);
0344         if (ret)
0345             DRM_DEV_ERROR(dev->dev, "failed to enable regulator: %d\n", ret);
0346     }
0347 
0348     DBG("setting lcdc_clk=%lu", pc);
0349     ret = clk_set_rate(mdp4_lcdc_encoder->lcdc_clk, pc);
0350     if (ret)
0351         DRM_DEV_ERROR(dev->dev, "failed to configure lcdc_clk: %d\n", ret);
0352     ret = clk_prepare_enable(mdp4_lcdc_encoder->lcdc_clk);
0353     if (ret)
0354         DRM_DEV_ERROR(dev->dev, "failed to enable lcdc_clk: %d\n", ret);
0355 
0356     panel = of_drm_find_panel(mdp4_lcdc_encoder->panel_node);
0357     if (!IS_ERR(panel)) {
0358         drm_panel_prepare(panel);
0359         drm_panel_enable(panel);
0360     }
0361 
0362     setup_phy(encoder);
0363 
0364     mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 1);
0365 
0366     mdp4_lcdc_encoder->enabled = true;
0367 }
0368 
0369 static const struct drm_encoder_helper_funcs mdp4_lcdc_encoder_helper_funcs = {
0370     .mode_set = mdp4_lcdc_encoder_mode_set,
0371     .disable = mdp4_lcdc_encoder_disable,
0372     .enable = mdp4_lcdc_encoder_enable,
0373 };
0374 
0375 long mdp4_lcdc_round_pixclk(struct drm_encoder *encoder, unsigned long rate)
0376 {
0377     struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
0378             to_mdp4_lcdc_encoder(encoder);
0379     return clk_round_rate(mdp4_lcdc_encoder->lcdc_clk, rate);
0380 }
0381 
0382 /* initialize encoder */
0383 struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev,
0384         struct device_node *panel_node)
0385 {
0386     struct drm_encoder *encoder = NULL;
0387     struct mdp4_lcdc_encoder *mdp4_lcdc_encoder;
0388     struct regulator *reg;
0389     int ret;
0390 
0391     mdp4_lcdc_encoder = kzalloc(sizeof(*mdp4_lcdc_encoder), GFP_KERNEL);
0392     if (!mdp4_lcdc_encoder) {
0393         ret = -ENOMEM;
0394         goto fail;
0395     }
0396 
0397     mdp4_lcdc_encoder->panel_node = panel_node;
0398 
0399     encoder = &mdp4_lcdc_encoder->base;
0400 
0401     drm_encoder_init(dev, encoder, &mdp4_lcdc_encoder_funcs,
0402              DRM_MODE_ENCODER_LVDS, NULL);
0403     drm_encoder_helper_add(encoder, &mdp4_lcdc_encoder_helper_funcs);
0404 
0405     /* TODO: do we need different pll in other cases? */
0406     mdp4_lcdc_encoder->lcdc_clk = mpd4_lvds_pll_init(dev);
0407     if (IS_ERR(mdp4_lcdc_encoder->lcdc_clk)) {
0408         DRM_DEV_ERROR(dev->dev, "failed to get lvds_clk\n");
0409         ret = PTR_ERR(mdp4_lcdc_encoder->lcdc_clk);
0410         goto fail;
0411     }
0412 
0413     /* TODO: different regulators in other cases? */
0414     reg = devm_regulator_get(dev->dev, "lvds-vccs-3p3v");
0415     if (IS_ERR(reg)) {
0416         ret = PTR_ERR(reg);
0417         DRM_DEV_ERROR(dev->dev, "failed to get lvds-vccs-3p3v: %d\n", ret);
0418         goto fail;
0419     }
0420     mdp4_lcdc_encoder->regs[0] = reg;
0421 
0422     reg = devm_regulator_get(dev->dev, "lvds-pll-vdda");
0423     if (IS_ERR(reg)) {
0424         ret = PTR_ERR(reg);
0425         DRM_DEV_ERROR(dev->dev, "failed to get lvds-pll-vdda: %d\n", ret);
0426         goto fail;
0427     }
0428     mdp4_lcdc_encoder->regs[1] = reg;
0429 
0430     reg = devm_regulator_get(dev->dev, "lvds-vdda");
0431     if (IS_ERR(reg)) {
0432         ret = PTR_ERR(reg);
0433         DRM_DEV_ERROR(dev->dev, "failed to get lvds-vdda: %d\n", ret);
0434         goto fail;
0435     }
0436     mdp4_lcdc_encoder->regs[2] = reg;
0437 
0438     return encoder;
0439 
0440 fail:
0441     if (encoder)
0442         mdp4_lcdc_encoder_destroy(encoder);
0443 
0444     return ERR_PTR(ret);
0445 }