linux/drivers/staging/gma500/cdv_intel_lvds.c
<<
>>
Prefs
   1/*
   2 * Copyright © 2006-2011 Intel Corporation
   3 *
   4 * This program is free software; you can redistribute it and/or modify it
   5 * under the terms and conditions of the GNU General Public License,
   6 * version 2, as published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope it will be useful, but WITHOUT
   9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  11 * more details.
  12 *
  13 * You should have received a copy of the GNU General Public License along with
  14 * this program; if not, write to the Free Software Foundation, Inc.,
  15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  16 *
  17 * Authors:
  18 *      Eric Anholt <eric@anholt.net>
  19 *      Dave Airlie <airlied@linux.ie>
  20 *      Jesse Barnes <jesse.barnes@intel.com>
  21 */
  22
  23#include <linux/i2c.h>
  24#include <linux/dmi.h>
  25#include <drm/drmP.h>
  26
  27#include "intel_bios.h"
  28#include "psb_drv.h"
  29#include "psb_intel_drv.h"
  30#include "psb_intel_reg.h"
  31#include "power.h"
  32#include <linux/pm_runtime.h>
  33#include "cdv_device.h"
  34
  35/**
  36 * LVDS I2C backlight control macros
  37 */
  38#define BRIGHTNESS_MAX_LEVEL 100
  39#define BRIGHTNESS_MASK 0xFF
  40#define BLC_I2C_TYPE    0x01
  41#define BLC_PWM_TYPT    0x02
  42
  43#define BLC_POLARITY_NORMAL 0
  44#define BLC_POLARITY_INVERSE 1
  45
  46#define PSB_BLC_MAX_PWM_REG_FREQ       (0xFFFE)
  47#define PSB_BLC_MIN_PWM_REG_FREQ        (0x2)
  48#define PSB_BLC_PWM_PRECISION_FACTOR    (10)
  49#define PSB_BACKLIGHT_PWM_CTL_SHIFT     (16)
  50#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
  51
  52struct cdv_intel_lvds_priv {
  53        /**
  54         * Saved LVDO output states
  55         */
  56        uint32_t savePP_ON;
  57        uint32_t savePP_OFF;
  58        uint32_t saveLVDS;
  59        uint32_t savePP_CONTROL;
  60        uint32_t savePP_CYCLE;
  61        uint32_t savePFIT_CONTROL;
  62        uint32_t savePFIT_PGM_RATIOS;
  63        uint32_t saveBLC_PWM_CTL;
  64};
  65
  66/*
  67 * Returns the maximum level of the backlight duty cycle field.
  68 */
  69static u32 cdv_intel_lvds_get_max_backlight(struct drm_device *dev)
  70{
  71        struct drm_psb_private *dev_priv = dev->dev_private;
  72        u32 retval;
  73
  74        if (gma_power_begin(dev, false)) {
  75                retval = ((REG_READ(BLC_PWM_CTL) &
  76                          BACKLIGHT_MODULATION_FREQ_MASK) >>
  77                          BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
  78
  79                gma_power_end(dev);
  80        } else
  81                retval = ((dev_priv->saveBLC_PWM_CTL &
  82                          BACKLIGHT_MODULATION_FREQ_MASK) >>
  83                          BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
  84
  85        return retval;
  86}
  87
  88/*
  89 * Set LVDS backlight level by I2C command
  90 */
  91static int cdv_lvds_i2c_set_brightness(struct drm_device *dev,
  92                                        unsigned int level)
  93{
  94        struct drm_psb_private *dev_priv = dev->dev_private;
  95        struct psb_intel_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus;
  96        u8 out_buf[2];
  97        unsigned int blc_i2c_brightness;
  98
  99        struct i2c_msg msgs[] = {
 100                {
 101                        .addr = lvds_i2c_bus->slave_addr,
 102                        .flags = 0,
 103                        .len = 2,
 104                        .buf = out_buf,
 105                }
 106        };
 107
 108        blc_i2c_brightness = BRIGHTNESS_MASK & ((unsigned int)level *
 109                             BRIGHTNESS_MASK /
 110                             BRIGHTNESS_MAX_LEVEL);
 111
 112        if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
 113                blc_i2c_brightness = BRIGHTNESS_MASK - blc_i2c_brightness;
 114
 115        out_buf[0] = dev_priv->lvds_bl->brightnesscmd;
 116        out_buf[1] = (u8)blc_i2c_brightness;
 117
 118        if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1)
 119                return 0;
 120
 121        DRM_ERROR("I2C transfer error\n");
 122        return -1;
 123}
 124
 125
 126static int cdv_lvds_pwm_set_brightness(struct drm_device *dev, int level)
 127{
 128        struct drm_psb_private *dev_priv = dev->dev_private;
 129
 130        u32 max_pwm_blc;
 131        u32 blc_pwm_duty_cycle;
 132
 133        max_pwm_blc = cdv_intel_lvds_get_max_backlight(dev);
 134
 135        /*BLC_PWM_CTL Should be initiated while backlight device init*/
 136        BUG_ON((max_pwm_blc & PSB_BLC_MAX_PWM_REG_FREQ) == 0);
 137
 138        blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL;
 139
 140        if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
 141                blc_pwm_duty_cycle = max_pwm_blc - blc_pwm_duty_cycle;
 142
 143        blc_pwm_duty_cycle &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
 144        REG_WRITE(BLC_PWM_CTL,
 145                  (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
 146                  (blc_pwm_duty_cycle));
 147
 148        return 0;
 149}
 150
 151/*
 152 * Set LVDS backlight level either by I2C or PWM
 153 */
 154void cdv_intel_lvds_set_brightness(struct drm_device *dev, int level)
 155{
 156        struct drm_psb_private *dev_priv = dev->dev_private;
 157
 158        if (!dev_priv->lvds_bl) {
 159                DRM_ERROR("NO LVDS Backlight Info\n");
 160                return;
 161        }
 162
 163        if (dev_priv->lvds_bl->type == BLC_I2C_TYPE)
 164                cdv_lvds_i2c_set_brightness(dev, level);
 165        else
 166                cdv_lvds_pwm_set_brightness(dev, level);
 167}
 168
 169/**
 170 * Sets the backlight level.
 171 *
 172 * level backlight level, from 0 to cdv_intel_lvds_get_max_backlight().
 173 */
 174static void cdv_intel_lvds_set_backlight(struct drm_device *dev, int level)
 175{
 176        struct drm_psb_private *dev_priv = dev->dev_private;
 177        u32 blc_pwm_ctl;
 178
 179        if (gma_power_begin(dev, false)) {
 180                blc_pwm_ctl =
 181                        REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
 182                REG_WRITE(BLC_PWM_CTL,
 183                                (blc_pwm_ctl |
 184                                (level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
 185                gma_power_end(dev);
 186        } else {
 187                blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL &
 188                                ~BACKLIGHT_DUTY_CYCLE_MASK;
 189                dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl |
 190                                        (level << BACKLIGHT_DUTY_CYCLE_SHIFT));
 191        }
 192}
 193
 194/**
 195 * Sets the power state for the panel.
 196 */
 197static void cdv_intel_lvds_set_power(struct drm_device *dev,
 198                                 struct psb_intel_output *output, bool on)
 199{
 200        u32 pp_status;
 201
 202        if (!gma_power_begin(dev, true))
 203                return;
 204
 205        if (on) {
 206                REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |
 207                          POWER_TARGET_ON);
 208                do {
 209                        pp_status = REG_READ(PP_STATUS);
 210                } while ((pp_status & PP_ON) == 0);
 211
 212                cdv_intel_lvds_set_backlight(dev,
 213                                         output->
 214                                         mode_dev->backlight_duty_cycle);
 215        } else {
 216                cdv_intel_lvds_set_backlight(dev, 0);
 217
 218                REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &
 219                          ~POWER_TARGET_ON);
 220                do {
 221                        pp_status = REG_READ(PP_STATUS);
 222                } while (pp_status & PP_ON);
 223        }
 224        gma_power_end(dev);
 225}
 226
 227static void cdv_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode)
 228{
 229        struct drm_device *dev = encoder->dev;
 230        struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
 231        if (mode == DRM_MODE_DPMS_ON)
 232                cdv_intel_lvds_set_power(dev, output, true);
 233        else
 234                cdv_intel_lvds_set_power(dev, output, false);
 235        /* XXX: We never power down the LVDS pairs. */
 236}
 237
 238static void cdv_intel_lvds_save(struct drm_connector *connector)
 239{
 240}
 241
 242static void cdv_intel_lvds_restore(struct drm_connector *connector)
 243{
 244}
 245
 246int cdv_intel_lvds_mode_valid(struct drm_connector *connector,
 247                                 struct drm_display_mode *mode)
 248{
 249        struct psb_intel_output *psb_intel_output =
 250                                to_psb_intel_output(connector);
 251        struct drm_display_mode *fixed_mode =
 252            psb_intel_output->mode_dev->panel_fixed_mode;
 253
 254        /* just in case */
 255        if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
 256                return MODE_NO_DBLESCAN;
 257
 258        /* just in case */
 259        if (mode->flags & DRM_MODE_FLAG_INTERLACE)
 260                return MODE_NO_INTERLACE;
 261
 262        if (fixed_mode) {
 263                if (mode->hdisplay > fixed_mode->hdisplay)
 264                        return MODE_PANEL;
 265                if (mode->vdisplay > fixed_mode->vdisplay)
 266                        return MODE_PANEL;
 267        }
 268        return MODE_OK;
 269}
 270
 271bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder,
 272                                  struct drm_display_mode *mode,
 273                                  struct drm_display_mode *adjusted_mode)
 274{
 275        struct psb_intel_mode_device *mode_dev =
 276            enc_to_psb_intel_output(encoder)->mode_dev;
 277        struct drm_device *dev = encoder->dev;
 278        struct drm_encoder *tmp_encoder;
 279        struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode;
 280
 281        /* Should never happen!! */
 282        list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list,
 283                            head) {
 284                if (tmp_encoder != encoder
 285                    && tmp_encoder->crtc == encoder->crtc) {
 286                        printk(KERN_ERR "Can't enable LVDS and another "
 287                               "encoder on the same pipe\n");
 288                        return false;
 289                }
 290        }
 291
 292        /*
 293         * If we have timings from the BIOS for the panel, put them in
 294         * to the adjusted mode.  The CRTC will be set up for this mode,
 295         * with the panel scaling set up to source from the H/VDisplay
 296         * of the original mode.
 297         */
 298        if (panel_fixed_mode != NULL) {
 299                adjusted_mode->hdisplay = panel_fixed_mode->hdisplay;
 300                adjusted_mode->hsync_start = panel_fixed_mode->hsync_start;
 301                adjusted_mode->hsync_end = panel_fixed_mode->hsync_end;
 302                adjusted_mode->htotal = panel_fixed_mode->htotal;
 303                adjusted_mode->vdisplay = panel_fixed_mode->vdisplay;
 304                adjusted_mode->vsync_start = panel_fixed_mode->vsync_start;
 305                adjusted_mode->vsync_end = panel_fixed_mode->vsync_end;
 306                adjusted_mode->vtotal = panel_fixed_mode->vtotal;
 307                adjusted_mode->clock = panel_fixed_mode->clock;
 308                drm_mode_set_crtcinfo(adjusted_mode,
 309                                      CRTC_INTERLACE_HALVE_V);
 310        }
 311
 312        /*
 313         * XXX: It would be nice to support lower refresh rates on the
 314         * panels to reduce power consumption, and perhaps match the
 315         * user's requested refresh rate.
 316         */
 317
 318        return true;
 319}
 320
 321static void cdv_intel_lvds_prepare(struct drm_encoder *encoder)
 322{
 323        struct drm_device *dev = encoder->dev;
 324        struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
 325        struct psb_intel_mode_device *mode_dev = output->mode_dev;
 326
 327        if (!gma_power_begin(dev, true))
 328                return;
 329
 330        mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
 331        mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL &
 332                                          BACKLIGHT_DUTY_CYCLE_MASK);
 333
 334        cdv_intel_lvds_set_power(dev, output, false);
 335
 336        gma_power_end(dev);
 337}
 338
 339static void cdv_intel_lvds_commit(struct drm_encoder *encoder)
 340{
 341        struct drm_device *dev = encoder->dev;
 342        struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
 343        struct psb_intel_mode_device *mode_dev = output->mode_dev;
 344
 345        if (mode_dev->backlight_duty_cycle == 0)
 346                mode_dev->backlight_duty_cycle =
 347                    cdv_intel_lvds_get_max_backlight(dev);
 348
 349        cdv_intel_lvds_set_power(dev, output, true);
 350}
 351
 352static void cdv_intel_lvds_mode_set(struct drm_encoder *encoder,
 353                                struct drm_display_mode *mode,
 354                                struct drm_display_mode *adjusted_mode)
 355{
 356        struct drm_device *dev = encoder->dev;
 357        struct drm_psb_private *dev_priv = dev->dev_private;
 358        u32 pfit_control;
 359
 360        /*
 361         * The LVDS pin pair will already have been turned on in the
 362         * cdv_intel_crtc_mode_set since it has a large impact on the DPLL
 363         * settings.
 364         */
 365
 366        /*
 367         * Enable automatic panel scaling so that non-native modes fill the
 368         * screen.  Should be enabled before the pipe is enabled, according to
 369         * register description and PRM.
 370         */
 371        if (mode->hdisplay != adjusted_mode->hdisplay ||
 372            mode->vdisplay != adjusted_mode->vdisplay)
 373                pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE |
 374                                HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR |
 375                                HORIZ_INTERP_BILINEAR);
 376        else
 377                pfit_control = 0;
 378
 379        if (dev_priv->lvds_dither)
 380                pfit_control |= PANEL_8TO6_DITHER_ENABLE;
 381
 382        REG_WRITE(PFIT_CONTROL, pfit_control);
 383}
 384
 385/**
 386 * Detect the LVDS connection.
 387 *
 388 * This always returns CONNECTOR_STATUS_CONNECTED.
 389 * This connector should only have
 390 * been set up if the LVDS was actually connected anyway.
 391 */
 392static enum drm_connector_status cdv_intel_lvds_detect(
 393                                struct drm_connector *connector, bool force)
 394{
 395        return connector_status_connected;
 396}
 397
 398/**
 399 * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
 400 */
 401static int cdv_intel_lvds_get_modes(struct drm_connector *connector)
 402{
 403        struct drm_device *dev = connector->dev;
 404        struct psb_intel_output *psb_intel_output =
 405                                        to_psb_intel_output(connector);
 406        struct psb_intel_mode_device *mode_dev =
 407                                        psb_intel_output->mode_dev;
 408        int ret;
 409
 410        ret = psb_intel_ddc_get_modes(psb_intel_output);
 411
 412        if (ret)
 413                return ret;
 414
 415        /* Didn't get an EDID, so
 416         * Set wide sync ranges so we get all modes
 417         * handed to valid_mode for checking
 418         */
 419        connector->display_info.min_vfreq = 0;
 420        connector->display_info.max_vfreq = 200;
 421        connector->display_info.min_hfreq = 0;
 422        connector->display_info.max_hfreq = 200;
 423        if (mode_dev->panel_fixed_mode != NULL) {
 424                struct drm_display_mode *mode =
 425                    drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
 426                drm_mode_probed_add(connector, mode);
 427                return 1;
 428        }
 429
 430        return 0;
 431}
 432
 433/**
 434 * cdv_intel_lvds_destroy - unregister and free LVDS structures
 435 * @connector: connector to free
 436 *
 437 * Unregister the DDC bus for this connector then free the driver private
 438 * structure.
 439 */
 440void cdv_intel_lvds_destroy(struct drm_connector *connector)
 441{
 442        struct psb_intel_output *psb_intel_output =
 443                                        to_psb_intel_output(connector);
 444
 445        if (psb_intel_output->ddc_bus)
 446                psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
 447        drm_sysfs_connector_remove(connector);
 448        drm_connector_cleanup(connector);
 449        kfree(connector);
 450}
 451
 452int cdv_intel_lvds_set_property(struct drm_connector *connector,
 453                                       struct drm_property *property,
 454                                       uint64_t value)
 455{
 456        struct drm_encoder *encoder = connector->encoder;
 457
 458        if (!strcmp(property->name, "scaling mode") && encoder) {
 459                struct psb_intel_crtc *crtc =
 460                                        to_psb_intel_crtc(encoder->crtc);
 461                uint64_t curValue;
 462
 463                if (!crtc)
 464                        return -1;
 465
 466                switch (value) {
 467                case DRM_MODE_SCALE_FULLSCREEN:
 468                        break;
 469                case DRM_MODE_SCALE_NO_SCALE:
 470                        break;
 471                case DRM_MODE_SCALE_ASPECT:
 472                        break;
 473                default:
 474                        return -1;
 475                }
 476
 477                if (drm_connector_property_get_value(connector,
 478                                                     property,
 479                                                     &curValue))
 480                        return -1;
 481
 482                if (curValue == value)
 483                        return 0;
 484
 485                if (drm_connector_property_set_value(connector,
 486                                                        property,
 487                                                        value))
 488                        return -1;
 489
 490                if (crtc->saved_mode.hdisplay != 0 &&
 491                    crtc->saved_mode.vdisplay != 0) {
 492                        if (!drm_crtc_helper_set_mode(encoder->crtc,
 493                                                      &crtc->saved_mode,
 494                                                      encoder->crtc->x,
 495                                                      encoder->crtc->y,
 496                                                      encoder->crtc->fb))
 497                                return -1;
 498                }
 499        } else if (!strcmp(property->name, "backlight") && encoder) {
 500                if (drm_connector_property_set_value(connector,
 501                                                        property,
 502                                                        value))
 503                        return -1;
 504                else {
 505#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
 506                        struct drm_psb_private *dev_priv =
 507                                                encoder->dev->dev_private;
 508                        struct backlight_device *bd =
 509                                                dev_priv->backlight_device;
 510                        bd->props.brightness = value;
 511                        backlight_update_status(bd);
 512#endif
 513                }
 514        } else if (!strcmp(property->name, "DPMS") && encoder) {
 515                struct drm_encoder_helper_funcs *helpers =
 516                                        encoder->helper_private;
 517                helpers->dpms(encoder, value);
 518        }
 519        return 0;
 520}
 521
 522static const struct drm_encoder_helper_funcs
 523                                        cdv_intel_lvds_helper_funcs = {
 524        .dpms = cdv_intel_lvds_encoder_dpms,
 525        .mode_fixup = cdv_intel_lvds_mode_fixup,
 526        .prepare = cdv_intel_lvds_prepare,
 527        .mode_set = cdv_intel_lvds_mode_set,
 528        .commit = cdv_intel_lvds_commit,
 529};
 530
 531static const struct drm_connector_helper_funcs
 532                                cdv_intel_lvds_connector_helper_funcs = {
 533        .get_modes = cdv_intel_lvds_get_modes,
 534        .mode_valid = cdv_intel_lvds_mode_valid,
 535        .best_encoder = psb_intel_best_encoder,
 536};
 537
 538static const struct drm_connector_funcs cdv_intel_lvds_connector_funcs = {
 539        .dpms = drm_helper_connector_dpms,
 540        .save = cdv_intel_lvds_save,
 541        .restore = cdv_intel_lvds_restore,
 542        .detect = cdv_intel_lvds_detect,
 543        .fill_modes = drm_helper_probe_single_connector_modes,
 544        .set_property = cdv_intel_lvds_set_property,
 545        .destroy = cdv_intel_lvds_destroy,
 546};
 547
 548
 549static void cdv_intel_lvds_enc_destroy(struct drm_encoder *encoder)
 550{
 551        drm_encoder_cleanup(encoder);
 552}
 553
 554const struct drm_encoder_funcs cdv_intel_lvds_enc_funcs = {
 555        .destroy = cdv_intel_lvds_enc_destroy,
 556};
 557
 558/**
 559 * cdv_intel_lvds_init - setup LVDS connectors on this device
 560 * @dev: drm device
 561 *
 562 * Create the connector, register the LVDS DDC bus, and try to figure out what
 563 * modes we can display on the LVDS panel (if present).
 564 */
 565void cdv_intel_lvds_init(struct drm_device *dev,
 566                     struct psb_intel_mode_device *mode_dev)
 567{
 568        struct psb_intel_output *psb_intel_output;
 569        struct cdv_intel_lvds_priv *lvds_priv;
 570        struct drm_connector *connector;
 571        struct drm_encoder *encoder;
 572        struct drm_display_mode *scan;
 573        struct drm_crtc *crtc;
 574        struct drm_psb_private *dev_priv = dev->dev_private;
 575        u32 lvds;
 576        int pipe;
 577
 578        psb_intel_output = kzalloc(sizeof(struct psb_intel_output) +
 579                        sizeof(struct cdv_intel_lvds_priv), GFP_KERNEL);
 580        if (!psb_intel_output)
 581                return;
 582
 583        lvds_priv = (struct cdv_intel_lvds_priv *)(psb_intel_output + 1);
 584
 585        psb_intel_output->dev_priv = lvds_priv;
 586
 587        psb_intel_output->mode_dev = mode_dev;
 588        connector = &psb_intel_output->base;
 589        encoder = &psb_intel_output->enc;
 590
 591
 592        drm_connector_init(dev, &psb_intel_output->base,
 593                           &cdv_intel_lvds_connector_funcs,
 594                           DRM_MODE_CONNECTOR_LVDS);
 595
 596        drm_encoder_init(dev, &psb_intel_output->enc,
 597                         &cdv_intel_lvds_enc_funcs,
 598                         DRM_MODE_ENCODER_LVDS);
 599
 600
 601        drm_mode_connector_attach_encoder(&psb_intel_output->base,
 602                                          &psb_intel_output->enc);
 603        psb_intel_output->type = INTEL_OUTPUT_LVDS;
 604
 605        drm_encoder_helper_add(encoder, &cdv_intel_lvds_helper_funcs);
 606        drm_connector_helper_add(connector,
 607                                 &cdv_intel_lvds_connector_helper_funcs);
 608        connector->display_info.subpixel_order = SubPixelHorizontalRGB;
 609        connector->interlace_allowed = false;
 610        connector->doublescan_allowed = false;
 611
 612        /*Attach connector properties*/
 613        drm_connector_attach_property(connector,
 614                                      dev->mode_config.scaling_mode_property,
 615                                      DRM_MODE_SCALE_FULLSCREEN);
 616        drm_connector_attach_property(connector,
 617                                      dev_priv->backlight_property,
 618                                      BRIGHTNESS_MAX_LEVEL);
 619
 620        /**
 621         * Set up I2C bus
 622         * FIXME: distroy i2c_bus when exit
 623         */
 624        psb_intel_output->i2c_bus = psb_intel_i2c_create(dev,
 625                                                         GPIOB,
 626                                                         "LVDSBLC_B");
 627        if (!psb_intel_output->i2c_bus) {
 628                dev_printk(KERN_ERR,
 629                        &dev->pdev->dev, "I2C bus registration failed.\n");
 630                goto failed_blc_i2c;
 631        }
 632        psb_intel_output->i2c_bus->slave_addr = 0x2C;
 633        dev_priv->lvds_i2c_bus =  psb_intel_output->i2c_bus;
 634
 635        /*
 636         * LVDS discovery:
 637         * 1) check for EDID on DDC
 638         * 2) check for VBT data
 639         * 3) check to see if LVDS is already on
 640         *    if none of the above, no panel
 641         * 4) make sure lid is open
 642         *    if closed, act like it's not there for now
 643         */
 644
 645        /* Set up the DDC bus. */
 646        psb_intel_output->ddc_bus = psb_intel_i2c_create(dev,
 647                                                         GPIOC,
 648                                                         "LVDSDDC_C");
 649        if (!psb_intel_output->ddc_bus) {
 650                dev_printk(KERN_ERR, &dev->pdev->dev,
 651                           "DDC bus registration " "failed.\n");
 652                goto failed_ddc;
 653        }
 654
 655        /*
 656         * Attempt to get the fixed panel mode from DDC.  Assume that the
 657         * preferred mode is the right one.
 658         */
 659        psb_intel_ddc_get_modes(psb_intel_output);
 660        list_for_each_entry(scan, &connector->probed_modes, head) {
 661                if (scan->type & DRM_MODE_TYPE_PREFERRED) {
 662                        mode_dev->panel_fixed_mode =
 663                            drm_mode_duplicate(dev, scan);
 664                        goto out;       /* FIXME: check for quirks */
 665                }
 666        }
 667
 668        /* Failed to get EDID, what about VBT? do we need this?*/
 669        if (dev_priv->lfp_lvds_vbt_mode) {
 670                mode_dev->panel_fixed_mode =
 671                        drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
 672                if (mode_dev->panel_fixed_mode) {
 673                        mode_dev->panel_fixed_mode->type |=
 674                                DRM_MODE_TYPE_PREFERRED;
 675                        goto out;       /* FIXME: check for quirks */
 676                }
 677        }
 678        /*
 679         * If we didn't get EDID, try checking if the panel is already turned
 680         * on.  If so, assume that whatever is currently programmed is the
 681         * correct mode.
 682         */
 683        lvds = REG_READ(LVDS);
 684        pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
 685        crtc = psb_intel_get_crtc_from_pipe(dev, pipe);
 686
 687        if (crtc && (lvds & LVDS_PORT_EN)) {
 688                mode_dev->panel_fixed_mode =
 689                    cdv_intel_crtc_mode_get(dev, crtc);
 690                if (mode_dev->panel_fixed_mode) {
 691                        mode_dev->panel_fixed_mode->type |=
 692                            DRM_MODE_TYPE_PREFERRED;
 693                        goto out;       /* FIXME: check for quirks */
 694                }
 695        }
 696
 697        /* If we still don't have a mode after all that, give up. */
 698        if (!mode_dev->panel_fixed_mode) {
 699                DRM_DEBUG
 700                        ("Found no modes on the lvds, ignoring the LVDS\n");
 701                goto failed_find;
 702        }
 703
 704out:
 705        drm_sysfs_connector_add(connector);
 706        return;
 707
 708failed_find:
 709        printk(KERN_ERR "Failed find\n");
 710        if (psb_intel_output->ddc_bus)
 711                psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
 712failed_ddc:
 713        printk(KERN_ERR "Failed DDC\n");
 714        if (psb_intel_output->i2c_bus)
 715                psb_intel_i2c_destroy(psb_intel_output->i2c_bus);
 716failed_blc_i2c:
 717        printk(KERN_ERR "Failed BLC\n");
 718        drm_encoder_cleanup(encoder);
 719        drm_connector_cleanup(connector);
 720        kfree(connector);
 721}
 722