root/drivers/gpu/drm/i915/display/dvo_ivch.c

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

DEFINITIONS

This source file includes following definitions.
  1. ivch_read
  2. ivch_write
  3. ivch_init
  4. ivch_detect
  5. ivch_mode_valid
  6. ivch_reset
  7. ivch_dpms
  8. ivch_get_hw_state
  9. ivch_mode_set
  10. ivch_dump_regs
  11. ivch_destroy

   1 /*
   2  * Copyright © 2006 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  *    Eric Anholt <eric@anholt.net>
  25  *    Thomas Richter <thor@math.tu-berlin.de>
  26  *
  27  * Minor modifications (Dithering enable):
  28  *    Thomas Richter <thor@math.tu-berlin.de>
  29  *
  30  */
  31 
  32 #include "intel_display_types.h"
  33 #include "intel_dvo_dev.h"
  34 
  35 /*
  36  * register definitions for the i82807aa.
  37  *
  38  * Documentation on this chipset can be found in datasheet #29069001 at
  39  * intel.com.
  40  */
  41 
  42 /*
  43  * VCH Revision & GMBus Base Addr
  44  */
  45 #define VR00            0x00
  46 # define VR00_BASE_ADDRESS_MASK         0x007f
  47 
  48 /*
  49  * Functionality Enable
  50  */
  51 #define VR01            0x01
  52 
  53 /*
  54  * Enable the panel fitter
  55  */
  56 # define VR01_PANEL_FIT_ENABLE          (1 << 3)
  57 /*
  58  * Enables the LCD display.
  59  *
  60  * This must not be set while VR01_DVO_BYPASS_ENABLE is set.
  61  */
  62 # define VR01_LCD_ENABLE                (1 << 2)
  63 /* Enables the DVO repeater. */
  64 # define VR01_DVO_BYPASS_ENABLE         (1 << 1)
  65 /* Enables the DVO clock */
  66 # define VR01_DVO_ENABLE                (1 << 0)
  67 /* Enable dithering for 18bpp panels. Not documented. */
  68 # define VR01_DITHER_ENABLE             (1 << 4)
  69 
  70 /*
  71  * LCD Interface Format
  72  */
  73 #define VR10            0x10
  74 /* Enables LVDS output instead of CMOS */
  75 # define VR10_LVDS_ENABLE               (1 << 4)
  76 /* Enables 18-bit LVDS output. */
  77 # define VR10_INTERFACE_1X18            (0 << 2)
  78 /* Enables 24-bit LVDS or CMOS output */
  79 # define VR10_INTERFACE_1X24            (1 << 2)
  80 /* Enables 2x18-bit LVDS or CMOS output. */
  81 # define VR10_INTERFACE_2X18            (2 << 2)
  82 /* Enables 2x24-bit LVDS output */
  83 # define VR10_INTERFACE_2X24            (3 << 2)
  84 /* Mask that defines the depth of the pipeline */
  85 # define VR10_INTERFACE_DEPTH_MASK      (3 << 2)
  86 
  87 /*
  88  * VR20 LCD Horizontal Display Size
  89  */
  90 #define VR20    0x20
  91 
  92 /*
  93  * LCD Vertical Display Size
  94  */
  95 #define VR21    0x21
  96 
  97 /*
  98  * Panel power down status
  99  */
 100 #define VR30            0x30
 101 /* Read only bit indicating that the panel is not in a safe poweroff state. */
 102 # define VR30_PANEL_ON                  (1 << 15)
 103 
 104 #define VR40            0x40
 105 # define VR40_STALL_ENABLE              (1 << 13)
 106 # define VR40_VERTICAL_INTERP_ENABLE    (1 << 12)
 107 # define VR40_ENHANCED_PANEL_FITTING    (1 << 11)
 108 # define VR40_HORIZONTAL_INTERP_ENABLE  (1 << 10)
 109 # define VR40_AUTO_RATIO_ENABLE         (1 << 9)
 110 # define VR40_CLOCK_GATING_ENABLE       (1 << 8)
 111 
 112 /*
 113  * Panel Fitting Vertical Ratio
 114  * (((image_height - 1) << 16) / ((panel_height - 1))) >> 2
 115  */
 116 #define VR41            0x41
 117 
 118 /*
 119  * Panel Fitting Horizontal Ratio
 120  * (((image_width - 1) << 16) / ((panel_width - 1))) >> 2
 121  */
 122 #define VR42            0x42
 123 
 124 /*
 125  * Horizontal Image Size
 126  */
 127 #define VR43            0x43
 128 
 129 /* VR80 GPIO 0
 130  */
 131 #define VR80        0x80
 132 #define VR81        0x81
 133 #define VR82        0x82
 134 #define VR83        0x83
 135 #define VR84        0x84
 136 #define VR85        0x85
 137 #define VR86        0x86
 138 #define VR87        0x87
 139 
 140 /* VR88 GPIO 8
 141  */
 142 #define VR88        0x88
 143 
 144 /* Graphics BIOS scratch 0
 145  */
 146 #define VR8E        0x8E
 147 # define VR8E_PANEL_TYPE_MASK           (0xf << 0)
 148 # define VR8E_PANEL_INTERFACE_CMOS      (0 << 4)
 149 # define VR8E_PANEL_INTERFACE_LVDS      (1 << 4)
 150 # define VR8E_FORCE_DEFAULT_PANEL       (1 << 5)
 151 
 152 /* Graphics BIOS scratch 1
 153  */
 154 #define VR8F        0x8F
 155 # define VR8F_VCH_PRESENT               (1 << 0)
 156 # define VR8F_DISPLAY_CONN              (1 << 1)
 157 # define VR8F_POWER_MASK                (0x3c)
 158 # define VR8F_POWER_POS                 (2)
 159 
 160 /* Some Bios implementations do not restore the DVO state upon
 161  * resume from standby. Thus, this driver has to handle it
 162  * instead. The following list contains all registers that
 163  * require saving.
 164  */
 165 static const u16 backup_addresses[] = {
 166         0x11, 0x12,
 167         0x18, 0x19, 0x1a, 0x1f,
 168         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
 169         0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
 170         0x8e, 0x8f,
 171         0x10            /* this must come last */
 172 };
 173 
 174 
 175 struct ivch_priv {
 176         bool quiet;
 177 
 178         u16 width, height;
 179 
 180         /* Register backup */
 181 
 182         u16 reg_backup[ARRAY_SIZE(backup_addresses)];
 183 };
 184 
 185 
 186 static void ivch_dump_regs(struct intel_dvo_device *dvo);
 187 /*
 188  * Reads a register on the ivch.
 189  *
 190  * Each of the 256 registers are 16 bits long.
 191  */
 192 static bool ivch_read(struct intel_dvo_device *dvo, int addr, u16 *data)
 193 {
 194         struct ivch_priv *priv = dvo->dev_priv;
 195         struct i2c_adapter *adapter = dvo->i2c_bus;
 196         u8 out_buf[1];
 197         u8 in_buf[2];
 198 
 199         struct i2c_msg msgs[] = {
 200                 {
 201                         .addr = dvo->slave_addr,
 202                         .flags = I2C_M_RD,
 203                         .len = 0,
 204                 },
 205                 {
 206                         .addr = 0,
 207                         .flags = I2C_M_NOSTART,
 208                         .len = 1,
 209                         .buf = out_buf,
 210                 },
 211                 {
 212                         .addr = dvo->slave_addr,
 213                         .flags = I2C_M_RD | I2C_M_NOSTART,
 214                         .len = 2,
 215                         .buf = in_buf,
 216                 }
 217         };
 218 
 219         out_buf[0] = addr;
 220 
 221         if (i2c_transfer(adapter, msgs, 3) == 3) {
 222                 *data = (in_buf[1] << 8) | in_buf[0];
 223                 return true;
 224         }
 225 
 226         if (!priv->quiet) {
 227                 DRM_DEBUG_KMS("Unable to read register 0x%02x from "
 228                                 "%s:%02x.\n",
 229                           addr, adapter->name, dvo->slave_addr);
 230         }
 231         return false;
 232 }
 233 
 234 /* Writes a 16-bit register on the ivch */
 235 static bool ivch_write(struct intel_dvo_device *dvo, int addr, u16 data)
 236 {
 237         struct ivch_priv *priv = dvo->dev_priv;
 238         struct i2c_adapter *adapter = dvo->i2c_bus;
 239         u8 out_buf[3];
 240         struct i2c_msg msg = {
 241                 .addr = dvo->slave_addr,
 242                 .flags = 0,
 243                 .len = 3,
 244                 .buf = out_buf,
 245         };
 246 
 247         out_buf[0] = addr;
 248         out_buf[1] = data & 0xff;
 249         out_buf[2] = data >> 8;
 250 
 251         if (i2c_transfer(adapter, &msg, 1) == 1)
 252                 return true;
 253 
 254         if (!priv->quiet) {
 255                 DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n",
 256                           addr, adapter->name, dvo->slave_addr);
 257         }
 258 
 259         return false;
 260 }
 261 
 262 /* Probes the given bus and slave address for an ivch */
 263 static bool ivch_init(struct intel_dvo_device *dvo,
 264                       struct i2c_adapter *adapter)
 265 {
 266         struct ivch_priv *priv;
 267         u16 temp;
 268         int i;
 269 
 270         priv = kzalloc(sizeof(struct ivch_priv), GFP_KERNEL);
 271         if (priv == NULL)
 272                 return false;
 273 
 274         dvo->i2c_bus = adapter;
 275         dvo->dev_priv = priv;
 276         priv->quiet = true;
 277 
 278         if (!ivch_read(dvo, VR00, &temp))
 279                 goto out;
 280         priv->quiet = false;
 281 
 282         /* Since the identification bits are probably zeroes, which doesn't seem
 283          * very unique, check that the value in the base address field matches
 284          * the address it's responding on.
 285          */
 286         if ((temp & VR00_BASE_ADDRESS_MASK) != dvo->slave_addr) {
 287                 DRM_DEBUG_KMS("ivch detect failed due to address mismatch "
 288                           "(%d vs %d)\n",
 289                           (temp & VR00_BASE_ADDRESS_MASK), dvo->slave_addr);
 290                 goto out;
 291         }
 292 
 293         ivch_read(dvo, VR20, &priv->width);
 294         ivch_read(dvo, VR21, &priv->height);
 295 
 296         /* Make a backup of the registers to be able to restore them
 297          * upon suspend.
 298          */
 299         for (i = 0; i < ARRAY_SIZE(backup_addresses); i++)
 300                 ivch_read(dvo, backup_addresses[i], priv->reg_backup + i);
 301 
 302         ivch_dump_regs(dvo);
 303 
 304         return true;
 305 
 306 out:
 307         kfree(priv);
 308         return false;
 309 }
 310 
 311 static enum drm_connector_status ivch_detect(struct intel_dvo_device *dvo)
 312 {
 313         return connector_status_connected;
 314 }
 315 
 316 static enum drm_mode_status ivch_mode_valid(struct intel_dvo_device *dvo,
 317                                             struct drm_display_mode *mode)
 318 {
 319         if (mode->clock > 112000)
 320                 return MODE_CLOCK_HIGH;
 321 
 322         return MODE_OK;
 323 }
 324 
 325 /* Restore the DVO registers after a resume
 326  * from RAM. Registers have been saved during
 327  * the initialization.
 328  */
 329 static void ivch_reset(struct intel_dvo_device *dvo)
 330 {
 331         struct ivch_priv *priv = dvo->dev_priv;
 332         int i;
 333 
 334         DRM_DEBUG_KMS("Resetting the IVCH registers\n");
 335 
 336         ivch_write(dvo, VR10, 0x0000);
 337 
 338         for (i = 0; i < ARRAY_SIZE(backup_addresses); i++)
 339                 ivch_write(dvo, backup_addresses[i], priv->reg_backup[i]);
 340 }
 341 
 342 /* Sets the power state of the panel connected to the ivch */
 343 static void ivch_dpms(struct intel_dvo_device *dvo, bool enable)
 344 {
 345         int i;
 346         u16 vr01, vr30, backlight;
 347 
 348         ivch_reset(dvo);
 349 
 350         /* Set the new power state of the panel. */
 351         if (!ivch_read(dvo, VR01, &vr01))
 352                 return;
 353 
 354         if (enable)
 355                 backlight = 1;
 356         else
 357                 backlight = 0;
 358 
 359         ivch_write(dvo, VR80, backlight);
 360 
 361         if (enable)
 362                 vr01 |= VR01_LCD_ENABLE | VR01_DVO_ENABLE;
 363         else
 364                 vr01 &= ~(VR01_LCD_ENABLE | VR01_DVO_ENABLE);
 365 
 366         ivch_write(dvo, VR01, vr01);
 367 
 368         /* Wait for the panel to make its state transition */
 369         for (i = 0; i < 100; i++) {
 370                 if (!ivch_read(dvo, VR30, &vr30))
 371                         break;
 372 
 373                 if (((vr30 & VR30_PANEL_ON) != 0) == enable)
 374                         break;
 375                 udelay(1000);
 376         }
 377         /* wait some more; vch may fail to resync sometimes without this */
 378         udelay(16 * 1000);
 379 }
 380 
 381 static bool ivch_get_hw_state(struct intel_dvo_device *dvo)
 382 {
 383         u16 vr01;
 384 
 385         ivch_reset(dvo);
 386 
 387         /* Set the new power state of the panel. */
 388         if (!ivch_read(dvo, VR01, &vr01))
 389                 return false;
 390 
 391         if (vr01 & VR01_LCD_ENABLE)
 392                 return true;
 393         else
 394                 return false;
 395 }
 396 
 397 static void ivch_mode_set(struct intel_dvo_device *dvo,
 398                           const struct drm_display_mode *mode,
 399                           const struct drm_display_mode *adjusted_mode)
 400 {
 401         struct ivch_priv *priv = dvo->dev_priv;
 402         u16 vr40 = 0;
 403         u16 vr01 = 0;
 404         u16 vr10;
 405 
 406         ivch_reset(dvo);
 407 
 408         vr10 = priv->reg_backup[ARRAY_SIZE(backup_addresses) - 1];
 409 
 410         /* Enable dithering for 18 bpp pipelines */
 411         vr10 &= VR10_INTERFACE_DEPTH_MASK;
 412         if (vr10 == VR10_INTERFACE_2X18 || vr10 == VR10_INTERFACE_1X18)
 413                 vr01 = VR01_DITHER_ENABLE;
 414 
 415         vr40 = (VR40_STALL_ENABLE | VR40_VERTICAL_INTERP_ENABLE |
 416                 VR40_HORIZONTAL_INTERP_ENABLE);
 417 
 418         if (mode->hdisplay != adjusted_mode->crtc_hdisplay ||
 419             mode->vdisplay != adjusted_mode->crtc_vdisplay) {
 420                 u16 x_ratio, y_ratio;
 421 
 422                 vr01 |= VR01_PANEL_FIT_ENABLE;
 423                 vr40 |= VR40_CLOCK_GATING_ENABLE;
 424                 x_ratio = (((mode->hdisplay - 1) << 16) /
 425                            (adjusted_mode->crtc_hdisplay - 1)) >> 2;
 426                 y_ratio = (((mode->vdisplay - 1) << 16) /
 427                            (adjusted_mode->crtc_vdisplay - 1)) >> 2;
 428                 ivch_write(dvo, VR42, x_ratio);
 429                 ivch_write(dvo, VR41, y_ratio);
 430         } else {
 431                 vr01 &= ~VR01_PANEL_FIT_ENABLE;
 432                 vr40 &= ~VR40_CLOCK_GATING_ENABLE;
 433         }
 434         vr40 &= ~VR40_AUTO_RATIO_ENABLE;
 435 
 436         ivch_write(dvo, VR01, vr01);
 437         ivch_write(dvo, VR40, vr40);
 438 }
 439 
 440 static void ivch_dump_regs(struct intel_dvo_device *dvo)
 441 {
 442         u16 val;
 443 
 444         ivch_read(dvo, VR00, &val);
 445         DRM_DEBUG_KMS("VR00: 0x%04x\n", val);
 446         ivch_read(dvo, VR01, &val);
 447         DRM_DEBUG_KMS("VR01: 0x%04x\n", val);
 448         ivch_read(dvo, VR10, &val);
 449         DRM_DEBUG_KMS("VR10: 0x%04x\n", val);
 450         ivch_read(dvo, VR30, &val);
 451         DRM_DEBUG_KMS("VR30: 0x%04x\n", val);
 452         ivch_read(dvo, VR40, &val);
 453         DRM_DEBUG_KMS("VR40: 0x%04x\n", val);
 454 
 455         /* GPIO registers */
 456         ivch_read(dvo, VR80, &val);
 457         DRM_DEBUG_KMS("VR80: 0x%04x\n", val);
 458         ivch_read(dvo, VR81, &val);
 459         DRM_DEBUG_KMS("VR81: 0x%04x\n", val);
 460         ivch_read(dvo, VR82, &val);
 461         DRM_DEBUG_KMS("VR82: 0x%04x\n", val);
 462         ivch_read(dvo, VR83, &val);
 463         DRM_DEBUG_KMS("VR83: 0x%04x\n", val);
 464         ivch_read(dvo, VR84, &val);
 465         DRM_DEBUG_KMS("VR84: 0x%04x\n", val);
 466         ivch_read(dvo, VR85, &val);
 467         DRM_DEBUG_KMS("VR85: 0x%04x\n", val);
 468         ivch_read(dvo, VR86, &val);
 469         DRM_DEBUG_KMS("VR86: 0x%04x\n", val);
 470         ivch_read(dvo, VR87, &val);
 471         DRM_DEBUG_KMS("VR87: 0x%04x\n", val);
 472         ivch_read(dvo, VR88, &val);
 473         DRM_DEBUG_KMS("VR88: 0x%04x\n", val);
 474 
 475         /* Scratch register 0 - AIM Panel type */
 476         ivch_read(dvo, VR8E, &val);
 477         DRM_DEBUG_KMS("VR8E: 0x%04x\n", val);
 478 
 479         /* Scratch register 1 - Status register */
 480         ivch_read(dvo, VR8F, &val);
 481         DRM_DEBUG_KMS("VR8F: 0x%04x\n", val);
 482 }
 483 
 484 static void ivch_destroy(struct intel_dvo_device *dvo)
 485 {
 486         struct ivch_priv *priv = dvo->dev_priv;
 487 
 488         if (priv) {
 489                 kfree(priv);
 490                 dvo->dev_priv = NULL;
 491         }
 492 }
 493 
 494 const struct intel_dvo_dev_ops ivch_ops = {
 495         .init = ivch_init,
 496         .dpms = ivch_dpms,
 497         .get_hw_state = ivch_get_hw_state,
 498         .mode_valid = ivch_mode_valid,
 499         .mode_set = ivch_mode_set,
 500         .detect = ivch_detect,
 501         .dump_regs = ivch_dump_regs,
 502         .destroy = ivch_destroy,
 503 };

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