Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/gpu/drm/radeon/   (Linux Kernel Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 143 kB image not shown  

Quelle  radeon_atombios.c   Sprache: C

 

/*
 * Copyright 2007-8 Advanced Micro Devices, Inc.
 * Copyright 2008 Red Hat Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors: Dave Airlie
 *          Alex Deucher
 */


#include <linux/pci.h>

#include <drm/drm_device.h>
#include <drm/drm_edid.h>
#include <drm/radeon_drm.h>

#include "radeon.h"

#include "atom.h"
#include "atom-bits.h"
#include "radeon_asic.h"
#include "radeon_atombios.h"
#include "radeon_legacy_encoders.h"

union atom_supported_devices {
 struct _ATOM_SUPPORTED_DEVICES_INFO info;
 struct _ATOM_SUPPORTED_DEVICES_INFO_2 info_2;
 struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 info_2d1;
};

static void radeon_lookup_i2c_gpio_quirks(struct radeon_device *rdev,
       ATOM_GPIO_I2C_ASSIGMENT *gpio,
       u8 index)
{
 /* r4xx mask is technically not used by the hw, so patch in the legacy mask bits */
 if ((rdev->family == CHIP_R420) ||
     (rdev->family == CHIP_R423) ||
     (rdev->family == CHIP_RV410)) {
  if ((le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0018) ||
      (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0019) ||
      (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x001a)) {
   gpio->ucClkMaskShift = 0x19;
   gpio->ucDataMaskShift = 0x18;
  }
 }

 /* some evergreen boards have bad data for this entry */
 if (ASIC_IS_DCE4(rdev)) {
  if ((index == 7) &&
      (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) &&
      (gpio->sucI2cId.ucAccess == 0)) {
   gpio->sucI2cId.ucAccess = 0x97;
   gpio->ucDataMaskShift = 8;
   gpio->ucDataEnShift = 8;
   gpio->ucDataY_Shift = 8;
   gpio->ucDataA_Shift = 8;
  }
 }

 /* some DCE3 boards have bad data for this entry */
 if (ASIC_IS_DCE3(rdev)) {
  if ((index == 4) &&
      (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) &&
      (gpio->sucI2cId.ucAccess == 0x94))
   gpio->sucI2cId.ucAccess = 0x14;
 }
}

static struct radeon_i2c_bus_rec radeon_get_bus_rec_for_i2c_gpio(ATOM_GPIO_I2C_ASSIGMENT *gpio)
{
 struct radeon_i2c_bus_rec i2c;

 memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));

 i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
 i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
 i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
 i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
 i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
 i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
 i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
 i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
 i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
 i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
 i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
 i2c.en_data_mask = (1 << gpio->ucDataEnShift);
 i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
 i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
 i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
 i2c.a_data_mask = (1 << gpio->ucDataA_Shift);

 if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
  i2c.hw_capable = true;
 else
  i2c.hw_capable = false;

 if (gpio->sucI2cId.ucAccess == 0xa0)
  i2c.mm_i2c = true;
 else
  i2c.mm_i2c = false;

 i2c.i2c_id = gpio->sucI2cId.ucAccess;

 if (i2c.mask_clk_reg)
  i2c.valid = true;
 else
  i2c.valid = false;

 return i2c;
}

static struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rdev,
              uint8_t id)
{
 struct atom_context *ctx = rdev->mode_info.atom_context;
 ATOM_GPIO_I2C_ASSIGMENT *gpio;
 struct radeon_i2c_bus_rec i2c;
 int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info);
 struct _ATOM_GPIO_I2C_INFO *i2c_info;
 uint16_t data_offset, size;
 int i, num_indices;

 memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
 i2c.valid = false;

 if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
  i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);

  num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
   sizeof(ATOM_GPIO_I2C_ASSIGMENT);

  gpio = &i2c_info->asGPIO_Info[0];
  for (i = 0; i < num_indices; i++) {

   radeon_lookup_i2c_gpio_quirks(rdev, gpio, i);

   if (gpio->sucI2cId.ucAccess == id) {
    i2c = radeon_get_bus_rec_for_i2c_gpio(gpio);
    break;
   }
   gpio = (ATOM_GPIO_I2C_ASSIGMENT *)
    ((u8 *)gpio + sizeof(ATOM_GPIO_I2C_ASSIGMENT));
  }
 }

 return i2c;
}

void radeon_atombios_i2c_init(struct radeon_device *rdev)
{
 struct atom_context *ctx = rdev->mode_info.atom_context;
 ATOM_GPIO_I2C_ASSIGMENT *gpio;
 struct radeon_i2c_bus_rec i2c;
 int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info);
 struct _ATOM_GPIO_I2C_INFO *i2c_info;
 uint16_t data_offset, size;
 int i, num_indices;
 char stmp[32];

 if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
  i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);

  num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
   sizeof(ATOM_GPIO_I2C_ASSIGMENT);

  gpio = &i2c_info->asGPIO_Info[0];
  for (i = 0; i < num_indices; i++) {
   radeon_lookup_i2c_gpio_quirks(rdev, gpio, i);

   i2c = radeon_get_bus_rec_for_i2c_gpio(gpio);

   if (i2c.valid) {
    sprintf(stmp, "0x%x", i2c.i2c_id);
    rdev->i2c_bus[i] = radeon_i2c_create(rdev_to_drm(rdev), &i2c, stmp);
   }
   gpio = (ATOM_GPIO_I2C_ASSIGMENT *)
    ((u8 *)gpio + sizeof(ATOM_GPIO_I2C_ASSIGMENT));
  }
 }
}

struct radeon_gpio_rec radeon_atombios_lookup_gpio(struct radeon_device *rdev,
         u8 id)
{
 struct atom_context *ctx = rdev->mode_info.atom_context;
 struct radeon_gpio_rec gpio;
 int index = GetIndexIntoMasterTable(DATA, GPIO_Pin_LUT);
 struct _ATOM_GPIO_PIN_LUT *gpio_info;
 ATOM_GPIO_PIN_ASSIGNMENT *pin;
 u16 data_offset, size;
 int i, num_indices;

 memset(&gpio, 0, sizeof(struct radeon_gpio_rec));
 gpio.valid = false;

 if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
  gpio_info = (struct _ATOM_GPIO_PIN_LUT *)(ctx->bios + data_offset);

  num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
   sizeof(ATOM_GPIO_PIN_ASSIGNMENT);

  pin = gpio_info->asGPIO_Pin;
  for (i = 0; i < num_indices; i++) {
   if (id == pin->ucGPIO_ID) {
    gpio.id = pin->ucGPIO_ID;
    gpio.reg = le16_to_cpu(pin->usGpioPin_AIndex) * 4;
    gpio.shift = pin->ucGpioPinBitShift;
    gpio.mask = (1 << pin->ucGpioPinBitShift);
    gpio.valid = true;
    break;
   }
   pin = (ATOM_GPIO_PIN_ASSIGNMENT *)
    ((u8 *)pin + sizeof(ATOM_GPIO_PIN_ASSIGNMENT));
  }
 }

 return gpio;
}

static struct radeon_hpd radeon_atom_get_hpd_info_from_gpio(struct radeon_device *rdev,
           struct radeon_gpio_rec *gpio)
{
 struct radeon_hpd hpd;
 u32 reg;

 memset(&hpd, 0, sizeof(struct radeon_hpd));

 if (ASIC_IS_DCE6(rdev))
  reg = SI_DC_GPIO_HPD_A;
 else if (ASIC_IS_DCE4(rdev))
  reg = EVERGREEN_DC_GPIO_HPD_A;
 else
  reg = AVIVO_DC_GPIO_HPD_A;

 hpd.gpio = *gpio;
 if (gpio->reg == reg) {
  switch(gpio->mask) {
  case (1 << 0):
   hpd.hpd = RADEON_HPD_1;
   break;
  case (1 << 8):
   hpd.hpd = RADEON_HPD_2;
   break;
  case (1 << 16):
   hpd.hpd = RADEON_HPD_3;
   break;
  case (1 << 24):
   hpd.hpd = RADEON_HPD_4;
   break;
  case (1 << 26):
   hpd.hpd = RADEON_HPD_5;
   break;
  case (1 << 28):
   hpd.hpd = RADEON_HPD_6;
   break;
  default:
   hpd.hpd = RADEON_HPD_NONE;
   break;
  }
 } else
  hpd.hpd = RADEON_HPD_NONE;
 return hpd;
}

static bool radeon_atom_apply_quirks(struct drm_device *dev,
         uint32_t supported_device,
         int *connector_type,
         struct radeon_i2c_bus_rec *i2c_bus,
         uint16_t *line_mux,
         struct radeon_hpd *hpd)
{
 struct pci_dev *pdev = to_pci_dev(dev->dev);

 /* Asus M2A-VM HDMI board lists the DVI port as HDMI */
 if ((pdev->device == 0x791e) &&
     (pdev->subsystem_vendor == 0x1043) &&
     (pdev->subsystem_device == 0x826d)) {
  if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
      (supported_device == ATOM_DEVICE_DFP3_SUPPORT))
   *connector_type = DRM_MODE_CONNECTOR_DVID;
 }

 /* Asrock RS600 board lists the DVI port as HDMI */
 if ((pdev->device == 0x7941) &&
     (pdev->subsystem_vendor == 0x1849) &&
     (pdev->subsystem_device == 0x7941)) {
  if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
      (supported_device == ATOM_DEVICE_DFP3_SUPPORT))
   *connector_type = DRM_MODE_CONNECTOR_DVID;
 }

 /* MSI K9A2GM V2/V3 board has no HDMI or DVI */
 if ((pdev->device == 0x796e) &&
     (pdev->subsystem_vendor == 0x1462) &&
     (pdev->subsystem_device == 0x7302)) {
  if ((supported_device == ATOM_DEVICE_DFP2_SUPPORT) ||
      (supported_device == ATOM_DEVICE_DFP3_SUPPORT))
   return false;
 }

 /* a-bit f-i90hd - ciaranm on #radeonhd - this board has no DVI */
 if ((pdev->device == 0x7941) &&
     (pdev->subsystem_vendor == 0x147b) &&
     (pdev->subsystem_device == 0x2412)) {
  if (*connector_type == DRM_MODE_CONNECTOR_DVII)
   return false;
 }

 /* Falcon NW laptop lists vga ddc line for LVDS */
 if ((pdev->device == 0x5653) &&
     (pdev->subsystem_vendor == 0x1462) &&
     (pdev->subsystem_device == 0x0291)) {
  if (*connector_type == DRM_MODE_CONNECTOR_LVDS) {
   i2c_bus->valid = false;
   *line_mux = 53;
  }
 }

 /* HIS X1300 is DVI+VGA, not DVI+DVI */
 if ((pdev->device == 0x7146) &&
     (pdev->subsystem_vendor == 0x17af) &&
     (pdev->subsystem_device == 0x2058)) {
  if (supported_device == ATOM_DEVICE_DFP1_SUPPORT)
   return false;
 }

 /* Gigabyte X1300 is DVI+VGA, not DVI+DVI */
 if ((pdev->device == 0x7142) &&
     (pdev->subsystem_vendor == 0x1458) &&
     (pdev->subsystem_device == 0x2134)) {
  if (supported_device == ATOM_DEVICE_DFP1_SUPPORT)
   return false;
 }


 /* Funky macbooks */
 if ((pdev->device == 0x71C5) &&
     (pdev->subsystem_vendor == 0x106b) &&
     (pdev->subsystem_device == 0x0080)) {
  if ((supported_device == ATOM_DEVICE_CRT1_SUPPORT) ||
      (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
   return false;
  if (supported_device == ATOM_DEVICE_CRT2_SUPPORT)
   *line_mux = 0x90;
 }

 /* mac rv630, rv730, others */
 if ((supported_device == ATOM_DEVICE_TV1_SUPPORT) &&
     (*connector_type == DRM_MODE_CONNECTOR_DVII)) {
  *connector_type = DRM_MODE_CONNECTOR_9PinDIN;
  *line_mux = CONNECTOR_7PIN_DIN_ENUM_ID1;
 }

 /* ASUS HD 3600 XT board lists the DVI port as HDMI */
 if ((pdev->device == 0x9598) &&
     (pdev->subsystem_vendor == 0x1043) &&
     (pdev->subsystem_device == 0x01da)) {
  if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
   *connector_type = DRM_MODE_CONNECTOR_DVII;
  }
 }

 /* ASUS HD 3600 board lists the DVI port as HDMI */
 if ((pdev->device == 0x9598) &&
     (pdev->subsystem_vendor == 0x1043) &&
     (pdev->subsystem_device == 0x01e4)) {
  if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
   *connector_type = DRM_MODE_CONNECTOR_DVII;
  }
 }

 /* ASUS HD 3450 board lists the DVI port as HDMI */
 if ((pdev->device == 0x95C5) &&
     (pdev->subsystem_vendor == 0x1043) &&
     (pdev->subsystem_device == 0x01e2)) {
  if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
   *connector_type = DRM_MODE_CONNECTOR_DVII;
  }
 }

 /* some BIOSes seem to report DAC on HDMI - usually this is a board with
  * HDMI + VGA reporting as HDMI
 */

 if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
  if (supported_device & (ATOM_DEVICE_CRT_SUPPORT)) {
   *connector_type = DRM_MODE_CONNECTOR_VGA;
   *line_mux = 0;
  }
 }

 /* Acer laptop (Acer TravelMate 5730/5730G) has an HDMI port
  * on the laptop and a DVI port on the docking station and
  * both share the same encoder, hpd pin, and ddc line.
  * So while the bios table is technically correct,
  * we drop the DVI port here since xrandr has no concept of
  * encoders and will try and drive both connectors
  * with different crtcs which isn't possible on the hardware
  * side and leaves no crtcs for LVDS or VGA.
 */

 if (((pdev->device == 0x95c4) || (pdev->device == 0x9591)) &&
     (pdev->subsystem_vendor == 0x1025) &&
     (pdev->subsystem_device == 0x013c)) {
  if ((*connector_type == DRM_MODE_CONNECTOR_DVII) &&
      (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) {
   /* actually it's a DVI-D port not DVI-I */
   *connector_type = DRM_MODE_CONNECTOR_DVID;
   return false;
  }
 }

 /* XFX Pine Group device rv730 reports no VGA DDC lines
  * even though they are wired up to record 0x93
 */

 if ((pdev->device == 0x9498) &&
     (pdev->subsystem_vendor == 0x1682) &&
     (pdev->subsystem_device == 0x2452) &&
     (i2c_bus->valid == false) &&
     !(supported_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))) {
  struct radeon_device *rdev = dev->dev_private;
  *i2c_bus = radeon_lookup_i2c_gpio(rdev, 0x93);
 }

 /* Fujitsu D3003-S2 board lists DVI-I as DVI-D and VGA */
 if (((pdev->device == 0x9802) ||
      (pdev->device == 0x9805) ||
      (pdev->device == 0x9806)) &&
     (pdev->subsystem_vendor == 0x1734) &&
     (pdev->subsystem_device == 0x11bd)) {
  if (*connector_type == DRM_MODE_CONNECTOR_VGA) {
   *connector_type = DRM_MODE_CONNECTOR_DVII;
   *line_mux = 0x3103;
  } else if (*connector_type == DRM_MODE_CONNECTOR_DVID) {
   *connector_type = DRM_MODE_CONNECTOR_DVII;
  }
 }

 return true;
}

static const int supported_devices_connector_convert[] = {
 DRM_MODE_CONNECTOR_Unknown,
 DRM_MODE_CONNECTOR_VGA,
 DRM_MODE_CONNECTOR_DVII,
 DRM_MODE_CONNECTOR_DVID,
 DRM_MODE_CONNECTOR_DVIA,
 DRM_MODE_CONNECTOR_SVIDEO,
 DRM_MODE_CONNECTOR_Composite,
 DRM_MODE_CONNECTOR_LVDS,
 DRM_MODE_CONNECTOR_Unknown,
 DRM_MODE_CONNECTOR_Unknown,
 DRM_MODE_CONNECTOR_HDMIA,
 DRM_MODE_CONNECTOR_HDMIB,
 DRM_MODE_CONNECTOR_Unknown,
 DRM_MODE_CONNECTOR_Unknown,
 DRM_MODE_CONNECTOR_9PinDIN,
 DRM_MODE_CONNECTOR_DisplayPort
};

static const uint16_t supported_devices_connector_object_id_convert[] = {
 CONNECTOR_OBJECT_ID_NONE,
 CONNECTOR_OBJECT_ID_VGA,
 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I, /* not all boards support DL */
 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D, /* not all boards support DL */
 CONNECTOR_OBJECT_ID_VGA, /* technically DVI-A */
 CONNECTOR_OBJECT_ID_COMPOSITE,
 CONNECTOR_OBJECT_ID_SVIDEO,
 CONNECTOR_OBJECT_ID_LVDS,
 CONNECTOR_OBJECT_ID_9PIN_DIN,
 CONNECTOR_OBJECT_ID_9PIN_DIN,
 CONNECTOR_OBJECT_ID_DISPLAYPORT,
 CONNECTOR_OBJECT_ID_HDMI_TYPE_A,
 CONNECTOR_OBJECT_ID_HDMI_TYPE_B,
 CONNECTOR_OBJECT_ID_SVIDEO
};

static const int object_connector_convert[] = {
 DRM_MODE_CONNECTOR_Unknown,
 DRM_MODE_CONNECTOR_DVII,
 DRM_MODE_CONNECTOR_DVII,
 DRM_MODE_CONNECTOR_DVID,
 DRM_MODE_CONNECTOR_DVID,
 DRM_MODE_CONNECTOR_VGA,
 DRM_MODE_CONNECTOR_Composite,
 DRM_MODE_CONNECTOR_SVIDEO,
 DRM_MODE_CONNECTOR_Unknown,
 DRM_MODE_CONNECTOR_Unknown,
 DRM_MODE_CONNECTOR_9PinDIN,
 DRM_MODE_CONNECTOR_Unknown,
 DRM_MODE_CONNECTOR_HDMIA,
 DRM_MODE_CONNECTOR_HDMIB,
 DRM_MODE_CONNECTOR_LVDS,
 DRM_MODE_CONNECTOR_9PinDIN,
 DRM_MODE_CONNECTOR_Unknown,
 DRM_MODE_CONNECTOR_Unknown,
 DRM_MODE_CONNECTOR_Unknown,
 DRM_MODE_CONNECTOR_DisplayPort,
 DRM_MODE_CONNECTOR_eDP,
 DRM_MODE_CONNECTOR_Unknown
};

bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
{
 struct radeon_device *rdev = dev->dev_private;
 struct radeon_mode_info *mode_info = &rdev->mode_info;
 struct atom_context *ctx = mode_info->atom_context;
 int index = GetIndexIntoMasterTable(DATA, Object_Header);
 u16 size, data_offset;
 u8 frev, crev;
 ATOM_CONNECTOR_OBJECT_TABLE *con_obj;
 ATOM_ENCODER_OBJECT_TABLE *enc_obj;
 ATOM_OBJECT_TABLE *router_obj;
 ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj;
 ATOM_OBJECT_HEADER *obj_header;
 int i, j, k, path_size, device_support;
 int connector_type;
 u16 igp_lane_info, conn_id, connector_object_id;
 struct radeon_i2c_bus_rec ddc_bus;
 struct radeon_router router;
 struct radeon_gpio_rec gpio;
 struct radeon_hpd hpd;

 if (!atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset))
  return false;

 if (crev < 2)
  return false;

 obj_header = (ATOM_OBJECT_HEADER *) (ctx->bios + data_offset);
 path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *)
     (ctx->bios + data_offset +
      le16_to_cpu(obj_header->usDisplayPathTableOffset));
 con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *)
     (ctx->bios + data_offset +
      le16_to_cpu(obj_header->usConnectorObjectTableOffset));
 enc_obj = (ATOM_ENCODER_OBJECT_TABLE *)
     (ctx->bios + data_offset +
      le16_to_cpu(obj_header->usEncoderObjectTableOffset));
 router_obj = (ATOM_OBJECT_TABLE *)
  (ctx->bios + data_offset +
   le16_to_cpu(obj_header->usRouterObjectTableOffset));
 device_support = le16_to_cpu(obj_header->usDeviceSupport);

 path_size = 0;
 for (i = 0; i < path_obj->ucNumOfDispPath; i++) {
  uint8_t *addr = (uint8_t *) path_obj->asDispPath;
  ATOM_DISPLAY_OBJECT_PATH *path;
  addr += path_size;
  path = (ATOM_DISPLAY_OBJECT_PATH *) addr;
  path_size += le16_to_cpu(path->usSize);

  if (device_support & le16_to_cpu(path->usDeviceTag)) {
   uint8_t con_obj_id, con_obj_num;

   con_obj_id =
       (le16_to_cpu(path->usConnObjectId) & OBJECT_ID_MASK)
       >> OBJECT_ID_SHIFT;
   con_obj_num =
       (le16_to_cpu(path->usConnObjectId) & ENUM_ID_MASK)
       >> ENUM_ID_SHIFT;

   /* TODO CV support */
   if (le16_to_cpu(path->usDeviceTag) ==
    ATOM_DEVICE_CV_SUPPORT)
    continue;

   /* IGP chips */
   if ((rdev->flags & RADEON_IS_IGP) &&
       (con_obj_id ==
        CONNECTOR_OBJECT_ID_PCIE_CONNECTOR)) {
    uint16_t igp_offset = 0;
    ATOM_INTEGRATED_SYSTEM_INFO_V2 *igp_obj;

    index =
        GetIndexIntoMasterTable(DATA,
           IntegratedSystemInfo);

    if (atom_parse_data_header(ctx, index, &size, &frev,
          &crev, &igp_offset)) {

     if (crev >= 2) {
      igp_obj =
       (ATOM_INTEGRATED_SYSTEM_INFO_V2
        *) (ctx->bios + igp_offset);

      if (igp_obj) {
       uint32_t slot_config, ct;

       if (con_obj_num == 1)
        slot_config =
         igp_obj->
         ulDDISlot1Config;
       else
        slot_config =
         igp_obj->
         ulDDISlot2Config;

       ct = (slot_config >> 16) & 0xff;
       connector_type =
        object_connector_convert
        [ct];
       connector_object_id = ct;
       igp_lane_info =
        slot_config & 0xffff;
      } else
       continue;
     } else
      continue;
    } else {
     igp_lane_info = 0;
     connector_type =
      object_connector_convert[con_obj_id];
     connector_object_id = con_obj_id;
    }
   } else {
    igp_lane_info = 0;
    connector_type =
        object_connector_convert[con_obj_id];
    connector_object_id = con_obj_id;
   }

   if (connector_type == DRM_MODE_CONNECTOR_Unknown)
    continue;

   router.ddc_valid = false;
   router.cd_valid = false;
   for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); j++) {
    uint8_t grph_obj_type =
        (le16_to_cpu(path->usGraphicObjIds[j]) &
         OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;

    if (grph_obj_type == GRAPH_OBJECT_TYPE_ENCODER) {
     for (k = 0; k < enc_obj->ucNumberOfObjects; k++) {
      u16 encoder_obj = le16_to_cpu(enc_obj->asObjects[k].usObjectID);
      if (le16_to_cpu(path->usGraphicObjIds[j]) == encoder_obj) {
       ATOM_COMMON_RECORD_HEADER *record = (ATOM_COMMON_RECORD_HEADER *)
        (ctx->bios + data_offset +
         le16_to_cpu(enc_obj->asObjects[k].usRecordOffset));
       ATOM_ENCODER_CAP_RECORD *cap_record;
       u16 caps = 0;

       while (record->ucRecordSize > 0 &&
              record->ucRecordType > 0 &&
              record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
        switch (record->ucRecordType) {
        case ATOM_ENCODER_CAP_RECORD_TYPE:
         cap_record =(ATOM_ENCODER_CAP_RECORD *)
          record;
         caps = le16_to_cpu(cap_record->usEncoderCap);
         break;
        }
        record = (ATOM_COMMON_RECORD_HEADER *)
         ((char *)record + record->ucRecordSize);
       }
       radeon_add_atom_encoder(dev,
          encoder_obj,
          le16_to_cpu
          (path->
           usDeviceTag),
          caps);
      }
     }
    } else if (grph_obj_type == GRAPH_OBJECT_TYPE_ROUTER) {
     for (k = 0; k < router_obj->ucNumberOfObjects; k++) {
      u16 router_obj_id = le16_to_cpu(router_obj->asObjects[k].usObjectID);
      if (le16_to_cpu(path->usGraphicObjIds[j]) == router_obj_id) {
       ATOM_COMMON_RECORD_HEADER *record = (ATOM_COMMON_RECORD_HEADER *)
        (ctx->bios + data_offset +
         le16_to_cpu(router_obj->asObjects[k].usRecordOffset));
       ATOM_I2C_RECORD *i2c_record;
       ATOM_I2C_ID_CONFIG_ACCESS *i2c_config;
       ATOM_ROUTER_DDC_PATH_SELECT_RECORD *ddc_path;
       ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD *cd_path;
       ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *router_src_dst_table =
        (ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *)
        (ctx->bios + data_offset +
         le16_to_cpu(router_obj->asObjects[k].usSrcDstTableOffset));
       u8 *num_dst_objs = (u8 *)
        ((u8 *)router_src_dst_table + 1 +
         (router_src_dst_table->ucNumberOfSrc * 2));
       u16 *dst_objs = (u16 *)(num_dst_objs + 1);
       int enum_id;

       router.router_id = router_obj_id;
       for (enum_id = 0; enum_id < (*num_dst_objs); enum_id++) {
        if (le16_to_cpu(path->usConnObjectId) ==
            le16_to_cpu(dst_objs[enum_id]))
         break;
       }

       while (record->ucRecordSize > 0 &&
              record->ucRecordType > 0 &&
              record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
        switch (record->ucRecordType) {
        case ATOM_I2C_RECORD_TYPE:
         i2c_record =
          (ATOM_I2C_RECORD *)
          record;
         i2c_config =
          (ATOM_I2C_ID_CONFIG_ACCESS *)
          &i2c_record->sucI2cId;
         router.i2c_info =
          radeon_lookup_i2c_gpio(rdev,
                   i2c_config->
                   ucAccess);
         router.i2c_addr = i2c_record->ucI2CAddr >> 1;
         break;
        case ATOM_ROUTER_DDC_PATH_SELECT_RECORD_TYPE:
         ddc_path = (ATOM_ROUTER_DDC_PATH_SELECT_RECORD *)
          record;
         router.ddc_valid = true;
         router.ddc_mux_type = ddc_path->ucMuxType;
         router.ddc_mux_control_pin = ddc_path->ucMuxControlPin;
         router.ddc_mux_state = ddc_path->ucMuxState[enum_id];
         break;
        case ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD_TYPE:
         cd_path = (ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD *)
          record;
         router.cd_valid = true;
         router.cd_mux_type = cd_path->ucMuxType;
         router.cd_mux_control_pin = cd_path->ucMuxControlPin;
         router.cd_mux_state = cd_path->ucMuxState[enum_id];
         break;
        }
        record = (ATOM_COMMON_RECORD_HEADER *)
         ((char *)record + record->ucRecordSize);
       }
      }
     }
    }
   }

   /* look up gpio for ddc, hpd */
   ddc_bus.valid = false;
   hpd.hpd = RADEON_HPD_NONE;
   if ((le16_to_cpu(path->usDeviceTag) &
        (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) == 0) {
    for (j = 0; j < con_obj->ucNumberOfObjects; j++) {
     if (le16_to_cpu(path->usConnObjectId) ==
         le16_to_cpu(con_obj->asObjects[j].
       usObjectID)) {
      ATOM_COMMON_RECORD_HEADER
          *record =
          (ATOM_COMMON_RECORD_HEADER
           *)
          (ctx->bios + data_offset +
           le16_to_cpu(con_obj->
         asObjects[j].
         usRecordOffset));
      ATOM_I2C_RECORD *i2c_record;
      ATOM_HPD_INT_RECORD *hpd_record;
      ATOM_I2C_ID_CONFIG_ACCESS *i2c_config;

      while (record->ucRecordSize > 0 &&
             record->ucRecordType > 0 &&
             record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
       switch (record->ucRecordType) {
       case ATOM_I2C_RECORD_TYPE:
        i2c_record =
            (ATOM_I2C_RECORD *)
         record;
        i2c_config =
         (ATOM_I2C_ID_CONFIG_ACCESS *)
         &i2c_record->sucI2cId;
        ddc_bus = radeon_lookup_i2c_gpio(rdev,
             i2c_config->
             ucAccess);
        break;
       case ATOM_HPD_INT_RECORD_TYPE:
        hpd_record =
         (ATOM_HPD_INT_RECORD *)
         record;
        gpio = radeon_atombios_lookup_gpio(rdev,
             hpd_record->ucHPDIntGPIOID);
        hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio);
        hpd.plugged_state = hpd_record->ucPlugged_PinState;
        break;
       }
       record =
           (ATOM_COMMON_RECORD_HEADER
            *) ((char *)record
         +
         record->
         ucRecordSize);
      }
      break;
     }
    }
   }

   /* needed for aux chan transactions */
   ddc_bus.hpd = hpd.hpd;

   conn_id = le16_to_cpu(path->usConnObjectId);

   if (!radeon_atom_apply_quirks
       (dev, le16_to_cpu(path->usDeviceTag), &connector_type,
        &ddc_bus, &conn_id, &hpd))
    continue;

   radeon_add_atom_connector(dev,
        conn_id,
        le16_to_cpu(path->
             usDeviceTag),
        connector_type, &ddc_bus,
        igp_lane_info,
        connector_object_id,
        &hpd,
        &router);

  }
 }

 radeon_link_encoder_connector(dev);
 return true;
}

static uint16_t atombios_get_connector_object_id(struct drm_device *dev,
       int connector_type,
       uint16_t devices)
{
 struct radeon_device *rdev = dev->dev_private;

 if (rdev->flags & RADEON_IS_IGP) {
  return supported_devices_connector_object_id_convert
   [connector_type];
 } else if (((connector_type == DRM_MODE_CONNECTOR_DVII) ||
      (connector_type == DRM_MODE_CONNECTOR_DVID)) &&
     (devices & ATOM_DEVICE_DFP2_SUPPORT))  {
  struct radeon_mode_info *mode_info = &rdev->mode_info;
  struct atom_context *ctx = mode_info->atom_context;
  int index = GetIndexIntoMasterTable(DATA, XTMDS_Info);
  uint16_t size, data_offset;
  uint8_t frev, crev;
  ATOM_XTMDS_INFO *xtmds;

  if (atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset)) {
   xtmds = (ATOM_XTMDS_INFO *)(ctx->bios + data_offset);

   if (xtmds->ucSupportedLink & ATOM_XTMDS_SUPPORTED_DUALLINK) {
    if (connector_type == DRM_MODE_CONNECTOR_DVII)
     return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I;
    else
     return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
   } else {
    if (connector_type == DRM_MODE_CONNECTOR_DVII)
     return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
    else
     return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D;
   }
  } else
   return supported_devices_connector_object_id_convert
    [connector_type];
 } else {
  return supported_devices_connector_object_id_convert
   [connector_type];
 }
}

struct bios_connector {
 bool valid;
 uint16_t line_mux;
 uint16_t devices;
 int connector_type;
 struct radeon_i2c_bus_rec ddc_bus;
 struct radeon_hpd hpd;
};

bool radeon_get_atom_connector_info_from_supported_devices_table(struct
         drm_device
         *dev)
{
 struct radeon_device *rdev = dev->dev_private;
 struct radeon_mode_info *mode_info = &rdev->mode_info;
 struct atom_context *ctx = mode_info->atom_context;
 int index = GetIndexIntoMasterTable(DATA, SupportedDevicesInfo);
 uint16_t size, data_offset;
 uint8_t frev, crev;
 uint16_t device_support;
 uint8_t dac;
 union atom_supported_devices *supported_devices;
 int i, j, max_device;
 struct bios_connector *bios_connectors;
 size_t bc_size = sizeof(*bios_connectors) * ATOM_MAX_SUPPORTED_DEVICE;
 struct radeon_router router;

 router.ddc_valid = false;
 router.cd_valid = false;

 bios_connectors = kzalloc(bc_size, GFP_KERNEL);
 if (!bios_connectors)
  return false;

 if (!atom_parse_data_header(ctx, index, &size, &frev, &crev,
        &data_offset)) {
  kfree(bios_connectors);
  return false;
 }

 supported_devices =
     (union atom_supported_devices *)(ctx->bios + data_offset);

 device_support = le16_to_cpu(supported_devices->info.usDeviceSupport);

 if (frev > 1)
  max_device = ATOM_MAX_SUPPORTED_DEVICE;
 else
  max_device = ATOM_MAX_SUPPORTED_DEVICE_INFO;

 for (i = 0; i < max_device; i++) {
  ATOM_CONNECTOR_INFO_I2C ci;

  if (frev > 1)
   ci = supported_devices->info_2d1.asConnInfo[i];
  else
   ci = supported_devices->info.asConnInfo[i];

  bios_connectors[i].valid = false;

  if (!(device_support & (1 << i))) {
   continue;
  }

  if (i == ATOM_DEVICE_CV_INDEX) {
   DRM_DEBUG_KMS("Skipping Component Video\n");
   continue;
  }

  bios_connectors[i].connector_type =
      supported_devices_connector_convert[ci.sucConnectorInfo.
       sbfAccess.
       bfConnectorType];

  if (bios_connectors[i].connector_type ==
      DRM_MODE_CONNECTOR_Unknown)
   continue;

  dac = ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC;

  bios_connectors[i].line_mux =
   ci.sucI2cId.ucAccess;

  /* give tv unique connector ids */
  if (i == ATOM_DEVICE_TV1_INDEX) {
   bios_connectors[i].ddc_bus.valid = false;
   bios_connectors[i].line_mux = 50;
  } else if (i == ATOM_DEVICE_TV2_INDEX) {
   bios_connectors[i].ddc_bus.valid = false;
   bios_connectors[i].line_mux = 51;
  } else if (i == ATOM_DEVICE_CV_INDEX) {
   bios_connectors[i].ddc_bus.valid = false;
   bios_connectors[i].line_mux = 52;
  } else
   bios_connectors[i].ddc_bus =
       radeon_lookup_i2c_gpio(rdev,
         bios_connectors[i].line_mux);

  if ((crev > 1) && (frev > 1)) {
   u8 isb = supported_devices->info_2d1.asIntSrcInfo[i].ucIntSrcBitmap;
   switch (isb) {
   case 0x4:
    bios_connectors[i].hpd.hpd = RADEON_HPD_1;
    break;
   case 0xa:
    bios_connectors[i].hpd.hpd = RADEON_HPD_2;
    break;
   default:
    bios_connectors[i].hpd.hpd = RADEON_HPD_NONE;
    break;
   }
  } else {
   if (i == ATOM_DEVICE_DFP1_INDEX)
    bios_connectors[i].hpd.hpd = RADEON_HPD_1;
   else if (i == ATOM_DEVICE_DFP2_INDEX)
    bios_connectors[i].hpd.hpd = RADEON_HPD_2;
   else
    bios_connectors[i].hpd.hpd = RADEON_HPD_NONE;
  }

  /* Always set the connector type to VGA for CRT1/CRT2. if they are
   * shared with a DVI port, we'll pick up the DVI connector when we
   * merge the outputs.  Some bioses incorrectly list VGA ports as DVI.
 */

  if (i == ATOM_DEVICE_CRT1_INDEX || i == ATOM_DEVICE_CRT2_INDEX)
   bios_connectors[i].connector_type =
       DRM_MODE_CONNECTOR_VGA;

  if (!radeon_atom_apply_quirks
      (dev, (1 << i), &bios_connectors[i].connector_type,
       &bios_connectors[i].ddc_bus, &bios_connectors[i].line_mux,
       &bios_connectors[i].hpd))
   continue;

  bios_connectors[i].valid = true;
  bios_connectors[i].devices = (1 << i);

  if (ASIC_IS_AVIVO(rdev) || radeon_r4xx_atom)
   radeon_add_atom_encoder(dev,
      radeon_get_encoder_enum(dev,
              (1 << i),
              dac),
      (1 << i),
      0);
  else
   radeon_add_legacy_encoder(dev,
        radeon_get_encoder_enum(dev,
         (1 << i),
         dac),
        (1 << i));
 }

 /* combine shared connectors */
 for (i = 0; i < max_device; i++) {
  if (bios_connectors[i].valid) {
   for (j = 0; j < max_device; j++) {
    if (bios_connectors[j].valid && (i != j)) {
     if (bios_connectors[i].line_mux ==
         bios_connectors[j].line_mux) {
      /* make sure not to combine LVDS */
      if (bios_connectors[i].devices & (ATOM_DEVICE_LCD_SUPPORT)) {
       bios_connectors[i].line_mux = 53;
       bios_connectors[i].ddc_bus.valid = false;
       continue;
      }
      if (bios_connectors[j].devices & (ATOM_DEVICE_LCD_SUPPORT)) {
       bios_connectors[j].line_mux = 53;
       bios_connectors[j].ddc_bus.valid = false;
       continue;
      }
      /* combine analog and digital for DVI-I */
      if (((bios_connectors[i].devices & (ATOM_DEVICE_DFP_SUPPORT)) &&
           (bios_connectors[j].devices & (ATOM_DEVICE_CRT_SUPPORT))) ||
          ((bios_connectors[j].devices & (ATOM_DEVICE_DFP_SUPPORT)) &&
           (bios_connectors[i].devices & (ATOM_DEVICE_CRT_SUPPORT)))) {
       bios_connectors[i].devices |=
        bios_connectors[j].devices;
       bios_connectors[i].connector_type =
        DRM_MODE_CONNECTOR_DVII;
       if (bios_connectors[j].devices & (ATOM_DEVICE_DFP_SUPPORT))
        bios_connectors[i].hpd =
         bios_connectors[j].hpd;
       bios_connectors[j].valid = false;
      }
     }
    }
   }
  }
 }

 /* add the connectors */
 for (i = 0; i < max_device; i++) {
  if (bios_connectors[i].valid) {
   uint16_t connector_object_id =
    atombios_get_connector_object_id(dev,
            bios_connectors[i].connector_type,
            bios_connectors[i].devices);
   radeon_add_atom_connector(dev,
        bios_connectors[i].line_mux,
        bios_connectors[i].devices,
        bios_connectors[i].
        connector_type,
        &bios_connectors[i].ddc_bus,
        0,
        connector_object_id,
        &bios_connectors[i].hpd,
        &router);
  }
 }

 radeon_link_encoder_connector(dev);

 kfree(bios_connectors);
 return true;
}

union firmware_info {
 ATOM_FIRMWARE_INFO info;
 ATOM_FIRMWARE_INFO_V1_2 info_12;
 ATOM_FIRMWARE_INFO_V1_3 info_13;
 ATOM_FIRMWARE_INFO_V1_4 info_14;
 ATOM_FIRMWARE_INFO_V2_1 info_21;
 ATOM_FIRMWARE_INFO_V2_2 info_22;
};

union igp_info {
 struct _ATOM_INTEGRATED_SYSTEM_INFO info;
 struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
 struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6;
 struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7;
 struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_8 info_8;
};

static void radeon_atombios_get_dentist_vco_freq(struct radeon_device *rdev)
{
 struct radeon_mode_info *mode_info = &rdev->mode_info;
 int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
 union igp_info *igp_info;
 u8 frev, crev;
 u16 data_offset;

 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
   &frev, &crev, &data_offset)) {
  igp_info = (union igp_info *)(mode_info->atom_context->bios +
   data_offset);
  rdev->clock.vco_freq =
   le32_to_cpu(igp_info->info_6.ulDentistVCOFreq);
 }
}

bool radeon_atom_get_clock_info(struct drm_device *dev)
{
 struct radeon_device *rdev = dev->dev_private;
 struct radeon_mode_info *mode_info = &rdev->mode_info;
 int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
 union firmware_info *firmware_info;
 uint8_t frev, crev;
 struct radeon_pll *p1pll = &rdev->clock.p1pll;
 struct radeon_pll *p2pll = &rdev->clock.p2pll;
 struct radeon_pll *dcpll = &rdev->clock.dcpll;
 struct radeon_pll *spll = &rdev->clock.spll;
 struct radeon_pll *mpll = &rdev->clock.mpll;
 uint16_t data_offset;

 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
       &frev, &crev, &data_offset)) {
  firmware_info =
   (union firmware_info *)(mode_info->atom_context->bios +
      data_offset);
  /* pixel clocks */
  p1pll->reference_freq =
      le16_to_cpu(firmware_info->info.usReferenceClock);
  p1pll->reference_div = 0;

  if ((frev < 2) && (crev < 2))
   p1pll->pll_out_min =
    le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Output);
  else
   p1pll->pll_out_min =
    le32_to_cpu(firmware_info->info_12.ulMinPixelClockPLL_Output);
  p1pll->pll_out_max =
      le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output);

  if (((frev < 2) && (crev >= 4)) || (frev >= 2)) {
   p1pll->lcd_pll_out_min =
    le16_to_cpu(firmware_info->info_14.usLcdMinPixelClockPLL_Output) * 100;
   if (p1pll->lcd_pll_out_min == 0)
    p1pll->lcd_pll_out_min = p1pll->pll_out_min;
   p1pll->lcd_pll_out_max =
    le16_to_cpu(firmware_info->info_14.usLcdMaxPixelClockPLL_Output) * 100;
   if (p1pll->lcd_pll_out_max == 0)
    p1pll->lcd_pll_out_max = p1pll->pll_out_max;
  } else {
   p1pll->lcd_pll_out_min = p1pll->pll_out_min;
   p1pll->lcd_pll_out_max = p1pll->pll_out_max;
  }

  if (p1pll->pll_out_min == 0) {
   if (ASIC_IS_AVIVO(rdev))
    p1pll->pll_out_min = 64800;
   else
    p1pll->pll_out_min = 20000;
  }

  p1pll->pll_in_min =
      le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Input);
  p1pll->pll_in_max =
      le16_to_cpu(firmware_info->info.usMaxPixelClockPLL_Input);

  *p2pll = *p1pll;

  /* system clock */
  if (ASIC_IS_DCE4(rdev))
   spll->reference_freq =
    le16_to_cpu(firmware_info->info_21.usCoreReferenceClock);
  else
   spll->reference_freq =
    le16_to_cpu(firmware_info->info.usReferenceClock);
  spll->reference_div = 0;

  spll->pll_out_min =
      le16_to_cpu(firmware_info->info.usMinEngineClockPLL_Output);
  spll->pll_out_max =
      le32_to_cpu(firmware_info->info.ulMaxEngineClockPLL_Output);

  /* ??? */
  if (spll->pll_out_min == 0) {
   if (ASIC_IS_AVIVO(rdev))
    spll->pll_out_min = 64800;
   else
    spll->pll_out_min = 20000;
  }

  spll->pll_in_min =
      le16_to_cpu(firmware_info->info.usMinEngineClockPLL_Input);
  spll->pll_in_max =
      le16_to_cpu(firmware_info->info.usMaxEngineClockPLL_Input);

  /* memory clock */
  if (ASIC_IS_DCE4(rdev))
   mpll->reference_freq =
    le16_to_cpu(firmware_info->info_21.usMemoryReferenceClock);
  else
   mpll->reference_freq =
    le16_to_cpu(firmware_info->info.usReferenceClock);
  mpll->reference_div = 0;

  mpll->pll_out_min =
      le16_to_cpu(firmware_info->info.usMinMemoryClockPLL_Output);
  mpll->pll_out_max =
      le32_to_cpu(firmware_info->info.ulMaxMemoryClockPLL_Output);

  /* ??? */
  if (mpll->pll_out_min == 0) {
   if (ASIC_IS_AVIVO(rdev))
    mpll->pll_out_min = 64800;
   else
    mpll->pll_out_min = 20000;
  }

  mpll->pll_in_min =
      le16_to_cpu(firmware_info->info.usMinMemoryClockPLL_Input);
  mpll->pll_in_max =
      le16_to_cpu(firmware_info->info.usMaxMemoryClockPLL_Input);

  rdev->clock.default_sclk =
      le32_to_cpu(firmware_info->info.ulDefaultEngineClock);
  rdev->clock.default_mclk =
      le32_to_cpu(firmware_info->info.ulDefaultMemoryClock);

  if (ASIC_IS_DCE4(rdev)) {
   rdev->clock.default_dispclk =
    le32_to_cpu(firmware_info->info_21.ulDefaultDispEngineClkFreq);
   if (rdev->clock.default_dispclk == 0) {
    if (ASIC_IS_DCE6(rdev))
     rdev->clock.default_dispclk = 60000; /* 600 Mhz */
    else if (ASIC_IS_DCE5(rdev))
     rdev->clock.default_dispclk = 54000; /* 540 Mhz */
    else
     rdev->clock.default_dispclk = 60000; /* 600 Mhz */
   }
   /* set a reasonable default for DP */
   if (ASIC_IS_DCE6(rdev) && (rdev->clock.default_dispclk < 53900)) {
    DRM_INFO("Changing default dispclk from %dMhz to 600Mhz\n",
      rdev->clock.default_dispclk / 100);
    rdev->clock.default_dispclk = 60000;
   }
   rdev->clock.dp_extclk =
    le16_to_cpu(firmware_info->info_21.usUniphyDPModeExtClkFreq);
   rdev->clock.current_dispclk = rdev->clock.default_dispclk;
  }
  *dcpll = *p1pll;

  rdev->clock.max_pixel_clock = le16_to_cpu(firmware_info->info.usMaxPixelClock);
  if (rdev->clock.max_pixel_clock == 0)
   rdev->clock.max_pixel_clock = 40000;

  /* not technically a clock, but... */
  rdev->mode_info.firmware_flags =
   le16_to_cpu(firmware_info->info.usFirmwareCapability.susAccess);

  if (ASIC_IS_DCE8(rdev))
   rdev->clock.vco_freq =
    le32_to_cpu(firmware_info->info_22.ulGPUPLL_OutputFreq);
  else if (ASIC_IS_DCE5(rdev))
   rdev->clock.vco_freq = rdev->clock.current_dispclk;
  else if (ASIC_IS_DCE41(rdev))
   radeon_atombios_get_dentist_vco_freq(rdev);
  else
   rdev->clock.vco_freq = rdev->clock.current_dispclk;

  if (rdev->clock.vco_freq == 0)
   rdev->clock.vco_freq = 360000; /* 3.6 GHz */

  return true;
 }

 return false;
}

bool radeon_atombios_sideport_present(struct radeon_device *rdev)
{
 struct radeon_mode_info *mode_info = &rdev->mode_info;
 int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
 union igp_info *igp_info;
 u8 frev, crev;
 u16 data_offset;

 /* sideport is AMD only */
 if (rdev->family == CHIP_RS600)
  return false;

 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
       &frev, &crev, &data_offset)) {
  igp_info = (union igp_info *)(mode_info->atom_context->bios +
          data_offset);
  switch (crev) {
  case 1:
   if (le32_to_cpu(igp_info->info.ulBootUpMemoryClock))
    return true;
   break;
  case 2:
   if (le32_to_cpu(igp_info->info_2.ulBootUpSidePortClock))
    return true;
   break;
  default:
   DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);
   break;
  }
 }
 return false;
}

bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder,
       struct radeon_encoder_int_tmds *tmds)
{
 struct drm_device *dev = encoder->base.dev;
 struct radeon_device *rdev = dev->dev_private;
 struct radeon_mode_info *mode_info = &rdev->mode_info;
 int index = GetIndexIntoMasterTable(DATA, TMDS_Info);
 uint16_t data_offset;
 struct _ATOM_TMDS_INFO *tmds_info;
 uint8_t frev, crev;
 uint16_t maxfreq;
 int i;

 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
       &frev, &crev, &data_offset)) {
  tmds_info =
   (struct _ATOM_TMDS_INFO *)(mode_info->atom_context->bios +
         data_offset);

  maxfreq = le16_to_cpu(tmds_info->usMaxFrequency);
  for (i = 0; i < 4; i++) {
   tmds->tmds_pll[i].freq =
       le16_to_cpu(tmds_info->asMiscInfo[i].usFrequency);
   tmds->tmds_pll[i].value =
       tmds_info->asMiscInfo[i].ucPLL_ChargePump & 0x3f;
   tmds->tmds_pll[i].value |=
       (tmds_info->asMiscInfo[i].
        ucPLL_VCO_Gain & 0x3f) << 6;
   tmds->tmds_pll[i].value |=
       (tmds_info->asMiscInfo[i].
        ucPLL_DutyCycle & 0xf) << 12;
   tmds->tmds_pll[i].value |=
       (tmds_info->asMiscInfo[i].
        ucPLL_VoltageSwing & 0xf) << 16;

   DRM_DEBUG_KMS("TMDS PLL From ATOMBIOS %u %x\n",
      tmds->tmds_pll[i].freq,
      tmds->tmds_pll[i].value);

   if (maxfreq == tmds->tmds_pll[i].freq) {
    tmds->tmds_pll[i].freq = 0xffffffff;
    break;
   }
  }
  return true;
 }
 return false;
}

bool radeon_atombios_get_ppll_ss_info(struct radeon_device *rdev,
          struct radeon_atom_ss *ss,
          int id)
{
 struct radeon_mode_info *mode_info = &rdev->mode_info;
 int index = GetIndexIntoMasterTable(DATA, PPLL_SS_Info);
 uint16_t data_offset, size;
 struct _ATOM_SPREAD_SPECTRUM_INFO *ss_info;
 struct _ATOM_SPREAD_SPECTRUM_ASSIGNMENT *ss_assign;
 uint8_t frev, crev;
 int i, num_indices;

 memset(ss, 0, sizeof(struct radeon_atom_ss));
 if (atom_parse_data_header(mode_info->atom_context, index, &size,
       &frev, &crev, &data_offset)) {
  ss_info =
   (struct _ATOM_SPREAD_SPECTRUM_INFO *)(mode_info->atom_context->bios + data_offset);

  num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
   sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);
  ss_assign = (struct _ATOM_SPREAD_SPECTRUM_ASSIGNMENT *)
   ((u8 *)&ss_info->asSS_Info[0]);
  for (i = 0; i < num_indices; i++) {
   if (ss_assign->ucSS_Id == id) {
    ss->percentage =
     le16_to_cpu(ss_assign->usSpreadSpectrumPercentage);
    ss->type = ss_assign->ucSpreadSpectrumType;
    ss->step = ss_assign->ucSS_Step;
    ss->delay = ss_assign->ucSS_Delay;
    ss->range = ss_assign->ucSS_Range;
    ss->refdiv = ss_assign->ucRecommendedRef_Div;
    return true;
   }
   ss_assign = (struct _ATOM_SPREAD_SPECTRUM_ASSIGNMENT *)
    ((u8 *)ss_assign + sizeof(struct _ATOM_SPREAD_SPECTRUM_ASSIGNMENT));
  }
 }
 return false;
}

static void radeon_atombios_get_igp_ss_overrides(struct radeon_device *rdev,
       struct radeon_atom_ss *ss,
       int id)
{
 struct radeon_mode_info *mode_info = &rdev->mode_info;
 int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
 u16 data_offset, size;
 union igp_info *igp_info;
 u8 frev, crev;
 u16 percentage = 0, rate = 0;

 /* get any igp specific overrides */
 if (atom_parse_data_header(mode_info->atom_context, index, &size,
       &frev, &crev, &data_offset)) {
  igp_info = (union igp_info *)
   (mode_info->atom_context->bios + data_offset);
  switch (crev) {
  case 6:
   switch (id) {
   case ASIC_INTERNAL_SS_ON_TMDS:
    percentage = le16_to_cpu(igp_info->info_6.usDVISSPercentage);
    rate = le16_to_cpu(igp_info->info_6.usDVISSpreadRateIn10Hz);
    break;
   case ASIC_INTERNAL_SS_ON_HDMI:
    percentage = le16_to_cpu(igp_info->info_6.usHDMISSPercentage);
    rate = le16_to_cpu(igp_info->info_6.usHDMISSpreadRateIn10Hz);
    break;
   case ASIC_INTERNAL_SS_ON_LVDS:
    percentage = le16_to_cpu(igp_info->info_6.usLvdsSSPercentage);
    rate = le16_to_cpu(igp_info->info_6.usLvdsSSpreadRateIn10Hz);
    break;
   }
   break;
  case 7:
   switch (id) {
   case ASIC_INTERNAL_SS_ON_TMDS:
    percentage = le16_to_cpu(igp_info->info_7.usDVISSPercentage);
    rate = le16_to_cpu(igp_info->info_7.usDVISSpreadRateIn10Hz);
    break;
   case ASIC_INTERNAL_SS_ON_HDMI:
    percentage = le16_to_cpu(igp_info->info_7.usHDMISSPercentage);
    rate = le16_to_cpu(igp_info->info_7.usHDMISSpreadRateIn10Hz);
    break;
   case ASIC_INTERNAL_SS_ON_LVDS:
    percentage = le16_to_cpu(igp_info->info_7.usLvdsSSPercentage);
    rate = le16_to_cpu(igp_info->info_7.usLvdsSSpreadRateIn10Hz);
    break;
   }
   break;
  case 8:
   switch (id) {
   case ASIC_INTERNAL_SS_ON_TMDS:
    percentage = le16_to_cpu(igp_info->info_8.usDVISSPercentage);
    rate = le16_to_cpu(igp_info->info_8.usDVISSpreadRateIn10Hz);
    break;
   case ASIC_INTERNAL_SS_ON_HDMI:
    percentage = le16_to_cpu(igp_info->info_8.usHDMISSPercentage);
    rate = le16_to_cpu(igp_info->info_8.usHDMISSpreadRateIn10Hz);
    break;
   case ASIC_INTERNAL_SS_ON_LVDS:
    percentage = le16_to_cpu(igp_info->info_8.usLvdsSSPercentage);
    rate = le16_to_cpu(igp_info->info_8.usLvdsSSpreadRateIn10Hz);
    break;
   }
   break;
  default:
   DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);
   break;
  }
  if (percentage)
   ss->percentage = percentage;
  if (rate)
   ss->rate = rate;
 }
}

union asic_ss_info {
 struct _ATOM_ASIC_INTERNAL_SS_INFO info;
 struct _ATOM_ASIC_INTERNAL_SS_INFO_V2 info_2;
 struct _ATOM_ASIC_INTERNAL_SS_INFO_V3 info_3;
};

union asic_ss_assignment {
 struct _ATOM_ASIC_SS_ASSIGNMENT v1;
 struct _ATOM_ASIC_SS_ASSIGNMENT_V2 v2;
 struct _ATOM_ASIC_SS_ASSIGNMENT_V3 v3;
};

bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev,
          struct radeon_atom_ss *ss,
          int id, u32 clock)
{
 struct radeon_mode_info *mode_info = &rdev->mode_info;
 int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info);
 uint16_t data_offset, size;
 union asic_ss_info *ss_info;
 union asic_ss_assignment *ss_assign;
 uint8_t frev, crev;
 int i, num_indices;

 if (id == ASIC_INTERNAL_MEMORY_SS) {
  if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_MEMORY_CLOCK_SS_SUPPORT))
   return false;
 }
 if (id == ASIC_INTERNAL_ENGINE_SS) {
  if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_ENGINE_CLOCK_SS_SUPPORT))
   return false;
 }

 memset(ss, 0, sizeof(struct radeon_atom_ss));
 if (atom_parse_data_header(mode_info->atom_context, index, &size,
       &frev, &crev, &data_offset)) {

  ss_info =
   (union asic_ss_info *)(mode_info->atom_context->bios + data_offset);

  switch (frev) {
  case 1:
   num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
    sizeof(ATOM_ASIC_SS_ASSIGNMENT);

   ss_assign = (union asic_ss_assignment *)((u8 *)&ss_info->info.asSpreadSpectrum[0]);
   for (i = 0; i < num_indices; i++) {
    if ((ss_assign->v1.ucClockIndication == id) &&
        (clock <= le32_to_cpu(ss_assign->v1.ulTargetClockRange))) {
     ss->percentage =
      le16_to_cpu(ss_assign->v1.usSpreadSpectrumPercentage);
     ss->type = ss_assign->v1.ucSpreadSpectrumMode;
     ss->rate = le16_to_cpu(ss_assign->v1.usSpreadRateInKhz);
     ss->percentage_divider = 100;
     return true;
    }
    ss_assign = (union asic_ss_assignment *)
     ((u8 *)ss_assign + sizeof(ATOM_ASIC_SS_ASSIGNMENT));
   }
   break;
  case 2:
   num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
    sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
   ss_assign = (union asic_ss_assignment *)((u8 *)&ss_info->info_2.asSpreadSpectrum[0]);
   for (i = 0; i < num_indices; i++) {
    if ((ss_assign->v2.ucClockIndication == id) &&
        (clock <= le32_to_cpu(ss_assign->v2.ulTargetClockRange))) {
     ss->percentage =
      le16_to_cpu(ss_assign->v2.usSpreadSpectrumPercentage);
     ss->type = ss_assign->v2.ucSpreadSpectrumMode;
     ss->rate = le16_to_cpu(ss_assign->v2.usSpreadRateIn10Hz);
     ss->percentage_divider = 100;
     if ((crev == 2) &&
         ((id == ASIC_INTERNAL_ENGINE_SS) ||
          (id == ASIC_INTERNAL_MEMORY_SS)))
      ss->rate /= 100;
     return true;
    }
    ss_assign = (union asic_ss_assignment *)
     ((u8 *)ss_assign + sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2));
   }
   break;
  case 3:
   num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
    sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
   ss_assign = (union asic_ss_assignment *)((u8 *)&ss_info->info_3.asSpreadSpectrum[0]);
   for (i = 0; i < num_indices; i++) {
    if ((ss_assign->v3.ucClockIndication == id) &&
        (clock <= le32_to_cpu(ss_assign->v3.ulTargetClockRange))) {
     ss->percentage =
      le16_to_cpu(ss_assign->v3.usSpreadSpectrumPercentage);
     ss->type = ss_assign->v3.ucSpreadSpectrumMode;
     ss->rate = le16_to_cpu(ss_assign->v3.usSpreadRateIn10Hz);
     if (ss_assign->v3.ucSpreadSpectrumMode &
         SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK)
      ss->percentage_divider = 1000;
     else
      ss->percentage_divider = 100;
     if ((id == ASIC_INTERNAL_ENGINE_SS) ||
         (id == ASIC_INTERNAL_MEMORY_SS))
      ss->rate /= 100;
     if (rdev->flags & RADEON_IS_IGP)
      radeon_atombios_get_igp_ss_overrides(rdev, ss, id);
     return true;
    }
    ss_assign = (union asic_ss_assignment *)
     ((u8 *)ss_assign + sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3));
   }
   break;
  default:
   DRM_ERROR("Unsupported ASIC_InternalSS_Info table: %d %d\n", frev, crev);
   break;
  }

 }
 return false;
}

union lvds_info {
 struct _ATOM_LVDS_INFO info;
 struct _ATOM_LVDS_INFO_V12 info_12;
};

struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
             radeon_encoder
             *encoder)
{
 struct drm_device *dev = encoder->base.dev;
 struct radeon_device *rdev = dev->dev_private;
 struct radeon_mode_info *mode_info = &rdev->mode_info;
 int index = GetIndexIntoMasterTable(DATA, LVDS_Info);
 uint16_t data_offset, misc;
 union lvds_info *lvds_info;
 uint8_t frev, crev;
 struct radeon_encoder_atom_dig *lvds = NULL;
 int encoder_enum = (encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;

 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
       &frev, &crev, &data_offset)) {
  lvds_info =
   (union lvds_info *)(mode_info->atom_context->bios + data_offset);
  lvds =
      kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);

  if (!lvds)
   return NULL;

  lvds->native_mode.clock =
      le16_to_cpu(lvds_info->info.sLCDTiming.usPixClk) * 10;
  lvds->native_mode.hdisplay =
      le16_to_cpu(lvds_info->info.sLCDTiming.usHActive);
  lvds->native_mode.vdisplay =
      le16_to_cpu(lvds_info->info.sLCDTiming.usVActive);
  lvds->native_mode.htotal = lvds->native_mode.hdisplay +
   le16_to_cpu(lvds_info->info.sLCDTiming.usHBlanking_Time);
  lvds->native_mode.hsync_start = lvds->native_mode.hdisplay +
   le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncOffset);
  lvds->native_mode.hsync_end = lvds->native_mode.hsync_start +
   le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncWidth);
  lvds->native_mode.vtotal = lvds->native_mode.vdisplay +
   le16_to_cpu(lvds_info->info.sLCDTiming.usVBlanking_Time);
  lvds->native_mode.vsync_start = lvds->native_mode.vdisplay +
   le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncOffset);
  lvds->native_mode.vsync_end = lvds->native_mode.vsync_start +
   le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth);
  lvds->panel_pwr_delay =
      le16_to_cpu(lvds_info->info.usOffDelayInMs);
  lvds->lcd_misc = lvds_info->info.ucLVDS_Misc;

  misc = le16_to_cpu(lvds_info->info.sLCDTiming.susModeMiscInfo.usAccess);
  if (misc & ATOM_VSYNC_POLARITY)
   lvds->native_mode.flags |= DRM_MODE_FLAG_NVSYNC;
  if (misc & ATOM_HSYNC_POLARITY)
   lvds->native_mode.flags |= DRM_MODE_FLAG_NHSYNC;
  if (misc & ATOM_COMPOSITESYNC)
   lvds->native_mode.flags |= DRM_MODE_FLAG_CSYNC;
  if (misc & ATOM_INTERLACE)
   lvds->native_mode.flags |= DRM_MODE_FLAG_INTERLACE;
  if (misc & ATOM_DOUBLE_CLOCK_MODE)
   lvds->native_mode.flags |= DRM_MODE_FLAG_DBLSCAN;

  lvds->native_mode.width_mm = le16_to_cpu(lvds_info->info.sLCDTiming.usImageHSize);
  lvds->native_mode.height_mm = le16_to_cpu(lvds_info->info.sLCDTiming.usImageVSize);

  /* set crtc values */
  drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V);

  lvds->lcd_ss_id = lvds_info->info.ucSS_Id;

  encoder->native_mode = lvds->native_mode;

  if (encoder_enum == 2)
   lvds->linkb = true;
  else
   lvds->linkb = false;

  /* parse the lcd record table */
  if (le16_to_cpu(lvds_info->info.usModePatchTableOffset)) {
   ATOM_FAKE_EDID_PATCH_RECORD *fake_edid_record;
   ATOM_PANEL_RESOLUTION_PATCH_RECORD *panel_res_record;
   bool bad_record = false;
   u8 *record;

   if ((frev == 1) && (crev < 2))
    /* absolute */
    record = (u8 *)(mode_info->atom_context->bios +
      le16_to_cpu(lvds_info->info.usModePatchTableOffset));
   else
    /* relative */
    record = (u8 *)(mode_info->atom_context->bios +
      data_offset +
      le16_to_cpu(lvds_info->info.usModePatchTableOffset));
   while (*record != ATOM_RECORD_END_TYPE) {
    switch (*record) {
    case LCD_MODE_PATCH_RECORD_MODE_TYPE:
     record += sizeof(ATOM_PATCH_RECORD_MODE);
     break;
    case LCD_RTS_RECORD_TYPE:
     record += sizeof(ATOM_LCD_RTS_RECORD);
     break;
    case LCD_CAP_RECORD_TYPE:
     record += sizeof(ATOM_LCD_MODE_CONTROL_CAP);
     break;
    case LCD_FAKE_EDID_PATCH_RECORD_TYPE:
     fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record;
     if (fake_edid_record->ucFakeEDIDLength) {
      const struct drm_edid *edid;
      int edid_size;

      if (fake_edid_record->ucFakeEDIDLength == 128)
       edid_size = fake_edid_record->ucFakeEDIDLength;
      else
       edid_size = fake_edid_record->ucFakeEDIDLength * 128;
      edid = drm_edid_alloc(fake_edid_record->ucFakeEDIDString, edid_size);
      if (drm_edid_valid(edid))
       rdev->mode_info.bios_hardcoded_edid = edid;
      else
       drm_edid_free(edid);
      record += struct_size(fake_edid_record,
              ucFakeEDIDString,
              edid_size);
     } else {
      /* empty fake edid record must be 3 bytes long */
      record += sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + 1;
     }
     break;
    case LCD_PANEL_RESOLUTION_RECORD_TYPE:
     panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record;
     lvds->native_mode.width_mm = panel_res_record->usHSize;
     lvds->native_mode.height_mm = panel_res_record->usVSize;
     record += sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD);
     break;
    default:
     DRM_ERROR("Bad LCD record %d\n", *record);
     bad_record = true;
     break;
    }
    if (bad_record)
     break;
   }
  }
 }
 return lvds;
}

struct radeon_encoder_primary_dac *
radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder)
{
 struct drm_device *dev = encoder->base.dev;
 struct radeon_device *rdev = dev->dev_private;
 struct radeon_mode_info *mode_info = &rdev->mode_info;
 int index = GetIndexIntoMasterTable(DATA, CompassionateData);
 uint16_t data_offset;
 struct _COMPASSIONATE_DATA *dac_info;
 uint8_t frev, crev;
 uint8_t bg, dac;
 struct radeon_encoder_primary_dac *p_dac = NULL;

 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
       &frev, &crev, &data_offset)) {
  dac_info = (struct _COMPASSIONATE_DATA *)
   (mode_info->atom_context->bios + data_offset);

  p_dac = kzalloc(sizeof(struct radeon_encoder_primary_dac), GFP_KERNEL);

  if (!p_dac)
   return NULL;

  bg = dac_info->ucDAC1_BG_Adjustment;
  dac = dac_info->ucDAC1_DAC_Adjustment;
  p_dac->ps2_pdac_adj = (bg << 8) | (dac);

 }
 return p_dac;
}

bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
    struct drm_display_mode *mode)
{
 struct radeon_mode_info *mode_info = &rdev->mode_info;
 ATOM_ANALOG_TV_INFO *tv_info;
 ATOM_ANALOG_TV_INFO_V1_2 *tv_info_v1_2;
 ATOM_DTD_FORMAT *dtd_timings;
 int data_index = GetIndexIntoMasterTable(DATA, AnalogTV_Info);
 u8 frev, crev;
 u16 data_offset, misc;

 if (!atom_parse_data_header(mode_info->atom_context, data_index, NULL,
        &frev, &crev, &data_offset))
  return false;

 switch (crev) {
 case 1:
  tv_info = (ATOM_ANALOG_TV_INFO *)(mode_info->atom_context->bios + data_offset);
  if (index >= MAX_SUPPORTED_TV_TIMING)
   return false;

  mode->crtc_htotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total);
  mode->crtc_hdisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp);
  mode->crtc_hsync_start = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart);
  mode->crtc_hsync_end = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart) +
   le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncWidth);

  mode->crtc_vtotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Total);
  mode->crtc_vdisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Disp);
  mode->crtc_vsync_start = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart);
  mode->crtc_vsync_end = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart) +
   le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncWidth);

  mode->flags = 0;
  misc = le16_to_cpu(tv_info->aModeTimings[index].susModeMiscInfo.usAccess);
  if (misc & ATOM_VSYNC_POLARITY)
   mode->flags |= DRM_MODE_FLAG_NVSYNC;
  if (misc & ATOM_HSYNC_POLARITY)
   mode->flags |= DRM_MODE_FLAG_NHSYNC;
  if (misc & ATOM_COMPOSITESYNC)
   mode->flags |= DRM_MODE_FLAG_CSYNC;
  if (misc & ATOM_INTERLACE)
   mode->flags |= DRM_MODE_FLAG_INTERLACE;
  if (misc & ATOM_DOUBLE_CLOCK_MODE)
   mode->flags |= DRM_MODE_FLAG_DBLSCAN;

  mode->crtc_clock = mode->clock =
   le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10;

  if (index == 1) {
   /* PAL timings appear to have wrong values for totals */
   mode->crtc_htotal -= 1;
   mode->crtc_vtotal -= 1;
  }
  break;
 case 2:
  tv_info_v1_2 = (ATOM_ANALOG_TV_INFO_V1_2 *)(mode_info->atom_context->bios + data_offset);
  if (index >= MAX_SUPPORTED_TV_TIMING_V1_2)
   return false;

  dtd_timings = &tv_info_v1_2->aModeTimings[index];
  mode->crtc_htotal = le16_to_cpu(dtd_timings->usHActive) +
   le16_to_cpu(dtd_timings->usHBlanking_Time);
  mode->crtc_hdisplay = le16_to_cpu(dtd_timings->usHActive);
  mode->crtc_hsync_start = le16_to_cpu(dtd_timings->usHActive) +
   le16_to_cpu(dtd_timings->usHSyncOffset);
  mode->crtc_hsync_end = mode->crtc_hsync_start +
   le16_to_cpu(dtd_timings->usHSyncWidth);

  mode->crtc_vtotal = le16_to_cpu(dtd_timings->usVActive) +
   le16_to_cpu(dtd_timings->usVBlanking_Time);
  mode->crtc_vdisplay = le16_to_cpu(dtd_timings->usVActive);
  mode->crtc_vsync_start = le16_to_cpu(dtd_timings->usVActive) +
   le16_to_cpu(dtd_timings->usVSyncOffset);
  mode->crtc_vsync_end = mode->crtc_vsync_start +
   le16_to_cpu(dtd_timings->usVSyncWidth);

  mode->flags = 0;
  misc = le16_to_cpu(dtd_timings->susModeMiscInfo.usAccess);
  if (misc & ATOM_VSYNC_POLARITY)
   mode->flags |= DRM_MODE_FLAG_NVSYNC;
  if (misc & ATOM_HSYNC_POLARITY)
   mode->flags |= DRM_MODE_FLAG_NHSYNC;
  if (misc & ATOM_COMPOSITESYNC)
   mode->flags |= DRM_MODE_FLAG_CSYNC;
  if (misc & ATOM_INTERLACE)
   mode->flags |= DRM_MODE_FLAG_INTERLACE;
  if (misc & ATOM_DOUBLE_CLOCK_MODE)
   mode->flags |= DRM_MODE_FLAG_DBLSCAN;

  mode->crtc_clock = mode->clock =
   le16_to_cpu(dtd_timings->usPixClk) * 10;
  break;
 }
 return true;
}

enum radeon_tv_std
radeon_atombios_get_tv_info(struct radeon_device *rdev)
{
 struct radeon_mode_info *mode_info = &rdev->mode_info;
 int index = GetIndexIntoMasterTable(DATA, AnalogTV_Info);
 uint16_t data_offset;
 uint8_t frev, crev;
 struct _ATOM_ANALOG_TV_INFO *tv_info;
 enum radeon_tv_std tv_std = TV_STD_NTSC;

 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
       &frev, &crev, &data_offset)) {

  tv_info = (struct _ATOM_ANALOG_TV_INFO *)
   (mode_info->atom_context->bios + data_offset);

  switch (tv_info->ucTV_BootUpDefaultStandard) {
  case ATOM_TV_NTSC:
   tv_std = TV_STD_NTSC;
   DRM_DEBUG_KMS("Default TV standard: NTSC\n");
   break;
  case ATOM_TV_NTSCJ:
   tv_std = TV_STD_NTSC_J;
   DRM_DEBUG_KMS("Default TV standard: NTSC-J\n");
   break;
  case ATOM_TV_PAL:
   tv_std = TV_STD_PAL;
   DRM_DEBUG_KMS("Default TV standard: PAL\n");
   break;
  case ATOM_TV_PALM:
   tv_std = TV_STD_PAL_M;
   DRM_DEBUG_KMS("Default TV standard: PAL-M\n");
   break;
  case ATOM_TV_PALN:
   tv_std = TV_STD_PAL_N;
   DRM_DEBUG_KMS("Default TV standard: PAL-N\n");
   break;
  case ATOM_TV_PALCN:
   tv_std = TV_STD_PAL_CN;
   DRM_DEBUG_KMS("Default TV standard: PAL-CN\n");
   break;
  case ATOM_TV_PAL60:
   tv_std = TV_STD_PAL_60;
   DRM_DEBUG_KMS("Default TV standard: PAL-60\n");
   break;
  case ATOM_TV_SECAM:
   tv_std = TV_STD_SECAM;
   DRM_DEBUG_KMS("Default TV standard: SECAM\n");
   break;
  default:
   tv_std = TV_STD_NTSC;
   DRM_DEBUG_KMS("Unknown TV standard; defaulting to NTSC\n");
   break;
  }
 }
 return tv_std;
}

struct radeon_encoder_tv_dac *
radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
{
 struct drm_device *dev = encoder->base.dev;
 struct radeon_device *rdev = dev->dev_private;
 struct radeon_mode_info *mode_info = &rdev->mode_info;
 int index = GetIndexIntoMasterTable(DATA, CompassionateData);
 uint16_t data_offset;
 struct _COMPASSIONATE_DATA *dac_info;
 uint8_t frev, crev;
 uint8_t bg, dac;
 struct radeon_encoder_tv_dac *tv_dac = NULL;

 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
       &frev, &crev, &data_offset)) {

  dac_info = (struct _COMPASSIONATE_DATA *)
   (mode_info->atom_context->bios + data_offset);

  tv_dac = kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL);

  if (!tv_dac)
   return NULL;

  bg = dac_info->ucDAC2_CRT2_BG_Adjustment;
  dac = dac_info->ucDAC2_CRT2_DAC_Adjustment;
  tv_dac->ps2_tvdac_adj = (bg << 16) | (dac << 20);

  bg = dac_info->ucDAC2_PAL_BG_Adjustment;
  dac = dac_info->ucDAC2_PAL_DAC_Adjustment;
  tv_dac->pal_tvdac_adj = (bg << 16) | (dac << 20);

  bg = dac_info->ucDAC2_NTSC_BG_Adjustment;
  dac = dac_info->ucDAC2_NTSC_DAC_Adjustment;
  tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20);

  tv_dac->tv_std = radeon_atombios_get_tv_info(rdev);
 }
 return tv_dac;
}

static const char *thermal_controller_names[] = {
 "NONE",
 "lm63",
 "adm1032",
 "adm1030",
 "max6649",
 "lm63", /* lm64 */
 "f75375",
 "asc7xxx",
};

static const char *pp_lib_thermal_controller_names[] = {
 "NONE",
 "lm63",
 "adm1032",
 "adm1030",
 "max6649",
 "lm63", /* lm64 */
 "f75375",
 "RV6xx",
 "RV770",
 "adt7473",
 "NONE",
 "External GPIO",
 "Evergreen",
 "emc2103",
 "Sumo",
 "Northern Islands",
 "Southern Islands",
 "lm96163",
 "Sea Islands",
};

union power_info {
 struct _ATOM_POWERPLAY_INFO info;
 struct _ATOM_POWERPLAY_INFO_V2 info_2;
 struct _ATOM_POWERPLAY_INFO_V3 info_3;
 struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
 struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
 struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
};

union pplib_clock_info {
 struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
 struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
 struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
 struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
 struct _ATOM_PPLIB_SI_CLOCK_INFO si;
 struct _ATOM_PPLIB_CI_CLOCK_INFO ci;
};

union pplib_power_state {
 struct _ATOM_PPLIB_STATE v1;
 struct _ATOM_PPLIB_STATE_V2 v2;
};

static void radeon_atombios_parse_misc_flags_1_3(struct radeon_device *rdev,
       int state_index,
       u32 misc, u32 misc2)
{
 rdev->pm.power_state[state_index].misc = misc;
 rdev->pm.power_state[state_index].misc2 = misc2;
 /* order matters! */
 if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
  rdev->pm.power_state[state_index].type =
   POWER_STATE_TYPE_POWERSAVE;
 if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE)
  rdev->pm.power_state[state_index].type =
   POWER_STATE_TYPE_BATTERY;
 if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE)
  rdev->pm.power_state[state_index].type =
   POWER_STATE_TYPE_BATTERY;
 if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
  rdev->pm.power_state[state_index].type =
   POWER_STATE_TYPE_BALANCED;
 if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) {
  rdev->pm.power_state[state_index].type =
   POWER_STATE_TYPE_PERFORMANCE;
  rdev->pm.power_state[state_index].flags &=
   ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
 }
 if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE)
  rdev->pm.power_state[state_index].type =
   POWER_STATE_TYPE_BALANCED;
 if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
  rdev->pm.power_state[state_index].type =
   POWER_STATE_TYPE_DEFAULT;
  rdev->pm.default_power_state_index = state_index;
  rdev->pm.power_state[state_index].default_clock_mode =
   &rdev->pm.power_state[state_index].clock_info[0];
 } else if (state_index == 0) {
  rdev->pm.power_state[state_index].clock_info[0].flags |=
   RADEON_PM_MODE_NO_DISPLAY;
 }
}

static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev)
{
 struct radeon_mode_info *mode_info = &rdev->mode_info;
 u32 misc, misc2 = 0;
 int num_modes = 0, i;
 int state_index = 0;
 struct radeon_i2c_bus_rec i2c_bus;
 union power_info *power_info;
 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
 u16 data_offset;
 u8 frev, crev;

 if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
       &frev, &crev, &data_offset))
  return state_index;
 power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);

 /* add the i2c bus for thermal/fan chip */
 if ((power_info->info.ucOverdriveThermalController > 0) &&
     (power_info->info.ucOverdriveThermalController < ARRAY_SIZE(thermal_controller_names))) {
  DRM_INFO("Possible %s thermal controller at 0x%02x\n",
    thermal_controller_names[power_info->info.ucOverdriveThermalController],
    power_info->info.ucOverdriveControllerAddress >> 1);
  i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine);
  rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
  if (rdev->pm.i2c_bus) {
   struct i2c_board_info info = { };
   const char *name = thermal_controller_names[power_info->info.
            ucOverdriveThermalController];
   info.addr = power_info->info.ucOverdriveControllerAddress >> 1;
   strscpy(info.type, name, sizeof(info.type));
   i2c_new_client_device(&rdev->pm.i2c_bus->adapter, &info);
  }
 }
 num_modes = power_info->info.ucNumOfPowerModeEntries;
 if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK)
  num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK;
 if (num_modes == 0)
  return state_index;
 rdev->pm.power_state = kcalloc(num_modes,
           sizeof(struct radeon_power_state),
           GFP_KERNEL);
 if (!rdev->pm.power_state)
  return state_index;
 /* last mode is usually default, array is low to high */
 for (i = 0; i < num_modes; i++) {
  /* avoid memory leaks from invalid modes or unknown frev. */
  if (!rdev->pm.power_state[state_index].clock_info) {
   rdev->pm.power_state[state_index].clock_info =
    kzalloc(sizeof(struct radeon_pm_clock_info),
     GFP_KERNEL);
  }
  if (!rdev->pm.power_state[state_index].clock_info)
   goto out;
  rdev->pm.power_state[state_index].num_clock_modes = 1;
  rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
  switch (frev) {
  case 1:
   rdev->pm.power_state[state_index].clock_info[0].mclk =
    le16_to_cpu(power_info->info.asPowerPlayInfo[i].usMemoryClock);
   rdev->pm.power_state[state_index].clock_info[0].sclk =
    le16_to_cpu(power_info->info.asPowerPlayInfo[i].usEngineClock);
   /* skip invalid modes */
   if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
       (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
    continue;
   rdev->pm.power_state[state_index].pcie_lanes =
    power_info->info.asPowerPlayInfo[i].ucNumPciELanes;
   misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo);
   if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
       (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
    rdev->pm.power_state[state_index].clock_info[0].voltage.type =
     VOLTAGE_GPIO;
    rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
     radeon_atombios_lookup_gpio(rdev,
          power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex);
    if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
     rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
      true;
    else
     rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
      false;
   } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
    rdev->pm.power_state[state_index].clock_info[0].voltage.type =
     VOLTAGE_VDDC;
    rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
     power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex;
   }
   rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
   radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, 0);
   state_index++;
   break;
  case 2:
   rdev->pm.power_state[state_index].clock_info[0].mclk =
    le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMemoryClock);
   rdev->pm.power_state[state_index].clock_info[0].sclk =
    le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulEngineClock);
   /* skip invalid modes */
   if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
       (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
    continue;
   rdev->pm.power_state[state_index].pcie_lanes =
    power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes;
   misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo);
   misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2);
   if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
       (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
    rdev->pm.power_state[state_index].clock_info[0].voltage.type =
     VOLTAGE_GPIO;
    rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
     radeon_atombios_lookup_gpio(rdev,
          power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex);
    if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
     rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
      true;
    else
     rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
      false;
   } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
    rdev->pm.power_state[state_index].clock_info[0].voltage.type =
     VOLTAGE_VDDC;
    rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
     power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex;
   }
   rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
   radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, misc2);
   state_index++;
   break;
  case 3:
   rdev->pm.power_state[state_index].clock_info[0].mclk =
    le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMemoryClock);
   rdev->pm.power_state[state_index].clock_info[0].sclk =
    le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulEngineClock);
   /* skip invalid modes */
   if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
       (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
    continue;
   rdev->pm.power_state[state_index].pcie_lanes =
    power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes;
   misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo);
   misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2);
   if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
       (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
    rdev->pm.power_state[state_index].clock_info[0].voltage.type =
     VOLTAGE_GPIO;
    rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
     radeon_atombios_lookup_gpio(rdev,
          power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex);
    if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
     rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
      true;
    else
     rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
      false;
   } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
    rdev->pm.power_state[state_index].clock_info[0].voltage.type =
     VOLTAGE_VDDC;
    rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
     power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex;
    if (misc2 & ATOM_PM_MISCINFO2_VDDCI_DYNAMIC_VOLTAGE_EN) {
     rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_enabled =
      true;
     rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_id =
      power_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex;
    }
   }
   rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
   radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, misc2);
   state_index++;
   break;
  }
 }
out:
 /* free any unused clock_info allocation. */
 if (state_index && state_index < num_modes) {
  kfree(rdev->pm.power_state[state_index].clock_info);
  rdev->pm.power_state[state_index].clock_info = NULL;
 }

 /* last mode is usually default */
 if (state_index && rdev->pm.default_power_state_index == -1) {
  rdev->pm.power_state[state_index - 1].type =
   POWER_STATE_TYPE_DEFAULT;
  rdev->pm.default_power_state_index = state_index - 1;
  rdev->pm.power_state[state_index - 1].default_clock_mode =
   &rdev->pm.power_state[state_index - 1].clock_info[0];
  rdev->pm.power_state[state_index - 1].flags &=
   ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
  rdev->pm.power_state[state_index - 1].misc = 0;
  rdev->pm.power_state[state_index - 1].misc2 = 0;
 }
 return state_index;
}

static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *rdev,
        ATOM_PPLIB_THERMALCONTROLLER *controller)
{
 struct radeon_i2c_bus_rec i2c_bus;

 /* add the i2c bus for thermal/fan chip */
 if (controller->ucType > 0) {
  if (controller->ucFanParameters & ATOM_PP_FANPARAMETERS_NOFAN)
   rdev->pm.no_fan = true;
  rdev->pm.fan_pulses_per_revolution =
   controller->ucFanParameters & ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
  if (rdev->pm.fan_pulses_per_revolution) {
   rdev->pm.fan_min_rpm = controller->ucFanMinRPM;
   rdev->pm.fan_max_rpm = controller->ucFanMaxRPM;
  }
  if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) {
   DRM_INFO("Internal thermal controller %s fan control\n",
     (controller->ucFanParameters &
      ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
   rdev->pm.int_thermal_type = THERMAL_TYPE_RV6XX;
  } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) {
   DRM_INFO("Internal thermal controller %s fan control\n",
     (controller->ucFanParameters &
      ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
   rdev->pm.int_thermal_type = THERMAL_TYPE_RV770;
  } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) {
   DRM_INFO("Internal thermal controller %s fan control\n",
     (controller->ucFanParameters &
      ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
   rdev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN;
  } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SUMO) {
   DRM_INFO("Internal thermal controller %s fan control\n",
     (controller->ucFanParameters &
      ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
   rdev->pm.int_thermal_type = THERMAL_TYPE_SUMO;
  } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_NISLANDS) {
   DRM_INFO("Internal thermal controller %s fan control\n",
     (controller->ucFanParameters &
      ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
   rdev->pm.int_thermal_type = THERMAL_TYPE_NI;
  } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SISLANDS) {
   DRM_INFO("Internal thermal controller %s fan control\n",
     (controller->ucFanParameters &
      ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
   rdev->pm.int_thermal_type = THERMAL_TYPE_SI;
  } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_CISLANDS) {
   DRM_INFO("Internal thermal controller %s fan control\n",
     (controller->ucFanParameters &
      ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
   rdev->pm.int_thermal_type = THERMAL_TYPE_CI;
  } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_KAVERI) {
   DRM_INFO("Internal thermal controller %s fan control\n",
     (controller->ucFanParameters &
      ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
   rdev->pm.int_thermal_type = THERMAL_TYPE_KV;
  } else if (controller->ucType ==
      ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) {
   DRM_INFO("External GPIO thermal controller %s fan control\n",
     (controller->ucFanParameters &
      ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
   rdev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL_GPIO;
  } else if (controller->ucType ==
      ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) {
   DRM_INFO("ADT7473 with internal thermal controller %s fan control\n",
     (controller->ucFanParameters &
      ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
   rdev->pm.int_thermal_type = THERMAL_TYPE_ADT7473_WITH_INTERNAL;
  } else if (controller->ucType ==
      ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL) {
   DRM_INFO("EMC2103 with internal thermal controller %s fan control\n",
     (controller->ucFanParameters &
      ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
   rdev->pm.int_thermal_type = THERMAL_TYPE_EMC2103_WITH_INTERNAL;
  } else if (controller->ucType < ARRAY_SIZE(pp_lib_thermal_controller_names)) {
   DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n",
     pp_lib_thermal_controller_names[controller->ucType],
     controller->ucI2cAddress >> 1,
     (controller->ucFanParameters &
      ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
   rdev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL;
   i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine);
   rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
   if (rdev->pm.i2c_bus) {
    struct i2c_board_info info = { };
    const char *name = pp_lib_thermal_controller_names[controller->ucType];
    info.addr = controller->ucI2cAddress >> 1;
    strscpy(info.type, name, sizeof(info.type));
    i2c_new_client_device(&rdev->pm.i2c_bus->adapter, &info);
   }
  } else {
   DRM_INFO("Unknown thermal controller type %d at 0x%02x %s fan control\n",
     controller->ucType,
     controller->ucI2cAddress >> 1,
     (controller->ucFanParameters &
      ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
  }
 }
}

void radeon_atombios_get_default_voltages(struct radeon_device *rdev,
       u16 *vddc, u16 *vddci, u16 *mvdd)
{
 struct radeon_mode_info *mode_info = &rdev->mode_info;
 int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
 u8 frev, crev;
 u16 data_offset;
 union firmware_info *firmware_info;

 *vddc = 0;
 *vddci = 0;
 *mvdd = 0;

 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
       &frev, &crev, &data_offset)) {
  firmware_info =
   (union firmware_info *)(mode_info->atom_context->bios +
      data_offset);
  *vddc = le16_to_cpu(firmware_info->info_14.usBootUpVDDCVoltage);
  if ((frev == 2) && (crev >= 2)) {
   *vddci = le16_to_cpu(firmware_info->info_22.usBootUpVDDCIVoltage);
   *mvdd = le16_to_cpu(firmware_info->info_22.usBootUpMVDDCVoltage);
  }
 }
}

static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rdev,
             int state_index, int mode_index,
             struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info)
{
 int j;
 u32 misc = le32_to_cpu(non_clock_info->ulCapsAndSettings);
 u32 misc2 = le16_to_cpu(non_clock_info->usClassification);
 u16 vddc, vddci, mvdd;

 radeon_atombios_get_default_voltages(rdev, &vddc, &vddci, &mvdd);

 rdev->pm.power_state[state_index].misc = misc;
 rdev->pm.power_state[state_index].misc2 = misc2;
 rdev->pm.power_state[state_index].pcie_lanes =
  ((misc & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >>
   ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;
 switch (misc2 & ATOM_PPLIB_CLASSIFICATION_UI_MASK) {
 case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY:
  rdev->pm.power_state[state_index].type =
   POWER_STATE_TYPE_BATTERY;
  break;
 case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED:
  rdev->pm.power_state[state_index].type =
   POWER_STATE_TYPE_BALANCED;
  break;
 case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE:
  rdev->pm.power_state[state_index].type =
   POWER_STATE_TYPE_PERFORMANCE;
  break;
 case ATOM_PPLIB_CLASSIFICATION_UI_NONE:
  if (misc2 & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
   rdev->pm.power_state[state_index].type =
    POWER_STATE_TYPE_PERFORMANCE;
  break;
 }
 rdev->pm.power_state[state_index].flags = 0;
 if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY)
  rdev->pm.power_state[state_index].flags |=
   RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
 if (misc2 & ATOM_PPLIB_CLASSIFICATION_BOOT) {
  rdev->pm.power_state[state_index].type =
   POWER_STATE_TYPE_DEFAULT;
  rdev->pm.default_power_state_index = state_index;
  rdev->pm.power_state[state_index].default_clock_mode =
   &rdev->pm.power_state[state_index].clock_info[mode_index - 1];
  if ((rdev->family >= CHIP_BARTS) && !(rdev->flags & RADEON_IS_IGP)) {
   /* NI chips post without MC ucode, so default clocks are strobe mode only */
   rdev->pm.default_sclk = rdev->pm.power_state[state_index].clock_info[0].sclk;
   rdev->pm.default_mclk = rdev->pm.power_state[state_index].clock_info[0].mclk;
   rdev->pm.default_vddc = rdev->pm.power_state[state_index].clock_info[0].voltage.voltage;
   rdev->pm.default_vddci = rdev->pm.power_state <inux/blkmq.
  } else {
   u16 max_vddci =

   if (ASIC_IS_DCE4(rdev))
 radeon_atom_get_max_voltage(rdev,
           SET_VOLTAGE_TYPE_ASIC_VDDCI   *osthandle
           
   the table withthe  sclk from firmware  *
 nvmet_req  req;
    rdev->pm.power_state[state_index].clock_info[j].mclk =
     rdev->clock  dev;/* dev for dma mapping */
    rdev->pm.power_state structjava.lang.StringIndexOutOfBoundsException: Range [19, 17) out of bounds for length 29
     rdev->clock.;
  if(ddc
  te.clock_infoj.voltage.oltage=
      vddc;
   if(max_vddci
    rdev->mpower_state[state_index].clock_info[j].voltage.vddci =
    max_vddci;
   }
  }
 }
}

void *osthandle
    int , int mode_index,
         union nvmet_fc_tgtport *tgtportjava.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35
{
 u32 sclk, mclk;
 u16 vddc;

 if (rdev->flags & RADEON_IS_IGP) {
 if>family= java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
   sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
   sclk |= clock_info->sumo.ucEngineClockHigh << 16;
   rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
  } else {
   sclk = le16_to_cpu(clock_info->rs780.usLowEngineClockLow);
   sclk |= clock_info->rs780.ucLowEngineClockHigh << 16;
 power_statestate_index.clock_info[mode_index].sclk = sclk;
  }
 } elsestatic inline u64
 java.lang.StringIndexOutOfBoundsException: Range [7, 6) out of bounds for length 54
  sclk |= clock_infostruct nvmet_fc_target_port
  mclk = le16_to_cpu(clock_info->ci.nvmet_req_to_fod( *nvme_req)
  mclk
  rdev>.power_state[]clock_info[mode_index].mclk = mclk
  rdev-voidnvmet_fc_fcp_rqst_op_defer_work(tructwork_struct *work);
 rdev-power_statestate_index].java.lang.StringIndexOutOfBoundsException: Range [47, 46) out of bounds for length 73
   VOLTAGE_NONE
 } else if (rdev->family  nvmet_fc_ls_req_op,java.lang.StringIndexOutOfBoundsException: Index 58 out of bounds for length 58
    clock_info->si.usEngineClockLow);
sclk>siucEngineClockHigh 16
  mclk =
  mclk |= clock_info->si.ucMemoryClockHigh << 16;
  rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk;
  rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
  rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
   VOLTAGE_SW;
  rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
   le16_to_cpu(clock_info->si.usVDDC);
  rdev->pm.power_state[state_index].clock_info[mode_index].voltage.vddci =
   le16_to_cpu(clock_info->si.usVDDCI);
 } else if (rdev->family >= CHIP_CEDAR) {
  sclkint
  sclk |= java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 0
 dir
  mclk |= clock_info->evergreen.ucMemoryClockHigh << 16;
>m[]clock_info[]mclk = mclk
->.power_statestate_index]clock_info[mode_index].sclk = sclk;
  rdev->pm.power_state[state_index].clock_info[mode_index]  (fc_dma_mapping_error(tgtport->dev, lsreq->rqstdma)) {
   java.lang.StringIndexOutOfBoundsException: Range [8, 7) out of bounds for length 34
  rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
   le16_to_cpu(clock_info->evergreen.usVDDC);
  rdev->pm.power_state[state_index].clock_info[mode_index].voltage.vddci =
   le16_to_cpu(clock_info->evergreen.usVDDCI);
 } else {
  sclk = le16_to_cpu(clock_info->r600.struct fcnvme_ls_disconnect_assoc_acc *discon_acc
 sclk | clock_info-r600.ucEngineClockHigh < 16
 mclk =le16_to_cpu(lock_infor600usMemoryClockLow)
  mclk |= clock_info->r600.ucMemoryClockHigh << 16;
  rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk;
  rdev->pm.power_state java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
 -power_states.[mode_indexvoltagetype java.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73
   VOLTAGE_SW;
  rdev->pm.power_state[state_index].clock_info> = java.lang.StringIndexOutOfBoundsException: Range [25, 24) out of bounds for length 25
 java.lang.StringIndexOutOfBoundsException: Range [15, 14) out of bounds for length 40
 }

/* patch up vddc if necessary */

 switch (rdev->pm.power_state[iod->;
 casejava.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
 case ATOM_VIRTUAL_VOLTAGE_ID1:
 case ATOM_VIRTUAL_VOLTAGE_ID2:
 casejava.lang.StringIndexOutOfBoundsException: Range [31, 30) out of bounds for length 31
 case ATOM_VIRTUAL_VOLTAGE_ID4:
  ATOM_VIRTUAL_VOLTAGE_ID5
 case ATOM_VIRTUAL_VOLTAGE_ID6:
 case ATOM_VIRTUAL_VOLTAGE_ID7:
  if ( kfree(tgtport->iod
          rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage(struct java.lang.StringIndexOutOfBoundsException: Range [47, 45) out of bounds for length 55
          &vddc) == 0-> );
   rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = vddc;
 ;
 default:
  break;
 }

 if (rdev->flags & nvmet_fc_prep_fcp_iodlist *tgtportjava.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59
  /* skip invalid modes */
  if (rdev->pm.power_state[java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 25
 ;
 } else {
/
  if ((rdev->pm.power_state[java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 28
      (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0))
   return false;
 }
 return true
}

static int
{
 struct radeon_mode_info *mode_info = &rdev->mode_info;
 struct _java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 4
 union pplib_power_state *power_state;
 int i, j;
 int state_index = 0, mode_index = 0;
 union pplib_clock_info *clock_info;
 bool valid;
 union power_info *power_info;
 int index =   fod
  data_offset;
 u8 frev, crev;

 if (!nvmet_fc_tgtportjava.lang.StringIndexOutOfBoundsException: Range [56, 55) out of bounds for length 56
       &frev, &crev, &data_offset))
  return /*
 power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);

 radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController);
 if (power_info->  ((-qid -1 -o : 0
  return state_index;
 rdev->pm.power_state = kcalloc(power_info->pplib.ucNumStates,
           sizeof(struct radeon_power_state),
           GFP_KERNEL);
 if (!> = false;
   fod->ritedataactive = false;
/* first mode is usually default, followed by low to high */

 for (i = 0; i <
  mode_index = 0;
  power_state = (union pplib_power_state *)
   (mode_info->atom_context->bios + data_offset +
    le16_to_cpu(power_info->pplib.usStateArrayOffset) +
    i * power_info->pplib.ucStateEntrySize>opsps-defer_rcv&fc_target_port;
 non_clock_info  (_ *)
   (mode_info->atom_context->bios + data_offset +
    le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) +
    (power_state
     power_info->pplib.ucNonClockSize));
  rdev->pm.power_state[i].clock_info =
   kcalloc ;
    (power_info->pplib.ucStateEntrySize - 1) : 1,
   s java.lang.StringIndexOutOfBoundsException: Range [39, 38) out of bounds for length 40
    java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 0
  if (!rdev->pm.power_state[i].clock_info)
   return state_index;
  if (power_info->atomic_set(&queue->sqtail;
   spin_&-qlock);
    clock_info = (union pplib_clock_info *)
     (mode_info->atom_context->bios + data_offset =nvmet_sq_init(java.lang.StringIndexOutOfBoundsException: Range [28, 27) out of bounds for length 55
    (-sClockInfoArrayOffset+
      (power_state->v1.ucClockStateIndices[java.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 14
       power_info->pplib.ucClockInfoSize));
    valid
                state_index, mode_index,
                clock_info);
    if (valid)
     mode_index++;
   }
 }else{
   ->cpreq
    rdev->clock.java.lang.StringIndexOutOfBoundsException: Range [0, 28) out of bounds for length 3
 -power_state[state_index.java.lang.StringIndexOutOfBoundsException: Range [48, 47) out of bounds for length 57
    rdev->clock.default_sclk;
   mode_index++;
  }
 = mode_index;
  if (mode_index) {
   radeon_atombios_parse_pplib_non_clock_info(rdev, state_index, mode_index
           -fcp_req_release(tgtport>,
   state_index++;
  }
 }
 /* if multiple clock modes, mark the lowest as no display */
 for (i = 0; i < state_index; i++) {
  if (rdev->pmflush_workqueue(queue-work_q)java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
   rdev->pm.power_state[i].clock_info[0].flags |=
    java.lang.StringIndexOutOfBoundsException: Range [0, 29) out of bounds for length 1
 }
 /* first mode is usually default */
if(rdev->pm.default_power_state_index==-1) {
  rdev->pm.power_state[0].type =
 ;
  rdev->pm.default_power_state_index = 0 if(ssociation_id == assoc->association_id) {
  rdev->pm.power_state[0].default_clock_mode =
  &rdev->power_state[].lock_info[]
 }
 return state_index;
}

static int radeon_atombios_parse_power_table_6(java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
{
 radeon_mode_info * = &dev;
 struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
 union pplib_power_state *power_state;
 int i, j, non_clock_array_index, clock_array_index;
 int state_index = 0, mode_index = 0;
 union pplib_clock_info *clock_info;
 struct _StateArray *state_array;
 struct _ClockInfoArray *clock_info_array;
 struct _NonClockInfoArray *non_clock_info_array;
 bool valid;
 union power_info *power_info;
 int index =
 u16 data_offset;
  if( == hosthandle&!host-invalid){
 u8   if(vmet_fc_hostport_gethost)java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35

 if (!atom_parse_data_header(mode_info-java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
       &frevstructnvmet_fc_hostport*ewhost match= NULL
  return state_index;
 power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);

 radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.java.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 17
 state_array = (struct _StateArray java.lang.StringIndexOutOfBoundsException: Range [33, 32) out of bounds for length 54
  (mode_info->java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 0
   le16_to_cpu(power_info->pplib.java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 26
 structC*
  (mode_info-> if ){
   le16_to_cpu(java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 17
uctNonClockInfoArrayjava.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
  (mode_info- kref_init(n>ef;
   le16_to_cpu(power_info->pplib.  list_add_tail(newhost>porth)
 if (state_array->ucNumEntries == java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  returnnvmet_fc_delete_assoc_workstruct work_struct *)
 rdev>.power_state  kcalloc(tate_array->ucNumEntries,
           sizeof(struct radeon_power_state),
        java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
 if (!rdev->pm.power_state)
  return state_index;
 power_state_offset = (u8 *)state_array->states;
for( =0 i< state_array->ucNumEntries; i++) {
  mode_index = 0;
  power_state   atomic_xchg&-,1);
  non_clock_array_index
java.lang.StringIndexOutOfBoundsException: Range [17, 16) out of bounds for length 55
   &non_clock_info_array->nonClockInfo[non_clock_array_index];
 -pm.power_state[]clock_infojava.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
   kcalloc(power_state->v2.ucNumDPMLevels ?
    power_state->v2.ucNumDPMLevels : 1,
  sizeof radeon_pm_clock_info)
    GFP_KERNEL);
  if (!rdev->pm.power_state[i].clock_info)
   return state_index;
  if (power_state->nvmet_fc_alloc_target_assoc(nvmet_fc_tgtport*,void*osthandlejava.lang.StringIndexOutOfBoundsException: Index 79 out of bounds for length 79
   for (j = 0; 
    clock_array_index = power_state->v2.clockInfoIndex[jjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
    clock_info = (union pplib_clock_info *)
     &clock_info_array-  idx< 0)
    valid = radeon_atombios_parse_pplib_clock_info(java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 29
                state_index, mode_index,
      java.lang.StringIndexOutOfBoundsException: Range [12, 10) out of bounds for length 57
    if (valid)
     mode_index++;
   }
}

    rdev->clock.default_mclk;
  
    rdev->clock.default_sclk;
   mode_index++;
  }
  rdev-
  if (mode_index) {
   radeon_atombios_parse_pplib_non_clock_info(rdev, state_index, mode_index,
           non_clock_info);
   state_index++;
 java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
 power_state_offset +2 +java.lang.StringIndexOutOfBoundsException: Range [40, 39) out of bounds for length 59
 }
 /* if multiple clock modes, mark the lowest as no display */
 for (i = 0; i < state_index; i++tassoc)
  if (rdev->pm.power_state[i spin_unlock_irqrestore(&tgtport->lock, flags);
   rdev->pm.power_state[i].clock_info[0].flags |=
    RADEON_PM_MODE_NO_DISPLAY; ida_free&tgtport->assoc_cnt,assoc>)
 }
 /* first mode is usually default */
 if (rdev->pm.default_power_state_index == -1) {
  rdev->pm.power_state[0].type =
 java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 >default_power_state_index0;
  rdev->pm.power_state
   &rdev->pm.power_state[0].clock_info[0];
}
 return state_index;
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1

void radeon_atombios_get_power_modes(struct java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 0
{
 struct radeon_mode_info *mode_info = &rdev->mode_info;
 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
 u16 data_offset;
 u8  "{%d:%}\"
 int state_index = 0;

  1

 if (atom_parse_data_header(mode_info->atom_context, java.lang.StringIndexOutOfBoundsException: Index 55 out of bounds for length 0
       &frev, &crev, &data_offset)) {
  switch (frev (assoc
 java.lang.StringIndexOutOfBoundsException: Range [8, 7) out of bounds for length 12
 casejava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
  case 3:
   state_index = radeon_atombios_parse_power_table_1_3
   break;
 :
   case
   state_index long flags;
    ( )
  case 6:
   state_index = radeon_atombios_parse_power_table_6(rdev);
   break;
  default:
   break;
  }


 java.lang.StringIndexOutOfBoundsException: Range [18, 16) out of bounds for length 24
  rdev->pm.()java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
  if (rdev->pm.power_state) {
   rdevjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
    kcalloc(1,
            sizeof(struct radeon_pm_clock_info),
            GFP_KERNEL);
   if (rdev->pm.power_state[0].clock_info) {
 *
    rdev->pm.power_state[state_index].type =
     POWER_STATE_TYPE_DEFAULT;
    rdev->pm.power_state[state_index].num_clock_modes = 1;
  rdev>power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
    rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
    rdev->pm.power_state[state_index].default_clock_mode =
  &>.java.lang.StringIndexOutOfBoundsException: Range [27, 26) out of bounds for length 54
    rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
    rdev->struct *java.lang.StringIndexOutOfBoundsException: Index 63 out of bounds for length 63
    rdev->pm.default_power_state_index = java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 45
    rdev-    -java.lang.StringIndexOutOfBoundsException: Range [30, 29) out of bounds for length 59
    state_index++;
   }
  }
 }

 rdev->pm.num_power_states = state_index;

 rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
java.lang.StringIndexOutOfBoundsException: Range [7, 5) out of bounds for length 39
 if (rdev->pm.default_power_state_index >= 0)
  rdev->pm.current_vddc =
   rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
 else
 rdev>m.=0;
}

union get_clock_dividers {
 struct v1;
 struct _java.lang.StringIndexOutOfBoundsException: Range [49, 48) out of bounds for length 52
 struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3completionstatus be0uponsuccess java.lang.StringIndexOutOfBoundsException: Range [58, 49) out of bounds for length 64
 struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 v4;
 struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5 v5;
 struct _COMPUTE_GPU_CLOCK_INPUT_PARAMETERS_V1_6 v6_in;

};

int radeon_atom_get_clock_dividers(struct radeon_device *rdev,
        structnvmet_fc_target_port **ortptr)
      java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
       bool strobe_mode,
       structf |
{
 union get_clock_dividers args;
 int index = GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL);
 u8 frev, crev;

 memset )
 memsetret=-NOMEM

 if (!atom_parse_cmd_header(rdev->mode_info.atom_context, java.lang.StringIndexOutOfBoundsException: Range [0, 63) out of bounds for length 52
  return -EINVAL;

 switch (crev) {
case1:
  /* r4xx, r5xx */
  args.v1.ucAction = clock_type;
  args.v1.ulClock =  newrec-private=&newrec[1];

  atom_execute_table(rdev->mode_info.atom_context, java.lang.StringIndexOutOfBoundsException: Index 55 out of bounds for length 35

 (newrec>ls_rcv_lists_rcv_list)java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
  dividers->fb_div = args.v1.ucFbDiv INIT_LIST_HEAD(&ewrec->s_busylist);
  dividers->enable_post_div = (-java.lang.StringIndexOutOfBoundsException: Range [36, 35) out of bounds for length 37
  break;
 case
 :
 5
  /* r6xx, r7xx, evergreen, ni, si */
  spin_lock_irqsave)
 v2=;
 v2ulClock=c);/* 10 khz */

   atom_execute_table(rdev ()

   dividers->post_div = args.v2.ucPostDiv;
   dividers->fb_div = le16_to_cpu(  java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
   dividers->ref_div = args.v2.ucAction;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
    dividers->enable_post_div = (le32_to_cpu(java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 39
     true : false;
   dividers->vco_mode  (e32_to_cpu(args.v2.ulClock) & (1 << 25)) ? 1 : 0;
    
 =dividersfb_div )?truefalse
  } else {
   if (clock_type == COMPUTE_ENGINE_PLL_PARAM) {
    args.v3.ulClockParams = cpu_to_le32((clock_type << 24) | clock);

    atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args, sizeof(args));

-post_div .ucPostDiv
    dividers->enable_post_div = (args.v3.ucCntlFlag &
            ATOM_PLL_CNTL_FLAG_PLL_POST_DIV_EN) ? true : false;
    dividers->enable_dithen = (args.v3.ucCntlFlag &
          ATOM_PLL_CNTL_FLAG_FRACTION_DISABLE) ? false : true;
    dividers->whole_fb_div = le16_to_cpu(args.v3.ulFbDiv.usFbDiv);
    dividers->;
    dividers->ref_div = args (!vmet_fc_tgt_a_get(
    dividers->vco_mode = (args.v3.ucCntlFlag  nvmet_fc_tgt_a_puta);
            ATOM_PLL_CNTL_FLAG_MPLL_VCO_MODE) ? 1 : 0;
   } else {
    /* for SI we use ComputeMemoryClockParam for memory plls */
    if (rdev->family >=  *                        remove a  '
     return -EINVAL;
    args.v5.ulClockParams = cpu_to_le32((clock_type << 24) | clock);
    if (strobe_mode)
     args.v5.ucInputFlag = ATOM_PLL_INPUT_FLAG_PLL_STROBE_MODE_EN;

    atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args, sizeof(args));

    dividers->post_div = args.v5.ucPostDiv;
    dividers->enable_post_div = (args.v5.ucCntlFlag &
            ATOM_PLL_CNTL_FLAG_PLL_POST_DIV_EN) ? true : false;
    dividers->enable_dithen = (args.v5.ucCntlFlag &
          ATOM_PLL_CNTL_FLAG_FRACTION_DISABLE) ? false : true;
    dividers->whole_fb_div = le16_to_cpu(args.v5.ulFbDiv.usFbDiv);
    dividers->frac_fb_div = le16_to_cpu(args.v5.ulFbDiv.usFbDivFrac);
    dividers->ref_div = args.v5.ucRefDiv;
    dividers->vco_mode = (args.v5.ucCntlFlag &
            ATOM_PLL_CNTL_FLAG_MPLL_VCO_MODE) ? 1 : 0;
   }
  }
  break;
 case 4:
  /* fusion */
  args.v4.ulClock = cpu_to_le32(clock); /* 10 khz */

  atom_execute_table(rdev->mode_info   bythe-transport -ctransport may

  dividers->post_divider = dividers->post_div = args.v4.  continuetoreferencehost handlewhile it cleans up 
  dividers->real_clock = le32_to_cpu(args.v4.ulClock);
  break;
 case 6:
  /* CI */
 */
  args.v6_in.ulClock.ulComputeClockFlag = clock_type;
  args.v6_in.ulClock.ulClockFreq = cpu_to_le32(clock); /* 10 khz */

  atom_execute_table(rdev->struct*,*;

  dividers->
  dividers->frac_fb_div = java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 12
  dividers->ref_div = args.v6_out.ucPllRefDiv;
  dividers->post_div = args.v6_out.ucPllPostDiv;
  java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 3
  dividers->real_clock = le32_to_cpu(args.v6_out.ulClock.ulClock);
  dividers->post_divider = args.v6_out.ulClock.ucPostDiv;
  break;
 default:
  return -EINVAL;
 }
 return 0;
}

int radeon_atom_get_memory_pll_dividers(struct radeon_device *rdev,
     u32 clock,
     bool strobe_mode,
     struct @ java.lang.StringIndexOutOfBoundsException: Range [25, 24) out of bounds for length 70
{
COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_1
 int index = GetIndexIntoMasterTable(COMMAND, ComputeMemoryClockParam);
 u8 frev, crev;

 memset(&args, 0, sizeof(args));
 memset(mpll_param, java.lang.StringIndexOutOfBoundsException: Range [19, 18) out of bounds for length 45

 if (_java.lang.StringIndexOutOfBoundsException: Range [24, 23) out of bounds for length 33
  return -EINVAL;

 switch (frev) {
 case 2:
  switch (crev) {
  case   assizes
   /* SI */
   java.lang.StringIndexOutOfBoundsException: Range [63, 7) out of bounds for length 63
   args.ucInputFlag = 0;
   if (strobe_mode)
    args.ucInputFlag |= MPLL_INPUT_FLAG_STROBE_MODE_EN;

 rdevmargs,sizeof)java.lang.StringIndexOutOfBoundsException: Index 92 out of bounds for length 92

   mpll_param->clkfrac = le16_to_cpu(args.ulFbDiv.usFbDivFrac java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
  clkf java.lang.StringIndexOutOfBoundsException: Range [34, 33) out of bounds for length 56
   mpll_param->post_div = args.ucPostDiv;
   mpll_param->dll_speed = args.ucDllSpeed;
      java.lang.StringIndexOutOfBoundsException: Range [32, 31) out of bounds for length 32
   mpll_param->vco_mode =
    (args.ucPllCntlFlag & MPLL_CNTL_FLAG_VCO_MODE_MASK tgtport->dev,
  y =
    java.lang.StringIndexOutOfBoundsException: Range [57, 54) out of bounds for length 64
   mpll_param->qdr =
    (args.ucPllCntlFlag & MPLL_CNTL_FLAG_QDR_ENABLEjava.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 9
   queue->ersp_ratio = be16_to_cpu(rqst->assoc_cmd.ersp_ratio);
    (args.ucPllCntlFlag & >  ;/* best place to init value */
   break;
  default:
   return -EINVAL;
  }
  break;
 default:
  return -EINVAL;
}
 return 0;
}

void radeon_atom_set_clock_gating(struct radeon_device *void radeon_atom_set_clock_gating(struct radeon_device *rdev
{
  java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
rTable(OMMAND );

 args.ucEnable = enable;

 java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 0
}

java.lang.StringIndexOutOfBoundsException: Range [25, 8) out of bounds for length 65
{
 s ))
 int index = GetIndexIntoMasterTable(java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 30

 atom_execute_table if(-desc_len!java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35
 ulReturnEngineClock
}

( radeon_device*rdev)
{
   ;
 int index = GetIndexIntoMasterTable(COMMAND else{

 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args, sizeof if !-)
return(.);
}

void radeon_atom_set_engine_clock(struct   java.lang.StringIndexOutOfBoundsException: Range [35, 34) out of bounds for length 44
      uint32_t eng_clock)
{
 SET_ENGINE_CLOCK_PS_ALLOCATION args;
 int index = GetIndexIntoMasterTable

 args.ulTargetEngineClock = cpu_to_le32(eng_clock" failed sn,

 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args, sizeof(java.lang.StringIndexOutOfBoundsException: Index 85 out of bounds for length 26
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1

void java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 1
 /
{
 SET_MEMORY_CLOCK_PS_ALLOCATION args;
 int index = GetIndexIntoMasterTable(COMMAND, SetMemoryClock);

 if (rdev->flags & RADEON_IS_IGP)
  return;

  nvmet_fc_tgtporttgtport

-., ,(int32_t)args,(args);
}

void java.lang.StringIndexOutOfBoundsException: Range [41, 40) out of bounds for length 68
      u32 eng_clock, u32 mem_clock)
{
 SET_ENGINE_CLOCK_PS_ALLOCATION args;
 int index = GetIndexIntoMasterTable(COMMAND, DynamicMemorySettingsjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 u32 tmp)java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12

 memset(&args, 0, sizeof(args));

 tmp = eng_clock & SET_CLOCK_FREQ_MASK;
 tmp |= (COMPUTE_ENGINE_PLL_PARAM << 24);

 args.ulTargetEngineClock r | assoc {
 if mem_clock)
  args.sReserved.ulClock = cpu_to_le32(mem_clock & SET_CLOCK_FREQ_MASK);

 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args, sizeof(args));
}

void radeon_atom_update_memory_dll ret==VERR_NO_ASSOC java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
       u32 mem_clock)
{
 u32 args;
 /

 args =java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 atom_execute_table(rdev->java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}

voidradeon_atom_set_ac_timingradeon_devicerdev,
          u32 mem_clock)
{
 SET_MEMORY_CLOCK_PS_ALLOCATION args;
 int index = GetIndexIntoMasterTable(COMMAND, DynamicMemorySettings);
 u32 tmp = mem_clock | (COMPUTE_MEMORY_PLL_PARAM << 24);

 args.ulTargetMemoryClock = cpu_to_le32(tmp); /* 10 khz */

 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args, sizeof(args));
}

union set_voltage {
 struct _ *it the one send 'reject
 struct _SET_VOLTAGE_PARAMETERS v1;
 struct _SET_VOLTAGE_PARAMETERS_V2 v2;
 struct _SET_VOLTAGE_PARAMETERS_V1_3 v3;
};

void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type)
{  {%:%}Multiple Disconnect AssociationLS java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50
 union set_voltage args;
 int index = GetIndexIntoMasterTable(COMMAND, SetVoltage);
 u8 frev, crev, volt_index = voltage_level;    sizeof(iod>rspbuf)java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27

 if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &java.lang.StringIndexOutOfBoundsException: Index 68 out of bounds for length 25
  return;

 /* 0xff01 is a flag rather then an actual voltage */
 if (voltage_level == 0xff01)
  return;

 )
 case 1:
  args.java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
  argsjava.lang.StringIndexOutOfBoundsException: Range [26, 24) out of bounds for length 49
  break;
 case 2:
  args.v2.ucVoltageType
  args  ret
 args.2.sVoltageLevel= cpu_to_le16(voltage_level);
  break;
 case 3:
  args.v3.ucVoltageType = voltage_type;
  args.v3.ucVoltageMode = ATOM_SET_VOLTAGE;
  args.v3.usVoltageLevel = cpu_to_le16(voltage_level);
  break;
 default:
  DRM_ERROR("Unknown  DRM_ERROR("Unknown table  receivedFCNVME LS java.lang.StringIndexOutOfBoundsException: Range [62, 61) out of bounds for length 74
  return;
 }

 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args, sizeof(args));
}

int radeon_atom_get_max_vddc(struct radeon_device *rdev, u8 java.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 34
        u16 voltage_id, iod->->one = nvmet_fc_xmt_ls_rsp_done;
{
 union set_voltage args;
 int index = GetIndexIntoMasterTable(COMMAND /*
 u8 frev, crev;

 if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
  return -EINVAL;

 switch (crev) {
 case 1:
  return -EINVAL;
 case 2:
  args.v2.ucVoltageType = SET_VOLTAGE_GET_MAX_VOLTAGE;
  args.v2.ucVoltageMode = 0;
  args.v2.usVoltageLevel = 0;

 java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

  *voltage = le16_to_cpu(args.v2.usVoltageLevel
  break;
 case 3:
  args.v3.ucVoltageType = voltage_type;
  args.v3.ucVoltageMode = ATOM_GET_VOLTAGE_LEVEL;
  args.v3.usVoltageLevel = java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 1

  atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args, sizeof(args));

  *voltage *
  break;
 default:
  DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
  return -EINVAL;
 }

 return 0;
}

int radeon_atom_get_leakage_vddc_based_on_leakage_idx *rdev,
            u16 *voltage,
            u16 leakage_idx)
{
 return radeon_atom_get_max_vddc(rdev, VOLTAGE_TYPE_VDDC, leakage_idx, voltage);
}

int radeon_atom_get_leakage_id_from_vbioslsreqbuf_len:in bytes, received LS 
       u16 *leakage_id)
{
    hosthandle,
 int index = GetIndexIntoMasterTable(COMMAND, SetVoltage);
 u8 frev, crev;

 if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
  return -EINVAL;

 switch (crev) {
 case 3:
 case 4:
  args.v3.ucVoltageType = 0;
  args.v3.ucVoltageMode = ATOM_GET_LEAKAGE_ID;
  args.v3.usVoltageLevel = 0;

 rdev->ode_info.atom_context,index,( *&argssizeof();

  *leakage_id = le16_to_cpu(args.v3.usVoltageLevel);
  break;
 default:
  DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
  return -java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 1
 }

 return 0;
}

int radeon_atom_get_leakage_vddc_based_on_leakage_params(struct radeon_device *rdev *Start  FCP 
 nvmet_fc_alloc_tgt_pgs(struct nvmet_fc_fcp_iod *)
        u16 virtual_voltage_id,
        u16 vbios_voltage_id)
{
 int index = GetIndexIntoMasterTable(DATA, ASIC_ProfilingInfo);
 u8 frev, crev;
 u16 data_offset, size;
 int i, jreturn 0;
 ATOM_ASIC_PROFILING_INFO_V2_1 *profile;
 u16 *leakage_bin, *vddc_id_buf, *vddc_buf, *vddci_id_buf, *vddci_buf;

  = 0;
 *vddci = 0;

 if (!atom_parse_data_header(rdev->mode_info.atom_context, index, &size,
        &frev, &crev, &data_offset))
  return -EINVAL;

 profile = (ATOM_ASIC_PROFILING_INFO_V2_1 *)
  (rdev->mode_info.atom_context->bios + data_offset);

 switch (
 case 1:
  return -EINVAL;
 case 2:
  switch (crev) {
  case 1:
   if (size < sizeof(ATOM_ASIC_PROFILING_INFO_V2_1))
    return -EINVAL;
   leakage_bin = (u16 *)
    (rdev->mode_info.atom_context->bios + data_offset +
     le16_to_cpu(profile->usLeakageBinArrayOffset));
   vddc_id_buf = (u16 *)
    (rdev->mode_info.atom_context->bios + data_offset +
     le16_to_cpu(profile->usElbVDDC_IdArrayOffset));
   vddc_buf = (u16 *)
    (rdev->mode_info.atom_context->bios + data_offset +
     le16_to_cpu(profile->usElbVDDC_LevelArrayOffset));
   vddci_id_buf = (u16 *)
    (    -CQE  knownin 
     le16_to_cpu(profile->usElbVDDCI_IdArrayOffset));
   vddci_buf = (u16 *)
    (rdev->mode_info.atom_context->bios + data_offset +
     le16_to_cpu(profile->usElbVDDCI_LevelArrayOffset));

   if (profile->ucElbVDDC_Num > 0) {
    for (i = 0; i < profile->ucElbVDDC_Num; i++) {
 java.lang.StringIndexOutOfBoundsException: Range [48, 45) out of bounds for length 48
      for (j = 0; j <      (le16_to_cpu(cqe->statusxFFFE)| [0]|cqewd]|
       
  ,java.lang.StringIndexOutOfBoundsException: Range [44, 42) out of bounds for length 44
 > =cpu_to_be16sizeof(ersp/()java.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 56
       }
      }
      break;
     }
    }
   }
   if (profile->ucElbVDDCI_Num > 0) {
    for (  *cpreq  -fcpreq;
     if (vddci_id_buf[i] == virtual_voltage_id) {
      for (j = 0; j < profile->ucLeakageBinNum; j++) {
       if  (ajava.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
        *vddci = vddci_buf[
 (tgtport
       }
     }
       fod->fcpre-op ;
    
    }
   }
   break;
  default:
   DRM_ERROR("Unknown table (  *gtportjava.lang.StringIndexOutOfBoundsException: Index 60 out of bounds for length 60
    struct s*  >ext_sgjava.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
  }
  break;

     ;
  return -EINVAL;
 }

 return 0;
}

union get_voltage_info {
 struct  _GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_2 in;
 struct  _GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_2 evv_out;
};

int radeon_atom_get_voltage_evv(struct radeon_device *rdev,
    u16 virtual_voltage_id,
    u16 *voltage)
{
 int index = GetIndexIntoMasterTable(COMMAND, GetVoltageInfo);
 u32 entry_id;
 u32 count = rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.count;
 union get_voltage_info args;

 for (entry_id = 0; entry_id < count; entry_id++) {
.[]v =java.lang.StringIndexOutOfBoundsException: Index 75 out of bounds for length 75
      virtual_voltage_id)
   break;
 }

 if (entry_id >= count)
  return -EINVAL;

 args.in.ucVoltageType = VOLTAGE_TYPE_VDDC;
 args.in.java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 2
 args.in.usVoltageLevel = cpu_to_le16(virtual_voltage_id);
 args.in.ulSCLKFreq =
  cpu_to_le32(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[entry_id].clk);

 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args, sizeof(args));

 *voltage = le16_to_cpu(args.evv_out.usVoltageLevel);

 return 0;
}

int radeon_atom_get_voltage_gpio_settings(struct radeon_device *rdev,
       u16 voltage_level, u8 voltage_type,
       u32 *gpio_value, u32 *gpio_mask)
{
 union set_voltage args;
 int index = GetIndexIntoMasterTable(COMMAND, SetVoltage);
 u8 frev, crev;

 if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
  return -EINVAL;

 switch (crev) {
 case 1:
  return -EINVAL;
 case 2:
  args.v2.ucVoltageType = voltage_type;
  args.v2.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_GET_GPIOMASK;
  args.v2.usVoltageLevel = cpu_to_le16(voltage_level);

  atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args, sizeof(args));

  *gpio_mask = le32_to_cpu(*(u32 *)&args.v2);

  args.v2.ucVoltageType = voltage_type;
  args.v2.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_GET_GPIOVAL;
   = cpu_to_le16(


  (->ode_infoatom_context, index, (uint32_t *)&args, sizeof(args));

  *gpio_value = le32_to_cpu(*(u32 *)&args.v2);
  break;
 default:
  DRM_ERROR("Unknown table version %d, %d return;
  return -EINVAL;
 }

 return 0;
java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 1

union voltage_object_info {
 struct _ATOM_VOLTAGE_OBJECT_INFO v1;
 struct _ATOM_VOLTAGE_OBJECT_INFO_V2 v2;
 struct _ATOM_VOLTAGE_OBJECT_INFO_V3_1 v3;
};

union voltage_object {
 struct _ATOM_VOLTAGE_OBJECT v1;
 struct _ATOM_VOLTAGE_OBJECT_V2 v2;
 union _ATOM_VOLTAGE_OBJECT_V3 v3;
};

static ATOM_VOLTAGE_OBJECT *atom_lookup_voltage_object_v1(ATOM_VOLTAGE_OBJECT_INFO *v1,
         u8 voltage_type)
{
 u32 size = le16_to_cpu(v1->sHeader.usStructureSize);
 u32 offset  nvmet_fc_free_tgt_pgs(fod);
 u8 *start = (u8 *)v1;

 while (offset < size) {
  ATOM_VOLTAGE_OBJECT *vo = (ATOM_VOLTAGE_OBJECT *)(start + offset);
  if (vo-ucVoltageType=
   return vo;
  offset += offsetof(ATOM_VOLTAGE_OBJECT, asFormula.ucVIDAdjustEntries) +
   vo->asFormula.ucNumOfVoltageEntries;
 }
 return NULL;
}

static ATOM_VOLTAGE_OBJECT_V2 *atom_lookup_voltage_object_v2(ATOM_VOLTAGE_OBJECT_INFO_V2 *v2,
            u8 voltage_type)
{
 u32 size = le16_to_cpu(v2->sHeader.usStructureSize);
 u32 offset = offsetof(ATOM_VOLTAGE_OBJECT_INFO_V2, asVoltageObj[0]);
 u8 *start = (u8 *)v2;

 while (offset < size) {
  ATOM_VOLTAGE_OBJECT_V2 *vo = (ATOM_VOLTAGE_OBJECT_V2 *)(start + offset);
  if (vo->ucVoltageType == voltage_type)
   return vo;
  offset += offsetof(ATOM_VOLTAGE_OBJECT_V2, asFormula.asVIDAdjustEntries) +
   (vo->asFormula.ucNumOfVoltageEntries * sizeof(VOLTAGE_LUT_ENTRY));
 }
 return NULL;
}

static ATOM_VOLTAGE_OBJECT_V3 *atom_lookup_voltage_object_v3java.lang.StringIndexOutOfBoundsException: Range [2, 1) out of bounds for length 8
            u8 java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 8
{
 u32 size = le16_to_cpu(v3->sHeader.usStructureSize);
 u32 offset = offsetof(ATOM_VOLTAGE_OBJECT_INFO_V3_1, asVoltageObj[0]);
 u8 *start = (u8 *)v3;

 while (offset < size) {
  java.lang.StringIndexOutOfBoundsException: Range [56, 24) out of bounds for length 74
  if ((vo->asGpioVoltageObj
      (vo->asGpioVoltageObj.sHeader.ucVoltageMode == voltage_mode))
   return vo;
  offset += le16_to_cpu(vo->asGpioVoltageObj.sHeader.usSize);
 }
 return;
}

bool
radeon_atom_is_voltage_gpio(struct radeon_device *rdev,
       u8 voltage_type, u8 voltage_mode)
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
 int abort) {
 u8 frev, crev;
 u16 data_offset, size;
 union voltage_object_info *voltage_info;
 union voltage_object *voltage_object = NULL;

 if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size,
       &frev, &crev, &data_offset)) {
  voltage_info = (union * try to push the data even java.lang.StringIndexOutOfBoundsException: Range [49, 48) out of bounds for length 61
   (rdev->mode_info.atom_context->bios + data_offset);

  switch (  if ((fod->io_dir == NVMET_FCP_READ) && (fod->data_sg_cnt)) {
  case 1:
   nvmet_java.lang.StringIndexOutOfBoundsException: Range [30, 29) out of bounds for length 43
   switch (crev) {
   case 1:
    voltage_object = (union voltage_object *)
     java.lang.StringIndexOutOfBoundsException: Range [1, 34) out of bounds for length 2
    if (voltage_object &&
        (voltage_object->v1.asControl.ucVoltageControlId == VOLTAGE_CONTROLLED_BY_GPIO))
     return true;
    break;
   case 2:
    voltage_object = (union voltage_object *)
     atom_lookup_voltage_object_v2(&voltage_info->v2, voltage_type);
    if (voltage_object &&
        (voltage_object->v2.asControl.ucVoltageControlId == VOLTAGE_CONTROLLED_BY_GPIO java.lang.StringIndexOutOfBoundsException: Range [26, 24) out of bounds for length 49
     return true;
    break;
   default:
    DRM_ERROR(*
    return false;
   }
    struct f)
  case 3:
   switch (crev) {
   case 1:
    if (java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 3
          voltage_type, voltage_mode))
     return true;
    ;
   default:
    DRM_ERRORjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
    return false;
  >  ;
  break;
  default:
   DRM_ERROR("unknown voltage object table  c>java.lang.StringIndexOutOfBoundsException: Range [25, 24) out of bounds for length 51
   return false;
 }

 }
 return false;
}

int radeon_atom_get_svi2_info(struct radeon_device *rdev,
         u8 voltage_type,
         u8 *svd_gpio_id, u8 *svc_gpio_id)
{
 int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo);
 u8 frev, crev;
 u16 data_offset, size;
 union voltage_object_info *voltage_info;
 union voltage_object *voltage_object = NULL;

 if (atom_parse_data_header(rdev->mode_info.atom_context, java.lang.StringIndexOutOfBoundsException: Index 60 out of bounds for length 45
       &frev, &crev, &data_offset)) {
  voltage_info = (union voltage_object_info *)
   (rdev >.java.lang.StringIndexOutOfBoundsException: Range [24, 22) out of bounds for length 32

  switch (frev) {atomic_inc(&od->>;
  case 3:
   switch (crev) {
   case 1:
    
     atom_lookup_voltage_object_v3(&voltage_info->v3,
              voltage_type,
              VOLTAGE_OBJ_SVID2);
 ( java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
     *svd_gpio_id = voltage_object->v3.asSVID2Obj.ucSVDGpioId;
     *svc_gpio_id = voltage_object->v3.asSVID2Obj.ucSVCGpioId;
    } else {
     return -EINVAL;
    }
    break;
   default:
    DRM_ERROR("unknown voltage object table\n");
 java.lang.StringIndexOutOfBoundsException: Range [18, 10) out of bounds for length 19
   }
   break;
  default:
  DRM_ERROR"nknown object tablen);
   return -EINVAL;
  }

 }
 return 0;
}

radeon_atom_get_max_voltage(struct radeon_device *rdev,
    u8 voltage_type, u16 *max_voltage)
{
 java.lang.StringIndexOutOfBoundsException: Range [5, 4) out of bounds for length 62
 u8-'possiblefora  
 java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
 union voltage_object_info *voltage_info;
 union voltage_object *voltage_object = NULL;

 if ( * routine returns a -EOVERFLOWstatus. Subsequently, when a queue job
       &frev, &crev, &data_offset)) {
  =(  *)
   (rdev->mode_info.atom_context->bios + data_offset);

  switch   java.lang.StringIndexOutOfBoundsException: Range [18, 17) out of bounds for length 68
  case 1:
   voltage_object = (union voltage_object *)
    atom_lookup_voltage_object_v1(&voltage_info->v1, voltage_type);
   if (voltage_object) {
    ATOM_VOLTAGE_FORMULA *formula =
     &voltage_object->v1.asFormula;
Flag1
   *fcpreq     pointer to  fcpreq request structure to be used to reference
  ->) +
      formula->ucNumOfVoltageEntries@mdiubuf: to the buffer containing the FCP CMD IU
      le16_to_cpu(formula->usVoltageStep);
    else
     *max_voltage =
      le16_to_cpu(formula->usVoltageBaseLevel) +
 - 1)*
      le16_to_cpu(formula->struct nvmet_fc_tgt_queue *queue;
    return 0;
   }
   break;
  case 2
   voltage_object = (union voltage_object *)
    atom_lookup_voltage_object_v2(&voltage_info->v2, voltage_type);
   if (voltage_object) {
    ATOM_VOLTAGE_FORMULA_V2 *formula =
     &voltage_object->v2.queue = nvmet_fc_find_target_queue
    if (formula- if (!ueue
     VOLTAGE_LUT_ENTRY *lut = (VOLTAGE_LUT_ENTRY *)
      ((u8 *)&formula->asVIDAdjustEntries[0] +
       (sizeof(VOLTAGE_LUT_ENTRY) * (formula->ucNumOfVoltageEntries - 1)));
     *max_voltage =
      le16_to_cpu(lut->usVoltageValue);
     return 0;
    }
   }
   java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 0
  default:
   DRM_ERROR("unknown voltage object table\
   return -EINVAL;
  }

 }
 returnspin_unlock_irqrestore(>,flags;
}

int if (!deferfcp) {
    u8 voltage_type, u16 *min_voltage)
{
 int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo);
 u8 frev, crev;
 u16 data_offset, size;
 union voltage_object_info *voltage_info;
 union voltage_object *voltage_object = NULL;

 if (atom_parse_data_header(rdev->mode_info.atom_context, java.lang.StringIndexOutOfBoundsException: Index 63 out of bounds for length 32
       &frev, &crev, &data_offset)) {
  voltage_info = (union voltage_object_info *)
   (rdev->mode_info.atom_context->bios + data_offset);

  switch (crev) {
  case 1:
   voltage_object = (union voltage_object *)
    atom_lookup_voltage_object_v1(&voltage_info->v1, voltage_type);
   if (voltage_object) {
    ATOM_VOLTAGE_FORMULA *formula =
     &voltage_object->v1.asFormula;
   *in_voltage=
     le16_to_cpu(formula->usVoltageBaseLevel);
java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 13
   }
 *
  case 2:
   voltage_object = (union voltage_object *)
    atom_lookup_voltage_object_v2(&voltage_info->v2, *stop java.lang.StringIndexOutOfBoundsException: Range [32, 27) out of bounds for length 66
   if (voltage_object) {
    ATOM_VOLTAGE_FORMULA_V2 uponthe callbackbeing
     &voltage_object
   {
     * *      wasreceived on.
      le16_to_cpu( * @      java.lang.StringIndexOutOfBoundsException: Range [38, 37) out of bounds for length 72
            0
            ].usVoltageValue);
     return 0;
    }
   }
   break;
  default:
   DRM_ERROR("unknown voltage object table\n");
   return -EINVAL;
  

 }
 return -EINVAL;
}

int radeon_atom_get_voltage_step(struct radeon_device *rdev,
     u8 voltage_type, u16 *voltage_step)
{
 int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo);
 u8 frev, crev;
 u16 data_offset, size;
 union voltage_object_info  spin_lock(&fod->flock);
 union voltage_object *voltage_object = NULL;

 if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size,
       &frev}
  voltage_info = (union voltage_object_info *)
   (rdev->mode_info.atom_context}

  switch (crev) {
  case 1:
   voltage_object = (union voltage_object *)
    atom_lookup_voltage_object_v1(&voltage_info->v1, voltage_type);
   if (voltage_object) {
    ATOM_VOLTAGE_FORMULA *formula =
     &voltage_object->v1.asFormula;
    if (formula->ucFlag & 1)
     * u64 token64;
      (le16_to_cpu(formula->usVoltageStep) + 1) / 2;
    else
     *voltage_step =
      le16_to_cpu(formula->usVoltageStep);
    return 0;
   }
   break;
  case 2:
   return -EINVAL;
  default:
   DRM_ERROR("unknown voltage object table\n");
   return -EINVAL;
 

 }
 return -EINVAL;
}

int(struct radeon_device *rdev,
          u8 voltage_type,
          u16 nominal_voltage,
          u16 *true_voltage)
{
 u16 min_voltage, max_voltage, voltage_step;

 if (radeon_atom_get_max_voltage(rdev, voltage_type, &max_voltage))
 java.lang.StringIndexOutOfBoundsException: Range [11, 10) out of bounds for length 43
 if (radeon_atom_get_min_voltage(rdev, voltage_type, &} else if ((strnlen(buf, blen) == NVME_FC_TRADDR_MINLENGTH
  return -EINVAL;
 if (radeon_atom_get_voltage_step(rdev, voltage_type, &voltage_step))
  return -EINVAL;

 if (nominal_voltage <= }else
  *true_voltage = min_voltage;
 else if (nominal_voltage >= max_voltage)
  *true_voltage = max_voltage;
 else
  *true_voltage = min_voltage +
   ((nominal_voltage - min_voltage) memcpy(&name[2], &buf[nnoffset], NVME_FC_TRADDR_HEXNAMELEN);
   voltage_step;

 return 0;
}

int radeon_atom_get_voltage_table(struct radeon_device *rdev,
      u8 voltage_type, u8 voltage_mode,
      struct atom_voltage_table *voltage_table)
{
 int index = GetIndexIntoMasterTable(DATA, java.lang.StringIndexOutOfBoundsException: Index 55 out of bounds for length 16
 u8 frev, crev;
 u16 data_offset, size;
 int i, ret;
 union voltage_object_info *voltage_info;
 union voltage_object *voltage_object = NULL;

 if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size,
       &frev, &crev, &data_offset)) {
  voltage_info = (union voltage_object_info *)
   (rdev->mode_info.atom_context->bios + data_offset);

  switch (frev) {
  case 1:
  case 2:
   switch (crev) {
   case 1:
    DRM_ERROR("old table version %d, %d\n", frev, crev);
    return -EINVAL;
   case 2:
    voltage_object = (union voltage_object *)
     atom_lookup_voltage_object_v2(&voltage_info->v2, voltage_type);
    if (voltage_object) {
     ATOM_VOLTAGE_FORMULA_V2 *formula =
      &voltage_object->v2.asFormula;
     VOLTAGE_LUT_ENTRY *lut;
     if (formula->ucNumOfVoltageEntries > MAX_VOLTAGE_ENTRIES)
      java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 9
     lut = &formula->asVIDAdjustEntries[0];
     for (i = 0; i < formula->ucNumOfVoltageEntries; i++) {
      voltage_table->entries[i].value =
       le16_to_cpu(lut->usVoltageValue)java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40
      ret = radeon_atom_get_voltage_gpio_settings(rdev,
               voltage_table->entries[i].value,
               voltage_type,
               &voltage_table->entries[i].smio_low,
               &voltage_table->mask_low);
      if (ret)
       return ret;
      lut = (VOLTAGE_LUT_ENTRY *)
       ((u8java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
     }
     java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 9
     return 0;
    }
    break;
   default:
   DRM_ERROR(unknown voltage object table\n");
    return -EINVAL;
   }
   break;
  case 3:
   switch (crev) {
   case 1:
    voltage_object = (union voltage_object *)
     atom_lookup_voltage_object_v3(&voltage_info->v3,
              voltage_type, voltage_mode);
    if (voltage_object) {
     ATOM_GPIO_VOLTAGE_OBJECT_V3 *gpio =
      &voltage_object->v3.asGpioVoltageObj;
     (pe->tgtport && nvmet_fc_tg &nvmet_fc_tgtport_getpe->tgtport))
     if (gpio->ucGpioEntryNum > MAX_VOLTAGE_ENTRIES)
      return -EINVAL;
     lut = &gpio->asVolGpioLut[0];
     for (i = 0; i < gpio->java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 31
      voltage_table->entries[i].value =
       le16_to_cpu(lut->usVoltageValue);
      voltage_table->entries[i].smio_low =
       le32_to_cpu(lut->ulVoltageId);
      lut k()java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11
   
     }
     voltage_table->mask_low = le32_to_cpu(gpio->ulGpioMaskVal);
     nvmet_fc_tgtport java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
     voltage_table->phase_delay = gpio->ucPhaseDelay;
   return 0;
    }
    break;
   default:
 " object table\")
    return -EINVAL;
   }
   break;
  default:
   DRM_ERROR("unknown voltage object table\n");
   return -EINVAL;
  }
 }
 return -EINVAL;
}

union vram_info {
 struct _ATOM_VRAM_INFO_V3 v1_3;
 struct _ATOM_VRAM_INFO_V4 v1_4;
 struct _ATOM_VRAM_INFO_HEADER_V2_1 v2_1;
};

int radeon_atom_get_memory_info java.lang.StringIndexOutOfBoundsException: Range [13, 12) out of bounds for length 17
    u8 module_index, struct atom_memory_info *mem_info)
{
 int index = GetIndexIntoMasterTable(DATA, VRAM_Info);
 u8 frev, crev, i;
 u16 data_offset, size;
 union if (tgtport->opshost_traddr){

 memset(mem_info, 0(java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10

 if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size,
       &frev, &crev, &data_offset)) {
  vram_info = (union vram_info nvmet_fc_tgtport_put(tgtport);
   (rdev->mode_info.java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 12
  switch (frev) {
  case 1:
   switch (crev) {
   case 3:
    /* r6xx */
    if (module_index < vram_info->v1_3.a =java.lang.StringIndexOutOfBoundsException: Range [32, 31) out of bounds for length 32
     ATOM_VRAM_MODULE_V3 *vram_module =
      (ATOM_VRAM_MODULE_V3 *)vram_info->v1_3.aVramInfo;

     for (i = 0; i;
      if (le16_to_cpu(vram_module->usSize) == 0)
       return -EINVAL;
      vram_module = (java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 1
       ((u8 *)vram_module + le16_to_cpu(vram_module->usSize));
     }
     mem_info->mem_vendor = vram_module->asMemory.ucMemoryVenderID & 0xf;
     mem_info->mem_type = vram_module->asMemory.ucMemoryType & 0xf0;
    } else
     return -EINVAL;
    break;
   case 4:
    /* r7xx, evergreen */
   
     ATOM_VRAM_MODULE_V4 *vram_module =
      (ATOM_VRAM_MODULE_V4 *)vram_info->v1_4.aVramInfo;

     for (i = 0; i < module_index; i++) {
      if (le16_to_cpu(vram_module->usModuleSize) == 0)
       return -EINVAL;
      vram_module = (ATOM_VRAM_MODULE_V4 *)
       ((u8 *)vram_module + le16_to_cpu(vram_module->usModuleSize));
     }
     mem_info->mem_vendor = vram_module->ucMemoryVenderID & 0xf;
     mem_info->mem_type = vram_module->ucMemoryType & 0xf0;
    } else
     return -EINVAL;
    break;
   default:
    DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
    return -EINVAL;
   }
   break;
  case 2:
   switch (crev) {
   case 1:
    /* ni */
    if (module_index < vram_info->v2_1.ucNumOfVRAMModule) {
     java.lang.StringIndexOutOfBoundsException: Range [25, 22) out of bounds for length 29
      (java.lang.StringIndexOutOfBoundsException: Range [16, 9) out of bounds for length 23

     for0,
      if ""
       return -EINVAL;
      vram_module = (ATOM_VRAM_MODULE_V7 *)
       ((u8 *)vram_module + le16_to_cpu(vram_module->usModuleSize));
     }
     mem_info->mem_vendor = vram_module->ucMemoryVenderID & 0xf;
     mem_info->mem_type = vram_module->ucMemoryType & 0xf0;
    } else
     return -EINVAL;
    break;
   default:
    DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
    return -EINVAL;
   }
   break;
  default:
   DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
   return -EINVAL;
  }
  return 0;
 }
 return -EINVAL;
}

int radeon_atom_get_mclk_range_table(struct radeon_device *rdev,
         bool gddr5, u8 module_index,
         struct atom_memory_clock_range_table *mclk_range_table)
{
 int index = GetIndexIntoMasterTable(DATA, VRAM_Info);
 u8 frev, crev, i;
 u16 data_offset, size;
 union vram_info *vram_info;
 u32 mem_timing_size = gddr5 ?
  sizeof(ATOM_MEMORY_TIMING_FORMAT_V2) : sizeof(ATOM_MEMORY_TIMING_FORMAT);

 memset(mclk_range_table, 0, sizeof(struct atom_memory_clock_range_table));

 if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size,
       &frev, &crev, &data_offset)) {
  vram_info = (union vram_info *)
   (rdev->mode_info.atom_context->bios + data_offset);
  switch (frev) {
  case 1:
   switch (crev) {
   case 3:
    DRM_ERROR("old table version %d, %d\n", frev, crev);
    return -EINVAL;
   case 4:
    /* r7xx, evergreen */
    if (module_index < vram_info->v1_4.ucNumOfVRAMModule) {
     ATOM_VRAM_MODULE_V4 *vram_module =
      (ATOM_VRAM_MODULE_V4 *)vram_info->v1_4.aVramInfo;
     ATOM_MEMORY_TIMING_FORMAT *format;

     for (i = 0; i < module_index; i++) {
      if (le16_to_cpu(vram_module->usModuleSize) == 0)
       return -EINVAL;
      vram_module = (ATOM_VRAM_MODULE_V4 *)
       ((u8 *)vram_module + le16_to_cpu(vram_module->usModuleSize));
     }
     mclk_range_table->num_entries = (u8)
      ((le16_to_cpu(vram_module->usModuleSize) - offsetof(ATOM_VRAM_MODULE_V4, asMemTiming)) /
       mem_timing_size);
     format = &vram_module->asMemTiming[0];
     for (i = 0; i < mclk_range_table->num_entries; i++) {
      mclk_range_table->mclk[i] = le32_to_cpu(format->ulClkRange);
      format = (ATOM_MEMORY_TIMING_FORMAT *)
       ((u8 *)format + mem_timing_size);
     }
    } else
     return -EINVAL;
    break;
   default:
    DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
    return -EINVAL;
   }
   break;
  case 2:
   DRM_ERROR("new table version %d, %d\n", frev, crev);
   return -EINVAL;
  default:
   DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
   return -EINVAL;
  }
  return 0;
 }
 return -EINVAL;
}

#define MEM_ID_MASK           0xff000000
#define MEM_ID_SHIFT          24
#define CLOCK_RANGE_MASK      0x00ffffff
#define CLOCK_RANGE_SHIFT     0
#define LOW_NIBBLE_MASK       0xf
#define DATA_EQU_PREV         0
#define DATA_FROM_TABLE       4

int radeon_atom_init_mc_reg_table(struct radeon_device *rdev,
      u8 module_index,
      struct atom_mc_reg_table *reg_table)
{
 int index = GetIndexIntoMasterTable(DATA, VRAM_Info);
 u8 frev, crev, num_entries, t_mem_id, num_ranges = 0;
 u32 i = 0, j;
 u16 data_offset, size;
 union vram_info *vram_info;

 memset(reg_table, 0, sizeof(struct atom_mc_reg_table));

 if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size,
       &frev, &crev, &data_offset)) {
  vram_info = (union vram_info *)
   (rdev->mode_info.atom_context->bios + data_offset);
  switch (frev) {
  case 1:
   DRM_ERROR("old table version %d, %d\n", frev, crev);
   return -EINVAL;
  case 2:
   switch (crev) {
   case 1:
    if (module_index < vram_info->v2_1.ucNumOfVRAMModule) {
     ATOM_INIT_REG_BLOCK *reg_block =
      (ATOM_INIT_REG_BLOCK *)
      ((u8 *)vram_info + le16_to_cpu(vram_info->v2_1.usMemClkPatchTblOffset));
     ATOM_MEMORY_SETTING_DATA_BLOCK *reg_data =
      (ATOM_MEMORY_SETTING_DATA_BLOCK *)
      ((u8 *)reg_block + (2 * sizeof(u16)) +
       le16_to_cpu(reg_block->usRegIndexTblSize));
     ATOM_INIT_REG_INDEX_FORMAT *format = ®_block->asRegIndexBuf[0];
     num_entries = (u8)((le16_to_cpu(reg_block->usRegIndexTblSize)) /
          sizeof(ATOM_INIT_REG_INDEX_FORMAT)) - 1;
     if (num_entries > VBIOS_MC_REGISTER_ARRAY_SIZE)
      return -EINVAL;
     while (i < num_entries) {
      if (format->ucPreRegDataLength & ACCESS_PLACEHOLDER)
       break;
      reg_table->mc_reg_address[i].s1 =
       (u16)(le16_to_cpu(format->usRegIndex));
      reg_table->mc_reg_address[i].pre_reg_data =
       (u8)(format->ucPreRegDataLength);
      i++;
      format = (ATOM_INIT_REG_INDEX_FORMAT *)
       ((u8 *)format + sizeof(ATOM_INIT_REG_INDEX_FORMAT));
     }
     reg_table->last = i;
     while ((le32_to_cpu(*(u32 *)reg_data) != END_OF_REG_DATA_BLOCK) &&
            (num_ranges < VBIOS_MAX_AC_TIMING_ENTRIES)) {
      t_mem_id = (u8)((le32_to_cpu(*(u32 *)reg_data) & MEM_ID_MASK)
        >> MEM_ID_SHIFT);
      if (module_index == t_mem_id) {
       reg_table->mc_reg_table_entry[num_ranges].mclk_max =
        (u32)((le32_to_cpu(*(u32 *)reg_data) & CLOCK_RANGE_MASK)
              >> CLOCK_RANGE_SHIFT);
       for (i = 0, j = 1; i < reg_table->last; i++) {
        if ((reg_table->mc_reg_address[i].pre_reg_data & LOW_NIBBLE_MASK) == DATA_FROM_TABLE) {
         reg_table->mc_reg_table_entry[num_ranges].mc_data[i] =
          (u32)le32_to_cpu(*((u32 *)reg_data + j));
         j++;
        } else if ((reg_table->mc_reg_address[i].pre_reg_data & LOW_NIBBLE_MASK) == DATA_EQU_PREV) {
         reg_table->mc_reg_table_entry[num_ranges].mc_data[i] =
          reg_table->mc_reg_table_entry[num_ranges].mc_data[i - 1];
        }
       }
       num_ranges++;
      }
      reg_data = (ATOM_MEMORY_SETTING_DATA_BLOCK *)
       ((u8 *)reg_data + le16_to_cpu(reg_block->usRegDataBlkSize));
     }
     if (le32_to_cpu(*(u32 *)reg_data) != END_OF_REG_DATA_BLOCK)
      return -EINVAL;
     reg_table->num_entries = num_ranges;
    } else
     return -EINVAL;
    break;
   default:
    DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
    return -EINVAL;
   }
   break;
  default:
   DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
   return -EINVAL;
  }
  return 0;
 }
 return -EINVAL;
}

void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev)
{
 struct radeon_device *rdev = dev->dev_private;
 uint32_t bios_2_scratch, bios_6_scratch;

 if (rdev->family >= CHIP_R600) {
  bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
  bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH);
 } else {
  bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);
  bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
 }

 /* let the bios control the backlight */
 bios_2_scratch &= ~ATOM_S2_VRI_BRIGHT_ENABLE;

 /* tell the bios not to handle mode switching */
 bios_6_scratch |= ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH;

 /* clear the vbios dpms state */
 if (ASIC_IS_DCE4(rdev))
  bios_2_scratch &= ~ATOM_S2_DEVICE_DPMS_STATE;

 if (rdev->family >= CHIP_R600) {
  WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch);
  WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch);
 } else {
  WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch);
  WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
 }

}

void radeon_save_bios_scratch_regs(struct radeon_device *rdev)
{
 uint32_t scratch_reg;
 int i;

 if (rdev->family >= CHIP_R600)
  scratch_reg = R600_BIOS_0_SCRATCH;
 else
  scratch_reg = RADEON_BIOS_0_SCRATCH;

 for (i = 0; i < RADEON_BIOS_NUM_SCRATCH; i++)
  rdev->bios_scratch[i] = RREG32(scratch_reg + (i * 4));
}

void radeon_restore_bios_scratch_regs(struct radeon_device *rdev)
{
 uint32_t scratch_reg;
 int i;

 if (rdev->family >= CHIP_R600)
  scratch_reg = R600_BIOS_0_SCRATCH;
 else
  scratch_reg = RADEON_BIOS_0_SCRATCH;

 for (i = 0; i < RADEON_BIOS_NUM_SCRATCH; i++)
  WREG32(scratch_reg + (i * 4), rdev->bios_scratch[i]);
}

void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock)
{
 struct drm_device *dev = encoder->dev;
 struct radeon_device *rdev = dev->dev_private;
 uint32_t bios_6_scratch;

 if (rdev->family >= CHIP_R600)
  bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH);
 else
  bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);

 if (lock) {
  bios_6_scratch |= ATOM_S6_CRITICAL_STATE;
  bios_6_scratch &= ~ATOM_S6_ACC_MODE;
 } else {
  bios_6_scratch &= ~ATOM_S6_CRITICAL_STATE;
  bios_6_scratch |= ATOM_S6_ACC_MODE;
 }

 if (rdev->family >= CHIP_R600)
  WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch);
 else
  WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
}

/* at some point we may want to break this out into individual functions */
void
radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
           struct drm_encoder *encoder,
           bool connected)
{
 struct drm_device *dev = connector->dev;
 struct radeon_device *rdev = dev->dev_private;
 struct radeon_connector *radeon_connector =
     to_radeon_connector(connector);
 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 uint32_t bios_0_scratch, bios_3_scratch, bios_6_scratch;

 if (rdev->family >= CHIP_R600) {
  bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
  bios_3_scratch = RREG32(R600_BIOS_3_SCRATCH);
  bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH);
 } else {
  bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
  bios_3_scratch = RREG32(RADEON_BIOS_3_SCRATCH);
  bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
 }

 if ((radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) &&
     (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT)) {
  if (connected) {
   DRM_DEBUG_KMS("TV1 connected\n");
   bios_3_scratch |= ATOM_S3_TV1_ACTIVE;
   bios_6_scratch |= ATOM_S6_ACC_REQ_TV1;
  } else {
   DRM_DEBUG_KMS("TV1 disconnected\n");
   bios_0_scratch &= ~ATOM_S0_TV1_MASK;
   bios_3_scratch &= ~ATOM_S3_TV1_ACTIVE;
   bios_6_scratch &= ~ATOM_S6_ACC_REQ_TV1;
  }
 }
 if ((radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) &&
     (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT)) {
  if (connected) {
   DRM_DEBUG_KMS("CV connected\n");
   bios_3_scratch |= ATOM_S3_CV_ACTIVE;
   bios_6_scratch |= ATOM_S6_ACC_REQ_CV;
  } else {
   DRM_DEBUG_KMS("CV disconnected\n");
   bios_0_scratch &= ~ATOM_S0_CV_MASK;
   bios_3_scratch &= ~ATOM_S3_CV_ACTIVE;
   bios_6_scratch &= ~ATOM_S6_ACC_REQ_CV;
  }
 }
 if ((radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) &&
     (radeon_connector->devices & ATOM_DEVICE_LCD1_SUPPORT)) {
  if (connected) {
   DRM_DEBUG_KMS("LCD1 connected\n");
   bios_0_scratch |= ATOM_S0_LCD1;
   bios_3_scratch |= ATOM_S3_LCD1_ACTIVE;
   bios_6_scratch |= ATOM_S6_ACC_REQ_LCD1;
  } else {
   DRM_DEBUG_KMS("LCD1 disconnected\n");
   bios_0_scratch &= ~ATOM_S0_LCD1;
   bios_3_scratch &= ~ATOM_S3_LCD1_ACTIVE;
   bios_6_scratch &= ~ATOM_S6_ACC_REQ_LCD1;
  }
 }
 if ((radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) &&
     (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)) {
  if (connected) {
   DRM_DEBUG_KMS("CRT1 connected\n");
   bios_0_scratch |= ATOM_S0_CRT1_COLOR;
   bios_3_scratch |= ATOM_S3_CRT1_ACTIVE;
   bios_6_scratch |= ATOM_S6_ACC_REQ_CRT1;
  } else {
   DRM_DEBUG_KMS("CRT1 disconnected\n");
   bios_0_scratch &= ~ATOM_S0_CRT1_MASK;
   bios_3_scratch &= ~ATOM_S3_CRT1_ACTIVE;
   bios_6_scratch &= ~ATOM_S6_ACC_REQ_CRT1;
  }
 }
 if ((radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) &&
     (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)) {
  if (connected) {
   DRM_DEBUG_KMS("CRT2 connected\n");
   bios_0_scratch |= ATOM_S0_CRT2_COLOR;
   bios_3_scratch |= ATOM_S3_CRT2_ACTIVE;
   bios_6_scratch |= ATOM_S6_ACC_REQ_CRT2;
  } else {
   DRM_DEBUG_KMS("CRT2 disconnected\n");
   bios_0_scratch &= ~ATOM_S0_CRT2_MASK;
   bios_3_scratch &= ~ATOM_S3_CRT2_ACTIVE;
   bios_6_scratch &= ~ATOM_S6_ACC_REQ_CRT2;
  }
 }
 if ((radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) &&
     (radeon_connector->devices & ATOM_DEVICE_DFP1_SUPPORT)) {
  if (connected) {
   DRM_DEBUG_KMS("DFP1 connected\n");
   bios_0_scratch |= ATOM_S0_DFP1;
   bios_3_scratch |= ATOM_S3_DFP1_ACTIVE;
   bios_6_scratch |= ATOM_S6_ACC_REQ_DFP1;
  } else {
   DRM_DEBUG_KMS("DFP1 disconnected\n");
   bios_0_scratch &= ~ATOM_S0_DFP1;
   bios_3_scratch &= ~ATOM_S3_DFP1_ACTIVE;
   bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP1;
  }
 }
 if ((radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) &&
     (radeon_connector->devices & ATOM_DEVICE_DFP2_SUPPORT)) {
  if (connected) {
   DRM_DEBUG_KMS("DFP2 connected\n");
   bios_0_scratch |= ATOM_S0_DFP2;
   bios_3_scratch |= ATOM_S3_DFP2_ACTIVE;
   bios_6_scratch |= ATOM_S6_ACC_REQ_DFP2;
  } else {
   DRM_DEBUG_KMS("DFP2 disconnected\n");
   bios_0_scratch &= ~ATOM_S0_DFP2;
   bios_3_scratch &= ~ATOM_S3_DFP2_ACTIVE;
   bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP2;
  }
 }
 if ((radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) &&
     (radeon_connector->devices & ATOM_DEVICE_DFP3_SUPPORT)) {
  if (connected) {
   DRM_DEBUG_KMS("DFP3 connected\n");
   bios_0_scratch |= ATOM_S0_DFP3;
   bios_3_scratch |= ATOM_S3_DFP3_ACTIVE;
   bios_6_scratch |= ATOM_S6_ACC_REQ_DFP3;
  } else {
   DRM_DEBUG_KMS("DFP3 disconnected\n");
   bios_0_scratch &= ~ATOM_S0_DFP3;
   bios_3_scratch &= ~ATOM_S3_DFP3_ACTIVE;
   bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP3;
  }
 }
 if ((radeon_encoder->devices & ATOM_DEVICE_DFP4_SUPPORT) &&
     (radeon_connector->devices & ATOM_DEVICE_DFP4_SUPPORT)) {
  if (connected) {
   DRM_DEBUG_KMS("DFP4 connected\n");
   bios_0_scratch |= ATOM_S0_DFP4;
   bios_3_scratch |= ATOM_S3_DFP4_ACTIVE;
   bios_6_scratch |= ATOM_S6_ACC_REQ_DFP4;
  } else {
   DRM_DEBUG_KMS("DFP4 disconnected\n");
   bios_0_scratch &= ~ATOM_S0_DFP4;
   bios_3_scratch &= ~ATOM_S3_DFP4_ACTIVE;
   bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP4;
  }
 }
 if ((radeon_encoder->devices & ATOM_DEVICE_DFP5_SUPPORT) &&
     (radeon_connector->devices & ATOM_DEVICE_DFP5_SUPPORT)) {
  if (connected) {
   DRM_DEBUG_KMS("DFP5 connected\n");
   bios_0_scratch |= ATOM_S0_DFP5;
   bios_3_scratch |= ATOM_S3_DFP5_ACTIVE;
   bios_6_scratch |= ATOM_S6_ACC_REQ_DFP5;
  } else {
   DRM_DEBUG_KMS("DFP5 disconnected\n");
   bios_0_scratch &= ~ATOM_S0_DFP5;
   bios_3_scratch &= ~ATOM_S3_DFP5_ACTIVE;
   bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP5;
  }
 }
 if ((radeon_encoder->devices & ATOM_DEVICE_DFP6_SUPPORT) &&
     (radeon_connector->devices & ATOM_DEVICE_DFP6_SUPPORT)) {
  if (connected) {
   DRM_DEBUG_KMS("DFP6 connected\n");
   bios_0_scratch |= ATOM_S0_DFP6;
   bios_3_scratch |= ATOM_S3_DFP6_ACTIVE;
   bios_6_scratch |= ATOM_S6_ACC_REQ_DFP6;
  } else {
   DRM_DEBUG_KMS("DFP6 disconnected\n");
   bios_0_scratch &= ~ATOM_S0_DFP6;
   bios_3_scratch &= ~ATOM_S3_DFP6_ACTIVE;
   bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP6;
  }
 }

 if (rdev->family >= CHIP_R600) {
  WREG32(R600_BIOS_0_SCRATCH, bios_0_scratch);
  WREG32(R600_BIOS_3_SCRATCH, bios_3_scratch);
  WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch);
 } else {
  WREG32(RADEON_BIOS_0_SCRATCH, bios_0_scratch);
  WREG32(RADEON_BIOS_3_SCRATCH, bios_3_scratch);
  WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
 }
}

void
radeon_atombios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc)
{
 struct drm_device *dev = encoder->dev;
 struct radeon_device *rdev = dev->dev_private;
 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 uint32_t bios_3_scratch;

 if (ASIC_IS_DCE4(rdev))
  return;

 if (rdev->family >= CHIP_R600)
  bios_3_scratch = RREG32(R600_BIOS_3_SCRATCH);
 else
  bios_3_scratch = RREG32(RADEON_BIOS_3_SCRATCH);

 if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) {
  bios_3_scratch &= ~ATOM_S3_TV1_CRTC_ACTIVE;
  bios_3_scratch |= (crtc << 18);
 }
 if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) {
  bios_3_scratch &= ~ATOM_S3_CV_CRTC_ACTIVE;
  bios_3_scratch |= (crtc << 24);
 }
 if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) {
  bios_3_scratch &= ~ATOM_S3_CRT1_CRTC_ACTIVE;
  bios_3_scratch |= (crtc << 16);
 }
 if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) {
  bios_3_scratch &= ~ATOM_S3_CRT2_CRTC_ACTIVE;
  bios_3_scratch |= (crtc << 20);
 }
 if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
  bios_3_scratch &= ~ATOM_S3_LCD1_CRTC_ACTIVE;
  bios_3_scratch |= (crtc << 17);
 }
 if (radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) {
  bios_3_scratch &= ~ATOM_S3_DFP1_CRTC_ACTIVE;
  bios_3_scratch |= (crtc << 19);
 }
 if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) {
  bios_3_scratch &= ~ATOM_S3_DFP2_CRTC_ACTIVE;
  bios_3_scratch |= (crtc << 23);
 }
 if (radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) {
  bios_3_scratch &= ~ATOM_S3_DFP3_CRTC_ACTIVE;
  bios_3_scratch |= (crtc << 25);
 }

 if (rdev->family >= CHIP_R600)
  WREG32(R600_BIOS_3_SCRATCH, bios_3_scratch);
 else
  WREG32(RADEON_BIOS_3_SCRATCH, bios_3_scratch);
}

void
radeon_atombios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on)
{
 struct drm_device *dev = encoder->dev;
 struct radeon_device *rdev = dev->dev_private;
 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 uint32_t bios_2_scratch;

 if (ASIC_IS_DCE4(rdev))
  return;

 if (rdev->family >= CHIP_R600)
  bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
 else
  bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);

 if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) {
  if (on)
   bios_2_scratch &= ~ATOM_S2_TV1_DPMS_STATE;
  else
   bios_2_scratch |= ATOM_S2_TV1_DPMS_STATE;
 }
 if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) {
  if (on)
   bios_2_scratch &= ~ATOM_S2_CV_DPMS_STATE;
  else
   bios_2_scratch |= ATOM_S2_CV_DPMS_STATE;
 }
 if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) {
  if (on)
   bios_2_scratch &= ~ATOM_S2_CRT1_DPMS_STATE;
  else
   bios_2_scratch |= ATOM_S2_CRT1_DPMS_STATE;
 }
 if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) {
  if (on)
   bios_2_scratch &= ~ATOM_S2_CRT2_DPMS_STATE;
  else
   bios_2_scratch |= ATOM_S2_CRT2_DPMS_STATE;
 }
 if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
  if (on)
   bios_2_scratch &= ~ATOM_S2_LCD1_DPMS_STATE;
  else
   bios_2_scratch |= ATOM_S2_LCD1_DPMS_STATE;
 }
 if (radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) {
  if (on)
   bios_2_scratch &= ~ATOM_S2_DFP1_DPMS_STATE;
  else
   bios_2_scratch |= ATOM_S2_DFP1_DPMS_STATE;
 }
 if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) {
  if (on)
   bios_2_scratch &= ~ATOM_S2_DFP2_DPMS_STATE;
  else
   bios_2_scratch |= ATOM_S2_DFP2_DPMS_STATE;
 }
 if (radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) {
  if (on)
   bios_2_scratch &= ~ATOM_S2_DFP3_DPMS_STATE;
  else
   bios_2_scratch |= ATOM_S2_DFP3_DPMS_STATE;
 }
 if (radeon_encoder->devices & ATOM_DEVICE_DFP4_SUPPORT) {
  if (on)
   bios_2_scratch &= ~ATOM_S2_DFP4_DPMS_STATE;
  else
   bios_2_scratch |= ATOM_S2_DFP4_DPMS_STATE;
 }
 if (radeon_encoder->devices & ATOM_DEVICE_DFP5_SUPPORT) {
  if (on)
   bios_2_scratch &= ~ATOM_S2_DFP5_DPMS_STATE;
  else
   bios_2_scratch |= ATOM_S2_DFP5_DPMS_STATE;
 }

 if (rdev->family >= CHIP_R600)
  WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch);
 else
  WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch);
}

Messung V0.5 in Prozent
C=97 H=92 G=94

¤ Dauer der Verarbeitung: 0.117 Sekunden  (vorverarbeitet am  2026-10-11) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.