LCOV - code coverage report
Current view: top level - drivers/gpu/drm/i915 - intel_csr.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 222 0.0 %
Date: 2022-03-28 16:04:14 Functions: 0 11 0.0 %
Branches: 0 114 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright © 2014 Intel Corporation
       3                 :            :  *
       4                 :            :  * Permission is hereby granted, free of charge, to any person obtaining a
       5                 :            :  * copy of this software and associated documentation files (the "Software"),
       6                 :            :  * to deal in the Software without restriction, including without limitation
       7                 :            :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       8                 :            :  * and/or sell copies of the Software, and to permit persons to whom the
       9                 :            :  * Software is furnished to do so, subject to the following conditions:
      10                 :            :  *
      11                 :            :  * The above copyright notice and this permission notice (including the next
      12                 :            :  * paragraph) shall be included in all copies or substantial portions of the
      13                 :            :  * Software.
      14                 :            :  *
      15                 :            :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16                 :            :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17                 :            :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      18                 :            :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19                 :            :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      20                 :            :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
      21                 :            :  * IN THE SOFTWARE.
      22                 :            :  *
      23                 :            :  */
      24                 :            : 
      25                 :            : #include <linux/firmware.h>
      26                 :            : 
      27                 :            : #include "i915_drv.h"
      28                 :            : #include "i915_reg.h"
      29                 :            : #include "intel_csr.h"
      30                 :            : 
      31                 :            : /**
      32                 :            :  * DOC: csr support for dmc
      33                 :            :  *
      34                 :            :  * Display Context Save and Restore (CSR) firmware support added from gen9
      35                 :            :  * onwards to drive newly added DMC (Display microcontroller) in display
      36                 :            :  * engine to save and restore the state of display engine when it enter into
      37                 :            :  * low-power state and comes back to normal.
      38                 :            :  */
      39                 :            : 
      40                 :            : #define GEN12_CSR_MAX_FW_SIZE           ICL_CSR_MAX_FW_SIZE
      41                 :            : 
      42                 :            : #define TGL_CSR_PATH                    "i915/tgl_dmc_ver2_04.bin"
      43                 :            : #define TGL_CSR_VERSION_REQUIRED        CSR_VERSION(2, 4)
      44                 :            : #define TGL_CSR_MAX_FW_SIZE             0x6000
      45                 :            : MODULE_FIRMWARE(TGL_CSR_PATH);
      46                 :            : 
      47                 :            : #define ICL_CSR_PATH                    "i915/icl_dmc_ver1_09.bin"
      48                 :            : #define ICL_CSR_VERSION_REQUIRED        CSR_VERSION(1, 9)
      49                 :            : #define ICL_CSR_MAX_FW_SIZE             0x6000
      50                 :            : MODULE_FIRMWARE(ICL_CSR_PATH);
      51                 :            : 
      52                 :            : #define CNL_CSR_PATH                    "i915/cnl_dmc_ver1_07.bin"
      53                 :            : #define CNL_CSR_VERSION_REQUIRED        CSR_VERSION(1, 7)
      54                 :            : #define CNL_CSR_MAX_FW_SIZE             GLK_CSR_MAX_FW_SIZE
      55                 :            : MODULE_FIRMWARE(CNL_CSR_PATH);
      56                 :            : 
      57                 :            : #define GLK_CSR_PATH                    "i915/glk_dmc_ver1_04.bin"
      58                 :            : #define GLK_CSR_VERSION_REQUIRED        CSR_VERSION(1, 4)
      59                 :            : #define GLK_CSR_MAX_FW_SIZE             0x4000
      60                 :            : MODULE_FIRMWARE(GLK_CSR_PATH);
      61                 :            : 
      62                 :            : #define KBL_CSR_PATH                    "i915/kbl_dmc_ver1_04.bin"
      63                 :            : #define KBL_CSR_VERSION_REQUIRED        CSR_VERSION(1, 4)
      64                 :            : #define KBL_CSR_MAX_FW_SIZE             BXT_CSR_MAX_FW_SIZE
      65                 :            : MODULE_FIRMWARE(KBL_CSR_PATH);
      66                 :            : 
      67                 :            : #define SKL_CSR_PATH                    "i915/skl_dmc_ver1_27.bin"
      68                 :            : #define SKL_CSR_VERSION_REQUIRED        CSR_VERSION(1, 27)
      69                 :            : #define SKL_CSR_MAX_FW_SIZE             BXT_CSR_MAX_FW_SIZE
      70                 :            : MODULE_FIRMWARE(SKL_CSR_PATH);
      71                 :            : 
      72                 :            : #define BXT_CSR_PATH                    "i915/bxt_dmc_ver1_07.bin"
      73                 :            : #define BXT_CSR_VERSION_REQUIRED        CSR_VERSION(1, 7)
      74                 :            : #define BXT_CSR_MAX_FW_SIZE             0x3000
      75                 :            : MODULE_FIRMWARE(BXT_CSR_PATH);
      76                 :            : 
      77                 :            : #define CSR_DEFAULT_FW_OFFSET           0xFFFFFFFF
      78                 :            : #define PACKAGE_MAX_FW_INFO_ENTRIES     20
      79                 :            : #define PACKAGE_V2_MAX_FW_INFO_ENTRIES  32
      80                 :            : #define DMC_V1_MAX_MMIO_COUNT           8
      81                 :            : #define DMC_V3_MAX_MMIO_COUNT           20
      82                 :            : 
      83                 :            : struct intel_css_header {
      84                 :            :         /* 0x09 for DMC */
      85                 :            :         u32 module_type;
      86                 :            : 
      87                 :            :         /* Includes the DMC specific header in dwords */
      88                 :            :         u32 header_len;
      89                 :            : 
      90                 :            :         /* always value would be 0x10000 */
      91                 :            :         u32 header_ver;
      92                 :            : 
      93                 :            :         /* Not used */
      94                 :            :         u32 module_id;
      95                 :            : 
      96                 :            :         /* Not used */
      97                 :            :         u32 module_vendor;
      98                 :            : 
      99                 :            :         /* in YYYYMMDD format */
     100                 :            :         u32 date;
     101                 :            : 
     102                 :            :         /* Size in dwords (CSS_Headerlen + PackageHeaderLen + dmc FWsLen)/4 */
     103                 :            :         u32 size;
     104                 :            : 
     105                 :            :         /* Not used */
     106                 :            :         u32 key_size;
     107                 :            : 
     108                 :            :         /* Not used */
     109                 :            :         u32 modulus_size;
     110                 :            : 
     111                 :            :         /* Not used */
     112                 :            :         u32 exponent_size;
     113                 :            : 
     114                 :            :         /* Not used */
     115                 :            :         u32 reserved1[12];
     116                 :            : 
     117                 :            :         /* Major Minor */
     118                 :            :         u32 version;
     119                 :            : 
     120                 :            :         /* Not used */
     121                 :            :         u32 reserved2[8];
     122                 :            : 
     123                 :            :         /* Not used */
     124                 :            :         u32 kernel_header_info;
     125                 :            : } __packed;
     126                 :            : 
     127                 :            : struct intel_fw_info {
     128                 :            :         u8 reserved1;
     129                 :            : 
     130                 :            :         /* reserved on package_header version 1, must be 0 on version 2 */
     131                 :            :         u8 dmc_id;
     132                 :            : 
     133                 :            :         /* Stepping (A, B, C, ..., *). * is a wildcard */
     134                 :            :         char stepping;
     135                 :            : 
     136                 :            :         /* Sub-stepping (0, 1, ..., *). * is a wildcard */
     137                 :            :         char substepping;
     138                 :            : 
     139                 :            :         u32 offset;
     140                 :            :         u32 reserved2;
     141                 :            : } __packed;
     142                 :            : 
     143                 :            : struct intel_package_header {
     144                 :            :         /* DMC container header length in dwords */
     145                 :            :         u8 header_len;
     146                 :            : 
     147                 :            :         /* 0x01, 0x02 */
     148                 :            :         u8 header_ver;
     149                 :            : 
     150                 :            :         u8 reserved[10];
     151                 :            : 
     152                 :            :         /* Number of valid entries in the FWInfo array below */
     153                 :            :         u32 num_entries;
     154                 :            : } __packed;
     155                 :            : 
     156                 :            : struct intel_dmc_header_base {
     157                 :            :         /* always value would be 0x40403E3E */
     158                 :            :         u32 signature;
     159                 :            : 
     160                 :            :         /* DMC binary header length */
     161                 :            :         u8 header_len;
     162                 :            : 
     163                 :            :         /* 0x01 */
     164                 :            :         u8 header_ver;
     165                 :            : 
     166                 :            :         /* Reserved */
     167                 :            :         u16 dmcc_ver;
     168                 :            : 
     169                 :            :         /* Major, Minor */
     170                 :            :         u32 project;
     171                 :            : 
     172                 :            :         /* Firmware program size (excluding header) in dwords */
     173                 :            :         u32 fw_size;
     174                 :            : 
     175                 :            :         /* Major Minor version */
     176                 :            :         u32 fw_version;
     177                 :            : } __packed;
     178                 :            : 
     179                 :            : struct intel_dmc_header_v1 {
     180                 :            :         struct intel_dmc_header_base base;
     181                 :            : 
     182                 :            :         /* Number of valid MMIO cycles present. */
     183                 :            :         u32 mmio_count;
     184                 :            : 
     185                 :            :         /* MMIO address */
     186                 :            :         u32 mmioaddr[DMC_V1_MAX_MMIO_COUNT];
     187                 :            : 
     188                 :            :         /* MMIO data */
     189                 :            :         u32 mmiodata[DMC_V1_MAX_MMIO_COUNT];
     190                 :            : 
     191                 :            :         /* FW filename  */
     192                 :            :         char dfile[32];
     193                 :            : 
     194                 :            :         u32 reserved1[2];
     195                 :            : } __packed;
     196                 :            : 
     197                 :            : struct intel_dmc_header_v3 {
     198                 :            :         struct intel_dmc_header_base base;
     199                 :            : 
     200                 :            :         /* DMC RAM start MMIO address */
     201                 :            :         u32 start_mmioaddr;
     202                 :            : 
     203                 :            :         u32 reserved[9];
     204                 :            : 
     205                 :            :         /* FW filename */
     206                 :            :         char dfile[32];
     207                 :            : 
     208                 :            :         /* Number of valid MMIO cycles present. */
     209                 :            :         u32 mmio_count;
     210                 :            : 
     211                 :            :         /* MMIO address */
     212                 :            :         u32 mmioaddr[DMC_V3_MAX_MMIO_COUNT];
     213                 :            : 
     214                 :            :         /* MMIO data */
     215                 :            :         u32 mmiodata[DMC_V3_MAX_MMIO_COUNT];
     216                 :            : } __packed;
     217                 :            : 
     218                 :            : struct stepping_info {
     219                 :            :         char stepping;
     220                 :            :         char substepping;
     221                 :            : };
     222                 :            : 
     223                 :            : static const struct stepping_info skl_stepping_info[] = {
     224                 :            :         {'A', '0'}, {'B', '0'}, {'C', '0'},
     225                 :            :         {'D', '0'}, {'E', '0'}, {'F', '0'},
     226                 :            :         {'G', '0'}, {'H', '0'}, {'I', '0'},
     227                 :            :         {'J', '0'}, {'K', '0'}
     228                 :            : };
     229                 :            : 
     230                 :            : static const struct stepping_info bxt_stepping_info[] = {
     231                 :            :         {'A', '0'}, {'A', '1'}, {'A', '2'},
     232                 :            :         {'B', '0'}, {'B', '1'}, {'B', '2'}
     233                 :            : };
     234                 :            : 
     235                 :            : static const struct stepping_info icl_stepping_info[] = {
     236                 :            :         {'A', '0'}, {'A', '1'}, {'A', '2'},
     237                 :            :         {'B', '0'}, {'B', '2'},
     238                 :            :         {'C', '0'}
     239                 :            : };
     240                 :            : 
     241                 :            : static const struct stepping_info no_stepping_info = { '*', '*' };
     242                 :            : 
     243                 :            : static const struct stepping_info *
     244                 :          0 : intel_get_stepping_info(struct drm_i915_private *dev_priv)
     245                 :            : {
     246                 :          0 :         const struct stepping_info *si;
     247                 :          0 :         unsigned int size;
     248                 :            : 
     249                 :          0 :         if (IS_ICELAKE(dev_priv)) {
     250                 :            :                 size = ARRAY_SIZE(icl_stepping_info);
     251                 :            :                 si = icl_stepping_info;
     252         [ #  # ]:          0 :         } else if (IS_SKYLAKE(dev_priv)) {
     253                 :            :                 size = ARRAY_SIZE(skl_stepping_info);
     254                 :            :                 si = skl_stepping_info;
     255         [ #  # ]:          0 :         } else if (IS_BROXTON(dev_priv)) {
     256                 :            :                 size = ARRAY_SIZE(bxt_stepping_info);
     257                 :            :                 si = bxt_stepping_info;
     258                 :            :         } else {
     259                 :          0 :                 size = 0;
     260                 :          0 :                 si = NULL;
     261                 :            :         }
     262                 :            : 
     263         [ #  # ]:          0 :         if (INTEL_REVID(dev_priv) < size)
     264                 :          0 :                 return si + INTEL_REVID(dev_priv);
     265                 :            : 
     266                 :            :         return &no_stepping_info;
     267                 :            : }
     268                 :            : 
     269                 :          0 : static void gen9_set_dc_state_debugmask(struct drm_i915_private *dev_priv)
     270                 :            : {
     271                 :          0 :         u32 val, mask;
     272                 :            : 
     273                 :          0 :         mask = DC_STATE_DEBUG_MASK_MEMORY_UP;
     274                 :            : 
     275   [ #  #  #  # ]:          0 :         if (IS_GEN9_LP(dev_priv))
     276                 :          0 :                 mask |= DC_STATE_DEBUG_MASK_CORES;
     277                 :            : 
     278                 :            :         /* The below bit doesn't need to be cleared ever afterwards */
     279                 :          0 :         val = I915_READ(DC_STATE_DEBUG);
     280         [ #  # ]:          0 :         if ((val & mask) != mask) {
     281                 :          0 :                 val |= mask;
     282                 :          0 :                 I915_WRITE(DC_STATE_DEBUG, val);
     283                 :          0 :                 POSTING_READ(DC_STATE_DEBUG);
     284                 :            :         }
     285                 :          0 : }
     286                 :            : 
     287                 :            : /**
     288                 :            :  * intel_csr_load_program() - write the firmware from memory to register.
     289                 :            :  * @dev_priv: i915 drm device.
     290                 :            :  *
     291                 :            :  * CSR firmware is read from a .bin file and kept in internal memory one time.
     292                 :            :  * Everytime display comes back from low power state this function is called to
     293                 :            :  * copy the firmware from internal memory to registers.
     294                 :            :  */
     295                 :          0 : void intel_csr_load_program(struct drm_i915_private *dev_priv)
     296                 :            : {
     297                 :          0 :         u32 *payload = dev_priv->csr.dmc_payload;
     298                 :          0 :         u32 i, fw_size;
     299                 :            : 
     300         [ #  # ]:          0 :         if (!HAS_CSR(dev_priv)) {
     301                 :          0 :                 DRM_ERROR("No CSR support available for this platform\n");
     302                 :          0 :                 return;
     303                 :            :         }
     304                 :            : 
     305         [ #  # ]:          0 :         if (!dev_priv->csr.dmc_payload) {
     306                 :          0 :                 DRM_ERROR("Tried to program CSR with empty payload\n");
     307                 :          0 :                 return;
     308                 :            :         }
     309                 :            : 
     310                 :          0 :         fw_size = dev_priv->csr.dmc_fw_size;
     311                 :          0 :         assert_rpm_wakelock_held(&dev_priv->runtime_pm);
     312                 :            : 
     313                 :          0 :         preempt_disable();
     314                 :            : 
     315         [ #  # ]:          0 :         for (i = 0; i < fw_size; i++)
     316                 :          0 :                 I915_WRITE_FW(CSR_PROGRAM(i), payload[i]);
     317                 :            : 
     318                 :          0 :         preempt_enable();
     319                 :            : 
     320         [ #  # ]:          0 :         for (i = 0; i < dev_priv->csr.mmio_count; i++) {
     321                 :          0 :                 I915_WRITE(dev_priv->csr.mmioaddr[i],
     322                 :            :                            dev_priv->csr.mmiodata[i]);
     323                 :            :         }
     324                 :            : 
     325                 :          0 :         dev_priv->csr.dc_state = 0;
     326                 :            : 
     327                 :          0 :         gen9_set_dc_state_debugmask(dev_priv);
     328                 :            : }
     329                 :            : 
     330                 :            : /*
     331                 :            :  * Search fw_info table for dmc_offset to find firmware binary: num_entries is
     332                 :            :  * already sanitized.
     333                 :            :  */
     334                 :          0 : static u32 find_dmc_fw_offset(const struct intel_fw_info *fw_info,
     335                 :            :                               unsigned int num_entries,
     336                 :            :                               const struct stepping_info *si,
     337                 :            :                               u8 package_ver)
     338                 :            : {
     339                 :          0 :         u32 dmc_offset = CSR_DEFAULT_FW_OFFSET;
     340                 :          0 :         unsigned int i;
     341                 :            : 
     342         [ #  # ]:          0 :         for (i = 0; i < num_entries; i++) {
     343   [ #  #  #  # ]:          0 :                 if (package_ver > 1 && fw_info[i].dmc_id != 0)
     344                 :          0 :                         continue;
     345                 :            : 
     346         [ #  # ]:          0 :                 if (fw_info[i].substepping == '*' &&
     347         [ #  # ]:          0 :                     si->stepping == fw_info[i].stepping) {
     348                 :          0 :                         dmc_offset = fw_info[i].offset;
     349                 :          0 :                         break;
     350                 :            :                 }
     351                 :            : 
     352         [ #  # ]:          0 :                 if (si->stepping == fw_info[i].stepping &&
     353         [ #  # ]:          0 :                     si->substepping == fw_info[i].substepping) {
     354                 :          0 :                         dmc_offset = fw_info[i].offset;
     355                 :          0 :                         break;
     356                 :            :                 }
     357                 :            : 
     358   [ #  #  #  # ]:          0 :                 if (fw_info[i].stepping == '*' &&
     359                 :            :                     fw_info[i].substepping == '*') {
     360                 :            :                         /*
     361                 :            :                          * In theory we should stop the search as generic
     362                 :            :                          * entries should always come after the more specific
     363                 :            :                          * ones, but let's continue to make sure to work even
     364                 :            :                          * with "broken" firmwares. If we don't find a more
     365                 :            :                          * specific one, then we use this entry
     366                 :            :                          */
     367                 :          0 :                         dmc_offset = fw_info[i].offset;
     368                 :            :                 }
     369                 :            :         }
     370                 :            : 
     371                 :          0 :         return dmc_offset;
     372                 :            : }
     373                 :            : 
     374                 :          0 : static u32 parse_csr_fw_dmc(struct intel_csr *csr,
     375                 :            :                             const struct intel_dmc_header_base *dmc_header,
     376                 :            :                             size_t rem_size)
     377                 :            : {
     378                 :          0 :         unsigned int header_len_bytes, dmc_header_size, payload_size, i;
     379                 :          0 :         const u32 *mmioaddr, *mmiodata;
     380                 :          0 :         u32 mmio_count, mmio_count_max;
     381                 :          0 :         u8 *payload;
     382                 :            : 
     383                 :          0 :         BUILD_BUG_ON(ARRAY_SIZE(csr->mmioaddr) < DMC_V3_MAX_MMIO_COUNT ||
     384                 :            :                      ARRAY_SIZE(csr->mmioaddr) < DMC_V1_MAX_MMIO_COUNT);
     385                 :            : 
     386                 :            :         /*
     387                 :            :          * Check if we can access common fields, we will checkc again below
     388                 :            :          * after we have read the version
     389                 :            :          */
     390         [ #  # ]:          0 :         if (rem_size < sizeof(struct intel_dmc_header_base))
     391                 :          0 :                 goto error_truncated;
     392                 :            : 
     393                 :            :         /* Cope with small differences between v1 and v3 */
     394         [ #  # ]:          0 :         if (dmc_header->header_ver == 3) {
     395                 :          0 :                 const struct intel_dmc_header_v3 *v3 =
     396                 :            :                         (const struct intel_dmc_header_v3 *)dmc_header;
     397                 :            : 
     398         [ #  # ]:          0 :                 if (rem_size < sizeof(struct intel_dmc_header_v3))
     399                 :          0 :                         goto error_truncated;
     400                 :            : 
     401                 :          0 :                 mmioaddr = v3->mmioaddr;
     402                 :          0 :                 mmiodata = v3->mmiodata;
     403                 :          0 :                 mmio_count = v3->mmio_count;
     404                 :          0 :                 mmio_count_max = DMC_V3_MAX_MMIO_COUNT;
     405                 :            :                 /* header_len is in dwords */
     406                 :          0 :                 header_len_bytes = dmc_header->header_len * 4;
     407                 :          0 :                 dmc_header_size = sizeof(*v3);
     408         [ #  # ]:          0 :         } else if (dmc_header->header_ver == 1) {
     409                 :          0 :                 const struct intel_dmc_header_v1 *v1 =
     410                 :            :                         (const struct intel_dmc_header_v1 *)dmc_header;
     411                 :            : 
     412         [ #  # ]:          0 :                 if (rem_size < sizeof(struct intel_dmc_header_v1))
     413                 :          0 :                         goto error_truncated;
     414                 :            : 
     415                 :          0 :                 mmioaddr = v1->mmioaddr;
     416                 :          0 :                 mmiodata = v1->mmiodata;
     417                 :          0 :                 mmio_count = v1->mmio_count;
     418                 :          0 :                 mmio_count_max = DMC_V1_MAX_MMIO_COUNT;
     419                 :          0 :                 header_len_bytes = dmc_header->header_len;
     420                 :          0 :                 dmc_header_size = sizeof(*v1);
     421                 :            :         } else {
     422                 :          0 :                 DRM_ERROR("Unknown DMC fw header version: %u\n",
     423                 :            :                           dmc_header->header_ver);
     424                 :          0 :                 return 0;
     425                 :            :         }
     426                 :            : 
     427         [ #  # ]:          0 :         if (header_len_bytes != dmc_header_size) {
     428                 :          0 :                 DRM_ERROR("DMC firmware has wrong dmc header length "
     429                 :            :                           "(%u bytes)\n", header_len_bytes);
     430                 :          0 :                 return 0;
     431                 :            :         }
     432                 :            : 
     433                 :            :         /* Cache the dmc header info. */
     434         [ #  # ]:          0 :         if (mmio_count > mmio_count_max) {
     435                 :          0 :                 DRM_ERROR("DMC firmware has wrong mmio count %u\n", mmio_count);
     436                 :          0 :                 return 0;
     437                 :            :         }
     438                 :            : 
     439         [ #  # ]:          0 :         for (i = 0; i < mmio_count; i++) {
     440         [ #  # ]:          0 :                 if (mmioaddr[i] < CSR_MMIO_START_RANGE ||
     441                 :            :                     mmioaddr[i] > CSR_MMIO_END_RANGE) {
     442                 :          0 :                         DRM_ERROR("DMC firmware has wrong mmio address 0x%x\n",
     443                 :            :                                   mmioaddr[i]);
     444                 :          0 :                         return 0;
     445                 :            :                 }
     446                 :          0 :                 csr->mmioaddr[i] = _MMIO(mmioaddr[i]);
     447                 :          0 :                 csr->mmiodata[i] = mmiodata[i];
     448                 :            :         }
     449                 :          0 :         csr->mmio_count = mmio_count;
     450                 :            : 
     451                 :          0 :         rem_size -= header_len_bytes;
     452                 :            : 
     453                 :            :         /* fw_size is in dwords, so multiplied by 4 to convert into bytes. */
     454                 :          0 :         payload_size = dmc_header->fw_size * 4;
     455         [ #  # ]:          0 :         if (rem_size < payload_size)
     456                 :          0 :                 goto error_truncated;
     457                 :            : 
     458         [ #  # ]:          0 :         if (payload_size > csr->max_fw_size) {
     459                 :          0 :                 DRM_ERROR("DMC FW too big (%u bytes)\n", payload_size);
     460                 :          0 :                 return 0;
     461                 :            :         }
     462                 :          0 :         csr->dmc_fw_size = dmc_header->fw_size;
     463                 :            : 
     464         [ #  # ]:          0 :         csr->dmc_payload = kmalloc(payload_size, GFP_KERNEL);
     465         [ #  # ]:          0 :         if (!csr->dmc_payload) {
     466                 :          0 :                 DRM_ERROR("Memory allocation failed for dmc payload\n");
     467                 :          0 :                 return 0;
     468                 :            :         }
     469                 :            : 
     470                 :          0 :         payload = (u8 *)(dmc_header) + header_len_bytes;
     471                 :          0 :         memcpy(csr->dmc_payload, payload, payload_size);
     472                 :            : 
     473                 :          0 :         return header_len_bytes + payload_size;
     474                 :            : 
     475                 :          0 : error_truncated:
     476                 :          0 :         DRM_ERROR("Truncated DMC firmware, refusing.\n");
     477                 :          0 :         return 0;
     478                 :            : }
     479                 :            : 
     480                 :            : static u32
     481                 :            : parse_csr_fw_package(struct intel_csr *csr,
     482                 :            :                      const struct intel_package_header *package_header,
     483                 :            :                      const struct stepping_info *si,
     484                 :            :                      size_t rem_size)
     485                 :            : {
     486                 :            :         u32 package_size = sizeof(struct intel_package_header);
     487                 :            :         u32 num_entries, max_entries, dmc_offset;
     488                 :            :         const struct intel_fw_info *fw_info;
     489                 :            : 
     490                 :            :         if (rem_size < package_size)
     491                 :            :                 goto error_truncated;
     492                 :            : 
     493                 :            :         if (package_header->header_ver == 1) {
     494                 :            :                 max_entries = PACKAGE_MAX_FW_INFO_ENTRIES;
     495                 :            :         } else if (package_header->header_ver == 2) {
     496                 :            :                 max_entries = PACKAGE_V2_MAX_FW_INFO_ENTRIES;
     497                 :            :         } else {
     498                 :            :                 DRM_ERROR("DMC firmware has unknown header version %u\n",
     499                 :            :                           package_header->header_ver);
     500                 :            :                 return 0;
     501                 :            :         }
     502                 :            : 
     503                 :            :         /*
     504                 :            :          * We should always have space for max_entries,
     505                 :            :          * even if not all are used
     506                 :            :          */
     507                 :            :         package_size += max_entries * sizeof(struct intel_fw_info);
     508                 :            :         if (rem_size < package_size)
     509                 :            :                 goto error_truncated;
     510                 :            : 
     511                 :            :         if (package_header->header_len * 4 != package_size) {
     512                 :            :                 DRM_ERROR("DMC firmware has wrong package header length "
     513                 :            :                           "(%u bytes)\n", package_size);
     514                 :            :                 return 0;
     515                 :            :         }
     516                 :            : 
     517                 :            :         num_entries = package_header->num_entries;
     518                 :            :         if (WARN_ON(package_header->num_entries > max_entries))
     519                 :            :                 num_entries = max_entries;
     520                 :            : 
     521                 :            :         fw_info = (const struct intel_fw_info *)
     522                 :            :                 ((u8 *)package_header + sizeof(*package_header));
     523                 :            :         dmc_offset = find_dmc_fw_offset(fw_info, num_entries, si,
     524                 :            :                                         package_header->header_ver);
     525                 :            :         if (dmc_offset == CSR_DEFAULT_FW_OFFSET) {
     526                 :            :                 DRM_ERROR("DMC firmware not supported for %c stepping\n",
     527                 :            :                           si->stepping);
     528                 :            :                 return 0;
     529                 :            :         }
     530                 :            : 
     531                 :            :         /* dmc_offset is in dwords */
     532                 :            :         return package_size + dmc_offset * 4;
     533                 :            : 
     534                 :            : error_truncated:
     535                 :            :         DRM_ERROR("Truncated DMC firmware, refusing.\n");
     536                 :            :         return 0;
     537                 :            : }
     538                 :            : 
     539                 :            : /* Return number of bytes parsed or 0 on error */
     540                 :            : static u32 parse_csr_fw_css(struct intel_csr *csr,
     541                 :            :                             struct intel_css_header *css_header,
     542                 :            :                             size_t rem_size)
     543                 :            : {
     544                 :            :         if (rem_size < sizeof(struct intel_css_header)) {
     545                 :            :                 DRM_ERROR("Truncated DMC firmware, refusing.\n");
     546                 :            :                 return 0;
     547                 :            :         }
     548                 :            : 
     549                 :            :         if (sizeof(struct intel_css_header) !=
     550                 :            :             (css_header->header_len * 4)) {
     551                 :            :                 DRM_ERROR("DMC firmware has wrong CSS header length "
     552                 :            :                           "(%u bytes)\n",
     553                 :            :                           (css_header->header_len * 4));
     554                 :            :                 return 0;
     555                 :            :         }
     556                 :            : 
     557                 :            :         if (csr->required_version &&
     558                 :            :             css_header->version != csr->required_version) {
     559                 :            :                 DRM_INFO("Refusing to load DMC firmware v%u.%u,"
     560                 :            :                          " please use v%u.%u\n",
     561                 :            :                          CSR_VERSION_MAJOR(css_header->version),
     562                 :            :                          CSR_VERSION_MINOR(css_header->version),
     563                 :            :                          CSR_VERSION_MAJOR(csr->required_version),
     564                 :            :                          CSR_VERSION_MINOR(csr->required_version));
     565                 :            :                 return 0;
     566                 :            :         }
     567                 :            : 
     568                 :            :         csr->version = css_header->version;
     569                 :            : 
     570                 :            :         return sizeof(struct intel_css_header);
     571                 :            : }
     572                 :            : 
     573                 :          0 : static void parse_csr_fw(struct drm_i915_private *dev_priv,
     574                 :            :                          const struct firmware *fw)
     575                 :            : {
     576                 :          0 :         struct intel_css_header *css_header;
     577                 :          0 :         struct intel_package_header *package_header;
     578                 :          0 :         struct intel_dmc_header_base *dmc_header;
     579                 :          0 :         struct intel_csr *csr = &dev_priv->csr;
     580         [ #  # ]:          0 :         const struct stepping_info *si = intel_get_stepping_info(dev_priv);
     581                 :          0 :         u32 readcount = 0;
     582                 :          0 :         u32 r;
     583                 :            : 
     584         [ #  # ]:          0 :         if (!fw)
     585                 :            :                 return;
     586                 :            : 
     587                 :            :         /* Extract CSS Header information */
     588                 :          0 :         css_header = (struct intel_css_header *)fw->data;
     589                 :          0 :         r = parse_csr_fw_css(csr, css_header, fw->size);
     590         [ #  # ]:          0 :         if (!r)
     591                 :            :                 return;
     592                 :            : 
     593                 :          0 :         readcount += r;
     594                 :            : 
     595                 :            :         /* Extract Package Header information */
     596                 :          0 :         package_header = (struct intel_package_header *)&fw->data[readcount];
     597                 :          0 :         r = parse_csr_fw_package(csr, package_header, si, fw->size - readcount);
     598         [ #  # ]:          0 :         if (!r)
     599                 :            :                 return;
     600                 :            : 
     601                 :          0 :         readcount += r;
     602                 :            : 
     603                 :            :         /* Extract dmc_header information */
     604                 :          0 :         dmc_header = (struct intel_dmc_header_base *)&fw->data[readcount];
     605                 :          0 :         parse_csr_fw_dmc(csr, dmc_header, fw->size - readcount);
     606                 :            : }
     607                 :            : 
     608                 :          0 : static void intel_csr_runtime_pm_get(struct drm_i915_private *dev_priv)
     609                 :            : {
     610         [ #  # ]:          0 :         WARN_ON(dev_priv->csr.wakeref);
     611                 :          0 :         dev_priv->csr.wakeref =
     612                 :          0 :                 intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
     613                 :          0 : }
     614                 :            : 
     615                 :          0 : static void intel_csr_runtime_pm_put(struct drm_i915_private *dev_priv)
     616                 :            : {
     617                 :          0 :         intel_wakeref_t wakeref __maybe_unused =
     618                 :          0 :                 fetch_and_zero(&dev_priv->csr.wakeref);
     619                 :            : 
     620                 :          0 :         intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref);
     621                 :          0 : }
     622                 :            : 
     623                 :          0 : static void csr_load_work_fn(struct work_struct *work)
     624                 :            : {
     625                 :          0 :         struct drm_i915_private *dev_priv;
     626                 :          0 :         struct intel_csr *csr;
     627                 :          0 :         const struct firmware *fw = NULL;
     628                 :            : 
     629                 :          0 :         dev_priv = container_of(work, typeof(*dev_priv), csr.work);
     630                 :          0 :         csr = &dev_priv->csr;
     631                 :            : 
     632                 :          0 :         request_firmware(&fw, dev_priv->csr.fw_path, &dev_priv->drm.pdev->dev);
     633                 :          0 :         parse_csr_fw(dev_priv, fw);
     634                 :            : 
     635         [ #  # ]:          0 :         if (dev_priv->csr.dmc_payload) {
     636                 :          0 :                 intel_csr_load_program(dev_priv);
     637                 :          0 :                 intel_csr_runtime_pm_put(dev_priv);
     638                 :            : 
     639                 :          0 :                 DRM_INFO("Finished loading DMC firmware %s (v%u.%u)\n",
     640                 :            :                          dev_priv->csr.fw_path,
     641                 :            :                          CSR_VERSION_MAJOR(csr->version),
     642                 :            :                          CSR_VERSION_MINOR(csr->version));
     643                 :            :         } else {
     644                 :          0 :                 dev_notice(dev_priv->drm.dev,
     645                 :            :                            "Failed to load DMC firmware %s."
     646                 :            :                            " Disabling runtime power management.\n",
     647                 :            :                            csr->fw_path);
     648                 :          0 :                 dev_notice(dev_priv->drm.dev, "DMC firmware homepage: %s",
     649                 :            :                            INTEL_UC_FIRMWARE_URL);
     650                 :            :         }
     651                 :            : 
     652                 :          0 :         release_firmware(fw);
     653                 :          0 : }
     654                 :            : 
     655                 :            : /**
     656                 :            :  * intel_csr_ucode_init() - initialize the firmware loading.
     657                 :            :  * @dev_priv: i915 drm device.
     658                 :            :  *
     659                 :            :  * This function is called at the time of loading the display driver to read
     660                 :            :  * firmware from a .bin file and copied into a internal memory.
     661                 :            :  */
     662                 :          0 : void intel_csr_ucode_init(struct drm_i915_private *dev_priv)
     663                 :            : {
     664                 :          0 :         struct intel_csr *csr = &dev_priv->csr;
     665                 :            : 
     666         [ #  # ]:          0 :         INIT_WORK(&dev_priv->csr.work, csr_load_work_fn);
     667                 :            : 
     668         [ #  # ]:          0 :         if (!HAS_CSR(dev_priv))
     669                 :            :                 return;
     670                 :            : 
     671                 :            :         /*
     672                 :            :          * Obtain a runtime pm reference, until CSR is loaded, to avoid entering
     673                 :            :          * runtime-suspend.
     674                 :            :          *
     675                 :            :          * On error, we return with the rpm wakeref held to prevent runtime
     676                 :            :          * suspend as runtime suspend *requires* a working CSR for whatever
     677                 :            :          * reason.
     678                 :            :          */
     679                 :          0 :         intel_csr_runtime_pm_get(dev_priv);
     680                 :            : 
     681         [ #  # ]:          0 :         if (INTEL_GEN(dev_priv) >= 12) {
     682                 :          0 :                 csr->fw_path = TGL_CSR_PATH;
     683                 :          0 :                 csr->required_version = TGL_CSR_VERSION_REQUIRED;
     684                 :            :                 /* Allow to load fw via parameter using the last known size */
     685                 :          0 :                 csr->max_fw_size = GEN12_CSR_MAX_FW_SIZE;
     686         [ #  # ]:          0 :         } else if (IS_GEN(dev_priv, 11)) {
     687                 :          0 :                 csr->fw_path = ICL_CSR_PATH;
     688                 :          0 :                 csr->required_version = ICL_CSR_VERSION_REQUIRED;
     689                 :          0 :                 csr->max_fw_size = ICL_CSR_MAX_FW_SIZE;
     690         [ #  # ]:          0 :         } else if (IS_CANNONLAKE(dev_priv)) {
     691                 :          0 :                 csr->fw_path = CNL_CSR_PATH;
     692                 :          0 :                 csr->required_version = CNL_CSR_VERSION_REQUIRED;
     693                 :          0 :                 csr->max_fw_size = CNL_CSR_MAX_FW_SIZE;
     694         [ #  # ]:          0 :         } else if (IS_GEMINILAKE(dev_priv)) {
     695                 :          0 :                 csr->fw_path = GLK_CSR_PATH;
     696                 :          0 :                 csr->required_version = GLK_CSR_VERSION_REQUIRED;
     697                 :          0 :                 csr->max_fw_size = GLK_CSR_MAX_FW_SIZE;
     698   [ #  #  #  # ]:          0 :         } else if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) {
     699                 :          0 :                 csr->fw_path = KBL_CSR_PATH;
     700                 :          0 :                 csr->required_version = KBL_CSR_VERSION_REQUIRED;
     701                 :          0 :                 csr->max_fw_size = KBL_CSR_MAX_FW_SIZE;
     702         [ #  # ]:          0 :         } else if (IS_SKYLAKE(dev_priv)) {
     703                 :          0 :                 csr->fw_path = SKL_CSR_PATH;
     704                 :          0 :                 csr->required_version = SKL_CSR_VERSION_REQUIRED;
     705                 :          0 :                 csr->max_fw_size = SKL_CSR_MAX_FW_SIZE;
     706         [ #  # ]:          0 :         } else if (IS_BROXTON(dev_priv)) {
     707                 :          0 :                 csr->fw_path = BXT_CSR_PATH;
     708                 :          0 :                 csr->required_version = BXT_CSR_VERSION_REQUIRED;
     709                 :          0 :                 csr->max_fw_size = BXT_CSR_MAX_FW_SIZE;
     710                 :            :         }
     711                 :            : 
     712         [ #  # ]:          0 :         if (i915_modparams.dmc_firmware_path) {
     713         [ #  # ]:          0 :                 if (strlen(i915_modparams.dmc_firmware_path) == 0) {
     714                 :          0 :                         csr->fw_path = NULL;
     715                 :          0 :                         DRM_INFO("Disabling CSR firmware and runtime PM\n");
     716                 :          0 :                         return;
     717                 :            :                 }
     718                 :            : 
     719                 :          0 :                 csr->fw_path = i915_modparams.dmc_firmware_path;
     720                 :            :                 /* Bypass version check for firmware override. */
     721                 :          0 :                 csr->required_version = 0;
     722                 :            :         }
     723                 :            : 
     724         [ #  # ]:          0 :         if (csr->fw_path == NULL) {
     725                 :          0 :                 DRM_DEBUG_KMS("No known CSR firmware for platform, disabling runtime PM\n");
     726                 :          0 :                 return;
     727                 :            :         }
     728                 :            : 
     729                 :          0 :         DRM_DEBUG_KMS("Loading %s\n", csr->fw_path);
     730                 :          0 :         schedule_work(&dev_priv->csr.work);
     731                 :            : }
     732                 :            : 
     733                 :            : /**
     734                 :            :  * intel_csr_ucode_suspend() - prepare CSR firmware before system suspend
     735                 :            :  * @dev_priv: i915 drm device
     736                 :            :  *
     737                 :            :  * Prepare the DMC firmware before entering system suspend. This includes
     738                 :            :  * flushing pending work items and releasing any resources acquired during
     739                 :            :  * init.
     740                 :            :  */
     741                 :          0 : void intel_csr_ucode_suspend(struct drm_i915_private *dev_priv)
     742                 :            : {
     743         [ #  # ]:          0 :         if (!HAS_CSR(dev_priv))
     744                 :            :                 return;
     745                 :            : 
     746                 :          0 :         flush_work(&dev_priv->csr.work);
     747                 :            : 
     748                 :            :         /* Drop the reference held in case DMC isn't loaded. */
     749         [ #  # ]:          0 :         if (!dev_priv->csr.dmc_payload)
     750                 :          0 :                 intel_csr_runtime_pm_put(dev_priv);
     751                 :            : }
     752                 :            : 
     753                 :            : /**
     754                 :            :  * intel_csr_ucode_resume() - init CSR firmware during system resume
     755                 :            :  * @dev_priv: i915 drm device
     756                 :            :  *
     757                 :            :  * Reinitialize the DMC firmware during system resume, reacquiring any
     758                 :            :  * resources released in intel_csr_ucode_suspend().
     759                 :            :  */
     760                 :          0 : void intel_csr_ucode_resume(struct drm_i915_private *dev_priv)
     761                 :            : {
     762         [ #  # ]:          0 :         if (!HAS_CSR(dev_priv))
     763                 :            :                 return;
     764                 :            : 
     765                 :            :         /*
     766                 :            :          * Reacquire the reference to keep RPM disabled in case DMC isn't
     767                 :            :          * loaded.
     768                 :            :          */
     769         [ #  # ]:          0 :         if (!dev_priv->csr.dmc_payload)
     770                 :          0 :                 intel_csr_runtime_pm_get(dev_priv);
     771                 :            : }
     772                 :            : 
     773                 :            : /**
     774                 :            :  * intel_csr_ucode_fini() - unload the CSR firmware.
     775                 :            :  * @dev_priv: i915 drm device.
     776                 :            :  *
     777                 :            :  * Firmmware unloading includes freeing the internal memory and reset the
     778                 :            :  * firmware loading status.
     779                 :            :  */
     780                 :          0 : void intel_csr_ucode_fini(struct drm_i915_private *dev_priv)
     781                 :            : {
     782         [ #  # ]:          0 :         if (!HAS_CSR(dev_priv))
     783                 :            :                 return;
     784                 :            : 
     785                 :          0 :         intel_csr_ucode_suspend(dev_priv);
     786         [ #  # ]:          0 :         WARN_ON(dev_priv->csr.wakeref);
     787                 :            : 
     788                 :          0 :         kfree(dev_priv->csr.dmc_payload);
     789                 :            : }

Generated by: LCOV version 1.14