LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/amdgpu - amdgpu_atombios.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 648 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 31 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2007-8 Advanced Micro Devices, Inc.
       3             :  * Copyright 2008 Red Hat Inc.
       4             :  *
       5             :  * Permission is hereby granted, free of charge, to any person obtaining a
       6             :  * copy of this software and associated documentation files (the "Software"),
       7             :  * to deal in the Software without restriction, including without limitation
       8             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       9             :  * and/or sell copies of the Software, and to permit persons to whom the
      10             :  * Software is furnished to do so, subject to the following conditions:
      11             :  *
      12             :  * The above copyright notice and this permission notice shall be included in
      13             :  * all copies or substantial portions of the Software.
      14             :  *
      15             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      18             :  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
      19             :  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      20             :  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
      21             :  * OTHER DEALINGS IN THE SOFTWARE.
      22             :  *
      23             :  * Authors: Dave Airlie
      24             :  *          Alex Deucher
      25             :  */
      26             : 
      27             : #include <drm/amdgpu_drm.h>
      28             : #include "amdgpu.h"
      29             : #include "amdgpu_atombios.h"
      30             : #include "amdgpu_atomfirmware.h"
      31             : #include "amdgpu_i2c.h"
      32             : #include "amdgpu_display.h"
      33             : 
      34             : #include "atom.h"
      35             : #include "atom-bits.h"
      36             : #include "atombios_encoders.h"
      37             : #include "bif/bif_4_1_d.h"
      38             : 
      39             : static void amdgpu_atombios_lookup_i2c_gpio_quirks(struct amdgpu_device *adev,
      40             :                                           ATOM_GPIO_I2C_ASSIGMENT *gpio,
      41             :                                           u8 index)
      42             : {
      43             : 
      44             : }
      45             : 
      46           0 : static struct amdgpu_i2c_bus_rec amdgpu_atombios_get_bus_rec_for_i2c_gpio(ATOM_GPIO_I2C_ASSIGMENT *gpio)
      47             : {
      48             :         struct amdgpu_i2c_bus_rec i2c;
      49             : 
      50           0 :         memset(&i2c, 0, sizeof(struct amdgpu_i2c_bus_rec));
      51             : 
      52           0 :         i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex);
      53           0 :         i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex);
      54           0 :         i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex);
      55           0 :         i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex);
      56           0 :         i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex);
      57           0 :         i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex);
      58           0 :         i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex);
      59           0 :         i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex);
      60           0 :         i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
      61           0 :         i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
      62           0 :         i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
      63           0 :         i2c.en_data_mask = (1 << gpio->ucDataEnShift);
      64           0 :         i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
      65           0 :         i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
      66           0 :         i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
      67           0 :         i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
      68             : 
      69           0 :         if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
      70           0 :                 i2c.hw_capable = true;
      71             :         else
      72           0 :                 i2c.hw_capable = false;
      73             : 
      74           0 :         if (gpio->sucI2cId.ucAccess == 0xa0)
      75           0 :                 i2c.mm_i2c = true;
      76             :         else
      77           0 :                 i2c.mm_i2c = false;
      78             : 
      79           0 :         i2c.i2c_id = gpio->sucI2cId.ucAccess;
      80             : 
      81           0 :         if (i2c.mask_clk_reg)
      82           0 :                 i2c.valid = true;
      83             :         else
      84           0 :                 i2c.valid = false;
      85             : 
      86           0 :         return i2c;
      87             : }
      88             : 
      89           0 : struct amdgpu_i2c_bus_rec amdgpu_atombios_lookup_i2c_gpio(struct amdgpu_device *adev,
      90             :                                                           uint8_t id)
      91             : {
      92           0 :         struct atom_context *ctx = adev->mode_info.atom_context;
      93             :         ATOM_GPIO_I2C_ASSIGMENT *gpio;
      94             :         struct amdgpu_i2c_bus_rec i2c;
      95           0 :         int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info);
      96             :         struct _ATOM_GPIO_I2C_INFO *i2c_info;
      97             :         uint16_t data_offset, size;
      98             :         int i, num_indices;
      99             : 
     100           0 :         memset(&i2c, 0, sizeof(struct amdgpu_i2c_bus_rec));
     101           0 :         i2c.valid = false;
     102             : 
     103           0 :         if (amdgpu_atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
     104           0 :                 i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
     105             : 
     106           0 :                 num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
     107             :                         sizeof(ATOM_GPIO_I2C_ASSIGMENT);
     108             : 
     109           0 :                 gpio = &i2c_info->asGPIO_Info[0];
     110           0 :                 for (i = 0; i < num_indices; i++) {
     111             : 
     112           0 :                         amdgpu_atombios_lookup_i2c_gpio_quirks(adev, gpio, i);
     113             : 
     114           0 :                         if (gpio->sucI2cId.ucAccess == id) {
     115           0 :                                 i2c = amdgpu_atombios_get_bus_rec_for_i2c_gpio(gpio);
     116           0 :                                 break;
     117             :                         }
     118           0 :                         gpio = (ATOM_GPIO_I2C_ASSIGMENT *)
     119             :                                 ((u8 *)gpio + sizeof(ATOM_GPIO_I2C_ASSIGMENT));
     120             :                 }
     121             :         }
     122             : 
     123           0 :         return i2c;
     124             : }
     125             : 
     126           0 : void amdgpu_atombios_i2c_init(struct amdgpu_device *adev)
     127             : {
     128           0 :         struct atom_context *ctx = adev->mode_info.atom_context;
     129             :         ATOM_GPIO_I2C_ASSIGMENT *gpio;
     130             :         struct amdgpu_i2c_bus_rec i2c;
     131           0 :         int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info);
     132             :         struct _ATOM_GPIO_I2C_INFO *i2c_info;
     133             :         uint16_t data_offset, size;
     134             :         int i, num_indices;
     135             :         char stmp[32];
     136             : 
     137           0 :         if (amdgpu_atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
     138           0 :                 i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
     139             : 
     140           0 :                 num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
     141             :                         sizeof(ATOM_GPIO_I2C_ASSIGMENT);
     142             : 
     143           0 :                 gpio = &i2c_info->asGPIO_Info[0];
     144           0 :                 for (i = 0; i < num_indices; i++) {
     145           0 :                         amdgpu_atombios_lookup_i2c_gpio_quirks(adev, gpio, i);
     146             : 
     147           0 :                         i2c = amdgpu_atombios_get_bus_rec_for_i2c_gpio(gpio);
     148             : 
     149           0 :                         if (i2c.valid) {
     150           0 :                                 sprintf(stmp, "0x%x", i2c.i2c_id);
     151           0 :                                 adev->i2c_bus[i] = amdgpu_i2c_create(adev_to_drm(adev), &i2c, stmp);
     152             :                         }
     153           0 :                         gpio = (ATOM_GPIO_I2C_ASSIGMENT *)
     154             :                                 ((u8 *)gpio + sizeof(ATOM_GPIO_I2C_ASSIGMENT));
     155             :                 }
     156             :         }
     157           0 : }
     158             : 
     159             : struct amdgpu_gpio_rec
     160           0 : amdgpu_atombios_lookup_gpio(struct amdgpu_device *adev,
     161             :                             u8 id)
     162             : {
     163           0 :         struct atom_context *ctx = adev->mode_info.atom_context;
     164             :         struct amdgpu_gpio_rec gpio;
     165           0 :         int index = GetIndexIntoMasterTable(DATA, GPIO_Pin_LUT);
     166             :         struct _ATOM_GPIO_PIN_LUT *gpio_info;
     167             :         ATOM_GPIO_PIN_ASSIGNMENT *pin;
     168             :         u16 data_offset, size;
     169             :         int i, num_indices;
     170             : 
     171           0 :         memset(&gpio, 0, sizeof(struct amdgpu_gpio_rec));
     172           0 :         gpio.valid = false;
     173             : 
     174           0 :         if (amdgpu_atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
     175           0 :                 gpio_info = (struct _ATOM_GPIO_PIN_LUT *)(ctx->bios + data_offset);
     176             : 
     177           0 :                 num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
     178             :                         sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
     179             : 
     180           0 :                 pin = gpio_info->asGPIO_Pin;
     181           0 :                 for (i = 0; i < num_indices; i++) {
     182           0 :                         if (id == pin->ucGPIO_ID) {
     183           0 :                                 gpio.id = pin->ucGPIO_ID;
     184           0 :                                 gpio.reg = le16_to_cpu(pin->usGpioPin_AIndex);
     185           0 :                                 gpio.shift = pin->ucGpioPinBitShift;
     186           0 :                                 gpio.mask = (1 << pin->ucGpioPinBitShift);
     187           0 :                                 gpio.valid = true;
     188           0 :                                 break;
     189             :                         }
     190           0 :                         pin = (ATOM_GPIO_PIN_ASSIGNMENT *)
     191             :                                 ((u8 *)pin + sizeof(ATOM_GPIO_PIN_ASSIGNMENT));
     192             :                 }
     193             :         }
     194             : 
     195           0 :         return gpio;
     196             : }
     197             : 
     198             : static struct amdgpu_hpd
     199           0 : amdgpu_atombios_get_hpd_info_from_gpio(struct amdgpu_device *adev,
     200             :                                        struct amdgpu_gpio_rec *gpio)
     201             : {
     202             :         struct amdgpu_hpd hpd;
     203             :         u32 reg;
     204             : 
     205           0 :         memset(&hpd, 0, sizeof(struct amdgpu_hpd));
     206             : 
     207           0 :         reg = amdgpu_display_hpd_get_gpio_reg(adev);
     208             : 
     209           0 :         hpd.gpio = *gpio;
     210           0 :         if (gpio->reg == reg) {
     211           0 :                 switch(gpio->mask) {
     212             :                 case (1 << 0):
     213           0 :                         hpd.hpd = AMDGPU_HPD_1;
     214           0 :                         break;
     215             :                 case (1 << 8):
     216           0 :                         hpd.hpd = AMDGPU_HPD_2;
     217           0 :                         break;
     218             :                 case (1 << 16):
     219           0 :                         hpd.hpd = AMDGPU_HPD_3;
     220           0 :                         break;
     221             :                 case (1 << 24):
     222           0 :                         hpd.hpd = AMDGPU_HPD_4;
     223           0 :                         break;
     224             :                 case (1 << 26):
     225           0 :                         hpd.hpd = AMDGPU_HPD_5;
     226           0 :                         break;
     227             :                 case (1 << 28):
     228           0 :                         hpd.hpd = AMDGPU_HPD_6;
     229           0 :                         break;
     230             :                 default:
     231           0 :                         hpd.hpd = AMDGPU_HPD_NONE;
     232           0 :                         break;
     233             :                 }
     234             :         } else
     235           0 :                 hpd.hpd = AMDGPU_HPD_NONE;
     236           0 :         return hpd;
     237             : }
     238             : 
     239             : static const int object_connector_convert[] = {
     240             :         DRM_MODE_CONNECTOR_Unknown,
     241             :         DRM_MODE_CONNECTOR_DVII,
     242             :         DRM_MODE_CONNECTOR_DVII,
     243             :         DRM_MODE_CONNECTOR_DVID,
     244             :         DRM_MODE_CONNECTOR_DVID,
     245             :         DRM_MODE_CONNECTOR_VGA,
     246             :         DRM_MODE_CONNECTOR_Composite,
     247             :         DRM_MODE_CONNECTOR_SVIDEO,
     248             :         DRM_MODE_CONNECTOR_Unknown,
     249             :         DRM_MODE_CONNECTOR_Unknown,
     250             :         DRM_MODE_CONNECTOR_9PinDIN,
     251             :         DRM_MODE_CONNECTOR_Unknown,
     252             :         DRM_MODE_CONNECTOR_HDMIA,
     253             :         DRM_MODE_CONNECTOR_HDMIB,
     254             :         DRM_MODE_CONNECTOR_LVDS,
     255             :         DRM_MODE_CONNECTOR_9PinDIN,
     256             :         DRM_MODE_CONNECTOR_Unknown,
     257             :         DRM_MODE_CONNECTOR_Unknown,
     258             :         DRM_MODE_CONNECTOR_Unknown,
     259             :         DRM_MODE_CONNECTOR_DisplayPort,
     260             :         DRM_MODE_CONNECTOR_eDP,
     261             :         DRM_MODE_CONNECTOR_Unknown
     262             : };
     263             : 
     264           0 : bool amdgpu_atombios_has_dce_engine_info(struct amdgpu_device *adev)
     265             : {
     266           0 :         struct amdgpu_mode_info *mode_info = &adev->mode_info;
     267           0 :         struct atom_context *ctx = mode_info->atom_context;
     268           0 :         int index = GetIndexIntoMasterTable(DATA, Object_Header);
     269             :         u16 size, data_offset;
     270             :         u8 frev, crev;
     271             :         ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj;
     272             :         ATOM_OBJECT_HEADER *obj_header;
     273             : 
     274           0 :         if (!amdgpu_atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset))
     275             :                 return false;
     276             : 
     277           0 :         if (crev < 2)
     278             :                 return false;
     279             : 
     280           0 :         obj_header = (ATOM_OBJECT_HEADER *) (ctx->bios + data_offset);
     281           0 :         path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *)
     282           0 :             (ctx->bios + data_offset +
     283           0 :              le16_to_cpu(obj_header->usDisplayPathTableOffset));
     284             : 
     285           0 :         if (path_obj->ucNumOfDispPath)
     286             :                 return true;
     287             :         else
     288           0 :                 return false;
     289             : }
     290             : 
     291           0 : bool amdgpu_atombios_get_connector_info_from_object_table(struct amdgpu_device *adev)
     292             : {
     293           0 :         struct amdgpu_mode_info *mode_info = &adev->mode_info;
     294           0 :         struct atom_context *ctx = mode_info->atom_context;
     295           0 :         int index = GetIndexIntoMasterTable(DATA, Object_Header);
     296             :         u16 size, data_offset;
     297             :         u8 frev, crev;
     298             :         ATOM_CONNECTOR_OBJECT_TABLE *con_obj;
     299             :         ATOM_ENCODER_OBJECT_TABLE *enc_obj;
     300             :         ATOM_OBJECT_TABLE *router_obj;
     301             :         ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj;
     302             :         ATOM_OBJECT_HEADER *obj_header;
     303             :         int i, j, k, path_size, device_support;
     304             :         int connector_type;
     305             :         u16 conn_id, connector_object_id;
     306             :         struct amdgpu_i2c_bus_rec ddc_bus;
     307             :         struct amdgpu_router router;
     308             :         struct amdgpu_gpio_rec gpio;
     309             :         struct amdgpu_hpd hpd;
     310             : 
     311           0 :         if (!amdgpu_atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset))
     312             :                 return false;
     313             : 
     314           0 :         if (crev < 2)
     315             :                 return false;
     316             : 
     317           0 :         obj_header = (ATOM_OBJECT_HEADER *) (ctx->bios + data_offset);
     318           0 :         path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *)
     319           0 :             (ctx->bios + data_offset +
     320           0 :              le16_to_cpu(obj_header->usDisplayPathTableOffset));
     321           0 :         con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *)
     322           0 :             (ctx->bios + data_offset +
     323           0 :              le16_to_cpu(obj_header->usConnectorObjectTableOffset));
     324           0 :         enc_obj = (ATOM_ENCODER_OBJECT_TABLE *)
     325           0 :             (ctx->bios + data_offset +
     326           0 :              le16_to_cpu(obj_header->usEncoderObjectTableOffset));
     327           0 :         router_obj = (ATOM_OBJECT_TABLE *)
     328           0 :                 (ctx->bios + data_offset +
     329           0 :                  le16_to_cpu(obj_header->usRouterObjectTableOffset));
     330           0 :         device_support = le16_to_cpu(obj_header->usDeviceSupport);
     331             : 
     332           0 :         path_size = 0;
     333           0 :         for (i = 0; i < path_obj->ucNumOfDispPath; i++) {
     334           0 :                 uint8_t *addr = (uint8_t *) path_obj->asDispPath;
     335             :                 ATOM_DISPLAY_OBJECT_PATH *path;
     336           0 :                 addr += path_size;
     337           0 :                 path = (ATOM_DISPLAY_OBJECT_PATH *) addr;
     338           0 :                 path_size += le16_to_cpu(path->usSize);
     339             : 
     340           0 :                 if (device_support & le16_to_cpu(path->usDeviceTag)) {
     341           0 :                         uint8_t con_obj_id =
     342           0 :                             (le16_to_cpu(path->usConnObjectId) & OBJECT_ID_MASK)
     343             :                             >> OBJECT_ID_SHIFT;
     344             : 
     345             :                         /* Skip TV/CV support */
     346           0 :                         if ((le16_to_cpu(path->usDeviceTag) ==
     347           0 :                              ATOM_DEVICE_TV1_SUPPORT) ||
     348             :                             (le16_to_cpu(path->usDeviceTag) ==
     349             :                              ATOM_DEVICE_CV_SUPPORT))
     350           0 :                                 continue;
     351             : 
     352           0 :                         if (con_obj_id >= ARRAY_SIZE(object_connector_convert)) {
     353           0 :                                 DRM_ERROR("invalid con_obj_id %d for device tag 0x%04x\n",
     354             :                                           con_obj_id, le16_to_cpu(path->usDeviceTag));
     355           0 :                                 continue;
     356             :                         }
     357             : 
     358           0 :                         connector_type =
     359           0 :                                 object_connector_convert[con_obj_id];
     360           0 :                         connector_object_id = con_obj_id;
     361             : 
     362           0 :                         if (connector_type == DRM_MODE_CONNECTOR_Unknown)
     363           0 :                                 continue;
     364             : 
     365           0 :                         router.ddc_valid = false;
     366           0 :                         router.cd_valid = false;
     367           0 :                         for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); j++) {
     368           0 :                                 uint8_t grph_obj_type =
     369           0 :                                     (le16_to_cpu(path->usGraphicObjIds[j]) &
     370           0 :                                      OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
     371             : 
     372           0 :                                 if (grph_obj_type == GRAPH_OBJECT_TYPE_ENCODER) {
     373           0 :                                         for (k = 0; k < enc_obj->ucNumberOfObjects; k++) {
     374           0 :                                                 u16 encoder_obj = le16_to_cpu(enc_obj->asObjects[k].usObjectID);
     375           0 :                                                 if (le16_to_cpu(path->usGraphicObjIds[j]) == encoder_obj) {
     376           0 :                                                         ATOM_COMMON_RECORD_HEADER *record = (ATOM_COMMON_RECORD_HEADER *)
     377           0 :                                                                 (ctx->bios + data_offset +
     378           0 :                                                                  le16_to_cpu(enc_obj->asObjects[k].usRecordOffset));
     379             :                                                         ATOM_ENCODER_CAP_RECORD *cap_record;
     380           0 :                                                         u16 caps = 0;
     381             : 
     382           0 :                                                         while (record->ucRecordSize > 0 &&
     383           0 :                                                                record->ucRecordType > 0 &&
     384             :                                                                record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
     385           0 :                                                                 switch (record->ucRecordType) {
     386             :                                                                 case ATOM_ENCODER_CAP_RECORD_TYPE:
     387           0 :                                                                         cap_record =(ATOM_ENCODER_CAP_RECORD *)
     388             :                                                                                 record;
     389           0 :                                                                         caps = le16_to_cpu(cap_record->usEncoderCap);
     390           0 :                                                                         break;
     391             :                                                                 }
     392           0 :                                                                 record = (ATOM_COMMON_RECORD_HEADER *)
     393           0 :                                                                         ((char *)record + record->ucRecordSize);
     394             :                                                         }
     395           0 :                                                         amdgpu_display_add_encoder(adev, encoder_obj,
     396             :                                                                                     le16_to_cpu(path->usDeviceTag),
     397             :                                                                                     caps);
     398             :                                                 }
     399             :                                         }
     400           0 :                                 } else if (grph_obj_type == GRAPH_OBJECT_TYPE_ROUTER) {
     401           0 :                                         for (k = 0; k < router_obj->ucNumberOfObjects; k++) {
     402           0 :                                                 u16 router_obj_id = le16_to_cpu(router_obj->asObjects[k].usObjectID);
     403           0 :                                                 if (le16_to_cpu(path->usGraphicObjIds[j]) == router_obj_id) {
     404           0 :                                                         ATOM_COMMON_RECORD_HEADER *record = (ATOM_COMMON_RECORD_HEADER *)
     405           0 :                                                                 (ctx->bios + data_offset +
     406           0 :                                                                  le16_to_cpu(router_obj->asObjects[k].usRecordOffset));
     407             :                                                         ATOM_I2C_RECORD *i2c_record;
     408             :                                                         ATOM_I2C_ID_CONFIG_ACCESS *i2c_config;
     409             :                                                         ATOM_ROUTER_DDC_PATH_SELECT_RECORD *ddc_path;
     410             :                                                         ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD *cd_path;
     411           0 :                                                         ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *router_src_dst_table =
     412             :                                                                 (ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *)
     413           0 :                                                                 (ctx->bios + data_offset +
     414           0 :                                                                  le16_to_cpu(router_obj->asObjects[k].usSrcDstTableOffset));
     415           0 :                                                         u8 *num_dst_objs = (u8 *)
     416           0 :                                                                 ((u8 *)router_src_dst_table + 1 +
     417           0 :                                                                  (router_src_dst_table->ucNumberOfSrc * 2));
     418           0 :                                                         u16 *dst_objs = (u16 *)(num_dst_objs + 1);
     419             :                                                         int enum_id;
     420             : 
     421           0 :                                                         router.router_id = router_obj_id;
     422           0 :                                                         for (enum_id = 0; enum_id < (*num_dst_objs); enum_id++) {
     423           0 :                                                                 if (le16_to_cpu(path->usConnObjectId) ==
     424           0 :                                                                     le16_to_cpu(dst_objs[enum_id]))
     425             :                                                                         break;
     426             :                                                         }
     427             : 
     428           0 :                                                         while (record->ucRecordSize > 0 &&
     429           0 :                                                                record->ucRecordType > 0 &&
     430             :                                                                record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
     431           0 :                                                                 switch (record->ucRecordType) {
     432             :                                                                 case ATOM_I2C_RECORD_TYPE:
     433           0 :                                                                         i2c_record =
     434             :                                                                                 (ATOM_I2C_RECORD *)
     435             :                                                                                 record;
     436           0 :                                                                         i2c_config =
     437             :                                                                                 (ATOM_I2C_ID_CONFIG_ACCESS *)
     438             :                                                                                 &i2c_record->sucI2cId;
     439           0 :                                                                         router.i2c_info =
     440           0 :                                                                                 amdgpu_atombios_lookup_i2c_gpio(adev,
     441           0 :                                                                                                        i2c_config->
     442             :                                                                                                        ucAccess);
     443           0 :                                                                         router.i2c_addr = i2c_record->ucI2CAddr >> 1;
     444           0 :                                                                         break;
     445             :                                                                 case ATOM_ROUTER_DDC_PATH_SELECT_RECORD_TYPE:
     446           0 :                                                                         ddc_path = (ATOM_ROUTER_DDC_PATH_SELECT_RECORD *)
     447             :                                                                                 record;
     448           0 :                                                                         router.ddc_valid = true;
     449           0 :                                                                         router.ddc_mux_type = ddc_path->ucMuxType;
     450           0 :                                                                         router.ddc_mux_control_pin = ddc_path->ucMuxControlPin;
     451           0 :                                                                         router.ddc_mux_state = ddc_path->ucMuxState[enum_id];
     452           0 :                                                                         break;
     453             :                                                                 case ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD_TYPE:
     454           0 :                                                                         cd_path = (ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD *)
     455             :                                                                                 record;
     456           0 :                                                                         router.cd_valid = true;
     457           0 :                                                                         router.cd_mux_type = cd_path->ucMuxType;
     458           0 :                                                                         router.cd_mux_control_pin = cd_path->ucMuxControlPin;
     459           0 :                                                                         router.cd_mux_state = cd_path->ucMuxState[enum_id];
     460           0 :                                                                         break;
     461             :                                                                 }
     462           0 :                                                                 record = (ATOM_COMMON_RECORD_HEADER *)
     463           0 :                                                                         ((char *)record + record->ucRecordSize);
     464             :                                                         }
     465             :                                                 }
     466             :                                         }
     467             :                                 }
     468             :                         }
     469             : 
     470             :                         /* look up gpio for ddc, hpd */
     471           0 :                         ddc_bus.valid = false;
     472           0 :                         hpd.hpd = AMDGPU_HPD_NONE;
     473           0 :                         if ((le16_to_cpu(path->usDeviceTag) &
     474             :                              (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) == 0) {
     475           0 :                                 for (j = 0; j < con_obj->ucNumberOfObjects; j++) {
     476           0 :                                         if (le16_to_cpu(path->usConnObjectId) ==
     477           0 :                                             le16_to_cpu(con_obj->asObjects[j].
     478             :                                                         usObjectID)) {
     479             :                                                 ATOM_COMMON_RECORD_HEADER
     480           0 :                                                     *record =
     481             :                                                     (ATOM_COMMON_RECORD_HEADER
     482             :                                                      *)
     483           0 :                                                     (ctx->bios + data_offset +
     484           0 :                                                      le16_to_cpu(con_obj->
     485             :                                                                  asObjects[j].
     486             :                                                                  usRecordOffset));
     487             :                                                 ATOM_I2C_RECORD *i2c_record;
     488             :                                                 ATOM_HPD_INT_RECORD *hpd_record;
     489             :                                                 ATOM_I2C_ID_CONFIG_ACCESS *i2c_config;
     490             : 
     491           0 :                                                 while (record->ucRecordSize > 0 &&
     492           0 :                                                        record->ucRecordType > 0 &&
     493             :                                                        record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
     494           0 :                                                         switch (record->ucRecordType) {
     495             :                                                         case ATOM_I2C_RECORD_TYPE:
     496           0 :                                                                 i2c_record =
     497             :                                                                     (ATOM_I2C_RECORD *)
     498             :                                                                         record;
     499           0 :                                                                 i2c_config =
     500             :                                                                         (ATOM_I2C_ID_CONFIG_ACCESS *)
     501             :                                                                         &i2c_record->sucI2cId;
     502           0 :                                                                 ddc_bus = amdgpu_atombios_lookup_i2c_gpio(adev,
     503           0 :                                                                                                  i2c_config->
     504             :                                                                                                  ucAccess);
     505           0 :                                                                 break;
     506             :                                                         case ATOM_HPD_INT_RECORD_TYPE:
     507           0 :                                                                 hpd_record =
     508             :                                                                         (ATOM_HPD_INT_RECORD *)
     509             :                                                                         record;
     510           0 :                                                                 gpio = amdgpu_atombios_lookup_gpio(adev,
     511           0 :                                                                                           hpd_record->ucHPDIntGPIOID);
     512           0 :                                                                 hpd = amdgpu_atombios_get_hpd_info_from_gpio(adev, &gpio);
     513           0 :                                                                 hpd.plugged_state = hpd_record->ucPlugged_PinState;
     514           0 :                                                                 break;
     515             :                                                         }
     516           0 :                                                         record =
     517             :                                                             (ATOM_COMMON_RECORD_HEADER
     518             :                                                              *) ((char *)record
     519             :                                                                  +
     520           0 :                                                                  record->
     521             :                                                                  ucRecordSize);
     522             :                                                 }
     523             :                                                 break;
     524             :                                         }
     525             :                                 }
     526             :                         }
     527             : 
     528             :                         /* needed for aux chan transactions */
     529           0 :                         ddc_bus.hpd = hpd.hpd;
     530             : 
     531           0 :                         conn_id = le16_to_cpu(path->usConnObjectId);
     532             : 
     533           0 :                         amdgpu_display_add_connector(adev,
     534             :                                                       conn_id,
     535             :                                                       le16_to_cpu(path->usDeviceTag),
     536             :                                                       connector_type, &ddc_bus,
     537             :                                                       connector_object_id,
     538             :                                                       &hpd,
     539             :                                                       &router);
     540             : 
     541             :                 }
     542             :         }
     543             : 
     544           0 :         amdgpu_link_encoder_connector(adev_to_drm(adev));
     545             : 
     546           0 :         return true;
     547             : }
     548             : 
     549             : union firmware_info {
     550             :         ATOM_FIRMWARE_INFO info;
     551             :         ATOM_FIRMWARE_INFO_V1_2 info_12;
     552             :         ATOM_FIRMWARE_INFO_V1_3 info_13;
     553             :         ATOM_FIRMWARE_INFO_V1_4 info_14;
     554             :         ATOM_FIRMWARE_INFO_V2_1 info_21;
     555             :         ATOM_FIRMWARE_INFO_V2_2 info_22;
     556             : };
     557             : 
     558           0 : int amdgpu_atombios_get_clock_info(struct amdgpu_device *adev)
     559             : {
     560           0 :         struct amdgpu_mode_info *mode_info = &adev->mode_info;
     561           0 :         int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
     562             :         uint8_t frev, crev;
     563             :         uint16_t data_offset;
     564           0 :         int ret = -EINVAL;
     565             : 
     566           0 :         if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
     567             :                                    &frev, &crev, &data_offset)) {
     568             :                 int i;
     569           0 :                 struct amdgpu_pll *ppll = &adev->clock.ppll[0];
     570           0 :                 struct amdgpu_pll *spll = &adev->clock.spll;
     571           0 :                 struct amdgpu_pll *mpll = &adev->clock.mpll;
     572           0 :                 union firmware_info *firmware_info =
     573           0 :                         (union firmware_info *)(mode_info->atom_context->bios +
     574             :                                                 data_offset);
     575             :                 /* pixel clocks */
     576           0 :                 ppll->reference_freq =
     577           0 :                     le16_to_cpu(firmware_info->info.usReferenceClock);
     578           0 :                 ppll->reference_div = 0;
     579             : 
     580           0 :                 ppll->pll_out_min =
     581           0 :                         le32_to_cpu(firmware_info->info_12.ulMinPixelClockPLL_Output);
     582           0 :                 ppll->pll_out_max =
     583           0 :                     le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output);
     584             : 
     585           0 :                 ppll->lcd_pll_out_min =
     586           0 :                         le16_to_cpu(firmware_info->info_14.usLcdMinPixelClockPLL_Output) * 100;
     587           0 :                 if (ppll->lcd_pll_out_min == 0)
     588           0 :                         ppll->lcd_pll_out_min = ppll->pll_out_min;
     589           0 :                 ppll->lcd_pll_out_max =
     590           0 :                         le16_to_cpu(firmware_info->info_14.usLcdMaxPixelClockPLL_Output) * 100;
     591           0 :                 if (ppll->lcd_pll_out_max == 0)
     592           0 :                         ppll->lcd_pll_out_max = ppll->pll_out_max;
     593             : 
     594           0 :                 if (ppll->pll_out_min == 0)
     595           0 :                         ppll->pll_out_min = 64800;
     596             : 
     597           0 :                 ppll->pll_in_min =
     598           0 :                     le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Input);
     599           0 :                 ppll->pll_in_max =
     600           0 :                     le16_to_cpu(firmware_info->info.usMaxPixelClockPLL_Input);
     601             : 
     602           0 :                 ppll->min_post_div = 2;
     603           0 :                 ppll->max_post_div = 0x7f;
     604           0 :                 ppll->min_frac_feedback_div = 0;
     605           0 :                 ppll->max_frac_feedback_div = 9;
     606           0 :                 ppll->min_ref_div = 2;
     607           0 :                 ppll->max_ref_div = 0x3ff;
     608           0 :                 ppll->min_feedback_div = 4;
     609           0 :                 ppll->max_feedback_div = 0xfff;
     610           0 :                 ppll->best_vco = 0;
     611             : 
     612           0 :                 for (i = 1; i < AMDGPU_MAX_PPLL; i++)
     613           0 :                         adev->clock.ppll[i] = *ppll;
     614             : 
     615             :                 /* system clock */
     616           0 :                 spll->reference_freq =
     617           0 :                         le16_to_cpu(firmware_info->info_21.usCoreReferenceClock);
     618           0 :                 spll->reference_div = 0;
     619             : 
     620           0 :                 spll->pll_out_min =
     621           0 :                     le16_to_cpu(firmware_info->info.usMinEngineClockPLL_Output);
     622           0 :                 spll->pll_out_max =
     623           0 :                     le32_to_cpu(firmware_info->info.ulMaxEngineClockPLL_Output);
     624             : 
     625             :                 /* ??? */
     626           0 :                 if (spll->pll_out_min == 0)
     627           0 :                         spll->pll_out_min = 64800;
     628             : 
     629           0 :                 spll->pll_in_min =
     630           0 :                     le16_to_cpu(firmware_info->info.usMinEngineClockPLL_Input);
     631           0 :                 spll->pll_in_max =
     632           0 :                     le16_to_cpu(firmware_info->info.usMaxEngineClockPLL_Input);
     633             : 
     634           0 :                 spll->min_post_div = 1;
     635           0 :                 spll->max_post_div = 1;
     636           0 :                 spll->min_ref_div = 2;
     637           0 :                 spll->max_ref_div = 0xff;
     638           0 :                 spll->min_feedback_div = 4;
     639           0 :                 spll->max_feedback_div = 0xff;
     640           0 :                 spll->best_vco = 0;
     641             : 
     642             :                 /* memory clock */
     643           0 :                 mpll->reference_freq =
     644           0 :                         le16_to_cpu(firmware_info->info_21.usMemoryReferenceClock);
     645           0 :                 mpll->reference_div = 0;
     646             : 
     647           0 :                 mpll->pll_out_min =
     648           0 :                     le16_to_cpu(firmware_info->info.usMinMemoryClockPLL_Output);
     649           0 :                 mpll->pll_out_max =
     650           0 :                     le32_to_cpu(firmware_info->info.ulMaxMemoryClockPLL_Output);
     651             : 
     652             :                 /* ??? */
     653           0 :                 if (mpll->pll_out_min == 0)
     654           0 :                         mpll->pll_out_min = 64800;
     655             : 
     656           0 :                 mpll->pll_in_min =
     657           0 :                     le16_to_cpu(firmware_info->info.usMinMemoryClockPLL_Input);
     658           0 :                 mpll->pll_in_max =
     659           0 :                     le16_to_cpu(firmware_info->info.usMaxMemoryClockPLL_Input);
     660             : 
     661           0 :                 adev->clock.default_sclk =
     662           0 :                     le32_to_cpu(firmware_info->info.ulDefaultEngineClock);
     663           0 :                 adev->clock.default_mclk =
     664           0 :                     le32_to_cpu(firmware_info->info.ulDefaultMemoryClock);
     665             : 
     666           0 :                 mpll->min_post_div = 1;
     667           0 :                 mpll->max_post_div = 1;
     668           0 :                 mpll->min_ref_div = 2;
     669           0 :                 mpll->max_ref_div = 0xff;
     670           0 :                 mpll->min_feedback_div = 4;
     671           0 :                 mpll->max_feedback_div = 0xff;
     672           0 :                 mpll->best_vco = 0;
     673             : 
     674             :                 /* disp clock */
     675           0 :                 adev->clock.default_dispclk =
     676           0 :                         le32_to_cpu(firmware_info->info_21.ulDefaultDispEngineClkFreq);
     677             :                 /* set a reasonable default for DP */
     678           0 :                 if (adev->clock.default_dispclk < 53900) {
     679           0 :                         DRM_DEBUG("Changing default dispclk from %dMhz to 600Mhz\n",
     680             :                                   adev->clock.default_dispclk / 100);
     681           0 :                         adev->clock.default_dispclk = 60000;
     682           0 :                 } else if (adev->clock.default_dispclk <= 60000) {
     683           0 :                         DRM_DEBUG("Changing default dispclk from %dMhz to 625Mhz\n",
     684             :                                   adev->clock.default_dispclk / 100);
     685           0 :                         adev->clock.default_dispclk = 62500;
     686             :                 }
     687           0 :                 adev->clock.dp_extclk =
     688           0 :                         le16_to_cpu(firmware_info->info_21.usUniphyDPModeExtClkFreq);
     689           0 :                 adev->clock.current_dispclk = adev->clock.default_dispclk;
     690             : 
     691           0 :                 adev->clock.max_pixel_clock = le16_to_cpu(firmware_info->info.usMaxPixelClock);
     692           0 :                 if (adev->clock.max_pixel_clock == 0)
     693           0 :                         adev->clock.max_pixel_clock = 40000;
     694             : 
     695             :                 /* not technically a clock, but... */
     696           0 :                 adev->mode_info.firmware_flags =
     697           0 :                         le16_to_cpu(firmware_info->info.usFirmwareCapability.susAccess);
     698             : 
     699           0 :                 ret = 0;
     700             :         }
     701             : 
     702           0 :         adev->pm.current_sclk = adev->clock.default_sclk;
     703           0 :         adev->pm.current_mclk = adev->clock.default_mclk;
     704             : 
     705           0 :         return ret;
     706             : }
     707             : 
     708             : union gfx_info {
     709             :         ATOM_GFX_INFO_V2_1 info;
     710             : };
     711             : 
     712           0 : int amdgpu_atombios_get_gfx_info(struct amdgpu_device *adev)
     713             : {
     714           0 :         struct amdgpu_mode_info *mode_info = &adev->mode_info;
     715           0 :         int index = GetIndexIntoMasterTable(DATA, GFX_Info);
     716             :         uint8_t frev, crev;
     717             :         uint16_t data_offset;
     718           0 :         int ret = -EINVAL;
     719             : 
     720           0 :         if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
     721             :                                    &frev, &crev, &data_offset)) {
     722           0 :                 union gfx_info *gfx_info = (union gfx_info *)
     723           0 :                         (mode_info->atom_context->bios + data_offset);
     724             : 
     725           0 :                 adev->gfx.config.max_shader_engines = gfx_info->info.max_shader_engines;
     726           0 :                 adev->gfx.config.max_tile_pipes = gfx_info->info.max_tile_pipes;
     727           0 :                 adev->gfx.config.max_cu_per_sh = gfx_info->info.max_cu_per_sh;
     728           0 :                 adev->gfx.config.max_sh_per_se = gfx_info->info.max_sh_per_se;
     729           0 :                 adev->gfx.config.max_backends_per_se = gfx_info->info.max_backends_per_se;
     730           0 :                 adev->gfx.config.max_texture_channel_caches =
     731           0 :                         gfx_info->info.max_texture_channel_caches;
     732             : 
     733           0 :                 ret = 0;
     734             :         }
     735           0 :         return ret;
     736             : }
     737             : 
     738             : union igp_info {
     739             :         struct _ATOM_INTEGRATED_SYSTEM_INFO info;
     740             :         struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
     741             :         struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6;
     742             :         struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7;
     743             :         struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_8 info_8;
     744             :         struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_9 info_9;
     745             : };
     746             : 
     747             : /*
     748             :  * Return vram width from integrated system info table, if available,
     749             :  * or 0 if not.
     750             :  */
     751           0 : int amdgpu_atombios_get_vram_width(struct amdgpu_device *adev)
     752             : {
     753           0 :         struct amdgpu_mode_info *mode_info = &adev->mode_info;
     754           0 :         int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
     755             :         u16 data_offset, size;
     756             :         union igp_info *igp_info;
     757             :         u8 frev, crev;
     758             : 
     759             :         /* get any igp specific overrides */
     760           0 :         if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, &size,
     761             :                                    &frev, &crev, &data_offset)) {
     762           0 :                 igp_info = (union igp_info *)
     763           0 :                         (mode_info->atom_context->bios + data_offset);
     764           0 :                 switch (crev) {
     765             :                 case 8:
     766             :                 case 9:
     767           0 :                         return igp_info->info_8.ucUMAChannelNumber * 64;
     768             :                 default:
     769             :                         return 0;
     770             :                 }
     771             :         }
     772             : 
     773             :         return 0;
     774             : }
     775             : 
     776           0 : static void amdgpu_atombios_get_igp_ss_overrides(struct amdgpu_device *adev,
     777             :                                                  struct amdgpu_atom_ss *ss,
     778             :                                                  int id)
     779             : {
     780           0 :         struct amdgpu_mode_info *mode_info = &adev->mode_info;
     781           0 :         int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
     782             :         u16 data_offset, size;
     783             :         union igp_info *igp_info;
     784             :         u8 frev, crev;
     785           0 :         u16 percentage = 0, rate = 0;
     786             : 
     787             :         /* get any igp specific overrides */
     788           0 :         if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, &size,
     789             :                                    &frev, &crev, &data_offset)) {
     790           0 :                 igp_info = (union igp_info *)
     791           0 :                         (mode_info->atom_context->bios + data_offset);
     792           0 :                 switch (crev) {
     793             :                 case 6:
     794           0 :                         switch (id) {
     795             :                         case ASIC_INTERNAL_SS_ON_TMDS:
     796           0 :                                 percentage = le16_to_cpu(igp_info->info_6.usDVISSPercentage);
     797           0 :                                 rate = le16_to_cpu(igp_info->info_6.usDVISSpreadRateIn10Hz);
     798           0 :                                 break;
     799             :                         case ASIC_INTERNAL_SS_ON_HDMI:
     800           0 :                                 percentage = le16_to_cpu(igp_info->info_6.usHDMISSPercentage);
     801           0 :                                 rate = le16_to_cpu(igp_info->info_6.usHDMISSpreadRateIn10Hz);
     802           0 :                                 break;
     803             :                         case ASIC_INTERNAL_SS_ON_LVDS:
     804           0 :                                 percentage = le16_to_cpu(igp_info->info_6.usLvdsSSPercentage);
     805           0 :                                 rate = le16_to_cpu(igp_info->info_6.usLvdsSSpreadRateIn10Hz);
     806           0 :                                 break;
     807             :                         }
     808             :                         break;
     809             :                 case 7:
     810           0 :                         switch (id) {
     811             :                         case ASIC_INTERNAL_SS_ON_TMDS:
     812           0 :                                 percentage = le16_to_cpu(igp_info->info_7.usDVISSPercentage);
     813           0 :                                 rate = le16_to_cpu(igp_info->info_7.usDVISSpreadRateIn10Hz);
     814           0 :                                 break;
     815             :                         case ASIC_INTERNAL_SS_ON_HDMI:
     816           0 :                                 percentage = le16_to_cpu(igp_info->info_7.usHDMISSPercentage);
     817           0 :                                 rate = le16_to_cpu(igp_info->info_7.usHDMISSpreadRateIn10Hz);
     818           0 :                                 break;
     819             :                         case ASIC_INTERNAL_SS_ON_LVDS:
     820           0 :                                 percentage = le16_to_cpu(igp_info->info_7.usLvdsSSPercentage);
     821           0 :                                 rate = le16_to_cpu(igp_info->info_7.usLvdsSSpreadRateIn10Hz);
     822           0 :                                 break;
     823             :                         }
     824             :                         break;
     825             :                 case 8:
     826           0 :                         switch (id) {
     827             :                         case ASIC_INTERNAL_SS_ON_TMDS:
     828           0 :                                 percentage = le16_to_cpu(igp_info->info_8.usDVISSPercentage);
     829           0 :                                 rate = le16_to_cpu(igp_info->info_8.usDVISSpreadRateIn10Hz);
     830           0 :                                 break;
     831             :                         case ASIC_INTERNAL_SS_ON_HDMI:
     832           0 :                                 percentage = le16_to_cpu(igp_info->info_8.usHDMISSPercentage);
     833           0 :                                 rate = le16_to_cpu(igp_info->info_8.usHDMISSpreadRateIn10Hz);
     834           0 :                                 break;
     835             :                         case ASIC_INTERNAL_SS_ON_LVDS:
     836           0 :                                 percentage = le16_to_cpu(igp_info->info_8.usLvdsSSPercentage);
     837           0 :                                 rate = le16_to_cpu(igp_info->info_8.usLvdsSSpreadRateIn10Hz);
     838           0 :                                 break;
     839             :                         }
     840             :                         break;
     841             :                 case 9:
     842           0 :                         switch (id) {
     843             :                         case ASIC_INTERNAL_SS_ON_TMDS:
     844           0 :                                 percentage = le16_to_cpu(igp_info->info_9.usDVISSPercentage);
     845           0 :                                 rate = le16_to_cpu(igp_info->info_9.usDVISSpreadRateIn10Hz);
     846           0 :                                 break;
     847             :                         case ASIC_INTERNAL_SS_ON_HDMI:
     848           0 :                                 percentage = le16_to_cpu(igp_info->info_9.usHDMISSPercentage);
     849           0 :                                 rate = le16_to_cpu(igp_info->info_9.usHDMISSpreadRateIn10Hz);
     850           0 :                                 break;
     851             :                         case ASIC_INTERNAL_SS_ON_LVDS:
     852           0 :                                 percentage = le16_to_cpu(igp_info->info_9.usLvdsSSPercentage);
     853           0 :                                 rate = le16_to_cpu(igp_info->info_9.usLvdsSSpreadRateIn10Hz);
     854           0 :                                 break;
     855             :                         }
     856             :                         break;
     857             :                 default:
     858           0 :                         DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);
     859           0 :                         break;
     860             :                 }
     861           0 :                 if (percentage)
     862           0 :                         ss->percentage = percentage;
     863           0 :                 if (rate)
     864           0 :                         ss->rate = rate;
     865             :         }
     866           0 : }
     867             : 
     868             : union asic_ss_info {
     869             :         struct _ATOM_ASIC_INTERNAL_SS_INFO info;
     870             :         struct _ATOM_ASIC_INTERNAL_SS_INFO_V2 info_2;
     871             :         struct _ATOM_ASIC_INTERNAL_SS_INFO_V3 info_3;
     872             : };
     873             : 
     874             : union asic_ss_assignment {
     875             :         struct _ATOM_ASIC_SS_ASSIGNMENT v1;
     876             :         struct _ATOM_ASIC_SS_ASSIGNMENT_V2 v2;
     877             :         struct _ATOM_ASIC_SS_ASSIGNMENT_V3 v3;
     878             : };
     879             : 
     880           0 : bool amdgpu_atombios_get_asic_ss_info(struct amdgpu_device *adev,
     881             :                                       struct amdgpu_atom_ss *ss,
     882             :                                       int id, u32 clock)
     883             : {
     884           0 :         struct amdgpu_mode_info *mode_info = &adev->mode_info;
     885           0 :         int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info);
     886             :         uint16_t data_offset, size;
     887             :         union asic_ss_info *ss_info;
     888             :         union asic_ss_assignment *ss_assign;
     889             :         uint8_t frev, crev;
     890             :         int i, num_indices;
     891             : 
     892           0 :         if (id == ASIC_INTERNAL_MEMORY_SS) {
     893           0 :                 if (!(adev->mode_info.firmware_flags & ATOM_BIOS_INFO_MEMORY_CLOCK_SS_SUPPORT))
     894             :                         return false;
     895             :         }
     896           0 :         if (id == ASIC_INTERNAL_ENGINE_SS) {
     897           0 :                 if (!(adev->mode_info.firmware_flags & ATOM_BIOS_INFO_ENGINE_CLOCK_SS_SUPPORT))
     898             :                         return false;
     899             :         }
     900             : 
     901           0 :         memset(ss, 0, sizeof(struct amdgpu_atom_ss));
     902           0 :         if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, &size,
     903             :                                    &frev, &crev, &data_offset)) {
     904             : 
     905           0 :                 ss_info =
     906           0 :                         (union asic_ss_info *)(mode_info->atom_context->bios + data_offset);
     907             : 
     908           0 :                 switch (frev) {
     909             :                 case 1:
     910           0 :                         num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
     911             :                                 sizeof(ATOM_ASIC_SS_ASSIGNMENT);
     912             : 
     913           0 :                         ss_assign = (union asic_ss_assignment *)((u8 *)&ss_info->info.asSpreadSpectrum[0]);
     914           0 :                         for (i = 0; i < num_indices; i++) {
     915           0 :                                 if ((ss_assign->v1.ucClockIndication == id) &&
     916           0 :                                     (clock <= le32_to_cpu(ss_assign->v1.ulTargetClockRange))) {
     917           0 :                                         ss->percentage =
     918           0 :                                                 le16_to_cpu(ss_assign->v1.usSpreadSpectrumPercentage);
     919           0 :                                         ss->type = ss_assign->v1.ucSpreadSpectrumMode;
     920           0 :                                         ss->rate = le16_to_cpu(ss_assign->v1.usSpreadRateInKhz);
     921           0 :                                         ss->percentage_divider = 100;
     922           0 :                                         return true;
     923             :                                 }
     924           0 :                                 ss_assign = (union asic_ss_assignment *)
     925             :                                         ((u8 *)ss_assign + sizeof(ATOM_ASIC_SS_ASSIGNMENT));
     926             :                         }
     927             :                         break;
     928             :                 case 2:
     929           0 :                         num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
     930             :                                 sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
     931           0 :                         ss_assign = (union asic_ss_assignment *)((u8 *)&ss_info->info_2.asSpreadSpectrum[0]);
     932           0 :                         for (i = 0; i < num_indices; i++) {
     933           0 :                                 if ((ss_assign->v2.ucClockIndication == id) &&
     934           0 :                                     (clock <= le32_to_cpu(ss_assign->v2.ulTargetClockRange))) {
     935           0 :                                         ss->percentage =
     936           0 :                                                 le16_to_cpu(ss_assign->v2.usSpreadSpectrumPercentage);
     937           0 :                                         ss->type = ss_assign->v2.ucSpreadSpectrumMode;
     938           0 :                                         ss->rate = le16_to_cpu(ss_assign->v2.usSpreadRateIn10Hz);
     939           0 :                                         ss->percentage_divider = 100;
     940           0 :                                         if ((crev == 2) &&
     941           0 :                                             ((id == ASIC_INTERNAL_ENGINE_SS) ||
     942             :                                              (id == ASIC_INTERNAL_MEMORY_SS)))
     943           0 :                                                 ss->rate /= 100;
     944             :                                         return true;
     945             :                                 }
     946           0 :                                 ss_assign = (union asic_ss_assignment *)
     947             :                                         ((u8 *)ss_assign + sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2));
     948             :                         }
     949             :                         break;
     950             :                 case 3:
     951           0 :                         num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
     952             :                                 sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
     953           0 :                         ss_assign = (union asic_ss_assignment *)((u8 *)&ss_info->info_3.asSpreadSpectrum[0]);
     954           0 :                         for (i = 0; i < num_indices; i++) {
     955           0 :                                 if ((ss_assign->v3.ucClockIndication == id) &&
     956           0 :                                     (clock <= le32_to_cpu(ss_assign->v3.ulTargetClockRange))) {
     957           0 :                                         ss->percentage =
     958           0 :                                                 le16_to_cpu(ss_assign->v3.usSpreadSpectrumPercentage);
     959           0 :                                         ss->type = ss_assign->v3.ucSpreadSpectrumMode;
     960           0 :                                         ss->rate = le16_to_cpu(ss_assign->v3.usSpreadRateIn10Hz);
     961           0 :                                         if (ss_assign->v3.ucSpreadSpectrumMode &
     962             :                                             SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK)
     963           0 :                                                 ss->percentage_divider = 1000;
     964             :                                         else
     965           0 :                                                 ss->percentage_divider = 100;
     966           0 :                                         if ((id == ASIC_INTERNAL_ENGINE_SS) ||
     967             :                                             (id == ASIC_INTERNAL_MEMORY_SS))
     968           0 :                                                 ss->rate /= 100;
     969           0 :                                         if (adev->flags & AMD_IS_APU)
     970           0 :                                                 amdgpu_atombios_get_igp_ss_overrides(adev, ss, id);
     971             :                                         return true;
     972             :                                 }
     973           0 :                                 ss_assign = (union asic_ss_assignment *)
     974             :                                         ((u8 *)ss_assign + sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3));
     975             :                         }
     976             :                         break;
     977             :                 default:
     978           0 :                         DRM_ERROR("Unsupported ASIC_InternalSS_Info table: %d %d\n", frev, crev);
     979           0 :                         break;
     980             :                 }
     981             : 
     982             :         }
     983             :         return false;
     984             : }
     985             : 
     986             : union get_clock_dividers {
     987             :         struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS v1;
     988             :         struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V2 v2;
     989             :         struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3 v3;
     990             :         struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 v4;
     991             :         struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5 v5;
     992             :         struct _COMPUTE_GPU_CLOCK_INPUT_PARAMETERS_V1_6 v6_in;
     993             :         struct _COMPUTE_GPU_CLOCK_OUTPUT_PARAMETERS_V1_6 v6_out;
     994             : };
     995             : 
     996           0 : int amdgpu_atombios_get_clock_dividers(struct amdgpu_device *adev,
     997             :                                        u8 clock_type,
     998             :                                        u32 clock,
     999             :                                        bool strobe_mode,
    1000             :                                        struct atom_clock_dividers *dividers)
    1001             : {
    1002             :         union get_clock_dividers args;
    1003           0 :         int index = GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL);
    1004             :         u8 frev, crev;
    1005             : 
    1006           0 :         memset(&args, 0, sizeof(args));
    1007           0 :         memset(dividers, 0, sizeof(struct atom_clock_dividers));
    1008             : 
    1009           0 :         if (!amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context, index, &frev, &crev))
    1010             :                 return -EINVAL;
    1011             : 
    1012           0 :         switch (crev) {
    1013             :         case 2:
    1014             :         case 3:
    1015             :         case 5:
    1016             :                 /* r6xx, r7xx, evergreen, ni, si.
    1017             :                  * TODO: add support for asic_type <= CHIP_RV770*/
    1018           0 :                 if (clock_type == COMPUTE_ENGINE_PLL_PARAM) {
    1019           0 :                         args.v3.ulClockParams = cpu_to_le32((clock_type << 24) | clock);
    1020             : 
    1021           0 :                         amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
    1022             : 
    1023           0 :                         dividers->post_div = args.v3.ucPostDiv;
    1024           0 :                         dividers->enable_post_div = (args.v3.ucCntlFlag &
    1025           0 :                                                      ATOM_PLL_CNTL_FLAG_PLL_POST_DIV_EN) ? true : false;
    1026           0 :                         dividers->enable_dithen = (args.v3.ucCntlFlag &
    1027           0 :                                                    ATOM_PLL_CNTL_FLAG_FRACTION_DISABLE) ? false : true;
    1028           0 :                         dividers->whole_fb_div = le16_to_cpu(args.v3.ulFbDiv.usFbDiv);
    1029           0 :                         dividers->frac_fb_div = le16_to_cpu(args.v3.ulFbDiv.usFbDivFrac);
    1030           0 :                         dividers->ref_div = args.v3.ucRefDiv;
    1031           0 :                         dividers->vco_mode = (args.v3.ucCntlFlag &
    1032           0 :                                               ATOM_PLL_CNTL_FLAG_MPLL_VCO_MODE) ? 1 : 0;
    1033             :                 } else {
    1034             :                         /* for SI we use ComputeMemoryClockParam for memory plls */
    1035             :                         if (adev->asic_type >= CHIP_TAHITI)
    1036             :                                 return -EINVAL;
    1037             :                         args.v5.ulClockParams = cpu_to_le32((clock_type << 24) | clock);
    1038             :                         if (strobe_mode)
    1039             :                                 args.v5.ucInputFlag = ATOM_PLL_INPUT_FLAG_PLL_STROBE_MODE_EN;
    1040             : 
    1041             :                         amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
    1042             : 
    1043             :                         dividers->post_div = args.v5.ucPostDiv;
    1044             :                         dividers->enable_post_div = (args.v5.ucCntlFlag &
    1045             :                                                      ATOM_PLL_CNTL_FLAG_PLL_POST_DIV_EN) ? true : false;
    1046             :                         dividers->enable_dithen = (args.v5.ucCntlFlag &
    1047             :                                                    ATOM_PLL_CNTL_FLAG_FRACTION_DISABLE) ? false : true;
    1048             :                         dividers->whole_fb_div = le16_to_cpu(args.v5.ulFbDiv.usFbDiv);
    1049             :                         dividers->frac_fb_div = le16_to_cpu(args.v5.ulFbDiv.usFbDivFrac);
    1050             :                         dividers->ref_div = args.v5.ucRefDiv;
    1051             :                         dividers->vco_mode = (args.v5.ucCntlFlag &
    1052             :                                               ATOM_PLL_CNTL_FLAG_MPLL_VCO_MODE) ? 1 : 0;
    1053             :                 }
    1054           0 :                 break;
    1055             :         case 4:
    1056             :                 /* fusion */
    1057           0 :                 args.v4.ulClock = cpu_to_le32(clock);   /* 10 khz */
    1058             : 
    1059           0 :                 amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
    1060             : 
    1061           0 :                 dividers->post_divider = dividers->post_div = args.v4.ucPostDiv;
    1062           0 :                 dividers->real_clock = le32_to_cpu(args.v4.ulClock);
    1063           0 :                 break;
    1064             :         case 6:
    1065             :                 /* CI */
    1066             :                 /* COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, COMPUTE_GPUCLK_INPUT_FLAG_SCLK */
    1067           0 :                 args.v6_in.ulClock.ulComputeClockFlag = clock_type;
    1068           0 :                 args.v6_in.ulClock.ulClockFreq = cpu_to_le32(clock);    /* 10 khz */
    1069             : 
    1070           0 :                 amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
    1071             : 
    1072           0 :                 dividers->whole_fb_div = le16_to_cpu(args.v6_out.ulFbDiv.usFbDiv);
    1073           0 :                 dividers->frac_fb_div = le16_to_cpu(args.v6_out.ulFbDiv.usFbDivFrac);
    1074           0 :                 dividers->ref_div = args.v6_out.ucPllRefDiv;
    1075           0 :                 dividers->post_div = args.v6_out.ucPllPostDiv;
    1076           0 :                 dividers->flags = args.v6_out.ucPllCntlFlag;
    1077           0 :                 dividers->real_clock = le32_to_cpu(args.v6_out.ulClock.ulClock);
    1078           0 :                 dividers->post_divider = args.v6_out.ulClock.ucPostDiv;
    1079           0 :                 break;
    1080             :         default:
    1081             :                 return -EINVAL;
    1082             :         }
    1083             :         return 0;
    1084             : }
    1085             : 
    1086             : #ifdef CONFIG_DRM_AMDGPU_SI
    1087             : int amdgpu_atombios_get_memory_pll_dividers(struct amdgpu_device *adev,
    1088             :                                             u32 clock,
    1089             :                                             bool strobe_mode,
    1090             :                                             struct atom_mpll_param *mpll_param)
    1091             : {
    1092             :         COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_1 args;
    1093             :         int index = GetIndexIntoMasterTable(COMMAND, ComputeMemoryClockParam);
    1094             :         u8 frev, crev;
    1095             : 
    1096             :         memset(&args, 0, sizeof(args));
    1097             :         memset(mpll_param, 0, sizeof(struct atom_mpll_param));
    1098             : 
    1099             :         if (!amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context, index, &frev, &crev))
    1100             :                 return -EINVAL;
    1101             : 
    1102             :         switch (frev) {
    1103             :         case 2:
    1104             :                 switch (crev) {
    1105             :                 case 1:
    1106             :                         /* SI */
    1107             :                         args.ulClock = cpu_to_le32(clock);      /* 10 khz */
    1108             :                         args.ucInputFlag = 0;
    1109             :                         if (strobe_mode)
    1110             :                                 args.ucInputFlag |= MPLL_INPUT_FLAG_STROBE_MODE_EN;
    1111             : 
    1112             :                         amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
    1113             : 
    1114             :                         mpll_param->clkfrac = le16_to_cpu(args.ulFbDiv.usFbDivFrac);
    1115             :                         mpll_param->clkf = le16_to_cpu(args.ulFbDiv.usFbDiv);
    1116             :                         mpll_param->post_div = args.ucPostDiv;
    1117             :                         mpll_param->dll_speed = args.ucDllSpeed;
    1118             :                         mpll_param->bwcntl = args.ucBWCntl;
    1119             :                         mpll_param->vco_mode =
    1120             :                                 (args.ucPllCntlFlag & MPLL_CNTL_FLAG_VCO_MODE_MASK);
    1121             :                         mpll_param->yclk_sel =
    1122             :                                 (args.ucPllCntlFlag & MPLL_CNTL_FLAG_BYPASS_DQ_PLL) ? 1 : 0;
    1123             :                         mpll_param->qdr =
    1124             :                                 (args.ucPllCntlFlag & MPLL_CNTL_FLAG_QDR_ENABLE) ? 1 : 0;
    1125             :                         mpll_param->half_rate =
    1126             :                                 (args.ucPllCntlFlag & MPLL_CNTL_FLAG_AD_HALF_RATE) ? 1 : 0;
    1127             :                         break;
    1128             :                 default:
    1129             :                         return -EINVAL;
    1130             :                 }
    1131             :                 break;
    1132             :         default:
    1133             :                 return -EINVAL;
    1134             :         }
    1135             :         return 0;
    1136             : }
    1137             : 
    1138             : void amdgpu_atombios_set_engine_dram_timings(struct amdgpu_device *adev,
    1139             :                                              u32 eng_clock, u32 mem_clock)
    1140             : {
    1141             :         SET_ENGINE_CLOCK_PS_ALLOCATION args;
    1142             :         int index = GetIndexIntoMasterTable(COMMAND, DynamicMemorySettings);
    1143             :         u32 tmp;
    1144             : 
    1145             :         memset(&args, 0, sizeof(args));
    1146             : 
    1147             :         tmp = eng_clock & SET_CLOCK_FREQ_MASK;
    1148             :         tmp |= (COMPUTE_ENGINE_PLL_PARAM << 24);
    1149             : 
    1150             :         args.ulTargetEngineClock = cpu_to_le32(tmp);
    1151             :         if (mem_clock)
    1152             :                 args.sReserved.ulClock = cpu_to_le32(mem_clock & SET_CLOCK_FREQ_MASK);
    1153             : 
    1154             :         amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
    1155             : }
    1156             : 
    1157             : void amdgpu_atombios_get_default_voltages(struct amdgpu_device *adev,
    1158             :                                           u16 *vddc, u16 *vddci, u16 *mvdd)
    1159             : {
    1160             :         struct amdgpu_mode_info *mode_info = &adev->mode_info;
    1161             :         int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
    1162             :         u8 frev, crev;
    1163             :         u16 data_offset;
    1164             :         union firmware_info *firmware_info;
    1165             : 
    1166             :         *vddc = 0;
    1167             :         *vddci = 0;
    1168             :         *mvdd = 0;
    1169             : 
    1170             :         if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
    1171             :                                    &frev, &crev, &data_offset)) {
    1172             :                 firmware_info =
    1173             :                         (union firmware_info *)(mode_info->atom_context->bios +
    1174             :                                                 data_offset);
    1175             :                 *vddc = le16_to_cpu(firmware_info->info_14.usBootUpVDDCVoltage);
    1176             :                 if ((frev == 2) && (crev >= 2)) {
    1177             :                         *vddci = le16_to_cpu(firmware_info->info_22.usBootUpVDDCIVoltage);
    1178             :                         *mvdd = le16_to_cpu(firmware_info->info_22.usBootUpMVDDCVoltage);
    1179             :                 }
    1180             :         }
    1181             : }
    1182             : 
    1183             : union set_voltage {
    1184             :         struct _SET_VOLTAGE_PS_ALLOCATION alloc;
    1185             :         struct _SET_VOLTAGE_PARAMETERS v1;
    1186             :         struct _SET_VOLTAGE_PARAMETERS_V2 v2;
    1187             :         struct _SET_VOLTAGE_PARAMETERS_V1_3 v3;
    1188             : };
    1189             : 
    1190             : int amdgpu_atombios_get_max_vddc(struct amdgpu_device *adev, u8 voltage_type,
    1191             :                              u16 voltage_id, u16 *voltage)
    1192             : {
    1193             :         union set_voltage args;
    1194             :         int index = GetIndexIntoMasterTable(COMMAND, SetVoltage);
    1195             :         u8 frev, crev;
    1196             : 
    1197             :         if (!amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context, index, &frev, &crev))
    1198             :                 return -EINVAL;
    1199             : 
    1200             :         switch (crev) {
    1201             :         case 1:
    1202             :                 return -EINVAL;
    1203             :         case 2:
    1204             :                 args.v2.ucVoltageType = SET_VOLTAGE_GET_MAX_VOLTAGE;
    1205             :                 args.v2.ucVoltageMode = 0;
    1206             :                 args.v2.usVoltageLevel = 0;
    1207             : 
    1208             :                 amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
    1209             : 
    1210             :                 *voltage = le16_to_cpu(args.v2.usVoltageLevel);
    1211             :                 break;
    1212             :         case 3:
    1213             :                 args.v3.ucVoltageType = voltage_type;
    1214             :                 args.v3.ucVoltageMode = ATOM_GET_VOLTAGE_LEVEL;
    1215             :                 args.v3.usVoltageLevel = cpu_to_le16(voltage_id);
    1216             : 
    1217             :                 amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
    1218             : 
    1219             :                 *voltage = le16_to_cpu(args.v3.usVoltageLevel);
    1220             :                 break;
    1221             :         default:
    1222             :                 DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
    1223             :                 return -EINVAL;
    1224             :         }
    1225             : 
    1226             :         return 0;
    1227             : }
    1228             : 
    1229             : int amdgpu_atombios_get_leakage_vddc_based_on_leakage_idx(struct amdgpu_device *adev,
    1230             :                                                       u16 *voltage,
    1231             :                                                       u16 leakage_idx)
    1232             : {
    1233             :         return amdgpu_atombios_get_max_vddc(adev, VOLTAGE_TYPE_VDDC, leakage_idx, voltage);
    1234             : }
    1235             : 
    1236             : union voltage_object_info {
    1237             :         struct _ATOM_VOLTAGE_OBJECT_INFO v1;
    1238             :         struct _ATOM_VOLTAGE_OBJECT_INFO_V2 v2;
    1239             :         struct _ATOM_VOLTAGE_OBJECT_INFO_V3_1 v3;
    1240             : };
    1241             : 
    1242             : union voltage_object {
    1243             :         struct _ATOM_VOLTAGE_OBJECT v1;
    1244             :         struct _ATOM_VOLTAGE_OBJECT_V2 v2;
    1245             :         union _ATOM_VOLTAGE_OBJECT_V3 v3;
    1246             : };
    1247             : 
    1248             : 
    1249             : static ATOM_VOLTAGE_OBJECT_V3 *amdgpu_atombios_lookup_voltage_object_v3(ATOM_VOLTAGE_OBJECT_INFO_V3_1 *v3,
    1250             :                                                                         u8 voltage_type, u8 voltage_mode)
    1251             : {
    1252             :         u32 size = le16_to_cpu(v3->sHeader.usStructureSize);
    1253             :         u32 offset = offsetof(ATOM_VOLTAGE_OBJECT_INFO_V3_1, asVoltageObj[0]);
    1254             :         u8 *start = (u8 *)v3;
    1255             : 
    1256             :         while (offset < size) {
    1257             :                 ATOM_VOLTAGE_OBJECT_V3 *vo = (ATOM_VOLTAGE_OBJECT_V3 *)(start + offset);
    1258             :                 if ((vo->asGpioVoltageObj.sHeader.ucVoltageType == voltage_type) &&
    1259             :                     (vo->asGpioVoltageObj.sHeader.ucVoltageMode == voltage_mode))
    1260             :                         return vo;
    1261             :                 offset += le16_to_cpu(vo->asGpioVoltageObj.sHeader.usSize);
    1262             :         }
    1263             :         return NULL;
    1264             : }
    1265             : 
    1266             : int amdgpu_atombios_get_svi2_info(struct amdgpu_device *adev,
    1267             :                               u8 voltage_type,
    1268             :                               u8 *svd_gpio_id, u8 *svc_gpio_id)
    1269             : {
    1270             :         int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo);
    1271             :         u8 frev, crev;
    1272             :         u16 data_offset, size;
    1273             :         union voltage_object_info *voltage_info;
    1274             :         union voltage_object *voltage_object = NULL;
    1275             : 
    1276             :         if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context, index, &size,
    1277             :                                    &frev, &crev, &data_offset)) {
    1278             :                 voltage_info = (union voltage_object_info *)
    1279             :                         (adev->mode_info.atom_context->bios + data_offset);
    1280             : 
    1281             :                 switch (frev) {
    1282             :                 case 3:
    1283             :                         switch (crev) {
    1284             :                         case 1:
    1285             :                                 voltage_object = (union voltage_object *)
    1286             :                                         amdgpu_atombios_lookup_voltage_object_v3(&voltage_info->v3,
    1287             :                                                                       voltage_type,
    1288             :                                                                       VOLTAGE_OBJ_SVID2);
    1289             :                                 if (voltage_object) {
    1290             :                                         *svd_gpio_id = voltage_object->v3.asSVID2Obj.ucSVDGpioId;
    1291             :                                         *svc_gpio_id = voltage_object->v3.asSVID2Obj.ucSVCGpioId;
    1292             :                                 } else {
    1293             :                                         return -EINVAL;
    1294             :                                 }
    1295             :                                 break;
    1296             :                         default:
    1297             :                                 DRM_ERROR("unknown voltage object table\n");
    1298             :                                 return -EINVAL;
    1299             :                         }
    1300             :                         break;
    1301             :                 default:
    1302             :                         DRM_ERROR("unknown voltage object table\n");
    1303             :                         return -EINVAL;
    1304             :                 }
    1305             : 
    1306             :         }
    1307             :         return 0;
    1308             : }
    1309             : 
    1310             : bool
    1311             : amdgpu_atombios_is_voltage_gpio(struct amdgpu_device *adev,
    1312             :                                 u8 voltage_type, u8 voltage_mode)
    1313             : {
    1314             :         int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo);
    1315             :         u8 frev, crev;
    1316             :         u16 data_offset, size;
    1317             :         union voltage_object_info *voltage_info;
    1318             : 
    1319             :         if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context, index, &size,
    1320             :                                    &frev, &crev, &data_offset)) {
    1321             :                 voltage_info = (union voltage_object_info *)
    1322             :                         (adev->mode_info.atom_context->bios + data_offset);
    1323             : 
    1324             :                 switch (frev) {
    1325             :                 case 3:
    1326             :                         switch (crev) {
    1327             :                         case 1:
    1328             :                                 if (amdgpu_atombios_lookup_voltage_object_v3(&voltage_info->v3,
    1329             :                                                                   voltage_type, voltage_mode))
    1330             :                                         return true;
    1331             :                                 break;
    1332             :                         default:
    1333             :                                 DRM_ERROR("unknown voltage object table\n");
    1334             :                                 return false;
    1335             :                         }
    1336             :                         break;
    1337             :                 default:
    1338             :                         DRM_ERROR("unknown voltage object table\n");
    1339             :                         return false;
    1340             :                 }
    1341             : 
    1342             :         }
    1343             :         return false;
    1344             : }
    1345             : 
    1346             : int amdgpu_atombios_get_voltage_table(struct amdgpu_device *adev,
    1347             :                                       u8 voltage_type, u8 voltage_mode,
    1348             :                                       struct atom_voltage_table *voltage_table)
    1349             : {
    1350             :         int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo);
    1351             :         u8 frev, crev;
    1352             :         u16 data_offset, size;
    1353             :         int i;
    1354             :         union voltage_object_info *voltage_info;
    1355             :         union voltage_object *voltage_object = NULL;
    1356             : 
    1357             :         if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context, index, &size,
    1358             :                                    &frev, &crev, &data_offset)) {
    1359             :                 voltage_info = (union voltage_object_info *)
    1360             :                         (adev->mode_info.atom_context->bios + data_offset);
    1361             : 
    1362             :                 switch (frev) {
    1363             :                 case 3:
    1364             :                         switch (crev) {
    1365             :                         case 1:
    1366             :                                 voltage_object = (union voltage_object *)
    1367             :                                         amdgpu_atombios_lookup_voltage_object_v3(&voltage_info->v3,
    1368             :                                                                       voltage_type, voltage_mode);
    1369             :                                 if (voltage_object) {
    1370             :                                         ATOM_GPIO_VOLTAGE_OBJECT_V3 *gpio =
    1371             :                                                 &voltage_object->v3.asGpioVoltageObj;
    1372             :                                         VOLTAGE_LUT_ENTRY_V2 *lut;
    1373             :                                         if (gpio->ucGpioEntryNum > MAX_VOLTAGE_ENTRIES)
    1374             :                                                 return -EINVAL;
    1375             :                                         lut = &gpio->asVolGpioLut[0];
    1376             :                                         for (i = 0; i < gpio->ucGpioEntryNum; i++) {
    1377             :                                                 voltage_table->entries[i].value =
    1378             :                                                         le16_to_cpu(lut->usVoltageValue);
    1379             :                                                 voltage_table->entries[i].smio_low =
    1380             :                                                         le32_to_cpu(lut->ulVoltageId);
    1381             :                                                 lut = (VOLTAGE_LUT_ENTRY_V2 *)
    1382             :                                                         ((u8 *)lut + sizeof(VOLTAGE_LUT_ENTRY_V2));
    1383             :                                         }
    1384             :                                         voltage_table->mask_low = le32_to_cpu(gpio->ulGpioMaskVal);
    1385             :                                         voltage_table->count = gpio->ucGpioEntryNum;
    1386             :                                         voltage_table->phase_delay = gpio->ucPhaseDelay;
    1387             :                                         return 0;
    1388             :                                 }
    1389             :                                 break;
    1390             :                         default:
    1391             :                                 DRM_ERROR("unknown voltage object table\n");
    1392             :                                 return -EINVAL;
    1393             :                         }
    1394             :                         break;
    1395             :                 default:
    1396             :                         DRM_ERROR("unknown voltage object table\n");
    1397             :                         return -EINVAL;
    1398             :                 }
    1399             :         }
    1400             :         return -EINVAL;
    1401             : }
    1402             : 
    1403             : union vram_info {
    1404             :         struct _ATOM_VRAM_INFO_V3 v1_3;
    1405             :         struct _ATOM_VRAM_INFO_V4 v1_4;
    1406             :         struct _ATOM_VRAM_INFO_HEADER_V2_1 v2_1;
    1407             : };
    1408             : 
    1409             : #define MEM_ID_MASK           0xff000000
    1410             : #define MEM_ID_SHIFT          24
    1411             : #define CLOCK_RANGE_MASK      0x00ffffff
    1412             : #define CLOCK_RANGE_SHIFT     0
    1413             : #define LOW_NIBBLE_MASK       0xf
    1414             : #define DATA_EQU_PREV         0
    1415             : #define DATA_FROM_TABLE       4
    1416             : 
    1417             : int amdgpu_atombios_init_mc_reg_table(struct amdgpu_device *adev,
    1418             :                                       u8 module_index,
    1419             :                                       struct atom_mc_reg_table *reg_table)
    1420             : {
    1421             :         int index = GetIndexIntoMasterTable(DATA, VRAM_Info);
    1422             :         u8 frev, crev, num_entries, t_mem_id, num_ranges = 0;
    1423             :         u32 i = 0, j;
    1424             :         u16 data_offset, size;
    1425             :         union vram_info *vram_info;
    1426             : 
    1427             :         memset(reg_table, 0, sizeof(struct atom_mc_reg_table));
    1428             : 
    1429             :         if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context, index, &size,
    1430             :                                    &frev, &crev, &data_offset)) {
    1431             :                 vram_info = (union vram_info *)
    1432             :                         (adev->mode_info.atom_context->bios + data_offset);
    1433             :                 switch (frev) {
    1434             :                 case 1:
    1435             :                         DRM_ERROR("old table version %d, %d\n", frev, crev);
    1436             :                         return -EINVAL;
    1437             :                 case 2:
    1438             :                         switch (crev) {
    1439             :                         case 1:
    1440             :                                 if (module_index < vram_info->v2_1.ucNumOfVRAMModule) {
    1441             :                                         ATOM_INIT_REG_BLOCK *reg_block =
    1442             :                                                 (ATOM_INIT_REG_BLOCK *)
    1443             :                                                 ((u8 *)vram_info + le16_to_cpu(vram_info->v2_1.usMemClkPatchTblOffset));
    1444             :                                         ATOM_MEMORY_SETTING_DATA_BLOCK *reg_data =
    1445             :                                                 (ATOM_MEMORY_SETTING_DATA_BLOCK *)
    1446             :                                                 ((u8 *)reg_block + (2 * sizeof(u16)) +
    1447             :                                                  le16_to_cpu(reg_block->usRegIndexTblSize));
    1448             :                                         ATOM_INIT_REG_INDEX_FORMAT *format = &reg_block->asRegIndexBuf[0];
    1449             :                                         num_entries = (u8)((le16_to_cpu(reg_block->usRegIndexTblSize)) /
    1450             :                                                            sizeof(ATOM_INIT_REG_INDEX_FORMAT)) - 1;
    1451             :                                         if (num_entries > VBIOS_MC_REGISTER_ARRAY_SIZE)
    1452             :                                                 return -EINVAL;
    1453             :                                         while (i < num_entries) {
    1454             :                                                 if (format->ucPreRegDataLength & ACCESS_PLACEHOLDER)
    1455             :                                                         break;
    1456             :                                                 reg_table->mc_reg_address[i].s1 =
    1457             :                                                         (u16)(le16_to_cpu(format->usRegIndex));
    1458             :                                                 reg_table->mc_reg_address[i].pre_reg_data =
    1459             :                                                         (u8)(format->ucPreRegDataLength);
    1460             :                                                 i++;
    1461             :                                                 format = (ATOM_INIT_REG_INDEX_FORMAT *)
    1462             :                                                         ((u8 *)format + sizeof(ATOM_INIT_REG_INDEX_FORMAT));
    1463             :                                         }
    1464             :                                         reg_table->last = i;
    1465             :                                         while ((le32_to_cpu(*(u32 *)reg_data) != END_OF_REG_DATA_BLOCK) &&
    1466             :                                                (num_ranges < VBIOS_MAX_AC_TIMING_ENTRIES)) {
    1467             :                                                 t_mem_id = (u8)((le32_to_cpu(*(u32 *)reg_data) & MEM_ID_MASK)
    1468             :                                                                 >> MEM_ID_SHIFT);
    1469             :                                                 if (module_index == t_mem_id) {
    1470             :                                                         reg_table->mc_reg_table_entry[num_ranges].mclk_max =
    1471             :                                                                 (u32)((le32_to_cpu(*(u32 *)reg_data) & CLOCK_RANGE_MASK)
    1472             :                                                                       >> CLOCK_RANGE_SHIFT);
    1473             :                                                         for (i = 0, j = 1; i < reg_table->last; i++) {
    1474             :                                                                 if ((reg_table->mc_reg_address[i].pre_reg_data & LOW_NIBBLE_MASK) == DATA_FROM_TABLE) {
    1475             :                                                                         reg_table->mc_reg_table_entry[num_ranges].mc_data[i] =
    1476             :                                                                                 (u32)le32_to_cpu(*((u32 *)reg_data + j));
    1477             :                                                                         j++;
    1478             :                                                                 } else if ((reg_table->mc_reg_address[i].pre_reg_data & LOW_NIBBLE_MASK) == DATA_EQU_PREV) {
    1479             :                                                                         reg_table->mc_reg_table_entry[num_ranges].mc_data[i] =
    1480             :                                                                                 reg_table->mc_reg_table_entry[num_ranges].mc_data[i - 1];
    1481             :                                                                 }
    1482             :                                                         }
    1483             :                                                         num_ranges++;
    1484             :                                                 }
    1485             :                                                 reg_data = (ATOM_MEMORY_SETTING_DATA_BLOCK *)
    1486             :                                                         ((u8 *)reg_data + le16_to_cpu(reg_block->usRegDataBlkSize));
    1487             :                                         }
    1488             :                                         if (le32_to_cpu(*(u32 *)reg_data) != END_OF_REG_DATA_BLOCK)
    1489             :                                                 return -EINVAL;
    1490             :                                         reg_table->num_entries = num_ranges;
    1491             :                                 } else
    1492             :                                         return -EINVAL;
    1493             :                                 break;
    1494             :                         default:
    1495             :                                 DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
    1496             :                                 return -EINVAL;
    1497             :                         }
    1498             :                         break;
    1499             :                 default:
    1500             :                         DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
    1501             :                         return -EINVAL;
    1502             :                 }
    1503             :                 return 0;
    1504             :         }
    1505             :         return -EINVAL;
    1506             : }
    1507             : #endif
    1508             : 
    1509           0 : bool amdgpu_atombios_has_gpu_virtualization_table(struct amdgpu_device *adev)
    1510             : {
    1511           0 :         int index = GetIndexIntoMasterTable(DATA, GPUVirtualizationInfo);
    1512             :         u8 frev, crev;
    1513             :         u16 data_offset, size;
    1514             : 
    1515           0 :         if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context, index, &size,
    1516             :                                           &frev, &crev, &data_offset))
    1517             :                 return true;
    1518             : 
    1519           0 :         return false;
    1520             : }
    1521             : 
    1522           0 : void amdgpu_atombios_scratch_regs_lock(struct amdgpu_device *adev, bool lock)
    1523             : {
    1524             :         uint32_t bios_6_scratch;
    1525             : 
    1526           0 :         bios_6_scratch = RREG32(adev->bios_scratch_reg_offset + 6);
    1527             : 
    1528           0 :         if (lock) {
    1529           0 :                 bios_6_scratch |= ATOM_S6_CRITICAL_STATE;
    1530           0 :                 bios_6_scratch &= ~ATOM_S6_ACC_MODE;
    1531             :         } else {
    1532           0 :                 bios_6_scratch &= ~ATOM_S6_CRITICAL_STATE;
    1533           0 :                 bios_6_scratch |= ATOM_S6_ACC_MODE;
    1534             :         }
    1535             : 
    1536           0 :         WREG32(adev->bios_scratch_reg_offset + 6, bios_6_scratch);
    1537           0 : }
    1538             : 
    1539           0 : static void amdgpu_atombios_scratch_regs_init(struct amdgpu_device *adev)
    1540             : {
    1541             :         uint32_t bios_2_scratch, bios_6_scratch;
    1542             : 
    1543           0 :         adev->bios_scratch_reg_offset = mmBIOS_SCRATCH_0;
    1544             : 
    1545           0 :         bios_2_scratch = RREG32(adev->bios_scratch_reg_offset + 2);
    1546           0 :         bios_6_scratch = RREG32(adev->bios_scratch_reg_offset + 6);
    1547             : 
    1548             :         /* let the bios control the backlight */
    1549           0 :         bios_2_scratch &= ~ATOM_S2_VRI_BRIGHT_ENABLE;
    1550             : 
    1551             :         /* tell the bios not to handle mode switching */
    1552           0 :         bios_6_scratch |= ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH;
    1553             : 
    1554             :         /* clear the vbios dpms state */
    1555           0 :         bios_2_scratch &= ~ATOM_S2_DEVICE_DPMS_STATE;
    1556             : 
    1557           0 :         WREG32(adev->bios_scratch_reg_offset + 2, bios_2_scratch);
    1558           0 :         WREG32(adev->bios_scratch_reg_offset + 6, bios_6_scratch);
    1559           0 : }
    1560             : 
    1561           0 : void amdgpu_atombios_scratch_regs_engine_hung(struct amdgpu_device *adev,
    1562             :                                               bool hung)
    1563             : {
    1564           0 :         u32 tmp = RREG32(adev->bios_scratch_reg_offset + 3);
    1565             : 
    1566           0 :         if (hung)
    1567           0 :                 tmp |= ATOM_S3_ASIC_GUI_ENGINE_HUNG;
    1568             :         else
    1569           0 :                 tmp &= ~ATOM_S3_ASIC_GUI_ENGINE_HUNG;
    1570             : 
    1571           0 :         WREG32(adev->bios_scratch_reg_offset + 3, tmp);
    1572           0 : }
    1573             : 
    1574           0 : void amdgpu_atombios_scratch_regs_set_backlight_level(struct amdgpu_device *adev,
    1575             :                                                       u32 backlight_level)
    1576             : {
    1577           0 :         u32 tmp = RREG32(adev->bios_scratch_reg_offset + 2);
    1578             : 
    1579           0 :         tmp &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK;
    1580           0 :         tmp |= (backlight_level << ATOM_S2_CURRENT_BL_LEVEL_SHIFT) &
    1581             :                 ATOM_S2_CURRENT_BL_LEVEL_MASK;
    1582             : 
    1583           0 :         WREG32(adev->bios_scratch_reg_offset + 2, tmp);
    1584           0 : }
    1585             : 
    1586           0 : bool amdgpu_atombios_scratch_need_asic_init(struct amdgpu_device *adev)
    1587             : {
    1588           0 :         u32 tmp = RREG32(adev->bios_scratch_reg_offset + 7);
    1589             : 
    1590           0 :         if (tmp & ATOM_S7_ASIC_INIT_COMPLETE_MASK)
    1591             :                 return false;
    1592             :         else
    1593           0 :                 return true;
    1594             : }
    1595             : 
    1596             : /* Atom needs data in little endian format so swap as appropriate when copying
    1597             :  * data to or from atom. Note that atom operates on dw units.
    1598             :  *
    1599             :  * Use to_le=true when sending data to atom and provide at least
    1600             :  * ALIGN(num_bytes,4) bytes in the dst buffer.
    1601             :  *
    1602             :  * Use to_le=false when receiving data from atom and provide ALIGN(num_bytes,4)
    1603             :  * byes in the src buffer.
    1604             :  */
    1605           0 : void amdgpu_atombios_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le)
    1606             : {
    1607             : #ifdef __BIG_ENDIAN
    1608             :         u32 src_tmp[5], dst_tmp[5];
    1609             :         int i;
    1610             :         u8 align_num_bytes = ALIGN(num_bytes, 4);
    1611             : 
    1612             :         if (to_le) {
    1613             :                 memcpy(src_tmp, src, num_bytes);
    1614             :                 for (i = 0; i < align_num_bytes / 4; i++)
    1615             :                         dst_tmp[i] = cpu_to_le32(src_tmp[i]);
    1616             :                 memcpy(dst, dst_tmp, align_num_bytes);
    1617             :         } else {
    1618             :                 memcpy(src_tmp, src, align_num_bytes);
    1619             :                 for (i = 0; i < align_num_bytes / 4; i++)
    1620             :                         dst_tmp[i] = le32_to_cpu(src_tmp[i]);
    1621             :                 memcpy(dst, dst_tmp, num_bytes);
    1622             :         }
    1623             : #else
    1624           0 :         memcpy(dst, src, num_bytes);
    1625             : #endif
    1626           0 : }
    1627             : 
    1628           0 : static int amdgpu_atombios_allocate_fb_scratch(struct amdgpu_device *adev)
    1629             : {
    1630           0 :         struct atom_context *ctx = adev->mode_info.atom_context;
    1631           0 :         int index = GetIndexIntoMasterTable(DATA, VRAM_UsageByFirmware);
    1632             :         uint16_t data_offset;
    1633           0 :         int usage_bytes = 0;
    1634             :         struct _ATOM_VRAM_USAGE_BY_FIRMWARE *firmware_usage;
    1635             :         u64 start_addr;
    1636             :         u64 size;
    1637             : 
    1638           0 :         if (amdgpu_atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset)) {
    1639           0 :                 firmware_usage = (struct _ATOM_VRAM_USAGE_BY_FIRMWARE *)(ctx->bios + data_offset);
    1640             : 
    1641           0 :                 DRM_DEBUG("atom firmware requested %08x %dkb\n",
    1642             :                           le32_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware),
    1643             :                           le16_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb));
    1644             : 
    1645           0 :                 start_addr = firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware;
    1646           0 :                 size = firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb;
    1647             : 
    1648           0 :                 if ((uint32_t)(start_addr & ATOM_VRAM_OPERATION_FLAGS_MASK) ==
    1649             :                         (uint32_t)(ATOM_VRAM_BLOCK_SRIOV_MSG_SHARE_RESERVATION <<
    1650             :                         ATOM_VRAM_OPERATION_FLAGS_SHIFT)) {
    1651             :                         /* Firmware request VRAM reservation for SR-IOV */
    1652           0 :                         adev->mman.fw_vram_usage_start_offset = (start_addr &
    1653           0 :                                 (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10;
    1654           0 :                         adev->mman.fw_vram_usage_size = size << 10;
    1655             :                         /* Use the default scratch size */
    1656           0 :                         usage_bytes = 0;
    1657             :                 } else {
    1658           0 :                         usage_bytes = le16_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb) * 1024;
    1659             :                 }
    1660             :         }
    1661           0 :         ctx->scratch_size_bytes = 0;
    1662           0 :         if (usage_bytes == 0)
    1663           0 :                 usage_bytes = 20 * 1024;
    1664             :         /* allocate some scratch memory */
    1665           0 :         ctx->scratch = kzalloc(usage_bytes, GFP_KERNEL);
    1666           0 :         if (!ctx->scratch)
    1667             :                 return -ENOMEM;
    1668           0 :         ctx->scratch_size_bytes = usage_bytes;
    1669           0 :         return 0;
    1670             : }
    1671             : 
    1672             : /* ATOM accessor methods */
    1673             : /*
    1674             :  * ATOM is an interpreted byte code stored in tables in the vbios.  The
    1675             :  * driver registers callbacks to access registers and the interpreter
    1676             :  * in the driver parses the tables and executes then to program specific
    1677             :  * actions (set display modes, asic init, etc.).  See amdgpu_atombios.c,
    1678             :  * atombios.h, and atom.c
    1679             :  */
    1680             : 
    1681             : /**
    1682             :  * cail_pll_read - read PLL register
    1683             :  *
    1684             :  * @info: atom card_info pointer
    1685             :  * @reg: PLL register offset
    1686             :  *
    1687             :  * Provides a PLL register accessor for the atom interpreter (r4xx+).
    1688             :  * Returns the value of the PLL register.
    1689             :  */
    1690           0 : static uint32_t cail_pll_read(struct card_info *info, uint32_t reg)
    1691             : {
    1692           0 :         return 0;
    1693             : }
    1694             : 
    1695             : /**
    1696             :  * cail_pll_write - write PLL register
    1697             :  *
    1698             :  * @info: atom card_info pointer
    1699             :  * @reg: PLL register offset
    1700             :  * @val: value to write to the pll register
    1701             :  *
    1702             :  * Provides a PLL register accessor for the atom interpreter (r4xx+).
    1703             :  */
    1704           0 : static void cail_pll_write(struct card_info *info, uint32_t reg, uint32_t val)
    1705             : {
    1706             : 
    1707           0 : }
    1708             : 
    1709             : /**
    1710             :  * cail_mc_read - read MC (Memory Controller) register
    1711             :  *
    1712             :  * @info: atom card_info pointer
    1713             :  * @reg: MC register offset
    1714             :  *
    1715             :  * Provides an MC register accessor for the atom interpreter (r4xx+).
    1716             :  * Returns the value of the MC register.
    1717             :  */
    1718           0 : static uint32_t cail_mc_read(struct card_info *info, uint32_t reg)
    1719             : {
    1720           0 :         return 0;
    1721             : }
    1722             : 
    1723             : /**
    1724             :  * cail_mc_write - write MC (Memory Controller) register
    1725             :  *
    1726             :  * @info: atom card_info pointer
    1727             :  * @reg: MC register offset
    1728             :  * @val: value to write to the pll register
    1729             :  *
    1730             :  * Provides a MC register accessor for the atom interpreter (r4xx+).
    1731             :  */
    1732           0 : static void cail_mc_write(struct card_info *info, uint32_t reg, uint32_t val)
    1733             : {
    1734             : 
    1735           0 : }
    1736             : 
    1737             : /**
    1738             :  * cail_reg_write - write MMIO register
    1739             :  *
    1740             :  * @info: atom card_info pointer
    1741             :  * @reg: MMIO register offset
    1742             :  * @val: value to write to the pll register
    1743             :  *
    1744             :  * Provides a MMIO register accessor for the atom interpreter (r4xx+).
    1745             :  */
    1746           0 : static void cail_reg_write(struct card_info *info, uint32_t reg, uint32_t val)
    1747             : {
    1748           0 :         struct amdgpu_device *adev = drm_to_adev(info->dev);
    1749             : 
    1750           0 :         WREG32(reg, val);
    1751           0 : }
    1752             : 
    1753             : /**
    1754             :  * cail_reg_read - read MMIO register
    1755             :  *
    1756             :  * @info: atom card_info pointer
    1757             :  * @reg: MMIO register offset
    1758             :  *
    1759             :  * Provides an MMIO register accessor for the atom interpreter (r4xx+).
    1760             :  * Returns the value of the MMIO register.
    1761             :  */
    1762           0 : static uint32_t cail_reg_read(struct card_info *info, uint32_t reg)
    1763             : {
    1764           0 :         struct amdgpu_device *adev = drm_to_adev(info->dev);
    1765             :         uint32_t r;
    1766             : 
    1767           0 :         r = RREG32(reg);
    1768           0 :         return r;
    1769             : }
    1770             : 
    1771           0 : static ssize_t amdgpu_atombios_get_vbios_version(struct device *dev,
    1772             :                                                  struct device_attribute *attr,
    1773             :                                                  char *buf)
    1774             : {
    1775           0 :         struct drm_device *ddev = dev_get_drvdata(dev);
    1776           0 :         struct amdgpu_device *adev = drm_to_adev(ddev);
    1777           0 :         struct atom_context *ctx = adev->mode_info.atom_context;
    1778             : 
    1779           0 :         return sysfs_emit(buf, "%s\n", ctx->vbios_version);
    1780             : }
    1781             : 
    1782             : static DEVICE_ATTR(vbios_version, 0444, amdgpu_atombios_get_vbios_version,
    1783             :                    NULL);
    1784             : 
    1785             : static struct attribute *amdgpu_vbios_version_attrs[] = {
    1786             :         &dev_attr_vbios_version.attr,
    1787             :         NULL
    1788             : };
    1789             : 
    1790             : const struct attribute_group amdgpu_vbios_version_attr_group = {
    1791             :         .attrs = amdgpu_vbios_version_attrs
    1792             : };
    1793             : 
    1794             : /**
    1795             :  * amdgpu_atombios_fini - free the driver info and callbacks for atombios
    1796             :  *
    1797             :  * @adev: amdgpu_device pointer
    1798             :  *
    1799             :  * Frees the driver info and register access callbacks for the ATOM
    1800             :  * interpreter (r4xx+).
    1801             :  * Called at driver shutdown.
    1802             :  */
    1803           0 : void amdgpu_atombios_fini(struct amdgpu_device *adev)
    1804             : {
    1805           0 :         if (adev->mode_info.atom_context) {
    1806           0 :                 kfree(adev->mode_info.atom_context->scratch);
    1807           0 :                 kfree(adev->mode_info.atom_context->iio);
    1808             :         }
    1809           0 :         kfree(adev->mode_info.atom_context);
    1810           0 :         adev->mode_info.atom_context = NULL;
    1811           0 :         kfree(adev->mode_info.atom_card_info);
    1812           0 :         adev->mode_info.atom_card_info = NULL;
    1813           0 : }
    1814             : 
    1815             : /**
    1816             :  * amdgpu_atombios_init - init the driver info and callbacks for atombios
    1817             :  *
    1818             :  * @adev: amdgpu_device pointer
    1819             :  *
    1820             :  * Initializes the driver info and register access callbacks for the
    1821             :  * ATOM interpreter (r4xx+).
    1822             :  * Returns 0 on sucess, -ENOMEM on failure.
    1823             :  * Called at driver startup.
    1824             :  */
    1825           0 : int amdgpu_atombios_init(struct amdgpu_device *adev)
    1826             : {
    1827           0 :         struct card_info *atom_card_info =
    1828             :             kzalloc(sizeof(struct card_info), GFP_KERNEL);
    1829             : 
    1830           0 :         if (!atom_card_info)
    1831             :                 return -ENOMEM;
    1832             : 
    1833           0 :         adev->mode_info.atom_card_info = atom_card_info;
    1834           0 :         atom_card_info->dev = adev_to_drm(adev);
    1835           0 :         atom_card_info->reg_read = cail_reg_read;
    1836           0 :         atom_card_info->reg_write = cail_reg_write;
    1837           0 :         atom_card_info->mc_read = cail_mc_read;
    1838           0 :         atom_card_info->mc_write = cail_mc_write;
    1839           0 :         atom_card_info->pll_read = cail_pll_read;
    1840           0 :         atom_card_info->pll_write = cail_pll_write;
    1841             : 
    1842           0 :         adev->mode_info.atom_context = amdgpu_atom_parse(atom_card_info, adev->bios);
    1843           0 :         if (!adev->mode_info.atom_context) {
    1844           0 :                 amdgpu_atombios_fini(adev);
    1845           0 :                 return -ENOMEM;
    1846             :         }
    1847             : 
    1848           0 :         mutex_init(&adev->mode_info.atom_context->mutex);
    1849           0 :         if (adev->is_atom_fw) {
    1850           0 :                 amdgpu_atomfirmware_scratch_regs_init(adev);
    1851           0 :                 amdgpu_atomfirmware_allocate_fb_scratch(adev);
    1852             :                 /* cached firmware_flags for further usage */
    1853           0 :                 adev->mode_info.firmware_flags =
    1854           0 :                         amdgpu_atomfirmware_query_firmware_capability(adev);
    1855             :         } else {
    1856           0 :                 amdgpu_atombios_scratch_regs_init(adev);
    1857           0 :                 amdgpu_atombios_allocate_fb_scratch(adev);
    1858             :         }
    1859             : 
    1860             :         return 0;
    1861             : }
    1862             : 
    1863           0 : int amdgpu_atombios_get_data_table(struct amdgpu_device *adev,
    1864             :                                    uint32_t table,
    1865             :                                    uint16_t *size,
    1866             :                                    uint8_t *frev,
    1867             :                                    uint8_t *crev,
    1868             :                                    uint8_t **addr)
    1869             : {
    1870             :         uint16_t data_start;
    1871             : 
    1872           0 :         if (!amdgpu_atom_parse_data_header(adev->mode_info.atom_context, table,
    1873             :                                            size, frev, crev, &data_start))
    1874             :                 return -EINVAL;
    1875             : 
    1876           0 :         *addr = (uint8_t *)adev->mode_info.atom_context->bios + data_start;
    1877             : 
    1878           0 :         return 0;
    1879             : }

Generated by: LCOV version 1.14