1250079Scarl/* 2304380Smav * Copyright 2007-8 Advanced Micro Devices, Inc. 3250079Scarl * Copyright 2008 Red Hat Inc. 4300373Smav * 5250079Scarl * Permission is hereby granted, free of charge, to any person obtaining a 6250079Scarl * copy of this software and associated documentation files (the "Software"), 7250079Scarl * to deal in the Software without restriction, including without limitation 8250079Scarl * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9250079Scarl * and/or sell copies of the Software, and to permit persons to whom the 10250079Scarl * Software is furnished to do so, subject to the following conditions: 11250079Scarl * 12250079Scarl * The above copyright notice and this permission notice shall be included in 13250079Scarl * all copies or substantial portions of the Software. 14250079Scarl * 15250079Scarl * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16250079Scarl * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17250079Scarl * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18250079Scarl * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19250079Scarl * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20250079Scarl * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21250079Scarl * OTHER DEALINGS IN THE SOFTWARE. 22250079Scarl * 23250079Scarl * Authors: Dave Airlie 24250079Scarl * Alex Deucher 25250079Scarl */ 26250079Scarl 27250079Scarl#include <sys/cdefs.h> 28250079Scarl__FBSDID("$FreeBSD$"); 29304380Smav 30304380Smav#include <dev/drm2/drmP.h> 31304380Smav#include <dev/drm2/radeon/radeon_drm.h> 32304380Smav#include "radeon.h" 33304380Smav#include "radeon_asic.h" /* Declares several prototypes; clang is pleased. */ 34304380Smav 35304380Smav#include "atom.h" 36304380Smav#include "atom-bits.h" 37304380Smav 38304380Smav/* local */ 39250079Scarlstatic int radeon_atom_get_max_vddc(struct radeon_device *rdev, u8 voltage_type, 40250079Scarl u16 voltage_id, u16 *voltage); 41250079Scarl 42250079Scarlunion atom_supported_devices { 43250079Scarl struct _ATOM_SUPPORTED_DEVICES_INFO info; 44250079Scarl struct _ATOM_SUPPORTED_DEVICES_INFO_2 info_2; 45250079Scarl struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 info_2d1; 46300373Smav}; 47304388Smav 48250079Scarlstatic void radeon_lookup_i2c_gpio_quirks(struct radeon_device *rdev, 49250079Scarl ATOM_GPIO_I2C_ASSIGMENT *gpio, 50301811Sngie u8 index) 51301811Sngie{ 52250079Scarl /* r4xx mask is technically not used by the hw, so patch in the legacy mask bits */ 53250079Scarl if ((rdev->family == CHIP_R420) || 54300373Smav (rdev->family == CHIP_R423) || 55300373Smav (rdev->family == CHIP_RV410)) { 56250079Scarl if ((le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0018) || 57250079Scarl (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0019) || 58250079Scarl (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x001a)) { 59301811Sngie gpio->ucClkMaskShift = 0x19; 60250079Scarl gpio->ucDataMaskShift = 0x18; 61250079Scarl } 62250079Scarl } 63250079Scarl 64250079Scarl /* some evergreen boards have bad data for this entry */ 65250079Scarl if (ASIC_IS_DCE4(rdev)) { 66304380Smav if ((index == 7) && 67250079Scarl (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) && 68300373Smav (gpio->sucI2cId.ucAccess == 0)) { 69250079Scarl gpio->sucI2cId.ucAccess = 0x97; 70300373Smav gpio->ucDataMaskShift = 8; 71300373Smav gpio->ucDataEnShift = 8; 72300373Smav gpio->ucDataY_Shift = 8; 73250079Scarl gpio->ucDataA_Shift = 8; 74301811Sngie } 75301811Sngie } 76301811Sngie 77301811Sngie /* some DCE3 boards have bad data for this entry */ 78301811Sngie if (ASIC_IS_DCE3(rdev)) { 79301811Sngie if ((index == 4) && 80301811Sngie (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) && 81301811Sngie (gpio->sucI2cId.ucAccess == 0x94)) 82301811Sngie gpio->sucI2cId.ucAccess = 0x14; 83301811Sngie } 84301811Sngie} 85301811Sngie 86250079Scarlstatic struct radeon_i2c_bus_rec radeon_get_bus_rec_for_i2c_gpio(ATOM_GPIO_I2C_ASSIGMENT *gpio) 87250079Scarl{ 88300373Smav struct radeon_i2c_bus_rec i2c; 89250079Scarl 90250079Scarl memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec)); 91300373Smav 92300373Smav i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; 93300373Smav i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; 94300373Smav i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4; 95300373Smav i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4; 96300373Smav i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4; 97300373Smav i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4; 98300373Smav i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4; 99300373Smav i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4; 100300373Smav i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift); 101300373Smav i2c.mask_data_mask = (1 << gpio->ucDataMaskShift); 102300373Smav i2c.en_clk_mask = (1 << gpio->ucClkEnShift); 103300373Smav i2c.en_data_mask = (1 << gpio->ucDataEnShift); 104300373Smav i2c.y_clk_mask = (1 << gpio->ucClkY_Shift); 105300373Smav i2c.y_data_mask = (1 << gpio->ucDataY_Shift); 106300373Smav i2c.a_clk_mask = (1 << gpio->ucClkA_Shift); 107300373Smav i2c.a_data_mask = (1 << gpio->ucDataA_Shift); 108300373Smav 109300373Smav if (gpio->sucI2cId.sbfAccess.bfHW_Capable) 110300373Smav i2c.hw_capable = true; 111301811Sngie else 112301811Sngie i2c.hw_capable = false; 113301811Sngie 114301811Sngie if (gpio->sucI2cId.ucAccess == 0xa0) 115301811Sngie i2c.mm_i2c = true; 116301811Sngie else 117301811Sngie i2c.mm_i2c = false; 118301811Sngie 119301811Sngie i2c.i2c_id = gpio->sucI2cId.ucAccess; 120301811Sngie 121301811Sngie if (i2c.mask_clk_reg) 122301811Sngie i2c.valid = true; 123255274Scarl else 124304380Smav i2c.valid = false; 125304380Smav 126255274Scarl return i2c; 127250079Scarl} 128250079Scarl 129255274Scarlstatic struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rdev, 130250079Scarl uint8_t id) 131300373Smav{ 132250079Scarl struct atom_context *ctx = rdev->mode_info.atom_context; 133250079Scarl ATOM_GPIO_I2C_ASSIGMENT *gpio; 134250079Scarl struct radeon_i2c_bus_rec i2c; 135250079Scarl int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info); 136250079Scarl struct _ATOM_GPIO_I2C_INFO *i2c_info; 137250079Scarl uint16_t data_offset, size; 138250079Scarl int i, num_indices; 139250079Scarl 140300373Smav memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec)); 141300373Smav i2c.valid = false; 142300373Smav 143300373Smav if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) { 144300373Smav i2c_info = (struct _ATOM_GPIO_I2C_INFO *)((char *)ctx->bios + data_offset); 145300373Smav 146300373Smav num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / 147300373Smav sizeof(ATOM_GPIO_I2C_ASSIGMENT); 148250079Scarl 149250079Scarl for (i = 0; i < num_indices; i++) { 150250079Scarl gpio = &i2c_info->asGPIO_Info[i]; 151250079Scarl 152250079Scarl radeon_lookup_i2c_gpio_quirks(rdev, gpio, i); 153250079Scarl 154250079Scarl if (gpio->sucI2cId.ucAccess == id) { 155250079Scarl i2c = radeon_get_bus_rec_for_i2c_gpio(gpio); 156300373Smav break; 157250079Scarl } 158300373Smav } 159301811Sngie } 160250079Scarl 161250079Scarl return i2c; 162300373Smav} 163300373Smav 164300373Smavvoid radeon_atombios_i2c_init(struct radeon_device *rdev) 165300373Smav{ 166300373Smav struct atom_context *ctx = rdev->mode_info.atom_context; 167300373Smav ATOM_GPIO_I2C_ASSIGMENT *gpio; 168300373Smav struct radeon_i2c_bus_rec i2c; 169300373Smav int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info); 170300373Smav struct _ATOM_GPIO_I2C_INFO *i2c_info; 171300373Smav uint16_t data_offset, size; 172300373Smav int i, num_indices; 173300373Smav char stmp[32]; 174300373Smav 175300373Smav if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) { 176300373Smav i2c_info = (struct _ATOM_GPIO_I2C_INFO *)((char *)ctx->bios + data_offset); 177300373Smav 178300373Smav num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / 179300373Smav sizeof(ATOM_GPIO_I2C_ASSIGMENT); 180300373Smav 181300373Smav for (i = 0; i < num_indices; i++) { 182300373Smav gpio = &i2c_info->asGPIO_Info[i]; 183300373Smav 184300373Smav radeon_lookup_i2c_gpio_quirks(rdev, gpio, i); 185300373Smav 186300373Smav i2c = radeon_get_bus_rec_for_i2c_gpio(gpio); 187300373Smav 188300373Smav if (i2c.valid) { 189300373Smav sprintf(stmp, "0x%x", i2c.i2c_id); 190300373Smav rdev->i2c_bus[i] = radeon_i2c_create(rdev->ddev, &i2c, stmp); 191300373Smav } 192300373Smav } 193300373Smav } 194300373Smav} 195300373Smav 196300373Smavstatic struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev, 197300373Smav u8 id) 198301811Sngie{ 199301811Sngie struct atom_context *ctx = rdev->mode_info.atom_context; 200301811Sngie struct radeon_gpio_rec gpio; 201301811Sngie int index = GetIndexIntoMasterTable(DATA, GPIO_Pin_LUT); 202301811Sngie struct _ATOM_GPIO_PIN_LUT *gpio_info; 203250079Scarl ATOM_GPIO_PIN_ASSIGNMENT *pin; 204304404Smav u16 data_offset, size; 205304404Smav int i, num_indices; 206304404Smav 207250079Scarl memset(&gpio, 0, sizeof(struct radeon_gpio_rec)); 208250079Scarl gpio.valid = false; 209300373Smav 210250079Scarl if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) { 211250079Scarl gpio_info = (struct _ATOM_GPIO_PIN_LUT *)((char *)ctx->bios + data_offset); 212250079Scarl 213250079Scarl num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / 214250079Scarl sizeof(ATOM_GPIO_PIN_ASSIGNMENT); 215301811Sngie 216301811Sngie for (i = 0; i < num_indices; i++) { 217301811Sngie pin = &gpio_info->asGPIO_Pin[i]; 218301811Sngie if (id == pin->ucGPIO_ID) { 219301811Sngie gpio.id = pin->ucGPIO_ID; 220301811Sngie gpio.reg = le16_to_cpu(pin->usGpioPin_AIndex) * 4; 221301811Sngie gpio.mask = (1 << pin->ucGpioPinBitShift); 222250079Scarl gpio.valid = true; 223250079Scarl break; 224250079Scarl } 225300373Smav } 226250079Scarl } 227300373Smav 228300373Smav return gpio; 229300373Smav} 230300373Smav 231300373Smavstatic struct radeon_hpd radeon_atom_get_hpd_info_from_gpio(struct radeon_device *rdev, 232300373Smav struct radeon_gpio_rec *gpio) 233300373Smav{ 234300373Smav struct radeon_hpd hpd; 235300373Smav u32 reg; 236301904Smav 237301811Sngie memset(&hpd, 0, sizeof(struct radeon_hpd)); 238300373Smav 239300373Smav if (ASIC_IS_DCE6(rdev)) 240300373Smav reg = SI_DC_GPIO_HPD_A; 241300373Smav else if (ASIC_IS_DCE4(rdev)) 242300373Smav reg = EVERGREEN_DC_GPIO_HPD_A; 243300373Smav else 244300373Smav reg = AVIVO_DC_GPIO_HPD_A; 245300373Smav 246300373Smav hpd.gpio = *gpio; 247300373Smav if (gpio->reg == reg) { 248300373Smav switch(gpio->mask) { 249300373Smav case (1 << 0): 250300373Smav hpd.hpd = RADEON_HPD_1; 251300373Smav break; 252300373Smav case (1 << 8): 253300373Smav hpd.hpd = RADEON_HPD_2; 254300373Smav break; 255300373Smav case (1 << 16): 256300373Smav hpd.hpd = RADEON_HPD_3; 257304388Smav break; 258300373Smav case (1 << 24): 259300373Smav hpd.hpd = RADEON_HPD_4; 260300373Smav break; 261300373Smav case (1 << 26): 262300373Smav hpd.hpd = RADEON_HPD_5; 263300373Smav break; 264300373Smav case (1 << 28): 265250079Scarl hpd.hpd = RADEON_HPD_6; 266250079Scarl break; 267300373Smav default: 268300373Smav hpd.hpd = RADEON_HPD_NONE; 269300373Smav break; 270300373Smav } 271300373Smav } else 272300373Smav hpd.hpd = RADEON_HPD_NONE; 273300373Smav return hpd; 274300373Smav} 275300373Smav 276300373Smavstatic bool radeon_atom_apply_quirks(struct drm_device *dev, 277300373Smav uint32_t supported_device, 278300373Smav int *connector_type, 279300373Smav struct radeon_i2c_bus_rec *i2c_bus, 280300373Smav uint16_t *line_mux, 281300373Smav struct radeon_hpd *hpd) 282300373Smav{ 283300373Smav 284300373Smav /* Asus M2A-VM HDMI board lists the DVI port as HDMI */ 285300373Smav if ((dev->pci_device == 0x791e) && 286300373Smav (dev->pci_subvendor == 0x1043) && 287304404Smav (dev->pci_subdevice == 0x826d)) { 288255279Scarl if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) && 289255279Scarl (supported_device == ATOM_DEVICE_DFP3_SUPPORT)) 290304404Smav *connector_type = DRM_MODE_CONNECTOR_DVID; 291255279Scarl } 292255279Scarl 293304404Smav /* Asrock RS600 board lists the DVI port as HDMI */ 294304404Smav if ((dev->pci_device == 0x7941) && 295304404Smav (dev->pci_subvendor == 0x1849) && 296304404Smav (dev->pci_subdevice == 0x7941)) { 297304404Smav if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) && 298304404Smav (supported_device == ATOM_DEVICE_DFP3_SUPPORT)) 299304404Smav *connector_type = DRM_MODE_CONNECTOR_DVID; 300304404Smav } 301304404Smav 302300373Smav /* MSI K9A2GM V2/V3 board has no HDMI or DVI */ 303250079Scarl if ((dev->pci_device == 0x796e) && 304304404Smav (dev->pci_subvendor == 0x1462) && 305304404Smav (dev->pci_subdevice == 0x7302)) { 306304404Smav if ((supported_device == ATOM_DEVICE_DFP2_SUPPORT) || 307304404Smav (supported_device == ATOM_DEVICE_DFP3_SUPPORT)) 308304404Smav return false; 309304404Smav } 310304404Smav 311304380Smav /* a-bit f-i90hd - ciaranm on #radeonhd - this board has no DVI */ 312304404Smav if ((dev->pci_device == 0x7941) && 313304380Smav (dev->pci_subvendor == 0x147b) && 314304404Smav (dev->pci_subdevice == 0x2412)) { 315304404Smav if (*connector_type == DRM_MODE_CONNECTOR_DVII) 316304404Smav return false; 317304380Smav } 318304404Smav 319304404Smav /* Falcon NW laptop lists vga ddc line for LVDS */ 320300373Smav if ((dev->pci_device == 0x5653) && 321300373Smav (dev->pci_subvendor == 0x1462) && 322300373Smav (dev->pci_subdevice == 0x0291)) { 323304404Smav if (*connector_type == DRM_MODE_CONNECTOR_LVDS) { 324304404Smav i2c_bus->valid = false; 325300373Smav *line_mux = 53; 326300373Smav } 327300373Smav } 328255272Scarl 329255272Scarl /* HIS X1300 is DVI+VGA, not DVI+DVI */ 330255272Scarl if ((dev->pci_device == 0x7146) && 331304404Smav (dev->pci_subvendor == 0x17af) && 332304404Smav (dev->pci_subdevice == 0x2058)) { 333304404Smav if (supported_device == ATOM_DEVICE_DFP1_SUPPORT) 334304404Smav return false; 335304404Smav } 336304404Smav 337304404Smav /* Gigabyte X1300 is DVI+VGA, not DVI+DVI */ 338304404Smav if ((dev->pci_device == 0x7142) && 339300373Smav (dev->pci_subvendor == 0x1458) && 340300373Smav (dev->pci_subdevice == 0x2134)) { 341300373Smav if (supported_device == ATOM_DEVICE_DFP1_SUPPORT) 342300373Smav return false; 343300373Smav } 344304404Smav 345304404Smav 346304404Smav /* Funky macbooks */ 347304404Smav if ((dev->pci_device == 0x71C5) && 348304404Smav (dev->pci_subvendor == 0x106b) && 349304404Smav (dev->pci_subdevice == 0x0080)) { 350304404Smav if ((supported_device == ATOM_DEVICE_CRT1_SUPPORT) || 351304404Smav (supported_device == ATOM_DEVICE_DFP2_SUPPORT)) 352304404Smav return false; 353304404Smav if (supported_device == ATOM_DEVICE_CRT2_SUPPORT) 354304404Smav *line_mux = 0x90; 355300373Smav } 356300373Smav 357300373Smav /* mac rv630, rv730, others */ 358300373Smav if ((supported_device == ATOM_DEVICE_TV1_SUPPORT) && 359300373Smav (*connector_type == DRM_MODE_CONNECTOR_DVII)) { 360300373Smav *connector_type = DRM_MODE_CONNECTOR_9PinDIN; 361300373Smav *line_mux = CONNECTOR_7PIN_DIN_ENUM_ID1; 362300373Smav } 363300373Smav 364300373Smav /* ASUS HD 3600 XT board lists the DVI port as HDMI */ 365301811Sngie if ((dev->pci_device == 0x9598) && 366300373Smav (dev->pci_subvendor == 0x1043) && 367304404Smav (dev->pci_subdevice == 0x01da)) { 368304404Smav if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) { 369300373Smav *connector_type = DRM_MODE_CONNECTOR_DVII; 370300373Smav } 371304404Smav } 372255274Scarl 373304404Smav /* ASUS HD 3600 board lists the DVI port as HDMI */ 374300373Smav if ((dev->pci_device == 0x9598) && 375301811Sngie (dev->pci_subvendor == 0x1043) && 376301811Sngie (dev->pci_subdevice == 0x01e4)) { 377300373Smav if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) { 378300373Smav *connector_type = DRM_MODE_CONNECTOR_DVII; 379250079Scarl } 380300373Smav } 381300516Smav 382300373Smav /* ASUS HD 3450 board lists the DVI port as HDMI */ 383300373Smav if ((dev->pci_device == 0x95C5) && 384304404Smav (dev->pci_subvendor == 0x1043) && 385300373Smav (dev->pci_subdevice == 0x01e2)) { 386300373Smav if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) { 387300373Smav *connector_type = DRM_MODE_CONNECTOR_DVII; 388300373Smav } 389300373Smav } 390300373Smav 391300373Smav /* some BIOSes seem to report DAC on HDMI - usually this is a board with 392300373Smav * HDMI + VGA reporting as HDMI 393300373Smav */ 394300373Smav if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) { 395300373Smav if (supported_device & (ATOM_DEVICE_CRT_SUPPORT)) { 396300373Smav *connector_type = DRM_MODE_CONNECTOR_VGA; 397300516Smav *line_mux = 0; 398300373Smav } 399300373Smav } 400300373Smav 401300373Smav /* Acer laptop (Acer TravelMate 5730/5730G) has an HDMI port 402300373Smav * on the laptop and a DVI port on the docking station and 403300373Smav * both share the same encoder, hpd pin, and ddc line. 404300373Smav * So while the bios table is technically correct, 405300373Smav * we drop the DVI port here since xrandr has no concept of 406300373Smav * encoders and will try and drive both connectors 407300373Smav * with different crtcs which isn't possible on the hardware 408304404Smav * side and leaves no crtcs for LVDS or VGA. 409300373Smav */ 410300373Smav if (((dev->pci_device == 0x95c4) || (dev->pci_device == 0x9591)) && 411300373Smav (dev->pci_subvendor == 0x1025) && 412300373Smav (dev->pci_subdevice == 0x013c)) { 413300373Smav if ((*connector_type == DRM_MODE_CONNECTOR_DVII) && 414300373Smav (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) { 415300373Smav /* actually it's a DVI-D port not DVI-I */ 416300373Smav *connector_type = DRM_MODE_CONNECTOR_DVID; 417300373Smav return false; 418300373Smav } 419300373Smav } 420300373Smav 421300373Smav /* XFX Pine Group device rv730 reports no VGA DDC lines 422300373Smav * even though they are wired up to record 0x93 423300373Smav */ 424300373Smav if ((dev->pci_device == 0x9498) && 425300373Smav (dev->pci_subvendor == 0x1682) && 426300373Smav (dev->pci_subdevice == 0x2452) && 427300373Smav (i2c_bus->valid == false) && 428300373Smav !(supported_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))) { 429300373Smav struct radeon_device *rdev = dev->dev_private; 430300373Smav *i2c_bus = radeon_lookup_i2c_gpio(rdev, 0x93); 431300373Smav } 432300373Smav 433300373Smav /* Fujitsu D3003-S2 board lists DVI-I as DVI-D and VGA */ 434304404Smav if (((dev->pci_device == 0x9802) || (dev->pci_device == 0x9806)) && 435300373Smav (dev->pci_subvendor == 0x1734) && 436300373Smav (dev->pci_subdevice == 0x11bd)) { 437300373Smav if (*connector_type == DRM_MODE_CONNECTOR_VGA) { 438300373Smav *connector_type = DRM_MODE_CONNECTOR_DVII; 439300373Smav *line_mux = 0x3103; 440300373Smav } else if (*connector_type == DRM_MODE_CONNECTOR_DVID) { 441300373Smav *connector_type = DRM_MODE_CONNECTOR_DVII; 442300373Smav } 443300373Smav } 444300373Smav 445300373Smav 446300373Smav return true; 447300373Smav} 448300373Smav 449300373Smavconst int supported_devices_connector_convert[] = { 450300373Smav DRM_MODE_CONNECTOR_Unknown, 451300373Smav DRM_MODE_CONNECTOR_VGA, 452300373Smav DRM_MODE_CONNECTOR_DVII, 453300373Smav DRM_MODE_CONNECTOR_DVID, 454300373Smav DRM_MODE_CONNECTOR_DVIA, 455304394Smav DRM_MODE_CONNECTOR_SVIDEO, 456304380Smav DRM_MODE_CONNECTOR_Composite, 457301811Sngie DRM_MODE_CONNECTOR_LVDS, 458301811Sngie DRM_MODE_CONNECTOR_Unknown, 459301811Sngie DRM_MODE_CONNECTOR_Unknown, 460301811Sngie DRM_MODE_CONNECTOR_HDMIA, 461301811Sngie DRM_MODE_CONNECTOR_HDMIB, 462301811Sngie DRM_MODE_CONNECTOR_Unknown, 463300373Smav DRM_MODE_CONNECTOR_Unknown, 464300516Smav DRM_MODE_CONNECTOR_9PinDIN, 465300373Smav DRM_MODE_CONNECTOR_DisplayPort 466300373Smav}; 467300373Smav 468300373Smavconst uint16_t supported_devices_connector_object_id_convert[] = { 469300373Smav CONNECTOR_OBJECT_ID_NONE, 470300373Smav CONNECTOR_OBJECT_ID_VGA, 471300373Smav CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I, /* not all boards support DL */ 472304380Smav CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D, /* not all boards support DL */ 473304380Smav CONNECTOR_OBJECT_ID_VGA, /* technically DVI-A */ 474304380Smav CONNECTOR_OBJECT_ID_COMPOSITE, 475304380Smav CONNECTOR_OBJECT_ID_SVIDEO, 476304380Smav CONNECTOR_OBJECT_ID_LVDS, 477304380Smav CONNECTOR_OBJECT_ID_9PIN_DIN, 478304380Smav CONNECTOR_OBJECT_ID_9PIN_DIN, 479304380Smav CONNECTOR_OBJECT_ID_DISPLAYPORT, 480304380Smav CONNECTOR_OBJECT_ID_HDMI_TYPE_A, 481304380Smav CONNECTOR_OBJECT_ID_HDMI_TYPE_B, 482304380Smav CONNECTOR_OBJECT_ID_SVIDEO 483304380Smav}; 484250079Scarl 485300373Smavconst int object_connector_convert[] = { 486300373Smav DRM_MODE_CONNECTOR_Unknown, 487300373Smav DRM_MODE_CONNECTOR_DVII, 488300373Smav DRM_MODE_CONNECTOR_DVII, 489300373Smav DRM_MODE_CONNECTOR_DVID, 490300373Smav DRM_MODE_CONNECTOR_DVID, 491300373Smav DRM_MODE_CONNECTOR_VGA, 492300373Smav DRM_MODE_CONNECTOR_Composite, 493300373Smav DRM_MODE_CONNECTOR_SVIDEO, 494300373Smav DRM_MODE_CONNECTOR_Unknown, 495300373Smav DRM_MODE_CONNECTOR_Unknown, 496300373Smav DRM_MODE_CONNECTOR_9PinDIN, 497300373Smav DRM_MODE_CONNECTOR_Unknown, 498300373Smav DRM_MODE_CONNECTOR_HDMIA, 499300373Smav DRM_MODE_CONNECTOR_HDMIB, 500300373Smav DRM_MODE_CONNECTOR_LVDS, 501300373Smav DRM_MODE_CONNECTOR_9PinDIN, 502300373Smav DRM_MODE_CONNECTOR_Unknown, 503300373Smav DRM_MODE_CONNECTOR_Unknown, 504250079Scarl DRM_MODE_CONNECTOR_Unknown, 505250079Scarl DRM_MODE_CONNECTOR_DisplayPort, 506300373Smav DRM_MODE_CONNECTOR_eDP, 507300373Smav DRM_MODE_CONNECTOR_Unknown 508300373Smav}; 509300373Smav 510300373Smavbool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) 511300373Smav{ 512300373Smav struct radeon_device *rdev = dev->dev_private; 513300373Smav struct radeon_mode_info *mode_info = &rdev->mode_info; 514300373Smav struct atom_context *ctx = mode_info->atom_context; 515300373Smav int index = GetIndexIntoMasterTable(DATA, Object_Header); 516300373Smav u16 size, data_offset; 517300373Smav u8 frev, crev; 518300373Smav ATOM_CONNECTOR_OBJECT_TABLE *con_obj; 519300373Smav ATOM_ENCODER_OBJECT_TABLE *enc_obj; 520300373Smav ATOM_OBJECT_TABLE *router_obj; 521300373Smav ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj; 522300373Smav ATOM_OBJECT_HEADER *obj_header; 523300373Smav int i, j, k, path_size, device_support; 524300373Smav int connector_type; 525300373Smav u16 igp_lane_info, conn_id, connector_object_id; 526300373Smav struct radeon_i2c_bus_rec ddc_bus; 527300373Smav struct radeon_router router; 528300373Smav struct radeon_gpio_rec gpio; 529300373Smav struct radeon_hpd hpd; 530300373Smav 531300373Smav if (!atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset)) 532300373Smav return false; 533300373Smav 534300373Smav if (crev < 2) 535300373Smav return false; 536300373Smav 537300373Smav obj_header = (ATOM_OBJECT_HEADER *) ((char *)ctx->bios + data_offset); 538300373Smav path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *) 539300373Smav ((char *)ctx->bios + data_offset + 540300373Smav le16_to_cpu(obj_header->usDisplayPathTableOffset)); 541300373Smav con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *) 542300373Smav ((char *)ctx->bios + data_offset + 543300373Smav le16_to_cpu(obj_header->usConnectorObjectTableOffset)); 544300373Smav enc_obj = (ATOM_ENCODER_OBJECT_TABLE *) 545300373Smav ((char *)ctx->bios + data_offset + 546300373Smav le16_to_cpu(obj_header->usEncoderObjectTableOffset)); 547300373Smav router_obj = (ATOM_OBJECT_TABLE *) 548300373Smav ((char *)ctx->bios + data_offset + 549300373Smav le16_to_cpu(obj_header->usRouterObjectTableOffset)); 550300373Smav device_support = le16_to_cpu(obj_header->usDeviceSupport); 551300373Smav 552300373Smav path_size = 0; 553300373Smav for (i = 0; i < path_obj->ucNumOfDispPath; i++) { 554300373Smav uint8_t *addr = (uint8_t *) path_obj->asDispPath; 555300373Smav ATOM_DISPLAY_OBJECT_PATH *path; 556300373Smav addr += path_size; 557300373Smav path = (ATOM_DISPLAY_OBJECT_PATH *) addr; 558300373Smav path_size += le16_to_cpu(path->usSize); 559300373Smav 560300373Smav if (device_support & le16_to_cpu(path->usDeviceTag)) { 561300373Smav uint8_t con_obj_id, con_obj_num, con_obj_type; 562300373Smav 563300373Smav con_obj_id = 564300373Smav (le16_to_cpu(path->usConnObjectId) & OBJECT_ID_MASK) 565300373Smav >> OBJECT_ID_SHIFT; 566300373Smav con_obj_num = 567300373Smav (le16_to_cpu(path->usConnObjectId) & ENUM_ID_MASK) 568300373Smav >> ENUM_ID_SHIFT; 569300373Smav con_obj_type = 570300373Smav (le16_to_cpu(path->usConnObjectId) & 571300373Smav OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; 572300373Smav 573300373Smav /* TODO CV support */ 574300373Smav if (le16_to_cpu(path->usDeviceTag) == 575300373Smav ATOM_DEVICE_CV_SUPPORT) 576300373Smav continue; 577300373Smav 578300373Smav /* IGP chips */ 579300373Smav if ((rdev->flags & RADEON_IS_IGP) && 580300373Smav (con_obj_id == 581300373Smav CONNECTOR_OBJECT_ID_PCIE_CONNECTOR)) { 582300373Smav uint16_t igp_offset = 0; 583300373Smav ATOM_INTEGRATED_SYSTEM_INFO_V2 *igp_obj; 584300373Smav 585300373Smav index = 586300373Smav GetIndexIntoMasterTable(DATA, 587300373Smav IntegratedSystemInfo); 588300373Smav 589300373Smav if (atom_parse_data_header(ctx, index, &size, &frev, 590300373Smav &crev, &igp_offset)) { 591300516Smav 592300373Smav if (crev >= 2) { 593300373Smav igp_obj = 594300373Smav (ATOM_INTEGRATED_SYSTEM_INFO_V2 595300373Smav *) ((char *)ctx->bios + igp_offset); 596300373Smav 597300516Smav if (igp_obj) { 598300373Smav uint32_t slot_config, ct; 599300373Smav 600300516Smav if (con_obj_num == 1) 601300373Smav slot_config = 602300373Smav igp_obj-> 603300373Smav ulDDISlot1Config; 604300516Smav else 605300373Smav slot_config = 606300373Smav igp_obj-> 607300373Smav ulDDISlot2Config; 608300373Smav 609300516Smav ct = (slot_config >> 16) & 0xff; 610300373Smav connector_type = 611300373Smav object_connector_convert 612300373Smav [ct]; 613300373Smav connector_object_id = ct; 614300373Smav igp_lane_info = 615300516Smav slot_config & 0xffff; 616300373Smav } else 617300373Smav continue; 618300516Smav } else 619300373Smav continue; 620300373Smav } else { 621300373Smav igp_lane_info = 0; 622300516Smav connector_type = 623300373Smav object_connector_convert[con_obj_id]; 624300373Smav connector_object_id = con_obj_id; 625300373Smav } 626300373Smav } else { 627250079Scarl igp_lane_info = 0; 628250079Scarl connector_type = 629250079Scarl object_connector_convert[con_obj_id]; 630250079Scarl connector_object_id = con_obj_id; 631250079Scarl } 632250079Scarl 633250079Scarl if (connector_type == DRM_MODE_CONNECTOR_Unknown) 634250079Scarl continue; 635250079Scarl 636304404Smav router.ddc_valid = false; 637250079Scarl router.cd_valid = false; 638300373Smav for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); j++) { 639250079Scarl uint8_t grph_obj_id, grph_obj_num, grph_obj_type; 640304404Smav 641300373Smav grph_obj_id = 642250079Scarl (le16_to_cpu(path->usGraphicObjIds[j]) & 643300373Smav OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; 644300373Smav grph_obj_num = 645300373Smav (le16_to_cpu(path->usGraphicObjIds[j]) & 646250079Scarl ENUM_ID_MASK) >> ENUM_ID_SHIFT; 647250079Scarl grph_obj_type = 648250079Scarl (le16_to_cpu(path->usGraphicObjIds[j]) & 649304404Smav OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; 650250079Scarl 651300373Smav if (grph_obj_type == GRAPH_OBJECT_TYPE_ENCODER) { 652300373Smav for (k = 0; k < enc_obj->ucNumberOfObjects; k++) { 653250079Scarl u16 encoder_obj = le16_to_cpu(enc_obj->asObjects[k].usObjectID); 654250079Scarl if (le16_to_cpu(path->usGraphicObjIds[j]) == encoder_obj) { 655304380Smav ATOM_COMMON_RECORD_HEADER *record = (ATOM_COMMON_RECORD_HEADER *) 656304404Smav ((char *)ctx->bios + data_offset + 657300373Smav le16_to_cpu(enc_obj->asObjects[k].usRecordOffset)); 658250079Scarl ATOM_ENCODER_CAP_RECORD *cap_record; 659250079Scarl u16 caps = 0; 660255274Scarl 661300373Smav while (record->ucRecordSize > 0 && 662301811Sngie record->ucRecordType > 0 && 663250079Scarl record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) { 664300373Smav switch (record->ucRecordType) { 665314667Savg case ATOM_ENCODER_CAP_RECORD_TYPE: 666314667Savg cap_record =(ATOM_ENCODER_CAP_RECORD *) 667301811Sngie record; 668300373Smav caps = le16_to_cpu(cap_record->usEncoderCap); 669250079Scarl break; 670300373Smav } 671304404Smav record = (ATOM_COMMON_RECORD_HEADER *) 672300373Smav ((char *)record + record->ucRecordSize); 673304404Smav } 674300373Smav radeon_add_atom_encoder(dev, 675300373Smav encoder_obj, 676250079Scarl le16_to_cpu 677304404Smav (path-> 678300373Smav usDeviceTag), 679250079Scarl caps); 680250079Scarl } 681304404Smav } 682300373Smav } else if (grph_obj_type == GRAPH_OBJECT_TYPE_ROUTER) { 683300373Smav for (k = 0; k < router_obj->ucNumberOfObjects; k++) { 684300373Smav u16 router_obj_id = le16_to_cpu(router_obj->asObjects[k].usObjectID); 685304404Smav if (le16_to_cpu(path->usGraphicObjIds[j]) == router_obj_id) { 686300373Smav ATOM_COMMON_RECORD_HEADER *record = (ATOM_COMMON_RECORD_HEADER *) 687304404Smav ((char *)ctx->bios + data_offset + 688300373Smav le16_to_cpu(router_obj->asObjects[k].usRecordOffset)); 689300373Smav ATOM_I2C_RECORD *i2c_record; 690300373Smav ATOM_I2C_ID_CONFIG_ACCESS *i2c_config; 691304404Smav ATOM_ROUTER_DDC_PATH_SELECT_RECORD *ddc_path; 692301811Sngie ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD *cd_path; 693304404Smav ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *router_src_dst_table = 694300373Smav (ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *) 695304404Smav ((char *)ctx->bios + data_offset + 696300373Smav le16_to_cpu(router_obj->asObjects[k].usSrcDstTableOffset)); 697304380Smav int enum_id; 698304404Smav 699304380Smav router.router_id = router_obj_id; 700300373Smav for (enum_id = 0; enum_id < router_src_dst_table->ucNumberOfDst; 701300373Smav enum_id++) { 702304404Smav if (le16_to_cpu(path->usConnObjectId) == 703250079Scarl le16_to_cpu(router_src_dst_table->usDstObjectID[enum_id])) 704250079Scarl break; 705250079Scarl } 706250079Scarl 707304404Smav while (record->ucRecordSize > 0 && 708250079Scarl record->ucRecordType > 0 && 709300373Smav record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) { 710250079Scarl switch (record->ucRecordType) { 711304380Smav case ATOM_I2C_RECORD_TYPE: 712300373Smav i2c_record = 713304380Smav (ATOM_I2C_RECORD *) 714304404Smav record; 715304380Smav i2c_config = 716301811Sngie (ATOM_I2C_ID_CONFIG_ACCESS *) 717301811Sngie &i2c_record->sucI2cId; 718301811Sngie router.i2c_info = 719301811Sngie radeon_lookup_i2c_gpio(rdev, 720301811Sngie i2c_config-> 721250079Scarl ucAccess); 722250079Scarl router.i2c_addr = i2c_record->ucI2CAddr >> 1; 723301811Sngie break; 724300373Smav case ATOM_ROUTER_DDC_PATH_SELECT_RECORD_TYPE: 725300373Smav ddc_path = (ATOM_ROUTER_DDC_PATH_SELECT_RECORD *) 726304404Smav record; 727304404Smav router.ddc_valid = true; 728300373Smav router.ddc_mux_type = ddc_path->ucMuxType; 729300373Smav router.ddc_mux_control_pin = ddc_path->ucMuxControlPin; 730300373Smav router.ddc_mux_state = ddc_path->ucMuxState[enum_id]; 731304404Smav break; 732250079Scarl case ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD_TYPE: 733250079Scarl cd_path = (ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD *) 734250079Scarl record; 735250079Scarl router.cd_valid = true; 736300373Smav router.cd_mux_type = cd_path->ucMuxType; 737300373Smav router.cd_mux_control_pin = cd_path->ucMuxControlPin; 738300373Smav router.cd_mux_state = cd_path->ucMuxState[enum_id]; 739300373Smav break; 740304404Smav } 741300373Smav record = (ATOM_COMMON_RECORD_HEADER *) 742300373Smav ((char *)record + record->ucRecordSize); 743300373Smav } 744300373Smav } 745300373Smav } 746300373Smav } 747300373Smav } 748300373Smav 749300373Smav /* look up gpio for ddc, hpd */ 750300373Smav ddc_bus.valid = false; 751300373Smav hpd.hpd = RADEON_HPD_NONE; 752300373Smav if ((le16_to_cpu(path->usDeviceTag) & 753300373Smav (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) == 0) { 754300373Smav for (j = 0; j < con_obj->ucNumberOfObjects; j++) { 755304380Smav if (le16_to_cpu(path->usConnObjectId) == 756300373Smav le16_to_cpu(con_obj->asObjects[j]. 757300373Smav usObjectID)) { 758300373Smav ATOM_COMMON_RECORD_HEADER 759300373Smav *record = 760300373Smav (ATOM_COMMON_RECORD_HEADER 761300373Smav *) 762300373Smav ((char *)ctx->bios + data_offset + 763300373Smav le16_to_cpu(con_obj-> 764300373Smav asObjects[j]. 765300373Smav usRecordOffset)); 766300373Smav ATOM_I2C_RECORD *i2c_record; 767300373Smav ATOM_HPD_INT_RECORD *hpd_record; 768300373Smav ATOM_I2C_ID_CONFIG_ACCESS *i2c_config; 769300373Smav 770300373Smav while (record->ucRecordSize > 0 && 771300373Smav record->ucRecordType > 0 && 772300373Smav record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) { 773300373Smav switch (record->ucRecordType) { 774300373Smav case ATOM_I2C_RECORD_TYPE: 775300373Smav i2c_record = 776300373Smav (ATOM_I2C_RECORD *) 777300373Smav record; 778300373Smav i2c_config = 779300373Smav (ATOM_I2C_ID_CONFIG_ACCESS *) 780300373Smav &i2c_record->sucI2cId; 781300373Smav ddc_bus = radeon_lookup_i2c_gpio(rdev, 782300373Smav i2c_config-> 783300373Smav ucAccess); 784300373Smav break; 785300373Smav case ATOM_HPD_INT_RECORD_TYPE: 786300373Smav hpd_record = 787300373Smav (ATOM_HPD_INT_RECORD *) 788300373Smav record; 789300373Smav gpio = radeon_lookup_gpio(rdev, 790300373Smav hpd_record->ucHPDIntGPIOID); 791300373Smav hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio); 792300373Smav hpd.plugged_state = hpd_record->ucPlugged_PinState; 793300373Smav break; 794300373Smav } 795250079Scarl record = 796304404Smav (ATOM_COMMON_RECORD_HEADER 797250079Scarl *) ((char *)record 798255272Scarl + 799250079Scarl record-> 800250079Scarl ucRecordSize); 801300373Smav } 802255272Scarl break; 803300373Smav } 804255272Scarl } 805300373Smav } 806300373Smav 807255272Scarl /* needed for aux chan transactions */ 808300373Smav ddc_bus.hpd = hpd.hpd; 809300373Smav 810300373Smav conn_id = le16_to_cpu(path->usConnObjectId); 811300373Smav 812255272Scarl if (!radeon_atom_apply_quirks 813300373Smav (dev, le16_to_cpu(path->usDeviceTag), &connector_type, 814300373Smav &ddc_bus, &conn_id, &hpd)) 815255272Scarl continue; 816300373Smav 817300373Smav radeon_add_atom_connector(dev, 818300373Smav conn_id, 819300373Smav le16_to_cpu(path-> 820255274Scarl usDeviceTag), 821304380Smav connector_type, &ddc_bus, 822300373Smav igp_lane_info, 823250079Scarl connector_object_id, 824300373Smav &hpd, 825300373Smav &router); 826300373Smav 827300373Smav } 828300373Smav } 829255272Scarl 830300373Smav radeon_link_encoder_connector(dev); 831300373Smav 832255272Scarl return true; 833255272Scarl} 834255272Scarl 835255272Scarlstatic uint16_t atombios_get_connector_object_id(struct drm_device *dev, 836255272Scarl int connector_type, 837300373Smav uint16_t devices) 838300373Smav{ 839300373Smav struct radeon_device *rdev = dev->dev_private; 840300373Smav 841300373Smav if (rdev->flags & RADEON_IS_IGP) { 842300373Smav return supported_devices_connector_object_id_convert 843300373Smav [connector_type]; 844300373Smav } else if (((connector_type == DRM_MODE_CONNECTOR_DVII) || 845300373Smav (connector_type == DRM_MODE_CONNECTOR_DVID)) && 846300373Smav (devices & ATOM_DEVICE_DFP2_SUPPORT)) { 847300373Smav struct radeon_mode_info *mode_info = &rdev->mode_info; 848300373Smav struct atom_context *ctx = mode_info->atom_context; 849300373Smav int index = GetIndexIntoMasterTable(DATA, XTMDS_Info); 850255272Scarl uint16_t size, data_offset; 851255272Scarl uint8_t frev, crev; 852255272Scarl ATOM_XTMDS_INFO *xtmds; 853255272Scarl 854255275Scarl if (atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset)) { 855300373Smav xtmds = (ATOM_XTMDS_INFO *)((char *)ctx->bios + data_offset); 856255272Scarl 857255272Scarl if (xtmds->ucSupportedLink & ATOM_XTMDS_SUPPORTED_DUALLINK) { 858300373Smav if (connector_type == DRM_MODE_CONNECTOR_DVII) 859300373Smav return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I; 860300373Smav else 861300373Smav return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D; 862300373Smav } else { 863255272Scarl if (connector_type == DRM_MODE_CONNECTOR_DVII) 864255272Scarl return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I; 865255272Scarl else 866255272Scarl return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D; 867255272Scarl } 868255272Scarl } else 869300373Smav return supported_devices_connector_object_id_convert 870255276Scarl [connector_type]; 871255272Scarl } else { 872300373Smav return supported_devices_connector_object_id_convert 873300373Smav [connector_type]; 874250079Scarl } 875255272Scarl} 876255272Scarl 877255276Scarlstruct bios_connector { 878300373Smav bool valid; 879300373Smav uint16_t line_mux; 880300373Smav uint16_t devices; 881300373Smav int connector_type; 882300373Smav struct radeon_i2c_bus_rec ddc_bus; 883300373Smav struct radeon_hpd hpd; 884300373Smav}; 885300373Smav 886300373Smavbool radeon_get_atom_connector_info_from_supported_devices_table(struct 887300373Smav drm_device 888300373Smav *dev) 889300373Smav{ 890300373Smav struct radeon_device *rdev = dev->dev_private; 891300373Smav struct radeon_mode_info *mode_info = &rdev->mode_info; 892300373Smav struct atom_context *ctx = mode_info->atom_context; 893300373Smav int index = GetIndexIntoMasterTable(DATA, SupportedDevicesInfo); 894300373Smav uint16_t size, data_offset; 895304380Smav uint8_t frev, crev; 896300373Smav uint16_t device_support; 897300373Smav uint8_t dac; 898300373Smav union atom_supported_devices *supported_devices; 899300373Smav int i, j, max_device; 900300373Smav struct bios_connector *bios_connectors; 901300373Smav size_t bc_size = sizeof(*bios_connectors) * ATOM_MAX_SUPPORTED_DEVICE; 902300373Smav struct radeon_router router; 903300373Smav 904300373Smav router.ddc_valid = false; 905300373Smav router.cd_valid = false; 906255272Scarl 907300373Smav bios_connectors = malloc(bc_size, DRM_MEM_DRIVER, M_WAITOK | M_ZERO); 908300373Smav if (!bios_connectors) 909255272Scarl return false; 910250079Scarl 911300373Smav if (!atom_parse_data_header(ctx, index, &size, &frev, &crev, 912300373Smav &data_offset)) { 913250079Scarl free(bios_connectors, DRM_MEM_DRIVER); 914300373Smav return false; 915300373Smav } 916300373Smav 917300373Smav supported_devices = 918300373Smav (union atom_supported_devices *)((char *)ctx->bios + data_offset); 919300373Smav 920300373Smav device_support = le16_to_cpu(supported_devices->info.usDeviceSupport); 921300373Smav 922304404Smav if (frev > 1) 923300373Smav max_device = ATOM_MAX_SUPPORTED_DEVICE; 924300373Smav else 925300373Smav max_device = ATOM_MAX_SUPPORTED_DEVICE_INFO; 926300373Smav 927300373Smav for (i = 0; i < max_device; i++) { 928300373Smav ATOM_CONNECTOR_INFO_I2C ci = 929300373Smav supported_devices->info.asConnInfo[i]; 930300373Smav 931300373Smav bios_connectors[i].valid = false; 932300373Smav 933300373Smav if (!(device_support & (1 << i))) { 934300373Smav continue; 935304404Smav } 936300373Smav 937300373Smav if (i == ATOM_DEVICE_CV_INDEX) { 938300373Smav DRM_DEBUG_KMS("Skipping Component Video\n"); 939300373Smav continue; 940300373Smav } 941300373Smav 942300373Smav bios_connectors[i].connector_type = 943304404Smav supported_devices_connector_convert[ci.sucConnectorInfo. 944300373Smav sbfAccess. 945250079Scarl bfConnectorType]; 946250079Scarl 947250079Scarl if (bios_connectors[i].connector_type == 948250079Scarl DRM_MODE_CONNECTOR_Unknown) 949304404Smav continue; 950250079Scarl 951250079Scarl dac = ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC; 952250079Scarl 953250079Scarl bios_connectors[i].line_mux = 954300373Smav ci.sucI2cId.ucAccess; 955250079Scarl 956250079Scarl /* give tv unique connector ids */ 957250079Scarl if (i == ATOM_DEVICE_TV1_INDEX) { 958250079Scarl bios_connectors[i].ddc_bus.valid = false; 959250079Scarl bios_connectors[i].line_mux = 50; 960250079Scarl } else if (i == ATOM_DEVICE_TV2_INDEX) { 961250079Scarl bios_connectors[i].ddc_bus.valid = false; 962250079Scarl bios_connectors[i].line_mux = 51; 963250079Scarl } else if (i == ATOM_DEVICE_CV_INDEX) { 964304404Smav bios_connectors[i].ddc_bus.valid = false; 965250079Scarl bios_connectors[i].line_mux = 52; 966300373Smav } else 967300373Smav bios_connectors[i].ddc_bus = 968250079Scarl radeon_lookup_i2c_gpio(rdev, 969300373Smav bios_connectors[i].line_mux); 970300373Smav 971300373Smav if ((crev > 1) && (frev > 1)) { 972300373Smav u8 isb = supported_devices->info_2d1.asIntSrcInfo[i].ucIntSrcBitmap; 973300373Smav switch (isb) { 974300373Smav case 0x4: 975300373Smav bios_connectors[i].hpd.hpd = RADEON_HPD_1; 976300373Smav break; 977300373Smav case 0xa: 978300373Smav bios_connectors[i].hpd.hpd = RADEON_HPD_2; 979300373Smav break; 980300373Smav default: 981300373Smav bios_connectors[i].hpd.hpd = RADEON_HPD_NONE; 982300373Smav break; 983300373Smav } 984300373Smav } else { 985300373Smav if (i == ATOM_DEVICE_DFP1_INDEX) 986300373Smav bios_connectors[i].hpd.hpd = RADEON_HPD_1; 987300373Smav else if (i == ATOM_DEVICE_DFP2_INDEX) 988300373Smav bios_connectors[i].hpd.hpd = RADEON_HPD_2; 989300373Smav else 990300373Smav bios_connectors[i].hpd.hpd = RADEON_HPD_NONE; 991300373Smav } 992300373Smav 993300373Smav /* Always set the connector type to VGA for CRT1/CRT2. if they are 994300373Smav * shared with a DVI port, we'll pick up the DVI connector when we 995300373Smav * merge the outputs. Some bioses incorrectly list VGA ports as DVI. 996300373Smav */ 997300373Smav if (i == ATOM_DEVICE_CRT1_INDEX || i == ATOM_DEVICE_CRT2_INDEX) 998300516Smav bios_connectors[i].connector_type = 999300373Smav DRM_MODE_CONNECTOR_VGA; 1000300373Smav 1001300373Smav if (!radeon_atom_apply_quirks 1002300373Smav (dev, (1 << i), &bios_connectors[i].connector_type, 1003300373Smav &bios_connectors[i].ddc_bus, &bios_connectors[i].line_mux, 1004300373Smav &bios_connectors[i].hpd)) 1005300373Smav continue; 1006300373Smav 1007300373Smav bios_connectors[i].valid = true; 1008300516Smav bios_connectors[i].devices = (1 << i); 1009300373Smav 1010300373Smav if (ASIC_IS_AVIVO(rdev) || radeon_r4xx_atom) 1011300373Smav radeon_add_atom_encoder(dev, 1012300373Smav radeon_get_encoder_enum(dev, 1013300373Smav (1 << i), 1014300373Smav dac), 1015300373Smav (1 << i), 1016300373Smav 0); 1017300373Smav else 1018300373Smav radeon_add_legacy_encoder(dev, 1019304404Smav radeon_get_encoder_enum(dev, 1020300373Smav (1 << i), 1021300373Smav dac), 1022300373Smav (1 << i)); 1023300373Smav } 1024300373Smav 1025300373Smav /* combine shared connectors */ 1026300373Smav for (i = 0; i < max_device; i++) { 1027300373Smav if (bios_connectors[i].valid) { 1028300373Smav for (j = 0; j < max_device; j++) { 1029300373Smav if (bios_connectors[j].valid && (i != j)) { 1030300373Smav if (bios_connectors[i].line_mux == 1031300373Smav bios_connectors[j].line_mux) { 1032300373Smav /* make sure not to combine LVDS */ 1033300373Smav if (bios_connectors[i].devices & (ATOM_DEVICE_LCD_SUPPORT)) { 1034300373Smav bios_connectors[i].line_mux = 53; 1035300373Smav bios_connectors[i].ddc_bus.valid = false; 1036300373Smav continue; 1037300373Smav } 1038300373Smav if (bios_connectors[j].devices & (ATOM_DEVICE_LCD_SUPPORT)) { 1039304404Smav bios_connectors[j].line_mux = 53; 1040300373Smav bios_connectors[j].ddc_bus.valid = false; 1041300373Smav continue; 1042300373Smav } 1043300373Smav /* combine analog and digital for DVI-I */ 1044250079Scarl if (((bios_connectors[i].devices & (ATOM_DEVICE_DFP_SUPPORT)) && 1045300373Smav (bios_connectors[j].devices & (ATOM_DEVICE_CRT_SUPPORT))) || 1046300373Smav ((bios_connectors[j].devices & (ATOM_DEVICE_DFP_SUPPORT)) && 1047250079Scarl (bios_connectors[i].devices & (ATOM_DEVICE_CRT_SUPPORT)))) { 1048301811Sngie bios_connectors[i].devices |= 1049250079Scarl bios_connectors[j].devices; 1050301811Sngie bios_connectors[i].connector_type = 1051301811Sngie DRM_MODE_CONNECTOR_DVII; 1052301811Sngie if (bios_connectors[j].devices & (ATOM_DEVICE_DFP_SUPPORT)) 1053301811Sngie bios_connectors[i].hpd = 1054250079Scarl bios_connectors[j].hpd; 1055300373Smav bios_connectors[j].valid = false; 1056300373Smav } 1057300373Smav } 1058300373Smav } 1059250079Scarl } 1060300373Smav } 1061300373Smav } 1062300373Smav 1063300373Smav /* add the connectors */ 1064300373Smav for (i = 0; i < max_device; i++) { 1065304404Smav if (bios_connectors[i].valid) { 1066300373Smav uint16_t connector_object_id = 1067300373Smav atombios_get_connector_object_id(dev, 1068300373Smav bios_connectors[i].connector_type, 1069300373Smav bios_connectors[i].devices); 1070300373Smav radeon_add_atom_connector(dev, 1071250079Scarl bios_connectors[i].line_mux, 1072300373Smav bios_connectors[i].devices, 1073300373Smav bios_connectors[i]. 1074300373Smav connector_type, 1075300373Smav &bios_connectors[i].ddc_bus, 1076300373Smav 0, 1077300373Smav connector_object_id, 1078304380Smav &bios_connectors[i].hpd, 1079301811Sngie &router); 1080301811Sngie } 1081301811Sngie } 1082301811Sngie 1083301811Sngie radeon_link_encoder_connector(dev); 1084300373Smav 1085300373Smav free(bios_connectors, DRM_MEM_DRIVER); 1086304404Smav return true; 1087300373Smav} 1088301811Sngie 1089304380Smavunion firmware_info { 1090301811Sngie ATOM_FIRMWARE_INFO info; 1091301811Sngie ATOM_FIRMWARE_INFO_V1_2 info_12; 1092301811Sngie ATOM_FIRMWARE_INFO_V1_3 info_13; 1093301811Sngie ATOM_FIRMWARE_INFO_V1_4 info_14; 1094301811Sngie ATOM_FIRMWARE_INFO_V2_1 info_21; 1095301811Sngie ATOM_FIRMWARE_INFO_V2_2 info_22; 1096304404Smav}; 1097304404Smav 1098250079Scarlbool radeon_atom_get_clock_info(struct drm_device *dev) 1099300373Smav{ 1100300373Smav struct radeon_device *rdev = dev->dev_private; 1101300373Smav struct radeon_mode_info *mode_info = &rdev->mode_info; 1102304404Smav int index = GetIndexIntoMasterTable(DATA, FirmwareInfo); 1103300373Smav union firmware_info *firmware_info; 1104250079Scarl uint8_t frev, crev; 1105300373Smav struct radeon_pll *p1pll = &rdev->clock.p1pll; 1106300373Smav struct radeon_pll *p2pll = &rdev->clock.p2pll; 1107250079Scarl struct radeon_pll *dcpll = &rdev->clock.dcpll; 1108300373Smav struct radeon_pll *spll = &rdev->clock.spll; 1109304404Smav struct radeon_pll *mpll = &rdev->clock.mpll; 1110300373Smav uint16_t data_offset; 1111300373Smav 1112300373Smav if (atom_parse_data_header(mode_info->atom_context, index, NULL, 1113300373Smav &frev, &crev, &data_offset)) { 1114300373Smav firmware_info = 1115300373Smav (union firmware_info *)((char *)mode_info->atom_context->bios + 1116300373Smav data_offset); 1117300373Smav /* pixel clocks */ 1118300373Smav p1pll->reference_freq = 1119250079Scarl le16_to_cpu(firmware_info->info.usReferenceClock); 1120250079Scarl p1pll->reference_div = 0; 1121300373Smav 1122300373Smav if (crev < 2) 1123300373Smav p1pll->pll_out_min = 1124300373Smav le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Output); 1125300373Smav else 1126300373Smav p1pll->pll_out_min = 1127300373Smav le32_to_cpu(firmware_info->info_12.ulMinPixelClockPLL_Output); 1128300373Smav p1pll->pll_out_max = 1129300373Smav le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output); 1130300373Smav 1131300373Smav if (crev >= 4) { 1132250079Scarl p1pll->lcd_pll_out_min = 1133250079Scarl le16_to_cpu(firmware_info->info_14.usLcdMinPixelClockPLL_Output) * 100; 1134250079Scarl if (p1pll->lcd_pll_out_min == 0) 1135250079Scarl p1pll->lcd_pll_out_min = p1pll->pll_out_min; 1136304404Smav p1pll->lcd_pll_out_max = 1137250079Scarl le16_to_cpu(firmware_info->info_14.usLcdMaxPixelClockPLL_Output) * 100; 1138250079Scarl if (p1pll->lcd_pll_out_max == 0) 1139250079Scarl p1pll->lcd_pll_out_max = p1pll->pll_out_max; 1140250079Scarl } else { 1141300373Smav p1pll->lcd_pll_out_min = p1pll->pll_out_min; 1142250079Scarl p1pll->lcd_pll_out_max = p1pll->pll_out_max; 1143250079Scarl } 1144250079Scarl 1145250079Scarl if (p1pll->pll_out_min == 0) { 1146250079Scarl if (ASIC_IS_AVIVO(rdev)) 1147250079Scarl p1pll->pll_out_min = 64800; 1148250079Scarl else 1149250079Scarl p1pll->pll_out_min = 20000; 1150250079Scarl } 1151250079Scarl 1152304404Smav p1pll->pll_in_min = 1153250079Scarl le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Input); 1154250079Scarl p1pll->pll_in_max = 1155250079Scarl le16_to_cpu(firmware_info->info.usMaxPixelClockPLL_Input); 1156300373Smav 1157300373Smav *p2pll = *p1pll; 1158300373Smav 1159300373Smav /* system clock */ 1160300373Smav if (ASIC_IS_DCE4(rdev)) 1161300373Smav spll->reference_freq = 1162250079Scarl le16_to_cpu(firmware_info->info_21.usCoreReferenceClock); 1163250079Scarl else 1164300373Smav spll->reference_freq = 1165304404Smav le16_to_cpu(firmware_info->info.usReferenceClock); 1166250079Scarl spll->reference_div = 0; 1167300373Smav 1168300373Smav spll->pll_out_min = 1169304404Smav le16_to_cpu(firmware_info->info.usMinEngineClockPLL_Output); 1170250079Scarl spll->pll_out_max = 1171250079Scarl le32_to_cpu(firmware_info->info.ulMaxEngineClockPLL_Output); 1172300373Smav 1173300373Smav /* ??? */ 1174250079Scarl if (spll->pll_out_min == 0) { 1175250079Scarl if (ASIC_IS_AVIVO(rdev)) 1176300373Smav spll->pll_out_min = 64800; 1177300373Smav else 1178300373Smav spll->pll_out_min = 20000; 1179300373Smav } 1180250079Scarl 1181300373Smav spll->pll_in_min = 1182300373Smav le16_to_cpu(firmware_info->info.usMinEngineClockPLL_Input); 1183300373Smav spll->pll_in_max = 1184250079Scarl le16_to_cpu(firmware_info->info.usMaxEngineClockPLL_Input); 1185250079Scarl 1186300373Smav /* memory clock */ 1187300373Smav if (ASIC_IS_DCE4(rdev)) 1188250079Scarl mpll->reference_freq = 1189250079Scarl le16_to_cpu(firmware_info->info_21.usMemoryReferenceClock); 1190300373Smav else 1191304404Smav mpll->reference_freq = 1192300373Smav le16_to_cpu(firmware_info->info.usReferenceClock); 1193300373Smav mpll->reference_div = 0; 1194250079Scarl 1195300373Smav mpll->pll_out_min = 1196304404Smav le16_to_cpu(firmware_info->info.usMinMemoryClockPLL_Output); 1197250079Scarl mpll->pll_out_max = 1198250079Scarl le32_to_cpu(firmware_info->info.ulMaxMemoryClockPLL_Output); 1199304380Smav 1200304404Smav /* ??? */ 1201250079Scarl if (mpll->pll_out_min == 0) { 1202304380Smav if (ASIC_IS_AVIVO(rdev)) 1203250079Scarl mpll->pll_out_min = 64800; 1204300373Smav else 1205300373Smav mpll->pll_out_min = 20000; 1206304388Smav } 1207304388Smav 1208300373Smav mpll->pll_in_min = 1209300373Smav le16_to_cpu(firmware_info->info.usMinMemoryClockPLL_Input); 1210250079Scarl mpll->pll_in_max = 1211304380Smav le16_to_cpu(firmware_info->info.usMaxMemoryClockPLL_Input); 1212304404Smav 1213300373Smav rdev->clock.default_sclk = 1214304380Smav le32_to_cpu(firmware_info->info.ulDefaultEngineClock); 1215304388Smav rdev->clock.default_mclk = 1216304388Smav le32_to_cpu(firmware_info->info.ulDefaultMemoryClock); 1217250079Scarl 1218300373Smav if (ASIC_IS_DCE4(rdev)) { 1219300373Smav rdev->clock.default_dispclk = 1220300373Smav le32_to_cpu(firmware_info->info_21.ulDefaultDispEngineClkFreq); 1221300373Smav if (rdev->clock.default_dispclk == 0) { 1222250079Scarl if (ASIC_IS_DCE5(rdev)) 1223300373Smav rdev->clock.default_dispclk = 54000; /* 540 Mhz */ 1224304388Smav else 1225300373Smav rdev->clock.default_dispclk = 60000; /* 600 Mhz */ 1226304388Smav } 1227304388Smav rdev->clock.dp_extclk = 1228304388Smav le16_to_cpu(firmware_info->info_21.usUniphyDPModeExtClkFreq); 1229304404Smav } 1230304388Smav *dcpll = *p1pll; 1231304388Smav 1232304388Smav rdev->clock.max_pixel_clock = le16_to_cpu(firmware_info->info.usMaxPixelClock); 1233304388Smav if (rdev->clock.max_pixel_clock == 0) 1234304388Smav rdev->clock.max_pixel_clock = 40000; 1235300373Smav 1236300373Smav /* not technically a clock, but... */ 1237300373Smav rdev->mode_info.firmware_flags = 1238304380Smav le16_to_cpu(firmware_info->info.usFirmwareCapability.susAccess); 1239304404Smav 1240300373Smav return true; 1241304380Smav } 1242300373Smav 1243304388Smav return false; 1244304388Smav} 1245301811Sngie 1246300373Smavunion igp_info { 1247300373Smav struct _ATOM_INTEGRATED_SYSTEM_INFO info; 1248300373Smav struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2; 1249304380Smav struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6; 1250304404Smav struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7; 1251300373Smav}; 1252304380Smav 1253300373Smavbool radeon_atombios_sideport_present(struct radeon_device *rdev) 1254300373Smav{ 1255300373Smav struct radeon_mode_info *mode_info = &rdev->mode_info; 1256300373Smav int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); 1257300373Smav union igp_info *igp_info; 1258300373Smav u8 frev, crev; 1259304380Smav u16 data_offset; 1260304388Smav 1261304388Smav /* sideport is AMD only */ 1262304388Smav if (rdev->family == CHIP_RS600) 1263301811Sngie return false; 1264301811Sngie 1265301811Sngie if (atom_parse_data_header(mode_info->atom_context, index, NULL, 1266300373Smav &frev, &crev, &data_offset)) { 1267300373Smav igp_info = (union igp_info *)((char *)mode_info->atom_context->bios + 1268300373Smav data_offset); 1269300373Smav switch (crev) { 1270304404Smav case 1: 1271300373Smav if (le32_to_cpu(igp_info->info.ulBootUpMemoryClock)) 1272300373Smav return true; 1273300373Smav break; 1274304388Smav case 2: 1275304388Smav if (le32_to_cpu(igp_info->info_2.ulBootUpSidePortClock)) 1276304388Smav return true; 1277304388Smav break; 1278304388Smav default: 1279304388Smav DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev); 1280304388Smav break; 1281304388Smav } 1282304388Smav } 1283304388Smav return false; 1284304388Smav} 1285304388Smav 1286304388Smavbool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder, 1287300373Smav struct radeon_encoder_int_tmds *tmds) 1288300373Smav{ 1289300373Smav struct drm_device *dev = encoder->base.dev; 1290300373Smav struct radeon_device *rdev = dev->dev_private; 1291300373Smav struct radeon_mode_info *mode_info = &rdev->mode_info; 1292300373Smav int index = GetIndexIntoMasterTable(DATA, TMDS_Info); 1293304404Smav uint16_t data_offset; 1294300373Smav struct _ATOM_TMDS_INFO *tmds_info; 1295300373Smav uint8_t frev, crev; 1296300373Smav uint16_t maxfreq; 1297300373Smav int i; 1298304404Smav 1299300373Smav if (atom_parse_data_header(mode_info->atom_context, index, NULL, 1300300373Smav &frev, &crev, &data_offset)) { 1301304404Smav tmds_info = 1302304380Smav (struct _ATOM_TMDS_INFO *)((char *)mode_info->atom_context->bios + 1303250079Scarl data_offset); 1304250079Scarl 1305304380Smav maxfreq = le16_to_cpu(tmds_info->usMaxFrequency); 1306301811Sngie for (i = 0; i < 4; i++) { 1307301811Sngie tmds->tmds_pll[i].freq = 1308304388Smav le16_to_cpu(tmds_info->asMiscInfo[i].usFrequency); 1309304388Smav tmds->tmds_pll[i].value = 1310304388Smav tmds_info->asMiscInfo[i].ucPLL_ChargePump & 0x3f; 1311304388Smav tmds->tmds_pll[i].value |= 1312304388Smav (tmds_info->asMiscInfo[i]. 1313304388Smav ucPLL_VCO_Gain & 0x3f) << 6; 1314304388Smav tmds->tmds_pll[i].value |= 1315304388Smav (tmds_info->asMiscInfo[i]. 1316304388Smav ucPLL_DutyCycle & 0xf) << 12; 1317304388Smav tmds->tmds_pll[i].value |= 1318301811Sngie (tmds_info->asMiscInfo[i]. 1319301811Sngie ucPLL_VoltageSwing & 0xf) << 16; 1320301811Sngie 1321300373Smav DRM_DEBUG_KMS("TMDS PLL From ATOMBIOS %u %x\n", 1322304380Smav tmds->tmds_pll[i].freq, 1323250079Scarl tmds->tmds_pll[i].value); 1324250079Scarl 1325300373Smav if (maxfreq == tmds->tmds_pll[i].freq) { 1326300373Smav tmds->tmds_pll[i].freq = 0xffffffff; 1327300373Smav break; 1328300373Smav } 1329300373Smav } 1330304404Smav return true; 1331300373Smav } 1332300373Smav return false; 1333300373Smav} 1334300373Smav 1335300373Smavbool radeon_atombios_get_ppll_ss_info(struct radeon_device *rdev, 1336300373Smav struct radeon_atom_ss *ss, 1337304404Smav int id) 1338300373Smav{ 1339300373Smav struct radeon_mode_info *mode_info = &rdev->mode_info; 1340250079Scarl int index = GetIndexIntoMasterTable(DATA, PPLL_SS_Info); 1341304404Smav uint16_t data_offset, size; 1342250079Scarl struct _ATOM_SPREAD_SPECTRUM_INFO *ss_info; 1343300373Smav uint8_t frev, crev; 1344250079Scarl int i, num_indices; 1345300373Smav 1346250079Scarl memset(ss, 0, sizeof(struct radeon_atom_ss)); 1347250079Scarl if (atom_parse_data_header(mode_info->atom_context, index, &size, 1348300373Smav &frev, &crev, &data_offset)) { 1349300373Smav ss_info = 1350250079Scarl (struct _ATOM_SPREAD_SPECTRUM_INFO *)((char *)mode_info->atom_context->bios + data_offset); 1351250079Scarl 1352250079Scarl num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / 1353250079Scarl sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT); 1354250079Scarl 1355250079Scarl for (i = 0; i < num_indices; i++) { 1356304404Smav if (ss_info->asSS_Info[i].ucSS_Id == id) { 1357250079Scarl ss->percentage = 1358250079Scarl le16_to_cpu(ss_info->asSS_Info[i].usSpreadSpectrumPercentage); 1359300373Smav ss->type = ss_info->asSS_Info[i].ucSpreadSpectrumType; 1360300373Smav ss->step = ss_info->asSS_Info[i].ucSS_Step; 1361250079Scarl ss->delay = ss_info->asSS_Info[i].ucSS_Delay; 1362300373Smav ss->range = ss_info->asSS_Info[i].ucSS_Range; 1363300373Smav ss->refdiv = ss_info->asSS_Info[i].ucRecommendedRef_Div; 1364250079Scarl return true; 1365250079Scarl } 1366301811Sngie } 1367304404Smav } 1368301811Sngie return false; 1369301811Sngie} 1370301811Sngie 1371301811Sngiestatic void radeon_atombios_get_igp_ss_overrides(struct radeon_device *rdev, 1372301811Sngie struct radeon_atom_ss *ss, 1373301811Sngie int id) 1374301811Sngie{ 1375301811Sngie struct radeon_mode_info *mode_info = &rdev->mode_info; 1376301811Sngie int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); 1377301811Sngie u16 data_offset, size; 1378301811Sngie union igp_info *igp_info; 1379301811Sngie u8 frev, crev; 1380301811Sngie u16 percentage = 0, rate = 0; 1381301811Sngie 1382301811Sngie /* get any igp specific overrides */ 1383304404Smav if (atom_parse_data_header(mode_info->atom_context, index, &size, 1384301811Sngie &frev, &crev, &data_offset)) { 1385301811Sngie igp_info = (union igp_info *) 1386301811Sngie ((char *)mode_info->atom_context->bios + data_offset); 1387301811Sngie switch (crev) { 1388301904Smav case 6: 1389301811Sngie switch (id) { 1390301811Sngie case ASIC_INTERNAL_SS_ON_TMDS: 1391301811Sngie percentage = le16_to_cpu(igp_info->info_6.usDVISSPercentage); 1392304404Smav rate = le16_to_cpu(igp_info->info_6.usDVISSpreadRateIn10Hz); 1393301811Sngie break; 1394301811Sngie case ASIC_INTERNAL_SS_ON_HDMI: 1395301811Sngie percentage = le16_to_cpu(igp_info->info_6.usHDMISSPercentage); 1396301811Sngie rate = le16_to_cpu(igp_info->info_6.usHDMISSpreadRateIn10Hz); 1397301811Sngie break; 1398250079Scarl case ASIC_INTERNAL_SS_ON_LVDS: 1399304404Smav percentage = le16_to_cpu(igp_info->info_6.usLvdsSSPercentage); 1400250079Scarl rate = le16_to_cpu(igp_info->info_6.usLvdsSSpreadRateIn10Hz); 1401250079Scarl break; 1402250079Scarl } 1403250079Scarl break; 1404250079Scarl case 7: 1405250079Scarl switch (id) { 1406250079Scarl case ASIC_INTERNAL_SS_ON_TMDS: 1407250079Scarl percentage = le16_to_cpu(igp_info->info_7.usDVISSPercentage); 1408250079Scarl rate = le16_to_cpu(igp_info->info_7.usDVISSpreadRateIn10Hz); 1409250079Scarl break; 1410250079Scarl case ASIC_INTERNAL_SS_ON_HDMI: 1411300373Smav percentage = le16_to_cpu(igp_info->info_7.usHDMISSPercentage); 1412304404Smav rate = le16_to_cpu(igp_info->info_7.usHDMISSpreadRateIn10Hz); 1413250079Scarl break; 1414250079Scarl case ASIC_INTERNAL_SS_ON_LVDS: 1415300373Smav percentage = le16_to_cpu(igp_info->info_7.usLvdsSSPercentage); 1416304404Smav rate = le16_to_cpu(igp_info->info_7.usLvdsSSpreadRateIn10Hz); 1417300373Smav break; 1418300373Smav } 1419300373Smav break; 1420304404Smav default: 1421300373Smav DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev); 1422300373Smav break; 1423300373Smav } 1424300373Smav if (percentage) 1425300373Smav ss->percentage = percentage; 1426300373Smav if (rate) 1427300373Smav ss->rate = rate; 1428304380Smav } 1429300373Smav} 1430250079Scarl 1431300373Smavunion asic_ss_info { 1432250079Scarl struct _ATOM_ASIC_INTERNAL_SS_INFO info; 1433250079Scarl struct _ATOM_ASIC_INTERNAL_SS_INFO_V2 info_2; 1434250079Scarl struct _ATOM_ASIC_INTERNAL_SS_INFO_V3 info_3; 1435304404Smav}; 1436250079Scarl 1437300373Smavbool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev, 1438250079Scarl struct radeon_atom_ss *ss, 1439300373Smav int id, u32 clock) 1440300373Smav{ 1441250079Scarl struct radeon_mode_info *mode_info = &rdev->mode_info; 1442300373Smav int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info); 1443300373Smav uint16_t data_offset, size; 1444300373Smav union asic_ss_info *ss_info; 1445300373Smav uint8_t frev, crev; 1446300373Smav int i, num_indices; 1447300373Smav 1448300373Smav memset(ss, 0, sizeof(struct radeon_atom_ss)); 1449300373Smav if (atom_parse_data_header(mode_info->atom_context, index, &size, 1450304394Smav &frev, &crev, &data_offset)) { 1451304394Smav 1452304394Smav ss_info = 1453304394Smav (union asic_ss_info *)((char *)mode_info->atom_context->bios + data_offset); 1454304394Smav 1455304394Smav switch (frev) { 1456304394Smav case 1: 1457304394Smav num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / 1458304394Smav sizeof(ATOM_ASIC_SS_ASSIGNMENT); 1459304394Smav 1460301811Sngie for (i = 0; i < num_indices; i++) { 1461301811Sngie if ((ss_info->info.asSpreadSpectrum[i].ucClockIndication == id) && 1462301811Sngie (clock <= le32_to_cpu(ss_info->info.asSpreadSpectrum[i].ulTargetClockRange))) { 1463301811Sngie ss->percentage = 1464304380Smav le16_to_cpu(ss_info->info.asSpreadSpectrum[i].usSpreadSpectrumPercentage); 1465301811Sngie ss->type = ss_info->info.asSpreadSpectrum[i].ucSpreadSpectrumMode; 1466300373Smav ss->rate = le16_to_cpu(ss_info->info.asSpreadSpectrum[i].usSpreadRateInKhz); 1467300373Smav return true; 1468300373Smav } 1469250079Scarl } 1470300373Smav break; 1471250079Scarl case 2: 1472250079Scarl num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / 1473300373Smav sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2); 1474250079Scarl for (i = 0; i < num_indices; i++) { 1475300373Smav if ((ss_info->info_2.asSpreadSpectrum[i].ucClockIndication == id) && 1476300373Smav (clock <= le32_to_cpu(ss_info->info_2.asSpreadSpectrum[i].ulTargetClockRange))) { 1477250079Scarl ss->percentage = 1478250079Scarl le16_to_cpu(ss_info->info_2.asSpreadSpectrum[i].usSpreadSpectrumPercentage); 1479300373Smav ss->type = ss_info->info_2.asSpreadSpectrum[i].ucSpreadSpectrumMode; 1480300373Smav ss->rate = le16_to_cpu(ss_info->info_2.asSpreadSpectrum[i].usSpreadRateIn10Hz); 1481250079Scarl return true; 1482300373Smav } 1483304404Smav } 1484300373Smav break; 1485300373Smav case 3: 1486300373Smav num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / 1487300373Smav sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3); 1488300373Smav for (i = 0; i < num_indices; i++) { 1489300373Smav if ((ss_info->info_3.asSpreadSpectrum[i].ucClockIndication == id) && 1490300373Smav (clock <= le32_to_cpu(ss_info->info_3.asSpreadSpectrum[i].ulTargetClockRange))) { 1491250079Scarl ss->percentage = 1492250079Scarl le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadSpectrumPercentage); 1493250079Scarl ss->type = ss_info->info_3.asSpreadSpectrum[i].ucSpreadSpectrumMode; 1494250079Scarl ss->rate = le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadRateIn10Hz); 1495300373Smav if (rdev->flags & RADEON_IS_IGP) 1496300373Smav radeon_atombios_get_igp_ss_overrides(rdev, ss, id); 1497300373Smav return true; 1498300373Smav } 1499300373Smav } 1500300373Smav break; 1501300373Smav default: 1502300373Smav DRM_ERROR("Unsupported ASIC_InternalSS_Info table: %d %d\n", frev, crev); 1503250079Scarl break; 1504250079Scarl } 1505250079Scarl 1506250079Scarl } 1507250079Scarl return false; 1508304404Smav} 1509250079Scarl 1510300373Smavunion lvds_info { 1511250079Scarl struct _ATOM_LVDS_INFO info; 1512300373Smav struct _ATOM_LVDS_INFO_V12 info_12; 1513300373Smav}; 1514300373Smav 1515300373Smavstruct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct 1516300373Smav radeon_encoder 1517250079Scarl *encoder) 1518300373Smav{ 1519250079Scarl struct drm_device *dev = encoder->base.dev; 1520300373Smav struct radeon_device *rdev = dev->dev_private; 1521250079Scarl struct radeon_mode_info *mode_info = &rdev->mode_info; 1522250079Scarl int index = GetIndexIntoMasterTable(DATA, LVDS_Info); 1523250079Scarl uint16_t data_offset, misc; 1524300373Smav union lvds_info *lvds_info; 1525300373Smav uint8_t frev, crev; 1526300373Smav struct radeon_encoder_atom_dig *lvds = NULL; 1527300373Smav int encoder_enum = (encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT; 1528300373Smav 1529304380Smav if (atom_parse_data_header(mode_info->atom_context, index, NULL, 1530304388Smav &frev, &crev, &data_offset)) { 1531301811Sngie lvds_info = 1532301811Sngie (union lvds_info *)((char *)mode_info->atom_context->bios + data_offset); 1533304404Smav lvds = 1534301811Sngie malloc(sizeof(struct radeon_encoder_atom_dig), 1535304404Smav DRM_MEM_DRIVER, M_WAITOK | M_ZERO); 1536301811Sngie 1537301811Sngie if (!lvds) 1538304380Smav return NULL; 1539301811Sngie 1540301811Sngie lvds->native_mode.clock = 1541301811Sngie le16_to_cpu(lvds_info->info.sLCDTiming.usPixClk) * 10; 1542301811Sngie lvds->native_mode.hdisplay = 1543301811Sngie le16_to_cpu(lvds_info->info.sLCDTiming.usHActive); 1544301811Sngie lvds->native_mode.vdisplay = 1545301811Sngie le16_to_cpu(lvds_info->info.sLCDTiming.usVActive); 1546300373Smav lvds->native_mode.htotal = lvds->native_mode.hdisplay + 1547300373Smav le16_to_cpu(lvds_info->info.sLCDTiming.usHBlanking_Time); 1548304404Smav lvds->native_mode.hsync_start = lvds->native_mode.hdisplay + 1549300373Smav le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncOffset); 1550304404Smav lvds->native_mode.hsync_end = lvds->native_mode.hsync_start + 1551301811Sngie le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncWidth); 1552300373Smav lvds->native_mode.vtotal = lvds->native_mode.vdisplay + 1553304380Smav le16_to_cpu(lvds_info->info.sLCDTiming.usVBlanking_Time); 1554300373Smav lvds->native_mode.vsync_start = lvds->native_mode.vdisplay + 1555300373Smav le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncOffset); 1556300373Smav lvds->native_mode.vsync_end = lvds->native_mode.vsync_start + 1557300373Smav le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth); 1558300373Smav lvds->panel_pwr_delay = 1559300373Smav le16_to_cpu(lvds_info->info.usOffDelayInMs); 1560300373Smav lvds->lcd_misc = lvds_info->info.ucLVDS_Misc; 1561300373Smav 1562300373Smav misc = le16_to_cpu(lvds_info->info.sLCDTiming.susModeMiscInfo.usAccess); 1563300373Smav if (misc & ATOM_VSYNC_POLARITY) 1564300373Smav lvds->native_mode.flags |= DRM_MODE_FLAG_NVSYNC; 1565300373Smav if (misc & ATOM_HSYNC_POLARITY) 1566300373Smav lvds->native_mode.flags |= DRM_MODE_FLAG_NHSYNC; 1567300373Smav if (misc & ATOM_COMPOSITESYNC) 1568300373Smav lvds->native_mode.flags |= DRM_MODE_FLAG_CSYNC; 1569250079Scarl if (misc & ATOM_INTERLACE) 1570300373Smav lvds->native_mode.flags |= DRM_MODE_FLAG_INTERLACE; 1571300373Smav if (misc & ATOM_DOUBLE_CLOCK_MODE) 1572300373Smav lvds->native_mode.flags |= DRM_MODE_FLAG_DBLSCAN; 1573300373Smav 1574250079Scarl lvds->native_mode.width_mm = le16_to_cpu(lvds_info->info.sLCDTiming.usImageHSize); 1575300373Smav lvds->native_mode.height_mm = le16_to_cpu(lvds_info->info.sLCDTiming.usImageVSize); 1576304404Smav 1577300373Smav /* set crtc values */ 1578250079Scarl drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V); 1579300373Smav 1580300373Smav lvds->lcd_ss_id = lvds_info->info.ucSS_Id; 1581300373Smav 1582301811Sngie encoder->native_mode = lvds->native_mode; 1583301811Sngie 1584301811Sngie if (encoder_enum == 2) 1585301811Sngie lvds->linkb = true; 1586250079Scarl else 1587304404Smav lvds->linkb = false; 1588300373Smav 1589300373Smav /* parse the lcd record table */ 1590250079Scarl if (le16_to_cpu(lvds_info->info.usModePatchTableOffset)) { 1591300373Smav ATOM_FAKE_EDID_PATCH_RECORD *fake_edid_record; 1592304404Smav ATOM_PANEL_RESOLUTION_PATCH_RECORD *panel_res_record; 1593300373Smav bool bad_record = false; 1594300373Smav u8 *record; 1595250079Scarl 1596300373Smav if ((frev == 1) && (crev < 2)) 1597300373Smav /* absolute */ 1598300373Smav record = (u8 *)((char *)mode_info->atom_context->bios + 1599300373Smav le16_to_cpu(lvds_info->info.usModePatchTableOffset)); 1600300373Smav else 1601300373Smav /* relative */ 1602300373Smav record = (u8 *)((char *)mode_info->atom_context->bios + 1603300373Smav data_offset + 1604300373Smav le16_to_cpu(lvds_info->info.usModePatchTableOffset)); 1605300373Smav while (*record != ATOM_RECORD_END_TYPE) { 1606300373Smav switch (*record) { 1607300373Smav case LCD_MODE_PATCH_RECORD_MODE_TYPE: 1608300373Smav record += sizeof(ATOM_PATCH_RECORD_MODE); 1609300373Smav break; 1610250079Scarl case LCD_RTS_RECORD_TYPE: 1611300373Smav record += sizeof(ATOM_LCD_RTS_RECORD); 1612250079Scarl break; 1613250079Scarl case LCD_CAP_RECORD_TYPE: 1614250079Scarl record += sizeof(ATOM_LCD_MODE_CONTROL_CAP); 1615250079Scarl break; 1616300373Smav case LCD_FAKE_EDID_PATCH_RECORD_TYPE: 1617250079Scarl fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record; 1618250079Scarl if (fake_edid_record->ucFakeEDIDLength) { 1619304404Smav struct edid *edid; 1620250079Scarl int edid_size = 1621250079Scarl max((int)EDID_LENGTH, (int)fake_edid_record->ucFakeEDIDLength); 1622304404Smav edid = malloc(edid_size, DRM_MEM_KMS, M_WAITOK); 1623300373Smav if (edid) { 1624300373Smav memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0], 1625300373Smav fake_edid_record->ucFakeEDIDLength); 1626300373Smav 1627304404Smav if (drm_edid_is_valid(edid)) { 1628300373Smav rdev->mode_info.bios_hardcoded_edid = edid; 1629300373Smav rdev->mode_info.bios_hardcoded_edid_size = edid_size; 1630300373Smav } else 1631250079Scarl free(edid, DRM_MEM_KMS); 1632250079Scarl } 1633250079Scarl } 1634300373Smav record += sizeof(ATOM_FAKE_EDID_PATCH_RECORD); 1635255279Scarl break; 1636300373Smav case LCD_PANEL_RESOLUTION_RECORD_TYPE: 1637255279Scarl panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record; 1638255279Scarl lvds->native_mode.width_mm = panel_res_record->usHSize; 1639255279Scarl lvds->native_mode.height_mm = panel_res_record->usVSize; 1640304404Smav record += sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD); 1641300373Smav break; 1642304404Smav default: 1643300373Smav DRM_ERROR("Bad LCD record %d\n", *record); 1644304404Smav bad_record = true; 1645304404Smav break; 1646255279Scarl } 1647304404Smav if (bad_record) 1648300373Smav break; 1649304404Smav } 1650300373Smav } 1651304404Smav } 1652304404Smav return lvds; 1653255279Scarl} 1654255279Scarl 1655255279Scarlstruct radeon_encoder_primary_dac * 1656300373Smavradeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder) 1657300373Smav{ 1658300373Smav struct drm_device *dev = encoder->base.dev; 1659300373Smav struct radeon_device *rdev = dev->dev_private; 1660300373Smav struct radeon_mode_info *mode_info = &rdev->mode_info; 1661300373Smav int index = GetIndexIntoMasterTable(DATA, CompassionateData); 1662300373Smav uint16_t data_offset; 1663300373Smav struct _COMPASSIONATE_DATA *dac_info; 1664300373Smav uint8_t frev, crev; 1665300373Smav uint8_t bg, dac; 1666300516Smav struct radeon_encoder_primary_dac *p_dac = NULL; 1667300373Smav 1668300373Smav if (atom_parse_data_header(mode_info->atom_context, index, NULL, 1669300373Smav &frev, &crev, &data_offset)) { 1670300373Smav dac_info = (struct _COMPASSIONATE_DATA *) 1671300373Smav ((char *)mode_info->atom_context->bios + data_offset); 1672255279Scarl 1673300373Smav p_dac = malloc(sizeof(struct radeon_encoder_primary_dac), 1674300373Smav DRM_MEM_DRIVER, M_WAITOK | M_ZERO); 1675255279Scarl 1676300373Smav if (!p_dac) 1677300373Smav return NULL; 1678255279Scarl 1679304380Smav bg = dac_info->ucDAC1_BG_Adjustment; 1680300373Smav dac = dac_info->ucDAC1_DAC_Adjustment; 1681300373Smav p_dac->ps2_pdac_adj = (bg << 8) | (dac); 1682300373Smav 1683300373Smav } 1684300373Smav return p_dac; 1685300373Smav} 1686300373Smav 1687255279Scarlbool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index, 1688300373Smav struct drm_display_mode *mode) 1689300373Smav{ 1690300373Smav struct radeon_mode_info *mode_info = &rdev->mode_info; 1691300373Smav ATOM_ANALOG_TV_INFO *tv_info; 1692300373Smav ATOM_ANALOG_TV_INFO_V1_2 *tv_info_v1_2; 1693300373Smav ATOM_DTD_FORMAT *dtd_timings; 1694300373Smav int data_index = GetIndexIntoMasterTable(DATA, AnalogTV_Info); 1695300373Smav u8 frev, crev; 1696300373Smav u16 data_offset, misc; 1697300373Smav 1698300373Smav if (!atom_parse_data_header(mode_info->atom_context, data_index, NULL, 1699301904Smav &frev, &crev, &data_offset)) 1700300373Smav return false; 1701300373Smav 1702300373Smav switch (crev) { 1703304376Smav case 1: 1704304376Smav tv_info = (ATOM_ANALOG_TV_INFO *)((char *)mode_info->atom_context->bios + data_offset); 1705304376Smav if (index >= MAX_SUPPORTED_TV_TIMING) 1706304376Smav return false; 1707304376Smav 1708304376Smav mode->crtc_htotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total); 1709300373Smav mode->crtc_hdisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp); 1710300373Smav mode->crtc_hsync_start = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart); 1711304404Smav mode->crtc_hsync_end = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart) + 1712304404Smav le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncWidth); 1713304399Smav 1714304399Smav mode->crtc_vtotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Total); 1715304404Smav mode->crtc_vdisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Disp); 1716304404Smav mode->crtc_vsync_start = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart); 1717301811Sngie mode->crtc_vsync_end = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart) + 1718304399Smav le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncWidth); 1719304404Smav 1720304404Smav mode->flags = 0; 1721304399Smav misc = le16_to_cpu(tv_info->aModeTimings[index].susModeMiscInfo.usAccess); 1722301811Sngie if (misc & ATOM_VSYNC_POLARITY) 1723304404Smav mode->flags |= DRM_MODE_FLAG_NVSYNC; 1724304404Smav if (misc & ATOM_HSYNC_POLARITY) 1725301811Sngie mode->flags |= DRM_MODE_FLAG_NHSYNC; 1726255279Scarl if (misc & ATOM_COMPOSITESYNC) 1727255279Scarl mode->flags |= DRM_MODE_FLAG_CSYNC; 1728255279Scarl if (misc & ATOM_INTERLACE) 1729250079Scarl mode->flags |= DRM_MODE_FLAG_INTERLACE; 1730300373Smav if (misc & ATOM_DOUBLE_CLOCK_MODE) 1731250079Scarl mode->flags |= DRM_MODE_FLAG_DBLSCAN; 1732300373Smav 1733250079Scarl mode->clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10; 1734300373Smav 1735304380Smav if (index == 1) { 1736304404Smav /* PAL timings appear to have wrong values for totals */ 1737304404Smav mode->crtc_htotal -= 1; 1738300373Smav mode->crtc_vtotal -= 1; 1739304404Smav } 1740304404Smav break; 1741300373Smav case 2: 1742300373Smav tv_info_v1_2 = (ATOM_ANALOG_TV_INFO_V1_2 *)((char *)mode_info->atom_context->bios + data_offset); 1743300373Smav if (index >= MAX_SUPPORTED_TV_TIMING_V1_2) 1744300373Smav return false; 1745300373Smav 1746300373Smav dtd_timings = &tv_info_v1_2->aModeTimings[index]; 1747300373Smav mode->crtc_htotal = le16_to_cpu(dtd_timings->usHActive) + 1748300373Smav le16_to_cpu(dtd_timings->usHBlanking_Time); 1749300373Smav mode->crtc_hdisplay = le16_to_cpu(dtd_timings->usHActive); 1750300373Smav mode->crtc_hsync_start = le16_to_cpu(dtd_timings->usHActive) + 1751300373Smav le16_to_cpu(dtd_timings->usHSyncOffset); 1752300373Smav mode->crtc_hsync_end = mode->crtc_hsync_start + 1753300373Smav le16_to_cpu(dtd_timings->usHSyncWidth); 1754300373Smav 1755300373Smav mode->crtc_vtotal = le16_to_cpu(dtd_timings->usVActive) + 1756300373Smav le16_to_cpu(dtd_timings->usVBlanking_Time); 1757300373Smav mode->crtc_vdisplay = le16_to_cpu(dtd_timings->usVActive); 1758300373Smav mode->crtc_vsync_start = le16_to_cpu(dtd_timings->usVActive) + 1759304404Smav le16_to_cpu(dtd_timings->usVSyncOffset); 1760300373Smav mode->crtc_vsync_end = mode->crtc_vsync_start + 1761300373Smav le16_to_cpu(dtd_timings->usVSyncWidth); 1762300373Smav 1763300373Smav mode->flags = 0; 1764300373Smav misc = le16_to_cpu(dtd_timings->susModeMiscInfo.usAccess); 1765300373Smav if (misc & ATOM_VSYNC_POLARITY) 1766300373Smav mode->flags |= DRM_MODE_FLAG_NVSYNC; 1767300373Smav if (misc & ATOM_HSYNC_POLARITY) 1768300373Smav mode->flags |= DRM_MODE_FLAG_NHSYNC; 1769300373Smav if (misc & ATOM_COMPOSITESYNC) 1770300373Smav mode->flags |= DRM_MODE_FLAG_CSYNC; 1771300373Smav if (misc & ATOM_INTERLACE) 1772300373Smav mode->flags |= DRM_MODE_FLAG_INTERLACE; 1773300373Smav if (misc & ATOM_DOUBLE_CLOCK_MODE) 1774300373Smav mode->flags |= DRM_MODE_FLAG_DBLSCAN; 1775250079Scarl 1776250079Scarl mode->clock = le16_to_cpu(dtd_timings->usPixClk) * 10; 1777250079Scarl break; 1778300373Smav } 1779300373Smav return true; 1780300373Smav} 1781300373Smav 1782300373Smavenum radeon_tv_std 1783300373Smavradeon_atombios_get_tv_info(struct radeon_device *rdev) 1784300373Smav{ 1785300373Smav struct radeon_mode_info *mode_info = &rdev->mode_info; 1786300373Smav int index = GetIndexIntoMasterTable(DATA, AnalogTV_Info); 1787300373Smav uint16_t data_offset; 1788300373Smav uint8_t frev, crev; 1789300373Smav struct _ATOM_ANALOG_TV_INFO *tv_info; 1790304380Smav enum radeon_tv_std tv_std = TV_STD_NTSC; 1791300373Smav 1792300373Smav if (atom_parse_data_header(mode_info->atom_context, index, NULL, 1793300373Smav &frev, &crev, &data_offset)) { 1794300373Smav 1795300373Smav tv_info = (struct _ATOM_ANALOG_TV_INFO *) 1796300373Smav ((char *)mode_info->atom_context->bios + data_offset); 1797300373Smav 1798300373Smav switch (tv_info->ucTV_BootUpDefaultStandard) { 1799304404Smav case ATOM_TV_NTSC: 1800300373Smav tv_std = TV_STD_NTSC; 1801300373Smav DRM_DEBUG_KMS("Default TV standard: NTSC\n"); 1802300373Smav break; 1803300373Smav case ATOM_TV_NTSCJ: 1804300373Smav tv_std = TV_STD_NTSC_J; 1805300373Smav DRM_DEBUG_KMS("Default TV standard: NTSC-J\n"); 1806300373Smav break; 1807300373Smav case ATOM_TV_PAL: 1808300373Smav tv_std = TV_STD_PAL; 1809300373Smav DRM_DEBUG_KMS("Default TV standard: PAL\n"); 1810304380Smav break; 1811300373Smav case ATOM_TV_PALM: 1812300373Smav tv_std = TV_STD_PAL_M; 1813300373Smav DRM_DEBUG_KMS("Default TV standard: PAL-M\n"); 1814300373Smav break; 1815300373Smav case ATOM_TV_PALN: 1816300373Smav tv_std = TV_STD_PAL_N; 1817300373Smav DRM_DEBUG_KMS("Default TV standard: PAL-N\n"); 1818300373Smav break; 1819300373Smav case ATOM_TV_PALCN: 1820304404Smav tv_std = TV_STD_PAL_CN; 1821304404Smav DRM_DEBUG_KMS("Default TV standard: PAL-CN\n"); 1822300373Smav break; 1823304380Smav case ATOM_TV_PAL60: 1824304396Smav tv_std = TV_STD_PAL_60; 1825304388Smav DRM_DEBUG_KMS("Default TV standard: PAL-60\n"); 1826301811Sngie break; 1827301811Sngie case ATOM_TV_SECAM: 1828301811Sngie tv_std = TV_STD_SECAM; 1829301811Sngie DRM_DEBUG_KMS("Default TV standard: SECAM\n"); 1830301811Sngie break; 1831304404Smav default: 1832304396Smav tv_std = TV_STD_NTSC; 1833304396Smav DRM_DEBUG_KMS("Unknown TV standard; defaulting to NTSC\n"); 1834304404Smav break; 1835304404Smav } 1836304404Smav } 1837301904Smav return tv_std; 1838304404Smav} 1839304404Smav 1840304404Smavstruct radeon_encoder_tv_dac * 1841301904Smavradeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder) 1842304388Smav{ 1843304388Smav struct drm_device *dev = encoder->base.dev; 1844301811Sngie struct radeon_device *rdev = dev->dev_private; 1845304404Smav struct radeon_mode_info *mode_info = &rdev->mode_info; 1846304404Smav int index = GetIndexIntoMasterTable(DATA, CompassionateData); 1847301811Sngie uint16_t data_offset; 1848300373Smav struct _COMPASSIONATE_DATA *dac_info; 1849304404Smav uint8_t frev, crev; 1850304404Smav uint8_t bg, dac; 1851300373Smav struct radeon_encoder_tv_dac *tv_dac = NULL; 1852300373Smav 1853300373Smav if (atom_parse_data_header(mode_info->atom_context, index, NULL, 1854304380Smav &frev, &crev, &data_offset)) { 1855300373Smav 1856300373Smav dac_info = (struct _COMPASSIONATE_DATA *) 1857300373Smav ((char *)mode_info->atom_context->bios + data_offset); 1858300373Smav 1859300373Smav tv_dac = malloc(sizeof(struct radeon_encoder_tv_dac), 1860300373Smav DRM_MEM_DRIVER, M_WAITOK | M_ZERO); 1861300373Smav 1862300373Smav if (!tv_dac) 1863300373Smav return NULL; 1864300373Smav 1865300373Smav bg = dac_info->ucDAC2_CRT2_BG_Adjustment; 1866304380Smav dac = dac_info->ucDAC2_CRT2_DAC_Adjustment; 1867300373Smav tv_dac->ps2_tvdac_adj = (bg << 16) | (dac << 20); 1868300373Smav 1869300373Smav bg = dac_info->ucDAC2_PAL_BG_Adjustment; 1870300373Smav dac = dac_info->ucDAC2_PAL_DAC_Adjustment; 1871300373Smav tv_dac->pal_tvdac_adj = (bg << 16) | (dac << 20); 1872300373Smav 1873300373Smav bg = dac_info->ucDAC2_NTSC_BG_Adjustment; 1874300373Smav dac = dac_info->ucDAC2_NTSC_DAC_Adjustment; 1875300373Smav tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20); 1876300373Smav 1877300373Smav tv_dac->tv_std = radeon_atombios_get_tv_info(rdev); 1878300373Smav } 1879304404Smav return tv_dac; 1880304404Smav} 1881300373Smav 1882250079Scarlstatic const char *thermal_controller_names[] = { 1883250079Scarl "NONE", 1884300373Smav "lm63", 1885301811Sngie "adm1032", 1886301811Sngie "adm1030", 1887301811Sngie "max6649", 1888301811Sngie "lm64", 1889301811Sngie "f75375", 1890301811Sngie "asc7xxx", 1891301811Sngie}; 1892301811Sngie 1893301811Sngiestatic const char *pp_lib_thermal_controller_names[] = { 1894300373Smav "NONE", 1895300373Smav "lm63", 1896300373Smav "adm1032", 1897301811Sngie "adm1030", 1898301811Sngie "max6649", 1899304380Smav "lm64", 1900300373Smav "f75375", 1901300373Smav "RV6xx", 1902300373Smav "RV770", 1903300373Smav "adt7473", 1904300373Smav "NONE", 1905300373Smav "External GPIO", 1906300373Smav "Evergreen", 1907300373Smav "emc2103", 1908300373Smav "Sumo", 1909300373Smav "Northern Islands", 1910300373Smav "Southern Islands", 1911300373Smav "lm96163", 1912304404Smav}; 1913300373Smav 1914300373Smavunion power_info { 1915300373Smav struct _ATOM_POWERPLAY_INFO info; 1916304404Smav struct _ATOM_POWERPLAY_INFO_V2 info_2; 1917300373Smav struct _ATOM_POWERPLAY_INFO_V3 info_3; 1918300373Smav struct _ATOM_PPLIB_POWERPLAYTABLE pplib; 1919300373Smav struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; 1920300373Smav struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; 1921250079Scarl}; 1922300373Smav 1923250079Scarlunion pplib_clock_info { 1924300373Smav struct _ATOM_PPLIB_R600_CLOCK_INFO r600; 1925300373Smav struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780; 1926300373Smav struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen; 1927300373Smav struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo; 1928300373Smav struct _ATOM_PPLIB_SI_CLOCK_INFO si; 1929300373Smav}; 1930300373Smav 1931300373Smavunion pplib_power_state { 1932300373Smav struct _ATOM_PPLIB_STATE v1; 1933300373Smav struct _ATOM_PPLIB_STATE_V2 v2; 1934300373Smav}; 1935300373Smav 1936300373Smavstatic void radeon_atombios_parse_misc_flags_1_3(struct radeon_device *rdev, 1937300373Smav int state_index, 1938300373Smav u32 misc, u32 misc2) 1939304404Smav{ 1940304380Smav rdev->pm.power_state[state_index].misc = misc; 1941300373Smav rdev->pm.power_state[state_index].misc2 = misc2; 1942300373Smav /* order matters! */ 1943300373Smav if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE) 1944300373Smav rdev->pm.power_state[state_index].type = 1945300373Smav POWER_STATE_TYPE_POWERSAVE; 1946300373Smav if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE) 1947300373Smav rdev->pm.power_state[state_index].type = 1948300373Smav POWER_STATE_TYPE_BATTERY; 1949300373Smav if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE) 1950300373Smav rdev->pm.power_state[state_index].type = 1951300373Smav POWER_STATE_TYPE_BATTERY; 1952300373Smav if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN) 1953300373Smav rdev->pm.power_state[state_index].type = 1954300373Smav POWER_STATE_TYPE_BALANCED; 1955250079Scarl if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) { 1956250079Scarl rdev->pm.power_state[state_index].type = 1957250079Scarl POWER_STATE_TYPE_PERFORMANCE; 1958304404Smav rdev->pm.power_state[state_index].flags &= 1959304404Smav ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; 1960304404Smav } 1961304404Smav if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE) 1962250079Scarl rdev->pm.power_state[state_index].type = 1963250079Scarl POWER_STATE_TYPE_BALANCED; 1964250079Scarl if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) { 1965250079Scarl rdev->pm.power_state[state_index].type = 1966250079Scarl POWER_STATE_TYPE_DEFAULT; 1967304404Smav rdev->pm.default_power_state_index = state_index; 1968250079Scarl rdev->pm.power_state[state_index].default_clock_mode = 1969304404Smav &rdev->pm.power_state[state_index].clock_info[0]; 1970250079Scarl } else if (state_index == 0) { 1971250079Scarl rdev->pm.power_state[state_index].clock_info[0].flags |= 1972304404Smav RADEON_PM_MODE_NO_DISPLAY; 1973300373Smav } 1974304404Smav} 1975250079Scarl 1976250079Scarlstatic int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) 1977304404Smav{ 1978300373Smav struct radeon_mode_info *mode_info = &rdev->mode_info; 1979304404Smav u32 misc, misc2 = 0; 1980250079Scarl int num_modes = 0, i; 1981304404Smav int state_index = 0; 1982300373Smav struct radeon_i2c_bus_rec i2c_bus; 1983304404Smav union power_info *power_info; 1984250079Scarl int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 1985250079Scarl u16 data_offset; 1986304404Smav u8 frev, crev; 1987300373Smav 1988304404Smav if (!atom_parse_data_header(mode_info->atom_context, index, NULL, 1989250079Scarl &frev, &crev, &data_offset)) 1990250079Scarl return state_index; 1991304380Smav power_info = (union power_info *)((char *)mode_info->atom_context->bios + data_offset); 1992304404Smav 1993304380Smav /* add the i2c bus for thermal/fan chip */ 1994300373Smav if ((power_info->info.ucOverdriveThermalController > 0) && 1995304380Smav (power_info->info.ucOverdriveThermalController < DRM_ARRAY_SIZE(thermal_controller_names))) { 1996300373Smav DRM_INFO("Possible %s thermal controller at 0x%02x\n", 1997250079Scarl thermal_controller_names[power_info->info.ucOverdriveThermalController], 1998304404Smav power_info->info.ucOverdriveControllerAddress >> 1); 1999301811Sngie i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine); 2000300373Smav rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); 2001300373Smav#ifdef DUMBBELL_WIP 2002300373Smav if (rdev->pm.i2c_bus) { 2003300373Smav struct i2c_board_info info = { }; 2004250079Scarl const char *name = thermal_controller_names[power_info->info. 2005250079Scarl ucOverdriveThermalController]; 2006300373Smav info.addr = power_info->info.ucOverdriveControllerAddress >> 1; 2007304380Smav strlcpy(info.type, name, sizeof(info.type)); 2008300373Smav i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); 2009300373Smav } 2010300373Smav#endif /* DUMBBELL_WIP */ 2011304404Smav } 2012300373Smav num_modes = power_info->info.ucNumOfPowerModeEntries; 2013300373Smav if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK) 2014300373Smav num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK; 2015304380Smav rdev->pm.power_state = malloc(sizeof(struct radeon_power_state) * num_modes, 2016300373Smav DRM_MEM_DRIVER, M_WAITOK | M_ZERO); 2017304404Smav if (!rdev->pm.power_state) 2018300373Smav return state_index; 2019250079Scarl /* last mode is usually default, array is low to high */ 2020250079Scarl for (i = 0; i < num_modes; i++) { 2021304380Smav rdev->pm.power_state[state_index].clock_info = 2022304404Smav malloc(sizeof(struct radeon_pm_clock_info) * 1, 2023300373Smav DRM_MEM_DRIVER, M_WAITOK | M_ZERO); 2024304380Smav if (!rdev->pm.power_state[state_index].clock_info) 2025300373Smav return state_index; 2026300373Smav rdev->pm.power_state[state_index].num_clock_modes = 1; 2027304404Smav rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; 2028301811Sngie switch (frev) { 2029300373Smav case 1: 2030304380Smav rdev->pm.power_state[state_index].clock_info[0].mclk = 2031300373Smav le16_to_cpu(power_info->info.asPowerPlayInfo[i].usMemoryClock); 2032300373Smav rdev->pm.power_state[state_index].clock_info[0].sclk = 2033300373Smav le16_to_cpu(power_info->info.asPowerPlayInfo[i].usEngineClock); 2034304404Smav /* skip invalid modes */ 2035300373Smav if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || 2036300373Smav (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) 2037304380Smav continue; 2038300373Smav rdev->pm.power_state[state_index].pcie_lanes = 2039300373Smav power_info->info.asPowerPlayInfo[i].ucNumPciELanes; 2040304404Smav misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo); 2041300373Smav if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || 2042300373Smav (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { 2043300373Smav rdev->pm.power_state[state_index].clock_info[0].voltage.type = 2044304380Smav VOLTAGE_GPIO; 2045304404Smav rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = 2046301811Sngie radeon_lookup_gpio(rdev, 2047304380Smav power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex); 2048301811Sngie if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) 2049301811Sngie rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = 2050301811Sngie true; 2051301811Sngie else 2052301811Sngie rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = 2053301811Sngie false; 2054301811Sngie } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { 2055301811Sngie rdev->pm.power_state[state_index].clock_info[0].voltage.type = 2056301811Sngie VOLTAGE_VDDC; 2057301811Sngie rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = 2058304404Smav power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex; 2059301811Sngie } 2060301811Sngie rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; 2061301811Sngie radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, 0); 2062250079Scarl state_index++; 2063300373Smav break; 2064250079Scarl case 2: 2065250079Scarl rdev->pm.power_state[state_index].clock_info[0].mclk = 2066300373Smav le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMemoryClock); 2067250079Scarl rdev->pm.power_state[state_index].clock_info[0].sclk = 2068250079Scarl le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulEngineClock); 2069300373Smav /* skip invalid modes */ 2070250079Scarl if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || 2071300373Smav (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) 2072300373Smav continue; 2073300373Smav rdev->pm.power_state[state_index].pcie_lanes = 2074300373Smav power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes; 2075300373Smav misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo); 2076300373Smav misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2); 2077300373Smav if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || 2078300373Smav (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { 2079250079Scarl rdev->pm.power_state[state_index].clock_info[0].voltage.type = 2080300373Smav VOLTAGE_GPIO; 2081250079Scarl rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = 2082250079Scarl radeon_lookup_gpio(rdev, 2083304404Smav power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex); 2084300373Smav if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) 2085300373Smav rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = 2086300373Smav true; 2087304404Smav else 2088300373Smav rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = 2089300373Smav false; 2090300373Smav } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { 2091300373Smav rdev->pm.power_state[state_index].clock_info[0].voltage.type = 2092300373Smav VOLTAGE_VDDC; 2093300373Smav rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = 2094250079Scarl power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex; 2095250079Scarl } 2096300373Smav rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; 2097300373Smav radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, misc2); 2098300373Smav state_index++; 2099250079Scarl break; 2100250079Scarl case 3: 2101250079Scarl rdev->pm.power_state[state_index].clock_info[0].mclk = 2102300373Smav le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMemoryClock); 2103250079Scarl rdev->pm.power_state[state_index].clock_info[0].sclk = 2104250079Scarl le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulEngineClock); 2105250079Scarl /* skip invalid modes */ 2106300373Smav if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || 2107300373Smav (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) 2108300373Smav continue; 2109300373Smav rdev->pm.power_state[state_index].pcie_lanes = 2110304404Smav power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes; 2111250079Scarl misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo); 2112250079Scarl misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2); 2113300373Smav if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || 2114250079Scarl (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { 2115300373Smav rdev->pm.power_state[state_index].clock_info[0].voltage.type = 2116304404Smav VOLTAGE_GPIO; 2117300373Smav rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = 2118300373Smav radeon_lookup_gpio(rdev, 2119300373Smav power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex); 2120300373Smav if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) 2121304404Smav rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = 2122250079Scarl true; 2123300373Smav else 2124250079Scarl rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = 2125300373Smav false; 2126300373Smav } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { 2127300373Smav rdev->pm.power_state[state_index].clock_info[0].voltage.type = 2128300373Smav VOLTAGE_VDDC; 2129300373Smav rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = 2130301811Sngie power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex; 2131304380Smav if (misc2 & ATOM_PM_MISCINFO2_VDDCI_DYNAMIC_VOLTAGE_EN) { 2132301811Sngie rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_enabled = 2133301811Sngie true; 2134301811Sngie rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_id = 2135304404Smav power_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex; 2136301811Sngie } 2137301811Sngie } 2138301811Sngie rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; 2139301811Sngie radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, misc2); 2140301811Sngie state_index++; 2141301811Sngie break; 2142301811Sngie } 2143250079Scarl } 2144300373Smav /* last mode is usually default */ 2145300373Smav if (rdev->pm.default_power_state_index == -1) { 2146250079Scarl rdev->pm.power_state[state_index - 1].type = 2147300373Smav POWER_STATE_TYPE_DEFAULT; 2148304404Smav rdev->pm.default_power_state_index = state_index - 1; 2149300373Smav rdev->pm.power_state[state_index - 1].default_clock_mode = 2150250079Scarl &rdev->pm.power_state[state_index - 1].clock_info[0]; 2151300373Smav rdev->pm.power_state[state_index].flags &= 2152300373Smav ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; 2153300373Smav rdev->pm.power_state[state_index].misc = 0; 2154250079Scarl rdev->pm.power_state[state_index].misc2 = 0; 2155250079Scarl } 2156300373Smav return state_index; 2157304404Smav} 2158250079Scarl 2159250079Scarlstatic void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *rdev, 2160300373Smav ATOM_PPLIB_THERMALCONTROLLER *controller) 2161300373Smav{ 2162300373Smav struct radeon_i2c_bus_rec i2c_bus; 2163300373Smav 2164250079Scarl /* add the i2c bus for thermal/fan chip */ 2165300373Smav if (controller->ucType > 0) { 2166300373Smav if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) { 2167250079Scarl DRM_INFO("Internal thermal controller %s fan control\n", 2168300373Smav (controller->ucFanParameters & 2169300373Smav ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 2170300373Smav rdev->pm.int_thermal_type = THERMAL_TYPE_RV6XX; 2171300373Smav } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) { 2172300373Smav DRM_INFO("Internal thermal controller %s fan control\n", 2173250079Scarl (controller->ucFanParameters & 2174300373Smav ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 2175300373Smav rdev->pm.int_thermal_type = THERMAL_TYPE_RV770; 2176300373Smav } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) { 2177300373Smav DRM_INFO("Internal thermal controller %s fan control\n", 2178300373Smav (controller->ucFanParameters & 2179304404Smav ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 2180250079Scarl rdev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN; 2181301811Sngie } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SUMO) { 2182300373Smav DRM_INFO("Internal thermal controller %s fan control\n", 2183300373Smav (controller->ucFanParameters & 2184250079Scarl ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 2185300373Smav rdev->pm.int_thermal_type = THERMAL_TYPE_SUMO; 2186301811Sngie } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_NISLANDS) { 2187250079Scarl DRM_INFO("Internal thermal controller %s fan control\n", 2188301811Sngie (controller->ucFanParameters & 2189301811Sngie ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 2190301811Sngie rdev->pm.int_thermal_type = THERMAL_TYPE_NI; 2191301811Sngie } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SISLANDS) { 2192301811Sngie DRM_INFO("Internal thermal controller %s fan control\n", 2193301811Sngie (controller->ucFanParameters & 2194301811Sngie ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 2195301811Sngie rdev->pm.int_thermal_type = THERMAL_TYPE_SI; 2196301811Sngie } else if ((controller->ucType == 2197301811Sngie ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) || 2198301811Sngie (controller->ucType == 2199301811Sngie ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) || 2200301811Sngie (controller->ucType == 2201300373Smav ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL)) { 2202250079Scarl DRM_INFO("Special thermal controller config\n"); 2203300373Smav } else if (controller->ucType < DRM_ARRAY_SIZE(pp_lib_thermal_controller_names)) { 2204300373Smav DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n", 2205300373Smav pp_lib_thermal_controller_names[controller->ucType], 2206300373Smav controller->ucI2cAddress >> 1, 2207300373Smav (controller->ucFanParameters & 2208300373Smav ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 2209300373Smav i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine); 2210300373Smav rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); 2211300373Smav#ifdef DUMBBELL_WIP 2212300373Smav if (rdev->pm.i2c_bus) { 2213300373Smav struct i2c_board_info info = { }; 2214300373Smav const char *name = pp_lib_thermal_controller_names[controller->ucType]; 2215300373Smav info.addr = controller->ucI2cAddress >> 1; 2216300373Smav strlcpy(info.type, name, sizeof(info.type)); 2217300373Smav i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); 2218300373Smav } 2219250079Scarl#endif /* DUMBBELL_WIP */ 2220250079Scarl } else { 2221300373Smav DRM_INFO("Unknown thermal controller type %d at 0x%02x %s fan control\n", 2222300373Smav controller->ucType, 2223300373Smav controller->ucI2cAddress >> 1, 2224250079Scarl (controller->ucFanParameters & 2225300373Smav ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 2226300373Smav } 2227300373Smav } 2228300373Smav} 2229300373Smav 2230300373Smavstatic void radeon_atombios_get_default_voltages(struct radeon_device *rdev, 2231250079Scarl u16 *vddc, u16 *vddci) 2232300373Smav{ 2233300373Smav struct radeon_mode_info *mode_info = &rdev->mode_info; 2234300373Smav int index = GetIndexIntoMasterTable(DATA, FirmwareInfo); 2235300373Smav u8 frev, crev; 2236300373Smav u16 data_offset; 2237300373Smav union firmware_info *firmware_info; 2238300373Smav 2239300373Smav *vddc = 0; 2240300373Smav *vddci = 0; 2241300373Smav 2242300373Smav if (atom_parse_data_header(mode_info->atom_context, index, NULL, 2243300373Smav &frev, &crev, &data_offset)) { 2244250079Scarl firmware_info = 2245300373Smav (union firmware_info *)((char *)mode_info->atom_context->bios + 2246300373Smav data_offset); 2247300373Smav *vddc = le16_to_cpu(firmware_info->info_14.usBootUpVDDCVoltage); 2248300373Smav if ((frev == 2) && (crev >= 2)) 2249300373Smav *vddci = le16_to_cpu(firmware_info->info_22.usBootUpVDDCIVoltage); 2250300373Smav } 2251300373Smav} 2252300373Smav 2253300373Smavstatic void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rdev, 2254300373Smav int state_index, int mode_index, 2255300373Smav struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info) 2256300373Smav{ 2257300373Smav int j; 2258300373Smav u32 misc = le32_to_cpu(non_clock_info->ulCapsAndSettings); 2259300373Smav u32 misc2 = le16_to_cpu(non_clock_info->usClassification); 2260300373Smav u16 vddc, vddci; 2261300373Smav 2262300373Smav radeon_atombios_get_default_voltages(rdev, &vddc, &vddci); 2263300373Smav 2264300373Smav rdev->pm.power_state[state_index].misc = misc; 2265300373Smav rdev->pm.power_state[state_index].misc2 = misc2; 2266300373Smav rdev->pm.power_state[state_index].pcie_lanes = 2267300373Smav ((misc & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> 2268300373Smav ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1; 2269300373Smav switch (misc2 & ATOM_PPLIB_CLASSIFICATION_UI_MASK) { 2270300373Smav case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY: 2271300373Smav rdev->pm.power_state[state_index].type = 2272300373Smav POWER_STATE_TYPE_BATTERY; 2273300373Smav break; 2274300373Smav case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED: 2275300373Smav rdev->pm.power_state[state_index].type = 2276300373Smav POWER_STATE_TYPE_BALANCED; 2277300373Smav break; 2278300373Smav case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE: 2279300373Smav rdev->pm.power_state[state_index].type = 2280300373Smav POWER_STATE_TYPE_PERFORMANCE; 2281300373Smav break; 2282304380Smav case ATOM_PPLIB_CLASSIFICATION_UI_NONE: 2283300373Smav if (misc2 & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) 2284300373Smav rdev->pm.power_state[state_index].type = 2285300373Smav POWER_STATE_TYPE_PERFORMANCE; 2286300373Smav break; 2287300373Smav } 2288300373Smav rdev->pm.power_state[state_index].flags = 0; 2289300373Smav if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) 2290300373Smav rdev->pm.power_state[state_index].flags |= 2291300373Smav RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; 2292300373Smav if (misc2 & ATOM_PPLIB_CLASSIFICATION_BOOT) { 2293300373Smav rdev->pm.power_state[state_index].type = 2294300373Smav POWER_STATE_TYPE_DEFAULT; 2295300373Smav rdev->pm.default_power_state_index = state_index; 2296300373Smav rdev->pm.power_state[state_index].default_clock_mode = 2297300373Smav &rdev->pm.power_state[state_index].clock_info[mode_index - 1]; 2298300373Smav if (ASIC_IS_DCE5(rdev) && !(rdev->flags & RADEON_IS_IGP)) { 2299300373Smav /* NI chips post without MC ucode, so default clocks are strobe mode only */ 2300300373Smav rdev->pm.default_sclk = rdev->pm.power_state[state_index].clock_info[0].sclk; 2301300373Smav rdev->pm.default_mclk = rdev->pm.power_state[state_index].clock_info[0].mclk; 2302304380Smav rdev->pm.default_vddc = rdev->pm.power_state[state_index].clock_info[0].voltage.voltage; 2303300373Smav rdev->pm.default_vddci = rdev->pm.power_state[state_index].clock_info[0].voltage.vddci; 2304300373Smav } else { 2305300373Smav /* patch the table values with the default slck/mclk from firmware info */ 2306300373Smav for (j = 0; j < mode_index; j++) { 2307300373Smav rdev->pm.power_state[state_index].clock_info[j].mclk = 2308300373Smav rdev->clock.default_mclk; 2309300373Smav rdev->pm.power_state[state_index].clock_info[j].sclk = 2310300373Smav rdev->clock.default_sclk; 2311300373Smav if (vddc) 2312300373Smav rdev->pm.power_state[state_index].clock_info[j].voltage.voltage = 2313300373Smav vddc; 2314300373Smav } 2315300373Smav } 2316300373Smav } 2317300373Smav} 2318300373Smav 2319250079Scarlstatic bool radeon_atombios_parse_pplib_clock_info(struct radeon_device *rdev, 2320250079Scarl int state_index, int mode_index, 2321300373Smav union pplib_clock_info *clock_info) 2322300373Smav{ 2323300373Smav u32 sclk, mclk; 2324300373Smav u16 vddc; 2325300373Smav 2326300373Smav if (rdev->flags & RADEON_IS_IGP) { 2327300373Smav if (rdev->family >= CHIP_PALM) { 2328250079Scarl sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow); 2329300373Smav sclk |= clock_info->sumo.ucEngineClockHigh << 16; 2330300373Smav rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; 2331300373Smav } else { 2332300373Smav sclk = le16_to_cpu(clock_info->rs780.usLowEngineClockLow); 2333300373Smav sclk |= clock_info->rs780.ucLowEngineClockHigh << 16; 2334300373Smav rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; 2335300373Smav } 2336300373Smav } else if (ASIC_IS_DCE6(rdev)) { 2337300373Smav sclk = le16_to_cpu(clock_info->si.usEngineClockLow); 2338300373Smav sclk |= clock_info->si.ucEngineClockHigh << 16; 2339300373Smav mclk = le16_to_cpu(clock_info->si.usMemoryClockLow); 2340300373Smav mclk |= clock_info->si.ucMemoryClockHigh << 16; 2341300373Smav rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; 2342300373Smav rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; 2343300373Smav rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type = 2344300373Smav VOLTAGE_SW; 2345300373Smav rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = 2346300373Smav le16_to_cpu(clock_info->si.usVDDC); 2347300373Smav rdev->pm.power_state[state_index].clock_info[mode_index].voltage.vddci = 2348300373Smav le16_to_cpu(clock_info->si.usVDDCI); 2349300373Smav } else if (ASIC_IS_DCE4(rdev)) { 2350300373Smav sclk = le16_to_cpu(clock_info->evergreen.usEngineClockLow); 2351300373Smav sclk |= clock_info->evergreen.ucEngineClockHigh << 16; 2352300373Smav mclk = le16_to_cpu(clock_info->evergreen.usMemoryClockLow); 2353300373Smav mclk |= clock_info->evergreen.ucMemoryClockHigh << 16; 2354300373Smav rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; 2355300373Smav rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; 2356300373Smav rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type = 2357300373Smav VOLTAGE_SW; 2358300373Smav rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = 2359300373Smav le16_to_cpu(clock_info->evergreen.usVDDC); 2360300373Smav rdev->pm.power_state[state_index].clock_info[mode_index].voltage.vddci = 2361300373Smav le16_to_cpu(clock_info->evergreen.usVDDCI); 2362300373Smav } else { 2363300373Smav sclk = le16_to_cpu(clock_info->r600.usEngineClockLow); 2364300373Smav sclk |= clock_info->r600.ucEngineClockHigh << 16; 2365300373Smav mclk = le16_to_cpu(clock_info->r600.usMemoryClockLow); 2366300373Smav mclk |= clock_info->r600.ucMemoryClockHigh << 16; 2367300373Smav rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; 2368300373Smav rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; 2369300373Smav rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type = 2370300373Smav VOLTAGE_SW; 2371300373Smav rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = 2372300373Smav le16_to_cpu(clock_info->r600.usVDDC); 2373300373Smav } 2374300373Smav 2375300373Smav /* patch up vddc if necessary */ 2376300373Smav switch (rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage) { 2377300373Smav case ATOM_VIRTUAL_VOLTAGE_ID0: 2378300373Smav case ATOM_VIRTUAL_VOLTAGE_ID1: 2379300373Smav case ATOM_VIRTUAL_VOLTAGE_ID2: 2380300373Smav case ATOM_VIRTUAL_VOLTAGE_ID3: 2381300373Smav if (radeon_atom_get_max_vddc(rdev, VOLTAGE_TYPE_VDDC, 2382300373Smav rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage, 2383300373Smav &vddc) == 0) 2384300373Smav rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = vddc; 2385300373Smav break; 2386300373Smav default: 2387300373Smav break; 2388300373Smav } 2389300373Smav 2390300373Smav if (rdev->flags & RADEON_IS_IGP) { 2391300373Smav /* skip invalid modes */ 2392300373Smav if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0) 2393304380Smav return false; 2394300373Smav } else { 2395300373Smav /* skip invalid modes */ 2396300373Smav if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) || 2397300373Smav (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)) 2398300373Smav return false; 2399300373Smav } 2400300373Smav return true; 2401300373Smav} 2402300373Smav 2403300373Smavstatic int radeon_atombios_parse_power_table_4_5(struct radeon_device *rdev) 2404300373Smav{ 2405300373Smav struct radeon_mode_info *mode_info = &rdev->mode_info; 2406300373Smav struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; 2407300373Smav union pplib_power_state *power_state; 2408300373Smav int i, j; 2409300373Smav int state_index = 0, mode_index = 0; 2410300373Smav union pplib_clock_info *clock_info; 2411300373Smav bool valid; 2412300373Smav union power_info *power_info; 2413304380Smav int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 2414300373Smav u16 data_offset; 2415300373Smav u8 frev, crev; 2416300373Smav 2417300373Smav if (!atom_parse_data_header(mode_info->atom_context, index, NULL, 2418300373Smav &frev, &crev, &data_offset)) 2419300373Smav return state_index; 2420300373Smav power_info = (union power_info *)((char *)mode_info->atom_context->bios + data_offset); 2421300373Smav 2422300373Smav radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController); 2423300373Smav rdev->pm.power_state = malloc(sizeof(struct radeon_power_state) * 2424300373Smav power_info->pplib.ucNumStates, 2425300373Smav DRM_MEM_DRIVER, M_WAITOK | M_ZERO); 2426300373Smav if (!rdev->pm.power_state) 2427300373Smav return state_index; 2428300373Smav /* first mode is usually default, followed by low to high */ 2429300373Smav for (i = 0; i < power_info->pplib.ucNumStates; i++) { 2430300373Smav mode_index = 0; 2431300373Smav power_state = (union pplib_power_state *) 2432300373Smav ((char *)mode_info->atom_context->bios + data_offset + 2433300373Smav le16_to_cpu(power_info->pplib.usStateArrayOffset) + 2434300373Smav i * power_info->pplib.ucStateEntrySize); 2435300373Smav non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) 2436300373Smav ((char *)mode_info->atom_context->bios + data_offset + 2437304380Smav le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) + 2438300373Smav (power_state->v1.ucNonClockStateIndex * 2439300373Smav power_info->pplib.ucNonClockSize)); 2440300373Smav rdev->pm.power_state[i].clock_info = malloc(sizeof(struct radeon_pm_clock_info) * 2441300373Smav ((power_info->pplib.ucStateEntrySize - 1) ? 2442300373Smav (power_info->pplib.ucStateEntrySize - 1) : 1), 2443300373Smav DRM_MEM_DRIVER, M_WAITOK | M_ZERO); 2444300373Smav if (!rdev->pm.power_state[i].clock_info) 2445300373Smav return state_index; 2446300373Smav if (power_info->pplib.ucStateEntrySize - 1) { 2447300373Smav for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) { 2448300373Smav clock_info = (union pplib_clock_info *) 2449300373Smav ((char *)mode_info->atom_context->bios + data_offset + 2450300373Smav le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) + 2451300373Smav (power_state->v1.ucClockStateIndices[j] * 2452300373Smav power_info->pplib.ucClockInfoSize)); 2453300373Smav valid = radeon_atombios_parse_pplib_clock_info(rdev, 2454300373Smav state_index, mode_index, 2455250079Scarl clock_info); 2456250079Scarl if (valid) 2457300373Smav mode_index++; 2458300373Smav } 2459250079Scarl } else { 2460304377Smav rdev->pm.power_state[state_index].clock_info[0].mclk = 2461300373Smav rdev->clock.default_mclk; 2462300373Smav rdev->pm.power_state[state_index].clock_info[0].sclk = 2463250079Scarl rdev->clock.default_sclk; 2464300373Smav mode_index++; 2465300373Smav } 2466300373Smav rdev->pm.power_state[state_index].num_clock_modes = mode_index; 2467300373Smav if (mode_index) { 2468300373Smav radeon_atombios_parse_pplib_non_clock_info(rdev, state_index, mode_index, 2469300373Smav non_clock_info); 2470300373Smav state_index++; 2471300373Smav } 2472300373Smav } 2473250079Scarl /* if multiple clock modes, mark the lowest as no display */ 2474250079Scarl for (i = 0; i < state_index; i++) { 2475300373Smav if (rdev->pm.power_state[i].num_clock_modes > 1) 2476301811Sngie rdev->pm.power_state[i].clock_info[0].flags |= 2477250079Scarl RADEON_PM_MODE_NO_DISPLAY; 2478304377Smav } 2479301811Sngie /* first mode is usually default */ 2480301811Sngie if (rdev->pm.default_power_state_index == -1) { 2481301811Sngie rdev->pm.power_state[0].type = 2482304404Smav POWER_STATE_TYPE_DEFAULT; 2483301811Sngie rdev->pm.default_power_state_index = 0; 2484301811Sngie rdev->pm.power_state[0].default_clock_mode = 2485301811Sngie &rdev->pm.power_state[0].clock_info[0]; 2486301811Sngie } 2487301811Sngie return state_index; 2488301811Sngie} 2489301811Sngie 2490301811Sngiestatic int radeon_atombios_parse_power_table_6(struct radeon_device *rdev) 2491301811Sngie{ 2492304404Smav struct radeon_mode_info *mode_info = &rdev->mode_info; 2493301811Sngie struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; 2494301811Sngie union pplib_power_state *power_state; 2495301811Sngie int i, j, non_clock_array_index, clock_array_index; 2496304404Smav int state_index = 0, mode_index = 0; 2497301811Sngie union pplib_clock_info *clock_info; 2498304404Smav struct _StateArray *state_array; 2499301811Sngie struct _ClockInfoArray *clock_info_array; 2500301811Sngie struct _NonClockInfoArray *non_clock_info_array; 2501301811Sngie bool valid; 2502301811Sngie union power_info *power_info; 2503301811Sngie int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 2504301811Sngie u16 data_offset; 2505304377Smav u8 frev, crev; 2506300373Smav 2507300373Smav if (!atom_parse_data_header(mode_info->atom_context, index, NULL, 2508300373Smav &frev, &crev, &data_offset)) 2509300373Smav return state_index; 2510250079Scarl power_info = (union power_info *)((char *)mode_info->atom_context->bios + data_offset); 2511300373Smav 2512300373Smav radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController); 2513304404Smav state_array = (struct _StateArray *) 2514300373Smav ((char *)mode_info->atom_context->bios + data_offset + 2515300373Smav le16_to_cpu(power_info->pplib.usStateArrayOffset)); 2516300373Smav clock_info_array = (struct _ClockInfoArray *) 2517300373Smav ((char *)mode_info->atom_context->bios + data_offset + 2518300373Smav le16_to_cpu(power_info->pplib.usClockInfoArrayOffset)); 2519300373Smav non_clock_info_array = (struct _NonClockInfoArray *) 2520300373Smav ((char *)mode_info->atom_context->bios + data_offset + 2521300373Smav le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); 2522300373Smav rdev->pm.power_state = malloc(sizeof(struct radeon_power_state) * 2523300373Smav state_array->ucNumEntries, 2524300373Smav DRM_MEM_DRIVER, M_WAITOK | M_ZERO); 2525250079Scarl if (!rdev->pm.power_state) 2526250079Scarl return state_index; 2527300373Smav for (i = 0; i < state_array->ucNumEntries; i++) { 2528301811Sngie mode_index = 0; 2529301811Sngie power_state = (union pplib_power_state *)&state_array->states[i]; 2530304377Smav /* XXX this might be an inagua bug... */ 2531301811Sngie non_clock_array_index = i; /* power_state->v2.nonClockInfoIndex */ 2532301811Sngie non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) 2533301811Sngie &non_clock_info_array->nonClockInfo[non_clock_array_index]; 2534304404Smav rdev->pm.power_state[i].clock_info = malloc(sizeof(struct radeon_pm_clock_info) * 2535301811Sngie (power_state->v2.ucNumDPMLevels ? 2536301811Sngie power_state->v2.ucNumDPMLevels : 1), 2537301811Sngie DRM_MEM_DRIVER, M_WAITOK | M_ZERO); 2538301811Sngie if (!rdev->pm.power_state[i].clock_info) 2539301811Sngie return state_index; 2540301811Sngie if (power_state->v2.ucNumDPMLevels) { 2541301811Sngie for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { 2542301811Sngie clock_array_index = power_state->v2.clockInfoIndex[j]; 2543300373Smav /* XXX this might be an inagua bug... */ 2544250079Scarl if (clock_array_index >= clock_info_array->ucNumEntries) 2545300373Smav continue; 2546300373Smav clock_info = (union pplib_clock_info *) 2547300373Smav &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize]; 2548300373Smav valid = radeon_atombios_parse_pplib_clock_info(rdev, 2549300373Smav state_index, mode_index, 2550300373Smav clock_info); 2551300373Smav if (valid) 2552300373Smav mode_index++; 2553300373Smav } 2554250079Scarl } else { 2555300373Smav rdev->pm.power_state[state_index].clock_info[0].mclk = 2556300373Smav rdev->clock.default_mclk; 2557300373Smav rdev->pm.power_state[state_index].clock_info[0].sclk = 2558300373Smav rdev->clock.default_sclk; 2559300373Smav mode_index++; 2560250079Scarl } 2561300373Smav rdev->pm.power_state[state_index].num_clock_modes = mode_index; 2562250079Scarl if (mode_index) { 2563300373Smav radeon_atombios_parse_pplib_non_clock_info(rdev, state_index, mode_index, 2564300373Smav non_clock_info); 2565300373Smav state_index++; 2566300373Smav } 2567300373Smav } 2568300373Smav /* if multiple clock modes, mark the lowest as no display */ 2569300373Smav for (i = 0; i < state_index; i++) { 2570300373Smav if (rdev->pm.power_state[i].num_clock_modes > 1) 2571300373Smav rdev->pm.power_state[i].clock_info[0].flags |= 2572300373Smav RADEON_PM_MODE_NO_DISPLAY; 2573304404Smav } 2574300373Smav /* first mode is usually default */ 2575300373Smav if (rdev->pm.default_power_state_index == -1) { 2576300373Smav rdev->pm.power_state[0].type = 2577300373Smav POWER_STATE_TYPE_DEFAULT; 2578300373Smav rdev->pm.default_power_state_index = 0; 2579300373Smav rdev->pm.power_state[0].default_clock_mode = 2580304404Smav &rdev->pm.power_state[0].clock_info[0]; 2581300373Smav } 2582300373Smav return state_index; 2583300373Smav} 2584300373Smav 2585300373Smavvoid radeon_atombios_get_power_modes(struct radeon_device *rdev) 2586300373Smav{ 2587304404Smav struct radeon_mode_info *mode_info = &rdev->mode_info; 2588300373Smav int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 2589300373Smav u16 data_offset; 2590300373Smav u8 frev, crev; 2591300373Smav int state_index = 0; 2592300373Smav 2593300373Smav rdev->pm.default_power_state_index = -1; 2594304404Smav 2595300373Smav if (atom_parse_data_header(mode_info->atom_context, index, NULL, 2596300373Smav &frev, &crev, &data_offset)) { 2597300373Smav switch (frev) { 2598300373Smav case 1: 2599300373Smav case 2: 2600300373Smav case 3: 2601300373Smav state_index = radeon_atombios_parse_power_table_1_3(rdev); 2602300373Smav break; 2603300373Smav case 4: 2604300373Smav case 5: 2605300373Smav state_index = radeon_atombios_parse_power_table_4_5(rdev); 2606300373Smav break; 2607300373Smav case 6: 2608300373Smav state_index = radeon_atombios_parse_power_table_6(rdev); 2609300373Smav break; 2610300373Smav default: 2611250079Scarl break; 2612250079Scarl } 2613300373Smav } else { 2614304404Smav rdev->pm.power_state = malloc(sizeof(struct radeon_power_state), 2615300373Smav DRM_MEM_DRIVER, M_WAITOK | M_ZERO); 2616300373Smav if (rdev->pm.power_state) { 2617301811Sngie rdev->pm.power_state[0].clock_info = 2618301811Sngie malloc(sizeof(struct radeon_pm_clock_info) * 1, 2619301811Sngie DRM_MEM_DRIVER, M_WAITOK | M_ZERO); 2620301811Sngie if (rdev->pm.power_state[0].clock_info) { 2621301811Sngie /* add the default mode */ 2622301811Sngie rdev->pm.power_state[state_index].type = 2623301811Sngie POWER_STATE_TYPE_DEFAULT; 2624301811Sngie rdev->pm.power_state[state_index].num_clock_modes = 1; 2625300373Smav rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk; 2626300373Smav rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk; 2627300373Smav rdev->pm.power_state[state_index].default_clock_mode = 2628304410Smav &rdev->pm.power_state[state_index].clock_info[0]; 2629304409Smav rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; 2630304409Smav rdev->pm.power_state[state_index].pcie_lanes = 16; 2631301811Sngie rdev->pm.default_power_state_index = state_index; 2632304409Smav rdev->pm.power_state[state_index].flags = 0; 2633304409Smav state_index++; 2634304409Smav } 2635304409Smav } 2636304409Smav } 2637304409Smav 2638304409Smav rdev->pm.num_power_states = state_index; 2639304410Smav 2640304409Smav rdev->pm.current_power_state_index = rdev->pm.default_power_state_index; 2641304409Smav rdev->pm.current_clock_mode_index = 0; 2642304404Smav if (rdev->pm.default_power_state_index >= 0) 2643301811Sngie rdev->pm.current_vddc = 2644301811Sngie rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage; 2645301811Sngie else 2646301811Sngie rdev->pm.current_vddc = 0; 2647301811Sngie} 2648301811Sngie 2649301811Sngievoid radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable) 2650301903Smav{ 2651301903Smav DYNAMIC_CLOCK_GATING_PS_ALLOCATION args; 2652301811Sngie int index = GetIndexIntoMasterTable(COMMAND, DynamicClockGating); 2653301811Sngie 2654301811Sngie args.ucEnable = enable; 2655304410Smav 2656304409Smav atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 2657304409Smav} 2658304409Smav 2659304410Smavuint32_t radeon_atom_get_engine_clock(struct radeon_device *rdev) 2660304409Smav{ 2661304404Smav GET_ENGINE_CLOCK_PS_ALLOCATION args; 2662301811Sngie int index = GetIndexIntoMasterTable(COMMAND, GetEngineClock); 2663304404Smav 2664301811Sngie atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 2665304404Smav return le32_to_cpu(args.ulReturnEngineClock); 2666301904Smav} 2667301811Sngie 2668304404Smavuint32_t radeon_atom_get_memory_clock(struct radeon_device *rdev) 2669301811Sngie{ 2670304404Smav GET_MEMORY_CLOCK_PS_ALLOCATION args; 2671301811Sngie int index = GetIndexIntoMasterTable(COMMAND, GetMemoryClock); 2672301811Sngie 2673301811Sngie atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 2674301811Sngie return le32_to_cpu(args.ulReturnMemoryClock); 2675304404Smav} 2676304404Smav 2677301811Sngievoid radeon_atom_set_engine_clock(struct radeon_device *rdev, 2678304404Smav uint32_t eng_clock) 2679304404Smav{ 2680301811Sngie SET_ENGINE_CLOCK_PS_ALLOCATION args; 2681301811Sngie int index = GetIndexIntoMasterTable(COMMAND, SetEngineClock); 2682301811Sngie 2683301811Sngie args.ulTargetEngineClock = cpu_to_le32(eng_clock); /* 10 khz */ 2684301811Sngie 2685301811Sngie atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 2686304404Smav} 2687304404Smav 2688301811Sngievoid radeon_atom_set_memory_clock(struct radeon_device *rdev, 2689301811Sngie uint32_t mem_clock) 2690301811Sngie{ 2691304406Smav SET_MEMORY_CLOCK_PS_ALLOCATION args; 2692301811Sngie int index = GetIndexIntoMasterTable(COMMAND, SetMemoryClock); 2693301903Smav 2694301903Smav if (rdev->flags & RADEON_IS_IGP) 2695301811Sngie return; 2696301903Smav 2697304404Smav args.ulTargetMemoryClock = cpu_to_le32(mem_clock); /* 10 khz */ 2698304380Smav 2699301811Sngie atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 2700301811Sngie} 2701301811Sngie 2702301811Sngieunion set_voltage { 2703301903Smav struct _SET_VOLTAGE_PS_ALLOCATION alloc; 2704301903Smav struct _SET_VOLTAGE_PARAMETERS v1; 2705301903Smav struct _SET_VOLTAGE_PARAMETERS_V2 v2; 2706304404Smav struct _SET_VOLTAGE_PARAMETERS_V1_3 v3; 2707301903Smav}; 2708304404Smav 2709301811Sngievoid radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type) 2710301811Sngie{ 2711300373Smav union set_voltage args; 2712300373Smav int index = GetIndexIntoMasterTable(COMMAND, SetVoltage); 2713300373Smav u8 frev, crev, volt_index = voltage_level; 2714300373Smav 2715304380Smav if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 2716304404Smav return; 2717250079Scarl 2718304380Smav /* 0xff01 is a flag rather then an actual voltage */ 2719250079Scarl if (voltage_level == 0xff01) 2720300373Smav return; 2721250079Scarl 2722250079Scarl switch (crev) { 2723304380Smav case 1: 2724304404Smav args.v1.ucVoltageType = voltage_type; 2725300373Smav args.v1.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_ALL_SOURCE; 2726304380Smav args.v1.ucVoltageIndex = volt_index; 2727301811Sngie break; 2728300373Smav case 2: 2729301811Sngie args.v2.ucVoltageType = voltage_type; 2730300373Smav args.v2.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE; 2731301811Sngie args.v2.usVoltageLevel = cpu_to_le16(voltage_level); 2732301811Sngie break; 2733301811Sngie case 3: 2734301811Sngie args.v3.ucVoltageType = voltage_type; 2735300373Smav args.v3.ucVoltageMode = ATOM_SET_VOLTAGE; 2736300373Smav args.v3.usVoltageLevel = cpu_to_le16(voltage_level); 2737304380Smav break; 2738304404Smav default: 2739250079Scarl DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 2740304380Smav return; 2741250079Scarl } 2742300373Smav 2743250079Scarl atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 2744250079Scarl} 2745304404Smav 2746250079Scarlstatic int radeon_atom_get_max_vddc(struct radeon_device *rdev, u8 voltage_type, 2747250079Scarl u16 voltage_id, u16 *voltage) 2748250079Scarl{ 2749250079Scarl union set_voltage args; 2750301811Sngie int index = GetIndexIntoMasterTable(COMMAND, SetVoltage); 2751301811Sngie u8 frev, crev; 2752301811Sngie 2753304380Smav if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 2754304404Smav return -EINVAL; 2755301811Sngie 2756304380Smav switch (crev) { 2757301811Sngie case 1: 2758301811Sngie return -EINVAL; 2759301811Sngie case 2: 2760304404Smav args.v2.ucVoltageType = SET_VOLTAGE_GET_MAX_VOLTAGE; 2761301811Sngie args.v2.ucVoltageMode = 0; 2762301811Sngie args.v2.usVoltageLevel = 0; 2763304380Smav 2764304404Smav atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 2765250079Scarl 2766304380Smav *voltage = le16_to_cpu(args.v2.usVoltageLevel); 2767250079Scarl break; 2768300373Smav case 3: 2769250079Scarl args.v3.ucVoltageType = voltage_type; 2770250079Scarl args.v3.ucVoltageMode = ATOM_GET_VOLTAGE_LEVEL; 2771304404Smav args.v3.usVoltageLevel = cpu_to_le16(voltage_id); 2772250079Scarl 2773250079Scarl atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 2774250079Scarl 2775250079Scarl *voltage = le16_to_cpu(args.v3.usVoltageLevel); 2776304380Smav break; 2777304404Smav default: 2778250079Scarl DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 2779304380Smav return -EINVAL; 2780250079Scarl } 2781300373Smav 2782250079Scarl return 0; 2783250079Scarl} 2784304380Smav 2785304404Smavvoid radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev) 2786255279Scarl{ 2787304404Smav struct radeon_device *rdev = dev->dev_private; 2788250079Scarl uint32_t bios_2_scratch, bios_6_scratch; 2789250079Scarl 2790250079Scarl if (rdev->family >= CHIP_R600) { 2791250079Scarl bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH); 2792304380Smav bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH); 2793304404Smav } else { 2794250079Scarl bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH); 2795304380Smav bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH); 2796250079Scarl } 2797300373Smav 2798250079Scarl /* let the bios control the backlight */ 2799250079Scarl bios_2_scratch &= ~ATOM_S2_VRI_BRIGHT_ENABLE; 2800304380Smav 2801304404Smav /* tell the bios not to handle mode switching */ 2802255279Scarl bios_6_scratch |= ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH; 2803304404Smav 2804250079Scarl if (rdev->family >= CHIP_R600) { 2805250079Scarl WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch); 2806250079Scarl WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch); 2807250079Scarl } else { 2808304380Smav WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch); 2809304404Smav WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch); 2810300373Smav } 2811300373Smav 2812250079Scarl} 2813304380Smav 2814300373Smavvoid radeon_save_bios_scratch_regs(struct radeon_device *rdev) 2815300373Smav{ 2816300373Smav uint32_t scratch_reg; 2817300373Smav int i; 2818250079Scarl 2819304404Smav if (rdev->family >= CHIP_R600) 2820300373Smav scratch_reg = R600_BIOS_0_SCRATCH; 2821304404Smav else 2822250079Scarl scratch_reg = RADEON_BIOS_0_SCRATCH; 2823304404Smav 2824300373Smav for (i = 0; i < RADEON_BIOS_NUM_SCRATCH; i++) 2825300373Smav rdev->bios_scratch[i] = RREG32(scratch_reg + (i * 4)); 2826300373Smav} 2827300373Smav 2828300373Smavvoid radeon_restore_bios_scratch_regs(struct radeon_device *rdev) 2829300373Smav{ 2830300373Smav uint32_t scratch_reg; 2831300373Smav int i; 2832300373Smav 2833300373Smav if (rdev->family >= CHIP_R600) 2834300373Smav scratch_reg = R600_BIOS_0_SCRATCH; 2835300373Smav else 2836300373Smav scratch_reg = RADEON_BIOS_0_SCRATCH; 2837300373Smav 2838300373Smav for (i = 0; i < RADEON_BIOS_NUM_SCRATCH; i++) 2839300373Smav WREG32(scratch_reg + (i * 4), rdev->bios_scratch[i]); 2840300373Smav} 2841300373Smav 2842300373Smavvoid radeon_atom_output_lock(struct drm_encoder *encoder, bool lock) 2843300373Smav{ 2844300373Smav struct drm_device *dev = encoder->dev; 2845300373Smav struct radeon_device *rdev = dev->dev_private; 2846300373Smav uint32_t bios_6_scratch; 2847300373Smav 2848300373Smav if (rdev->family >= CHIP_R600) 2849300373Smav bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH); 2850250079Scarl else 2851250079Scarl bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH); 2852304380Smav 2853304404Smav if (lock) { 2854250079Scarl bios_6_scratch |= ATOM_S6_CRITICAL_STATE; 2855304380Smav bios_6_scratch &= ~ATOM_S6_ACC_MODE; 2856300373Smav } else { 2857300373Smav bios_6_scratch &= ~ATOM_S6_CRITICAL_STATE; 2858300373Smav bios_6_scratch |= ATOM_S6_ACC_MODE; 2859300373Smav } 2860300373Smav 2861250079Scarl if (rdev->family >= CHIP_R600) 2862304404Smav WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch); 2863300373Smav else 2864304404Smav WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch); 2865250079Scarl} 2866304404Smav 2867300373Smav/* at some point we may want to break this out into individual functions */ 2868300373Smavvoid 2869300373Smavradeon_atombios_connected_scratch_regs(struct drm_connector *connector, 2870300373Smav struct drm_encoder *encoder, 2871300373Smav bool connected) 2872300373Smav{ 2873300373Smav struct drm_device *dev = connector->dev; 2874300373Smav struct radeon_device *rdev = dev->dev_private; 2875300373Smav struct radeon_connector *radeon_connector = 2876300373Smav to_radeon_connector(connector); 2877300373Smav struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 2878300373Smav uint32_t bios_0_scratch, bios_3_scratch, bios_6_scratch; 2879300373Smav 2880300373Smav if (rdev->family >= CHIP_R600) { 2881300373Smav bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH); 2882300373Smav bios_3_scratch = RREG32(R600_BIOS_3_SCRATCH); 2883300373Smav bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH); 2884300373Smav } else { 2885300373Smav bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH); 2886304404Smav bios_3_scratch = RREG32(RADEON_BIOS_3_SCRATCH); 2887300373Smav bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH); 2888300373Smav } 2889300373Smav 2890300373Smav if ((radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) && 2891300373Smav (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT)) { 2892304404Smav if (connected) { 2893304404Smav DRM_DEBUG_KMS("TV1 connected\n"); 2894300373Smav bios_3_scratch |= ATOM_S3_TV1_ACTIVE; 2895304404Smav bios_6_scratch |= ATOM_S6_ACC_REQ_TV1; 2896300373Smav } else { 2897300373Smav DRM_DEBUG_KMS("TV1 disconnected\n"); 2898300373Smav bios_0_scratch &= ~ATOM_S0_TV1_MASK; 2899300373Smav bios_3_scratch &= ~ATOM_S3_TV1_ACTIVE; 2900304404Smav bios_6_scratch &= ~ATOM_S6_ACC_REQ_TV1; 2901304404Smav } 2902300373Smav } 2903304404Smav if ((radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) && 2904304404Smav (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT)) { 2905300373Smav if (connected) { 2906300373Smav DRM_DEBUG_KMS("CV connected\n"); 2907300373Smav bios_3_scratch |= ATOM_S3_CV_ACTIVE; 2908300373Smav bios_6_scratch |= ATOM_S6_ACC_REQ_CV; 2909300373Smav } else { 2910300373Smav DRM_DEBUG_KMS("CV disconnected\n"); 2911300373Smav bios_0_scratch &= ~ATOM_S0_CV_MASK; 2912300373Smav bios_3_scratch &= ~ATOM_S3_CV_ACTIVE; 2913300373Smav bios_6_scratch &= ~ATOM_S6_ACC_REQ_CV; 2914300373Smav } 2915304404Smav } 2916300373Smav if ((radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) && 2917300373Smav (radeon_connector->devices & ATOM_DEVICE_LCD1_SUPPORT)) { 2918300373Smav if (connected) { 2919300373Smav DRM_DEBUG_KMS("LCD1 connected\n"); 2920300373Smav bios_0_scratch |= ATOM_S0_LCD1; 2921304404Smav bios_3_scratch |= ATOM_S3_LCD1_ACTIVE; 2922304404Smav bios_6_scratch |= ATOM_S6_ACC_REQ_LCD1; 2923300373Smav } else { 2924304404Smav DRM_DEBUG_KMS("LCD1 disconnected\n"); 2925300373Smav bios_0_scratch &= ~ATOM_S0_LCD1; 2926300373Smav bios_3_scratch &= ~ATOM_S3_LCD1_ACTIVE; 2927300373Smav bios_6_scratch &= ~ATOM_S6_ACC_REQ_LCD1; 2928300373Smav } 2929304404Smav } 2930304404Smav if ((radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) && 2931300373Smav (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)) { 2932304404Smav if (connected) { 2933304404Smav DRM_DEBUG_KMS("CRT1 connected\n"); 2934300373Smav bios_0_scratch |= ATOM_S0_CRT1_COLOR; 2935300373Smav bios_3_scratch |= ATOM_S3_CRT1_ACTIVE; 2936300373Smav bios_6_scratch |= ATOM_S6_ACC_REQ_CRT1; 2937300373Smav } else { 2938250079Scarl DRM_DEBUG_KMS("CRT1 disconnected\n"); 2939250079Scarl bios_0_scratch &= ~ATOM_S0_CRT1_MASK; 2940304380Smav bios_3_scratch &= ~ATOM_S3_CRT1_ACTIVE; 2941304404Smav bios_6_scratch &= ~ATOM_S6_ACC_REQ_CRT1; 2942250079Scarl } 2943250079Scarl } 2944304404Smav if ((radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) && 2945300373Smav (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)) { 2946300373Smav if (connected) { 2947304380Smav DRM_DEBUG_KMS("CRT2 connected\n"); 2948304404Smav bios_0_scratch |= ATOM_S0_CRT2_COLOR; 2949300373Smav bios_3_scratch |= ATOM_S3_CRT2_ACTIVE; 2950304380Smav bios_6_scratch |= ATOM_S6_ACC_REQ_CRT2; 2951300373Smav } else { 2952300373Smav DRM_DEBUG_KMS("CRT2 disconnected\n"); 2953304404Smav bios_0_scratch &= ~ATOM_S0_CRT2_MASK; 2954300373Smav bios_3_scratch &= ~ATOM_S3_CRT2_ACTIVE; 2955304404Smav bios_6_scratch &= ~ATOM_S6_ACC_REQ_CRT2; 2956300373Smav } 2957304404Smav } 2958300373Smav if ((radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) && 2959300373Smav (radeon_connector->devices & ATOM_DEVICE_DFP1_SUPPORT)) { 2960300373Smav if (connected) { 2961300373Smav DRM_DEBUG_KMS("DFP1 connected\n"); 2962304380Smav bios_0_scratch |= ATOM_S0_DFP1; 2963304404Smav bios_3_scratch |= ATOM_S3_DFP1_ACTIVE; 2964300373Smav bios_6_scratch |= ATOM_S6_ACC_REQ_DFP1; 2965304380Smav } else { 2966300373Smav DRM_DEBUG_KMS("DFP1 disconnected\n"); 2967304404Smav bios_0_scratch &= ~ATOM_S0_DFP1; 2968300373Smav bios_3_scratch &= ~ATOM_S3_DFP1_ACTIVE; 2969300373Smav bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP1; 2970304404Smav } 2971304404Smav } 2972300373Smav if ((radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) && 2973300373Smav (radeon_connector->devices & ATOM_DEVICE_DFP2_SUPPORT)) { 2974300373Smav if (connected) { 2975304404Smav DRM_DEBUG_KMS("DFP2 connected\n"); 2976300373Smav bios_0_scratch |= ATOM_S0_DFP2; 2977300373Smav bios_3_scratch |= ATOM_S3_DFP2_ACTIVE; 2978300373Smav bios_6_scratch |= ATOM_S6_ACC_REQ_DFP2; 2979300373Smav } else { 2980304404Smav DRM_DEBUG_KMS("DFP2 disconnected\n"); 2981300373Smav bios_0_scratch &= ~ATOM_S0_DFP2; 2982250079Scarl bios_3_scratch &= ~ATOM_S3_DFP2_ACTIVE; 2983250079Scarl bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP2; 2984300373Smav } 2985300373Smav } 2986300373Smav if ((radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) && 2987300373Smav (radeon_connector->devices & ATOM_DEVICE_DFP3_SUPPORT)) { 2988300373Smav if (connected) { 2989250079Scarl DRM_DEBUG_KMS("DFP3 connected\n"); 2990250079Scarl bios_0_scratch |= ATOM_S0_DFP3; 2991304380Smav bios_3_scratch |= ATOM_S3_DFP3_ACTIVE; 2992304404Smav bios_6_scratch |= ATOM_S6_ACC_REQ_DFP3; 2993250079Scarl } else { 2994304380Smav DRM_DEBUG_KMS("DFP3 disconnected\n"); 2995250079Scarl bios_0_scratch &= ~ATOM_S0_DFP3; 2996304380Smav bios_3_scratch &= ~ATOM_S3_DFP3_ACTIVE; 2997301811Sngie bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP3; 2998301811Sngie } 2999301811Sngie } 3000301811Sngie if ((radeon_encoder->devices & ATOM_DEVICE_DFP4_SUPPORT) && 3001301811Sngie (radeon_connector->devices & ATOM_DEVICE_DFP4_SUPPORT)) { 3002301811Sngie if (connected) { 3003304404Smav DRM_DEBUG_KMS("DFP4 connected\n"); 3004301811Sngie bios_0_scratch |= ATOM_S0_DFP4; 3005301811Sngie bios_3_scratch |= ATOM_S3_DFP4_ACTIVE; 3006301811Sngie bios_6_scratch |= ATOM_S6_ACC_REQ_DFP4; 3007301811Sngie } else { 3008301811Sngie DRM_DEBUG_KMS("DFP4 disconnected\n"); 3009301811Sngie bios_0_scratch &= ~ATOM_S0_DFP4; 3010301811Sngie bios_3_scratch &= ~ATOM_S3_DFP4_ACTIVE; 3011301811Sngie bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP4; 3012304380Smav } 3013304404Smav } 3014250079Scarl if ((radeon_encoder->devices & ATOM_DEVICE_DFP5_SUPPORT) && 3015300373Smav (radeon_connector->devices & ATOM_DEVICE_DFP5_SUPPORT)) { 3016250079Scarl if (connected) { 3017300373Smav DRM_DEBUG_KMS("DFP5 connected\n"); 3018300373Smav bios_0_scratch |= ATOM_S0_DFP5; 3019300373Smav bios_3_scratch |= ATOM_S3_DFP5_ACTIVE; 3020304380Smav bios_6_scratch |= ATOM_S6_ACC_REQ_DFP5; 3021304404Smav } else { 3022300373Smav DRM_DEBUG_KMS("DFP5 disconnected\n"); 3023304380Smav bios_0_scratch &= ~ATOM_S0_DFP5; 3024300373Smav bios_3_scratch &= ~ATOM_S3_DFP5_ACTIVE; 3025300373Smav bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP5; 3026300373Smav } 3027304380Smav } 3028300373Smav if ((radeon_encoder->devices & ATOM_DEVICE_DFP6_SUPPORT) && 3029304380Smav (radeon_connector->devices & ATOM_DEVICE_DFP6_SUPPORT)) { 3030300373Smav if (connected) { 3031300373Smav DRM_DEBUG_KMS("DFP6 connected\n"); 3032300373Smav bios_0_scratch |= ATOM_S0_DFP6; 3033300373Smav bios_3_scratch |= ATOM_S3_DFP6_ACTIVE; 3034300373Smav bios_6_scratch |= ATOM_S6_ACC_REQ_DFP6; 3035300373Smav } else { 3036304404Smav DRM_DEBUG_KMS("DFP6 disconnected\n"); 3037300373Smav bios_0_scratch &= ~ATOM_S0_DFP6; 3038250079Scarl bios_3_scratch &= ~ATOM_S3_DFP6_ACTIVE; 3039300373Smav bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP6; 3040300373Smav } 3041300373Smav } 3042304380Smav 3043304380Smav if (rdev->family >= CHIP_R600) { 3044304380Smav WREG32(R600_BIOS_0_SCRATCH, bios_0_scratch); 3045250079Scarl WREG32(R600_BIOS_3_SCRATCH, bios_3_scratch); 3046250079Scarl WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch); 3047304380Smav } else { 3048304404Smav WREG32(RADEON_BIOS_0_SCRATCH, bios_0_scratch); 3049250079Scarl WREG32(RADEON_BIOS_3_SCRATCH, bios_3_scratch); 3050304380Smav WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch); 3051250079Scarl } 3052300373Smav} 3053250079Scarl 3054250079Scarlvoid 3055304380Smavradeon_atombios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc) 3056304404Smav{ 3057300373Smav struct drm_device *dev = encoder->dev; 3058304380Smav struct radeon_device *rdev = dev->dev_private; 3059300373Smav struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 3060304380Smav uint32_t bios_3_scratch; 3061304380Smav 3062304380Smav if (ASIC_IS_DCE4(rdev)) 3063304380Smav return; 3064304404Smav 3065304380Smav if (rdev->family >= CHIP_R600) 3066304380Smav bios_3_scratch = RREG32(R600_BIOS_3_SCRATCH); 3067304380Smav else 3068300373Smav bios_3_scratch = RREG32(RADEON_BIOS_3_SCRATCH); 3069300373Smav 3070304404Smav if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) { 3071300373Smav bios_3_scratch &= ~ATOM_S3_TV1_CRTC_ACTIVE; 3072300373Smav bios_3_scratch |= (crtc << 18); 3073304380Smav } 3074304404Smav if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) { 3075250079Scarl bios_3_scratch &= ~ATOM_S3_CV_CRTC_ACTIVE; 3076304380Smav bios_3_scratch |= (crtc << 24); 3077250079Scarl } 3078300373Smav if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) { 3079304404Smav bios_3_scratch &= ~ATOM_S3_CRT1_CRTC_ACTIVE; 3080300373Smav bios_3_scratch |= (crtc << 16); 3081304404Smav } 3082300373Smav if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) { 3083250079Scarl bios_3_scratch &= ~ATOM_S3_CRT2_CRTC_ACTIVE; 3084250079Scarl bios_3_scratch |= (crtc << 20); 3085255272Scarl } 3086255272Scarl if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) { 3087250079Scarl bios_3_scratch &= ~ATOM_S3_LCD1_CRTC_ACTIVE; 3088255272Scarl bios_3_scratch |= (crtc << 17); 3089300373Smav } 3090300373Smav if (radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) { 3091300373Smav bios_3_scratch &= ~ATOM_S3_DFP1_CRTC_ACTIVE; 3092300373Smav bios_3_scratch |= (crtc << 19); 3093300373Smav } 3094250079Scarl if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) { 3095255268Scarl bios_3_scratch &= ~ATOM_S3_DFP2_CRTC_ACTIVE; 3096304380Smav bios_3_scratch |= (crtc << 23); 3097304380Smav } 3098304404Smav if (radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) { 3099304404Smav bios_3_scratch &= ~ATOM_S3_DFP3_CRTC_ACTIVE; 3100304404Smav bios_3_scratch |= (crtc << 25); 3101304380Smav } 3102304404Smav 3103304404Smav if (rdev->family >= CHIP_R600) 3104304404Smav WREG32(R600_BIOS_3_SCRATCH, bios_3_scratch); 3105304404Smav else 3106304404Smav WREG32(RADEON_BIOS_3_SCRATCH, bios_3_scratch); 3107304404Smav} 3108304404Smav 3109304404Smavvoid 3110304404Smavradeon_atombios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on) 3111304404Smav{ 3112304404Smav struct drm_device *dev = encoder->dev; 3113304404Smav struct radeon_device *rdev = dev->dev_private; 3114304404Smav struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 3115304404Smav uint32_t bios_2_scratch; 3116304404Smav 3117304404Smav if (ASIC_IS_DCE4(rdev)) 3118304404Smav return; 3119304404Smav 3120304404Smav if (rdev->family >= CHIP_R600) 3121304404Smav bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH); 3122304404Smav else 3123304404Smav bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH); 3124304404Smav 3125304404Smav if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) { 3126304404Smav if (on) 3127304380Smav bios_2_scratch &= ~ATOM_S2_TV1_DPMS_STATE; 3128304380Smav else 3129255268Scarl bios_2_scratch |= ATOM_S2_TV1_DPMS_STATE; 3130304380Smav } 3131304380Smav if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) { 3132304380Smav if (on) 3133304380Smav bios_2_scratch &= ~ATOM_S2_CV_DPMS_STATE; 3134304380Smav else 3135 bios_2_scratch |= ATOM_S2_CV_DPMS_STATE; 3136 } 3137 if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) { 3138 if (on) 3139 bios_2_scratch &= ~ATOM_S2_CRT1_DPMS_STATE; 3140 else 3141 bios_2_scratch |= ATOM_S2_CRT1_DPMS_STATE; 3142 } 3143 if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) { 3144 if (on) 3145 bios_2_scratch &= ~ATOM_S2_CRT2_DPMS_STATE; 3146 else 3147 bios_2_scratch |= ATOM_S2_CRT2_DPMS_STATE; 3148 } 3149 if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) { 3150 if (on) 3151 bios_2_scratch &= ~ATOM_S2_LCD1_DPMS_STATE; 3152 else 3153 bios_2_scratch |= ATOM_S2_LCD1_DPMS_STATE; 3154 } 3155 if (radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) { 3156 if (on) 3157 bios_2_scratch &= ~ATOM_S2_DFP1_DPMS_STATE; 3158 else 3159 bios_2_scratch |= ATOM_S2_DFP1_DPMS_STATE; 3160 } 3161 if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) { 3162 if (on) 3163 bios_2_scratch &= ~ATOM_S2_DFP2_DPMS_STATE; 3164 else 3165 bios_2_scratch |= ATOM_S2_DFP2_DPMS_STATE; 3166 } 3167 if (radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) { 3168 if (on) 3169 bios_2_scratch &= ~ATOM_S2_DFP3_DPMS_STATE; 3170 else 3171 bios_2_scratch |= ATOM_S2_DFP3_DPMS_STATE; 3172 } 3173 if (radeon_encoder->devices & ATOM_DEVICE_DFP4_SUPPORT) { 3174 if (on) 3175 bios_2_scratch &= ~ATOM_S2_DFP4_DPMS_STATE; 3176 else 3177 bios_2_scratch |= ATOM_S2_DFP4_DPMS_STATE; 3178 } 3179 if (radeon_encoder->devices & ATOM_DEVICE_DFP5_SUPPORT) { 3180 if (on) 3181 bios_2_scratch &= ~ATOM_S2_DFP5_DPMS_STATE; 3182 else 3183 bios_2_scratch |= ATOM_S2_DFP5_DPMS_STATE; 3184 } 3185 3186 if (rdev->family >= CHIP_R600) 3187 WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch); 3188 else 3189 WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch); 3190} 3191