root/drivers/gpu/drm/gma500/mdfld_dsi_output.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. parse_LABC_control
  2. mdfld_dsi_gen_fifo_ready
  3. mdfld_dsi_brightness_init
  4. mdfld_dsi_brightness_control
  5. mdfld_dsi_get_panel_status
  6. mdfld_dsi_get_power_mode
  7. mdfld_dsi_controller_init
  8. mdfld_dsi_connector_save
  9. mdfld_dsi_connector_restore
  10. mdfld_dsi_connector_detect
  11. mdfld_dsi_connector_set_property
  12. mdfld_dsi_connector_destroy
  13. mdfld_dsi_connector_get_modes
  14. mdfld_dsi_connector_mode_valid
  15. mdfld_dsi_connector_best_encoder
  16. mdfld_dsi_get_default_config
  17. mdfld_dsi_panel_reset
  18. mdfld_dsi_output_init

   1 /*
   2  * Copyright © 2010 Intel Corporation
   3  *
   4  * Permission is hereby granted, free of charge, to any person obtaining a
   5  * copy of this software and associated documentation files (the "Software"),
   6  * to deal in the Software without restriction, including without limitation
   7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8  * and/or sell copies of the Software, and to permit persons to whom the
   9  * Software is furnished to do so, subject to the following conditions:
  10  *
  11  * The above copyright notice and this permission notice (including the next
  12  * paragraph) shall be included in all copies or substantial portions of the
  13  * Software.
  14  *
  15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21  * DEALINGS IN THE SOFTWARE.
  22  *
  23  * Authors:
  24  * jim liu <jim.liu@intel.com>
  25  * Jackie Li<yaodong.li@intel.com>
  26  */
  27 
  28 #include <linux/delay.h>
  29 #include <linux/moduleparam.h>
  30 #include <linux/pm_runtime.h>
  31 
  32 #include <asm/intel_scu_ipc.h>
  33 
  34 #include "mdfld_dsi_dpi.h"
  35 #include "mdfld_dsi_output.h"
  36 #include "mdfld_dsi_pkg_sender.h"
  37 #include "mdfld_output.h"
  38 #include "tc35876x-dsi-lvds.h"
  39 
  40 /* get the LABC from command line. */
  41 static int LABC_control = 1;
  42 
  43 #ifdef MODULE
  44 module_param(LABC_control, int, 0644);
  45 #else
  46 
  47 static int __init parse_LABC_control(char *arg)
  48 {
  49         /* LABC control can be passed in as a cmdline parameter */
  50         /* to enable this feature add LABC=1 to cmdline */
  51         /* to disable this feature add LABC=0 to cmdline */
  52         if (!arg)
  53                 return -EINVAL;
  54 
  55         if (!strcasecmp(arg, "0"))
  56                 LABC_control = 0;
  57         else if (!strcasecmp(arg, "1"))
  58                 LABC_control = 1;
  59 
  60         return 0;
  61 }
  62 early_param("LABC", parse_LABC_control);
  63 #endif
  64 
  65 /**
  66  * Check and see if the generic control or data buffer is empty and ready.
  67  */
  68 void mdfld_dsi_gen_fifo_ready(struct drm_device *dev, u32 gen_fifo_stat_reg,
  69                                                         u32 fifo_stat)
  70 {
  71         u32 GEN_BF_time_out_count;
  72 
  73         /* Check MIPI Adatper command registers */
  74         for (GEN_BF_time_out_count = 0;
  75                         GEN_BF_time_out_count < GEN_FB_TIME_OUT;
  76                         GEN_BF_time_out_count++) {
  77                 if ((REG_READ(gen_fifo_stat_reg) & fifo_stat) == fifo_stat)
  78                         break;
  79                 udelay(100);
  80         }
  81 
  82         if (GEN_BF_time_out_count == GEN_FB_TIME_OUT)
  83                 DRM_ERROR("mdfld_dsi_gen_fifo_ready, Timeout. gen_fifo_stat_reg = 0x%x.\n",
  84                                         gen_fifo_stat_reg);
  85 }
  86 
  87 /**
  88  * Manage the DSI MIPI keyboard and display brightness.
  89  * FIXME: this is exported to OSPM code. should work out an specific
  90  * display interface to OSPM.
  91  */
  92 
  93 void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, int pipe)
  94 {
  95         struct mdfld_dsi_pkg_sender *sender =
  96                                 mdfld_dsi_get_pkg_sender(dsi_config);
  97         struct drm_device *dev;
  98         struct drm_psb_private *dev_priv;
  99         u32 gen_ctrl_val;
 100 
 101         if (!sender) {
 102                 DRM_ERROR("No sender found\n");
 103                 return;
 104         }
 105 
 106         dev = sender->dev;
 107         dev_priv = dev->dev_private;
 108 
 109         /* Set default display backlight value to 85% (0xd8)*/
 110         mdfld_dsi_send_mcs_short(sender, write_display_brightness, 0xd8, 1,
 111                                 true);
 112 
 113         /* Set minimum brightness setting of CABC function to 20% (0x33)*/
 114         mdfld_dsi_send_mcs_short(sender, write_cabc_min_bright, 0x33, 1, true);
 115 
 116         /* Enable backlight or/and LABC */
 117         gen_ctrl_val = BRIGHT_CNTL_BLOCK_ON | DISPLAY_DIMMING_ON |
 118                                                                 BACKLIGHT_ON;
 119         if (LABC_control == 1)
 120                 gen_ctrl_val |= DISPLAY_DIMMING_ON | DISPLAY_BRIGHTNESS_AUTO
 121                                                                 | GAMMA_AUTO;
 122 
 123         if (LABC_control == 1)
 124                 gen_ctrl_val |= AMBIENT_LIGHT_SENSE_ON;
 125 
 126         dev_priv->mipi_ctrl_display = gen_ctrl_val;
 127 
 128         mdfld_dsi_send_mcs_short(sender, write_ctrl_display, (u8)gen_ctrl_val,
 129                                 1, true);
 130 
 131         mdfld_dsi_send_mcs_short(sender, write_ctrl_cabc, UI_IMAGE, 1, true);
 132 }
 133 
 134 void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe, int level)
 135 {
 136         struct mdfld_dsi_pkg_sender *sender;
 137         struct drm_psb_private *dev_priv;
 138         struct mdfld_dsi_config *dsi_config;
 139         u32 gen_ctrl_val = 0;
 140         int p_type = TMD_VID;
 141 
 142         if (!dev || (pipe != 0 && pipe != 2)) {
 143                 DRM_ERROR("Invalid parameter\n");
 144                 return;
 145         }
 146 
 147         p_type = mdfld_get_panel_type(dev, 0);
 148 
 149         dev_priv = dev->dev_private;
 150 
 151         if (pipe)
 152                 dsi_config = dev_priv->dsi_configs[1];
 153         else
 154                 dsi_config = dev_priv->dsi_configs[0];
 155 
 156         sender = mdfld_dsi_get_pkg_sender(dsi_config);
 157 
 158         if (!sender) {
 159                 DRM_ERROR("No sender found\n");
 160                 return;
 161         }
 162 
 163         gen_ctrl_val = (level * 0xff / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL) & 0xff;
 164 
 165         dev_dbg(sender->dev->dev, "pipe = %d, gen_ctrl_val = %d.\n",
 166                                                         pipe, gen_ctrl_val);
 167 
 168         if (p_type == TMD_VID) {
 169                 /* Set display backlight value */
 170                 mdfld_dsi_send_mcs_short(sender, tmd_write_display_brightness,
 171                                         (u8)gen_ctrl_val, 1, true);
 172         } else {
 173                 /* Set display backlight value */
 174                 mdfld_dsi_send_mcs_short(sender, write_display_brightness,
 175                                         (u8)gen_ctrl_val, 1, true);
 176 
 177                 /* Enable backlight control */
 178                 if (level == 0)
 179                         gen_ctrl_val = 0;
 180                 else
 181                         gen_ctrl_val = dev_priv->mipi_ctrl_display;
 182 
 183                 mdfld_dsi_send_mcs_short(sender, write_ctrl_display,
 184                                         (u8)gen_ctrl_val, 1, true);
 185         }
 186 }
 187 
 188 static int mdfld_dsi_get_panel_status(struct mdfld_dsi_config *dsi_config,
 189                                 u8 dcs, u32 *data, bool hs)
 190 {
 191         struct mdfld_dsi_pkg_sender *sender
 192                 = mdfld_dsi_get_pkg_sender(dsi_config);
 193 
 194         if (!sender || !data) {
 195                 DRM_ERROR("Invalid parameter\n");
 196                 return -EINVAL;
 197         }
 198 
 199         return mdfld_dsi_read_mcs(sender, dcs, data, 1, hs);
 200 }
 201 
 202 int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config, u32 *mode,
 203                         bool hs)
 204 {
 205         if (!dsi_config || !mode) {
 206                 DRM_ERROR("Invalid parameter\n");
 207                 return -EINVAL;
 208         }
 209 
 210         return mdfld_dsi_get_panel_status(dsi_config, 0x0a, mode, hs);
 211 }
 212 
 213 /*
 214  * NOTE: this function was used by OSPM.
 215  * TODO: will be removed later, should work out display interfaces for OSPM
 216  */
 217 void mdfld_dsi_controller_init(struct mdfld_dsi_config *dsi_config, int pipe)
 218 {
 219         if (!dsi_config || ((pipe != 0) && (pipe != 2))) {
 220                 DRM_ERROR("Invalid parameters\n");
 221                 return;
 222         }
 223 
 224         mdfld_dsi_dpi_controller_init(dsi_config, pipe);
 225 }
 226 
 227 static void mdfld_dsi_connector_save(struct drm_connector *connector)
 228 {
 229 }
 230 
 231 static void mdfld_dsi_connector_restore(struct drm_connector *connector)
 232 {
 233 }
 234 
 235 /* FIXME: start using the force parameter */
 236 static enum drm_connector_status
 237 mdfld_dsi_connector_detect(struct drm_connector *connector, bool force)
 238 {
 239         struct mdfld_dsi_connector *dsi_connector
 240                 = mdfld_dsi_connector(connector);
 241 
 242         dsi_connector->status = connector_status_connected;
 243 
 244         return dsi_connector->status;
 245 }
 246 
 247 static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
 248                                 struct drm_property *property,
 249                                 uint64_t value)
 250 {
 251         struct drm_encoder *encoder = connector->encoder;
 252 
 253         if (!strcmp(property->name, "scaling mode") && encoder) {
 254                 struct gma_crtc *gma_crtc = to_gma_crtc(encoder->crtc);
 255                 bool centerechange;
 256                 uint64_t val;
 257 
 258                 if (!gma_crtc)
 259                         goto set_prop_error;
 260 
 261                 switch (value) {
 262                 case DRM_MODE_SCALE_FULLSCREEN:
 263                         break;
 264                 case DRM_MODE_SCALE_NO_SCALE:
 265                         break;
 266                 case DRM_MODE_SCALE_ASPECT:
 267                         break;
 268                 default:
 269                         goto set_prop_error;
 270                 }
 271 
 272                 if (drm_object_property_get_value(&connector->base, property, &val))
 273                         goto set_prop_error;
 274 
 275                 if (val == value)
 276                         goto set_prop_done;
 277 
 278                 if (drm_object_property_set_value(&connector->base,
 279                                                         property, value))
 280                         goto set_prop_error;
 281 
 282                 centerechange = (val == DRM_MODE_SCALE_NO_SCALE) ||
 283                         (value == DRM_MODE_SCALE_NO_SCALE);
 284 
 285                 if (gma_crtc->saved_mode.hdisplay != 0 &&
 286                     gma_crtc->saved_mode.vdisplay != 0) {
 287                         if (centerechange) {
 288                                 if (!drm_crtc_helper_set_mode(encoder->crtc,
 289                                                 &gma_crtc->saved_mode,
 290                                                 encoder->crtc->x,
 291                                                 encoder->crtc->y,
 292                                                 encoder->crtc->primary->fb))
 293                                         goto set_prop_error;
 294                         } else {
 295                                 const struct drm_encoder_helper_funcs *funcs =
 296                                                 encoder->helper_private;
 297                                 funcs->mode_set(encoder,
 298                                         &gma_crtc->saved_mode,
 299                                         &gma_crtc->saved_adjusted_mode);
 300                         }
 301                 }
 302         } else if (!strcmp(property->name, "backlight") && encoder) {
 303                 if (drm_object_property_set_value(&connector->base, property,
 304                                                                         value))
 305                         goto set_prop_error;
 306                 else
 307                         gma_backlight_set(encoder->dev, value);
 308         }
 309 set_prop_done:
 310         return 0;
 311 set_prop_error:
 312         return -1;
 313 }
 314 
 315 static void mdfld_dsi_connector_destroy(struct drm_connector *connector)
 316 {
 317         struct mdfld_dsi_connector *dsi_connector =
 318                                         mdfld_dsi_connector(connector);
 319         struct mdfld_dsi_pkg_sender *sender;
 320 
 321         if (!dsi_connector)
 322                 return;
 323         drm_connector_unregister(connector);
 324         drm_connector_cleanup(connector);
 325         sender = dsi_connector->pkg_sender;
 326         mdfld_dsi_pkg_sender_destroy(sender);
 327         kfree(dsi_connector);
 328 }
 329 
 330 static int mdfld_dsi_connector_get_modes(struct drm_connector *connector)
 331 {
 332         struct mdfld_dsi_connector *dsi_connector =
 333                                 mdfld_dsi_connector(connector);
 334         struct mdfld_dsi_config *dsi_config =
 335                                 mdfld_dsi_get_config(dsi_connector);
 336         struct drm_display_mode *fixed_mode = dsi_config->fixed_mode;
 337         struct drm_display_mode *dup_mode = NULL;
 338         struct drm_device *dev = connector->dev;
 339 
 340         if (fixed_mode) {
 341                 dev_dbg(dev->dev, "fixed_mode %dx%d\n",
 342                                 fixed_mode->hdisplay, fixed_mode->vdisplay);
 343                 dup_mode = drm_mode_duplicate(dev, fixed_mode);
 344                 drm_mode_probed_add(connector, dup_mode);
 345                 return 1;
 346         }
 347         DRM_ERROR("Didn't get any modes!\n");
 348         return 0;
 349 }
 350 
 351 static enum drm_mode_status mdfld_dsi_connector_mode_valid(struct drm_connector *connector,
 352                                                 struct drm_display_mode *mode)
 353 {
 354         struct mdfld_dsi_connector *dsi_connector =
 355                                         mdfld_dsi_connector(connector);
 356         struct mdfld_dsi_config *dsi_config =
 357                                         mdfld_dsi_get_config(dsi_connector);
 358         struct drm_display_mode *fixed_mode = dsi_config->fixed_mode;
 359 
 360         if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
 361                 return MODE_NO_DBLESCAN;
 362 
 363         if (mode->flags & DRM_MODE_FLAG_INTERLACE)
 364                 return MODE_NO_INTERLACE;
 365 
 366         /**
 367          * FIXME: current DC has no fitting unit, reject any mode setting
 368          * request
 369          * Will figure out a way to do up-scaling(pannel fitting) later.
 370          **/
 371         if (fixed_mode) {
 372                 if (mode->hdisplay != fixed_mode->hdisplay)
 373                         return MODE_PANEL;
 374 
 375                 if (mode->vdisplay != fixed_mode->vdisplay)
 376                         return MODE_PANEL;
 377         }
 378 
 379         return MODE_OK;
 380 }
 381 
 382 static struct drm_encoder *mdfld_dsi_connector_best_encoder(
 383                                 struct drm_connector *connector)
 384 {
 385         struct mdfld_dsi_connector *dsi_connector =
 386                                 mdfld_dsi_connector(connector);
 387         struct mdfld_dsi_config *dsi_config =
 388                                 mdfld_dsi_get_config(dsi_connector);
 389         return &dsi_config->encoder->base.base;
 390 }
 391 
 392 /*DSI connector funcs*/
 393 static const struct drm_connector_funcs mdfld_dsi_connector_funcs = {
 394         .dpms = drm_helper_connector_dpms,
 395         .detect = mdfld_dsi_connector_detect,
 396         .fill_modes = drm_helper_probe_single_connector_modes,
 397         .set_property = mdfld_dsi_connector_set_property,
 398         .destroy = mdfld_dsi_connector_destroy,
 399 };
 400 
 401 /*DSI connector helper funcs*/
 402 static const struct drm_connector_helper_funcs
 403         mdfld_dsi_connector_helper_funcs = {
 404         .get_modes = mdfld_dsi_connector_get_modes,
 405         .mode_valid = mdfld_dsi_connector_mode_valid,
 406         .best_encoder = mdfld_dsi_connector_best_encoder,
 407 };
 408 
 409 static int mdfld_dsi_get_default_config(struct drm_device *dev,
 410                                 struct mdfld_dsi_config *config, int pipe)
 411 {
 412         if (!dev || !config) {
 413                 DRM_ERROR("Invalid parameters");
 414                 return -EINVAL;
 415         }
 416 
 417         config->bpp = 24;
 418         if (mdfld_get_panel_type(dev, pipe) == TC35876X)
 419                 config->lane_count = 4;
 420         else
 421                 config->lane_count = 2;
 422         config->channel_num = 0;
 423 
 424         if (mdfld_get_panel_type(dev, pipe) == TMD_VID)
 425                 config->video_mode = MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE;
 426         else if (mdfld_get_panel_type(dev, pipe) == TC35876X)
 427                 config->video_mode =
 428                                 MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_EVENTS;
 429         else
 430                 config->video_mode = MDFLD_DSI_VIDEO_BURST_MODE;
 431 
 432         return 0;
 433 }
 434 
 435 int mdfld_dsi_panel_reset(int pipe)
 436 {
 437         unsigned gpio;
 438         int ret = 0;
 439 
 440         switch (pipe) {
 441         case 0:
 442                 gpio = 128;
 443                 break;
 444         case 2:
 445                 gpio = 34;
 446                 break;
 447         default:
 448                 DRM_ERROR("Invalid output\n");
 449                 return -EINVAL;
 450         }
 451 
 452         ret = gpio_request(gpio, "gfx");
 453         if (ret) {
 454                 DRM_ERROR("gpio_rqueset failed\n");
 455                 return ret;
 456         }
 457 
 458         ret = gpio_direction_output(gpio, 1);
 459         if (ret) {
 460                 DRM_ERROR("gpio_direction_output failed\n");
 461                 goto gpio_error;
 462         }
 463 
 464         gpio_get_value(128);
 465 
 466 gpio_error:
 467         if (gpio_is_valid(gpio))
 468                 gpio_free(gpio);
 469 
 470         return ret;
 471 }
 472 
 473 /*
 474  * MIPI output init
 475  * @dev drm device
 476  * @pipe pipe number. 0 or 2
 477  * @config
 478  *
 479  * Do the initialization of a MIPI output, including create DRM mode objects
 480  * initialization of DSI output on @pipe
 481  */
 482 void mdfld_dsi_output_init(struct drm_device *dev,
 483                            int pipe,
 484                            const struct panel_funcs *p_vid_funcs)
 485 {
 486         struct mdfld_dsi_config *dsi_config;
 487         struct mdfld_dsi_connector *dsi_connector;
 488         struct drm_connector *connector;
 489         struct mdfld_dsi_encoder *encoder;
 490         struct drm_psb_private *dev_priv = dev->dev_private;
 491         struct panel_info dsi_panel_info;
 492         u32 width_mm, height_mm;
 493 
 494         dev_dbg(dev->dev, "init DSI output on pipe %d\n", pipe);
 495 
 496         if (pipe != 0 && pipe != 2) {
 497                 DRM_ERROR("Invalid parameter\n");
 498                 return;
 499         }
 500 
 501         /*create a new connetor*/
 502         dsi_connector = kzalloc(sizeof(struct mdfld_dsi_connector), GFP_KERNEL);
 503         if (!dsi_connector) {
 504                 DRM_ERROR("No memory");
 505                 return;
 506         }
 507 
 508         dsi_connector->pipe =  pipe;
 509 
 510         dsi_config = kzalloc(sizeof(struct mdfld_dsi_config),
 511                         GFP_KERNEL);
 512         if (!dsi_config) {
 513                 DRM_ERROR("cannot allocate memory for DSI config\n");
 514                 goto dsi_init_err0;
 515         }
 516         mdfld_dsi_get_default_config(dev, dsi_config, pipe);
 517 
 518         dsi_connector->private = dsi_config;
 519 
 520         dsi_config->changed = 1;
 521         dsi_config->dev = dev;
 522 
 523         dsi_config->fixed_mode = p_vid_funcs->get_config_mode(dev);
 524         if (p_vid_funcs->get_panel_info(dev, pipe, &dsi_panel_info))
 525                         goto dsi_init_err0;
 526 
 527         width_mm = dsi_panel_info.width_mm;
 528         height_mm = dsi_panel_info.height_mm;
 529 
 530         dsi_config->mode = dsi_config->fixed_mode;
 531         dsi_config->connector = dsi_connector;
 532 
 533         if (!dsi_config->fixed_mode) {
 534                 DRM_ERROR("No pannel fixed mode was found\n");
 535                 goto dsi_init_err0;
 536         }
 537 
 538         if (pipe && dev_priv->dsi_configs[0]) {
 539                 dsi_config->dvr_ic_inited = 0;
 540                 dev_priv->dsi_configs[1] = dsi_config;
 541         } else if (pipe == 0) {
 542                 dsi_config->dvr_ic_inited = 1;
 543                 dev_priv->dsi_configs[0] = dsi_config;
 544         } else {
 545                 DRM_ERROR("Trying to init MIPI1 before MIPI0\n");
 546                 goto dsi_init_err0;
 547         }
 548 
 549 
 550         connector = &dsi_connector->base.base;
 551         dsi_connector->base.save = mdfld_dsi_connector_save;
 552         dsi_connector->base.restore = mdfld_dsi_connector_restore;
 553 
 554         drm_connector_init(dev, connector, &mdfld_dsi_connector_funcs,
 555                                                 DRM_MODE_CONNECTOR_LVDS);
 556         drm_connector_helper_add(connector, &mdfld_dsi_connector_helper_funcs);
 557 
 558         connector->display_info.subpixel_order = SubPixelHorizontalRGB;
 559         connector->display_info.width_mm = width_mm;
 560         connector->display_info.height_mm = height_mm;
 561         connector->interlace_allowed = false;
 562         connector->doublescan_allowed = false;
 563 
 564         /*attach properties*/
 565         drm_object_attach_property(&connector->base,
 566                                 dev->mode_config.scaling_mode_property,
 567                                 DRM_MODE_SCALE_FULLSCREEN);
 568         drm_object_attach_property(&connector->base,
 569                                 dev_priv->backlight_property,
 570                                 MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
 571 
 572         /*init DSI package sender on this output*/
 573         if (mdfld_dsi_pkg_sender_init(dsi_connector, pipe)) {
 574                 DRM_ERROR("Package Sender initialization failed on pipe %d\n",
 575                                                                         pipe);
 576                 goto dsi_init_err0;
 577         }
 578 
 579         encoder = mdfld_dsi_dpi_init(dev, dsi_connector, p_vid_funcs);
 580         if (!encoder) {
 581                 DRM_ERROR("Create DPI encoder failed\n");
 582                 goto dsi_init_err1;
 583         }
 584         encoder->private = dsi_config;
 585         dsi_config->encoder = encoder;
 586         encoder->base.type = (pipe == 0) ? INTEL_OUTPUT_MIPI :
 587                 INTEL_OUTPUT_MIPI2;
 588         drm_connector_register(connector);
 589         return;
 590 
 591         /*TODO: add code to destroy outputs on error*/
 592 dsi_init_err1:
 593         /*destroy sender*/
 594         mdfld_dsi_pkg_sender_destroy(dsi_connector->pkg_sender);
 595 
 596         drm_connector_cleanup(connector);
 597 
 598         kfree(dsi_config->fixed_mode);
 599         kfree(dsi_config);
 600 dsi_init_err0:
 601         kfree(dsi_connector);
 602 }

/* [<][>][^][v][top][bottom][index][help] */