max_freq = (IS_BROXTON(dev) ? rp_state_cap >> 0 :
                            rp_state_cap >> 16) & 0xff;
-               max_freq *= (IS_SKYLAKE(dev) ? GEN9_FREQ_SCALER : 1);
+               max_freq *= (IS_SKYLAKE(dev) || IS_KABYLAKE(dev) ?
+                            GEN9_FREQ_SCALER : 1);
                seq_printf(m, "Lowest (RPN) frequency: %dMHz\n",
                           intel_gpu_freq(dev_priv, max_freq));
 
                max_freq = (rp_state_cap & 0xff00) >> 8;
-               max_freq *= (IS_SKYLAKE(dev) ? GEN9_FREQ_SCALER : 1);
+               max_freq *= (IS_SKYLAKE(dev) || IS_KABYLAKE(dev) ?
+                            GEN9_FREQ_SCALER : 1);
                seq_printf(m, "Nominal (RP1) frequency: %dMHz\n",
                           intel_gpu_freq(dev_priv, max_freq));
 
                max_freq = (IS_BROXTON(dev) ? rp_state_cap >> 16 :
                            rp_state_cap >> 0) & 0xff;
-               max_freq *= (IS_SKYLAKE(dev) ? GEN9_FREQ_SCALER : 1);
+               max_freq *= (IS_SKYLAKE(dev) || IS_KABYLAKE(dev) ?
+                            GEN9_FREQ_SCALER : 1);
                seq_printf(m, "Max non-overclocked (RP0) frequency: %dMHz\n",
                           intel_gpu_freq(dev_priv, max_freq));
                seq_printf(m, "Max overclocked frequency: %dMHz\n",
        if (ret)
                goto out;
 
-       if (IS_SKYLAKE(dev)) {
+       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
                /* Convert GT frequency to 50 HZ units */
                min_gpu_freq =
                        dev_priv->rps.min_freq_softlimit / GEN9_FREQ_SCALER;
                                       &ia_freq);
                seq_printf(m, "%d\t\t%d\t\t\t\t%d\n",
                           intel_gpu_freq(dev_priv, (gpu_freq *
-                               (IS_SKYLAKE(dev) ? GEN9_FREQ_SCALER : 1))),
+                               (IS_SKYLAKE(dev) || IS_KABYLAKE(dev) ?
+                                GEN9_FREQ_SCALER : 1))),
                           ((ia_freq >> 0) & 0xff) * 100,
                           ((ia_freq >> 8) & 0xff) * 100);
        }
 
                stat->slice_total++;
 
-               if (IS_SKYLAKE(dev))
+               if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
                        ss_cnt = INTEL_INFO(dev)->subslice_per_slice;
 
                for (ss = 0; ss < ss_max; ss++) {
 
         * supports EU power gating on devices with more than one EU
         * pair per subslice.
        */
-       info->has_slice_pg = (IS_SKYLAKE(dev) && (info->slice_total > 1));
+       info->has_slice_pg = ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) &&
+                              (info->slice_total > 1));
        info->has_subslice_pg = (IS_BROXTON(dev) && (info->subslice_total > 1));
        info->has_eu_pg = (info->eu_per_subslice > 2);
 }
 
        IVB_CURSOR_OFFSETS,
 };
 
+static const struct intel_device_info intel_kabylake_info = {
+       .is_preliminary = 1,
+       .is_kabylake = 1,
+       .gen = 9,
+       .num_pipes = 3,
+       .need_gfx_hws = 1, .has_hotplug = 1,
+       .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
+       .has_llc = 1,
+       .has_ddi = 1,
+       .has_fpga_dbg = 1,
+       .has_fbc = 1,
+       GEN_DEFAULT_PIPEOFFSETS,
+       IVB_CURSOR_OFFSETS,
+};
+
+static const struct intel_device_info intel_kabylake_gt3_info = {
+       .is_preliminary = 1,
+       .is_kabylake = 1,
+       .gen = 9,
+       .num_pipes = 3,
+       .need_gfx_hws = 1, .has_hotplug = 1,
+       .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
+       .has_llc = 1,
+       .has_ddi = 1,
+       .has_fpga_dbg = 1,
+       .has_fbc = 1,
+       GEN_DEFAULT_PIPEOFFSETS,
+       IVB_CURSOR_OFFSETS,
+};
+
 /*
  * Make sure any device matches here are from most specific to most
  * general.  For example, since the Quanta match is based on the subsystem
        } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
                ret = PCH_LPT;
                DRM_DEBUG_KMS("Assuming LynxPoint PCH\n");
-       } else if (IS_SKYLAKE(dev)) {
+       } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
                ret = PCH_SPT;
                DRM_DEBUG_KMS("Assuming SunrisePoint PCH\n");
        }
                        } else if (id == INTEL_PCH_SPT_DEVICE_ID_TYPE) {
                                dev_priv->pch_type = PCH_SPT;
                                DRM_DEBUG_KMS("Found SunrisePoint PCH\n");
-                               WARN_ON(!IS_SKYLAKE(dev));
+                               WARN_ON(!IS_SKYLAKE(dev) &&
+                                       !IS_KABYLAKE(dev));
                        } else if (id == INTEL_PCH_SPT_LP_DEVICE_ID_TYPE) {
                                dev_priv->pch_type = PCH_SPT;
                                DRM_DEBUG_KMS("Found SunrisePoint LP PCH\n");
-                               WARN_ON(!IS_SKYLAKE(dev));
+                               WARN_ON(!IS_SKYLAKE(dev) &&
+                                       !IS_KABYLAKE(dev));
                        } else if (id == INTEL_PCH_P2X_DEVICE_ID_TYPE) {
                                dev_priv->pch_type = intel_virt_detect_pch(dev);
                        } else
 
        if (IS_BROXTON(dev))
                ret = bxt_resume_prepare(dev_priv);
-       else if (IS_SKYLAKE(dev_priv))
+       else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
                ret = skl_resume_prepare(dev_priv);
        else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
                hsw_disable_pc8(dev_priv);
 
        if (IS_BROXTON(dev))
                ret = bxt_resume_prepare(dev_priv);
-       else if (IS_SKYLAKE(dev))
+       else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
                ret = skl_resume_prepare(dev_priv);
        else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
                hsw_disable_pc8(dev_priv);
 
        if (IS_BROXTON(dev_priv))
                ret = bxt_suspend_complete(dev_priv);
-       else if (IS_SKYLAKE(dev_priv))
+       else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
                ret = skl_suspend_complete(dev_priv);
        else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
                ret = hsw_suspend_complete(dev_priv);
 
        func(is_haswell) sep \
        func(is_skylake) sep \
        func(is_broxton) sep \
+       func(is_kabylake) sep \
        func(is_preliminary) sep \
        func(has_fbc) sep \
        func(has_pipe_cxsr) sep \
 #define IS_BROADWELL(dev)      (!INTEL_INFO(dev)->is_valleyview && IS_GEN8(dev))
 #define IS_SKYLAKE(dev)        (INTEL_INFO(dev)->is_skylake)
 #define IS_BROXTON(dev)                (INTEL_INFO(dev)->is_broxton)
+#define IS_KABYLAKE(dev)       (INTEL_INFO(dev)->is_kabylake)
 #define IS_MOBILE(dev)         (INTEL_INFO(dev)->is_mobile)
 #define IS_HSW_EARLY_SDV(dev)  (IS_HASWELL(dev) && \
                                 (INTEL_DEVID(dev) & 0xFF00) == 0x0C00)
 #define HAS_FPGA_DBG_UNCLAIMED(dev)    (INTEL_INFO(dev)->has_fpga_dbg)
 #define HAS_PSR(dev)           (IS_HASWELL(dev) || IS_BROADWELL(dev) || \
                                 IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev) || \
-                                IS_SKYLAKE(dev))
+                                IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
 #define HAS_RUNTIME_PM(dev)    (IS_GEN6(dev) || IS_HASWELL(dev) || \
                                 IS_BROADWELL(dev) || IS_VALLEYVIEW(dev) || \
-                                IS_SKYLAKE(dev))
+                                IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
 #define HAS_RC6(dev)           (INTEL_INFO(dev)->gen >= 6)
 #define HAS_RC6p(dev)          (INTEL_INFO(dev)->gen == 6 || IS_IVYBRIDGE(dev))
 
 
                                         &reserved_size);
                break;
        default:
-               if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv))
+               if (IS_BROADWELL(dev_priv) ||
+                   IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev))
                        bdw_get_stolen_reserved(dev_priv, &reserved_base,
                                                &reserved_size);
                else
 
        struct drm_i915_private *dev_priv = dev_to_i915(dev);
        u32 tmp;
 
-       if (!IS_SKYLAKE(dev_priv))
+       if (!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv))
                return;
 
        /*
        u32 tmp;
        int n;
 
-       /* HSW, BDW SKL need this fix */
+       /* HSW, BDW, SKL, KBL need this fix */
        if (!IS_SKYLAKE(dev_priv) &&
-               !IS_BROADWELL(dev_priv) &&
-               !IS_HASWELL(dev_priv))
+           !IS_KABYLAKE(dev_priv) &&
+           !IS_BROADWELL(dev_priv) &&
+           !IS_HASWELL(dev_priv))
                return 0;
 
        mutex_lock(&dev_priv->av_mutex);
 
                bxt_ddi_vswing_sequence(dev, hdmi_level, port,
                                        INTEL_OUTPUT_HDMI);
                return;
-       } else if (IS_SKYLAKE(dev)) {
+       } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
                ddi_translations_fdi = NULL;
                ddi_translations_dp =
                                skl_get_buf_trans_dp(dev, &n_dp_entries);
 
        if (INTEL_INFO(dev)->gen <= 8)
                hsw_ddi_clock_get(encoder, pipe_config);
-       else if (IS_SKYLAKE(dev))
+       else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
                skl_ddi_clock_get(encoder, pipe_config);
        else if (IS_BROXTON(dev))
                bxt_ddi_clock_get(encoder, pipe_config);
        struct intel_encoder *intel_encoder =
                intel_ddi_get_crtc_new_encoder(crtc_state);
 
-       if (IS_SKYLAKE(dev))
+       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
                return skl_ddi_pll_select(intel_crtc, crtc_state,
                                          intel_encoder);
        else if (IS_BROXTON(dev))
 
        level = translate_signal_level(signal_levels);
 
-       if (IS_SKYLAKE(dev))
+       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
                skl_ddi_set_iboost(dev, level, port, encoder->type);
        else if (IS_BROXTON(dev))
                bxt_ddi_vswing_sequence(dev, level, port, encoder->type);
                intel_edp_panel_on(intel_dp);
        }
 
-       if (IS_SKYLAKE(dev)) {
+       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
                uint32_t dpll = crtc->config->ddi_pll_sel;
                uint32_t val;
 
                intel_edp_panel_off(intel_dp);
        }
 
-       if (IS_SKYLAKE(dev))
+       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
                I915_WRITE(DPLL_CTRL2, (I915_READ(DPLL_CTRL2) |
                                        DPLL_CTRL2_DDI_CLK_OFF(port)));
        else if (INTEL_INFO(dev)->gen < 9)
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t val = I915_READ(LCPLL_CTL);
 
-       if (IS_SKYLAKE(dev))
+       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
                skl_shared_dplls_init(dev_priv);
        else if (IS_BROXTON(dev))
                bxt_shared_dplls_init(dev_priv);
        else
                hsw_shared_dplls_init(dev_priv);
 
-       if (IS_SKYLAKE(dev)) {
+       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
                int cdclk_freq;
 
                cdclk_freq = dev_priv->display.get_display_clock_speed(dev);
 
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       if (IS_SKYLAKE(dev)) {
+       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
                u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK;
 
                if (limit == SKL_DFSM_CDCLK_LIMIT_675)
 
        port = (tmp & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT;
 
-       if (IS_SKYLAKE(dev))
+       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
                skylake_get_ddi_pll(dev_priv, port, pipe_config);
        else if (IS_BROXTON(dev))
                bxt_get_ddi_pll(dev_priv, port, pipe_config);
                              pipe_config->dpll_hw_state.pll9,
                              pipe_config->dpll_hw_state.pll10,
                              pipe_config->dpll_hw_state.pcsdw12);
-       } else if (IS_SKYLAKE(dev)) {
+       } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
                DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: "
                              "ctrl1: 0x%x, cfgcr1: 0x%x, cfgcr2: 0x%x\n",
                              pipe_config->ddi_pll_sel,
                 */
                found = I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_INIT_DISPLAY_DETECTED;
                /* WaIgnoreDDIAStrap: skl */
-               if (found || IS_SKYLAKE(dev))
+               if (found || IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
                        intel_ddi_init(dev, PORT_A);
 
                /* DDI B, C and D detection is indicated by the SFUSE_STRAP
                /*
                 * On SKL we don't have a way to detect DDI-E so we rely on VBT.
                 */
-               if (IS_SKYLAKE(dev) &&
+               if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) &&
                    (dev_priv->vbt.ddi_port_info[PORT_E].supports_dp ||
                     dev_priv->vbt.ddi_port_info[PORT_E].supports_dvi ||
                     dev_priv->vbt.ddi_port_info[PORT_E].supports_hdmi))
        }
 
        /* Returns the core display clock speed */
-       if (IS_SKYLAKE(dev))
+       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
                dev_priv->display.get_display_clock_speed =
                        skylake_get_display_clock_speed;
        else if (IS_BROXTON(dev))
 
        /* On SKL we don't have Aux for port E so we rely on VBT to set
         * a proper alternate aux channel.
         */
-       if (IS_SKYLAKE(dev) && port == PORT_E) {
+       if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) && port == PORT_E) {
                switch (info->alternate_aux_channel) {
                case DP_AUX_B:
                        porte_aux_ctl_reg = DPB_AUX_CH_CTL;
        if (IS_BROXTON(dev)) {
                *source_rates = bxt_rates;
                size = ARRAY_SIZE(bxt_rates);
-       } else if (IS_SKYLAKE(dev)) {
+       } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
                *source_rates = skl_rates;
                size = ARRAY_SIZE(skl_rates);
        } else {
                                &pipe_config->dp_m2_n2);
        }
 
-       if (IS_SKYLAKE(dev) && is_edp(intel_dp))
+       if ((IS_SKYLAKE(dev)  || IS_KABYLAKE(dev)) && is_edp(intel_dp))
                skl_edp_set_pll_config(pipe_config);
        else if (IS_BROXTON(dev))
                /* handled in ddi */;
 
         * reserved range size, so it always assumes the maximum (8mb) is used.
         * If we enable FBC using a CFB on that memory range we'll get FIFO
         * underruns, even if that range is not reserved by the BIOS. */
-       if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv))
+       if (IS_BROADWELL(dev_priv) ||
+           IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
                end = dev_priv->gtt.stolen_size - 8 * 1024 * 1024;
        else
                end = dev_priv->gtt.stolen_usable_size;
 
 {
        if (IS_BROXTON(dev_priv))
                return &gmbus_pins_bxt[pin];
-       else if (IS_SKYLAKE(dev_priv))
+       else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
                return &gmbus_pins_skl[pin];
        else if (IS_BROADWELL(dev_priv))
                return &gmbus_pins_bdw[pin];
 
        if (IS_BROXTON(dev_priv))
                size = ARRAY_SIZE(gmbus_pins_bxt);
-       else if (IS_SKYLAKE(dev_priv))
+       else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
                size = ARRAY_SIZE(gmbus_pins_skl);
        else if (IS_BROADWELL(dev_priv))
                size = ARRAY_SIZE(gmbus_pins_bdw);
 
 {
        bool result = false;
 
-       if (IS_SKYLAKE(dev)) {
+       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
                table->size  = ARRAY_SIZE(skylake_mocs_table);
                table->table = skylake_mocs_table;
                result = true;
 
        dev_priv->rps.max_freq          = dev_priv->rps.rp0_freq;
 
        dev_priv->rps.efficient_freq = dev_priv->rps.rp1_freq;
-       if (IS_HASWELL(dev) || IS_BROADWELL(dev) || IS_SKYLAKE(dev)) {
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev) ||
+           IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
                ret = sandybridge_pcode_read(dev_priv,
                                        HSW_PCODE_DYNAMIC_DUTY_CYCLE_CONTROL,
                                        &ddcc_status);
                                        dev_priv->rps.max_freq);
        }
 
-       if (IS_SKYLAKE(dev)) {
+       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
                /* Store the frequency values in 16.66 MHZ units, which is
                   the natural hardware unit for SKL */
                dev_priv->rps.rp0_freq *= GEN9_FREQ_SCALER;
        /* convert DDR frequency from units of 266.6MHz to bandwidth */
        min_ring_freq = mult_frac(min_ring_freq, 8, 3);
 
-       if (IS_SKYLAKE(dev)) {
+       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
                /* Convert GT frequency to 50 HZ units */
                min_gpu_freq = dev_priv->rps.min_freq / GEN9_FREQ_SCALER;
                max_gpu_freq = dev_priv->rps.max_freq / GEN9_FREQ_SCALER;
                int diff = max_gpu_freq - gpu_freq;
                unsigned int ia_freq = 0, ring_freq = 0;
 
-               if (IS_SKYLAKE(dev)) {
+               if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
                        /*
                         * ring_freq = 2 * GT. ring_freq is in 100MHz units
                         * No floor required for ring frequency on SKL.
        } else if (INTEL_INFO(dev)->gen >= 9) {
                gen9_enable_rc6(dev);
                gen9_enable_rps(dev);
-               if (IS_SKYLAKE(dev))
+               if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
                        __gen6_update_ring_freq(dev);
        } else if (IS_BROADWELL(dev)) {
                gen8_enable_rps(dev);
 
                set_power_wells(power_domains, hsw_power_wells);
        } else if (IS_BROADWELL(dev_priv->dev)) {
                set_power_wells(power_domains, bdw_power_wells);
-       } else if (IS_SKYLAKE(dev_priv->dev)) {
+       } else if (IS_SKYLAKE(dev_priv->dev) || IS_KABYLAKE(dev_priv->dev)) {
                set_power_wells(power_domains, skl_power_wells);
        } else if (IS_BROXTON(dev_priv->dev)) {
                set_power_wells(power_domains, bxt_power_wells);