LCOV - code coverage report
Current view: top level - dev/pci/drm/i915 - intel_fbdev.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 256 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 11 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright © 2007 David Airlie
       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
      21             :  * DEALINGS IN THE SOFTWARE.
      22             :  *
      23             :  * Authors:
      24             :  *     David Airlie
      25             :  */
      26             : 
      27             : #ifdef __linux__
      28             : #include <linux/async.h>
      29             : #include <linux/module.h>
      30             : #include <linux/kernel.h>
      31             : #include <linux/console.h>
      32             : #include <linux/errno.h>
      33             : #include <linux/string.h>
      34             : #include <linux/mm.h>
      35             : #include <linux/tty.h>
      36             : #include <linux/sysrq.h>
      37             : #include <linux/delay.h>
      38             : #include <linux/fb.h>
      39             : #include <linux/init.h>
      40             : #include <linux/vga_switcheroo.h>
      41             : #endif
      42             : 
      43             : #include <dev/pci/drm/drmP.h>
      44             : #include <dev/pci/drm/drm_crtc.h>
      45             : #include <dev/pci/drm/drm_fb_helper.h>
      46             : #include "intel_drv.h"
      47             : #include <dev/pci/drm/i915_drm.h>
      48             : #include "i915_drv.h"
      49             : 
      50             : #ifdef notyet
      51             : 
      52             : static int intel_fbdev_set_par(struct fb_info *info)
      53             : {
      54             :         struct drm_fb_helper *fb_helper = info->par;
      55             :         struct intel_fbdev *ifbdev =
      56             :                 container_of(fb_helper, struct intel_fbdev, helper);
      57             :         int ret;
      58             : 
      59             :         ret = drm_fb_helper_set_par(info);
      60             : 
      61             :         if (ret == 0) {
      62             :                 mutex_lock(&fb_helper->dev->struct_mutex);
      63             :                 intel_fb_obj_invalidate(ifbdev->fb->obj, ORIGIN_GTT);
      64             :                 mutex_unlock(&fb_helper->dev->struct_mutex);
      65             :         }
      66             : 
      67             :         return ret;
      68             : }
      69             : 
      70             : static int intel_fbdev_blank(int blank, struct fb_info *info)
      71             : {
      72             :         struct drm_fb_helper *fb_helper = info->par;
      73             :         struct intel_fbdev *ifbdev =
      74             :                 container_of(fb_helper, struct intel_fbdev, helper);
      75             :         int ret;
      76             : 
      77             :         ret = drm_fb_helper_blank(blank, info);
      78             : 
      79             :         if (ret == 0) {
      80             :                 mutex_lock(&fb_helper->dev->struct_mutex);
      81             :                 intel_fb_obj_invalidate(ifbdev->fb->obj, ORIGIN_GTT);
      82             :                 mutex_unlock(&fb_helper->dev->struct_mutex);
      83             :         }
      84             : 
      85             :         return ret;
      86             : }
      87             : 
      88             : static int intel_fbdev_pan_display(struct fb_var_screeninfo *var,
      89             :                                    struct fb_info *info)
      90             : {
      91             :         struct drm_fb_helper *fb_helper = info->par;
      92             :         struct intel_fbdev *ifbdev =
      93             :                 container_of(fb_helper, struct intel_fbdev, helper);
      94             : 
      95             :         int ret;
      96             :         ret = drm_fb_helper_pan_display(var, info);
      97             : 
      98             :         if (ret == 0) {
      99             :                 mutex_lock(&fb_helper->dev->struct_mutex);
     100             :                 intel_fb_obj_invalidate(ifbdev->fb->obj, ORIGIN_GTT);
     101             :                 mutex_unlock(&fb_helper->dev->struct_mutex);
     102             :         }
     103             : 
     104             :         return ret;
     105             : }
     106             : 
     107             : static struct fb_ops intelfb_ops = {
     108             :         .owner = THIS_MODULE,
     109             :         .fb_check_var = drm_fb_helper_check_var,
     110             :         .fb_set_par = intel_fbdev_set_par,
     111             :         .fb_fillrect = drm_fb_helper_cfb_fillrect,
     112             :         .fb_copyarea = drm_fb_helper_cfb_copyarea,
     113             :         .fb_imageblit = drm_fb_helper_cfb_imageblit,
     114             :         .fb_pan_display = intel_fbdev_pan_display,
     115             :         .fb_blank = intel_fbdev_blank,
     116             :         .fb_setcmap = drm_fb_helper_setcmap,
     117             :         .fb_debug_enter = drm_fb_helper_debug_enter,
     118             :         .fb_debug_leave = drm_fb_helper_debug_leave,
     119             : };
     120             : 
     121             : #endif
     122             : 
     123           0 : static int intelfb_alloc(struct drm_fb_helper *helper,
     124             :                          struct drm_fb_helper_surface_size *sizes)
     125             : {
     126             :         struct intel_fbdev *ifbdev =
     127           0 :                 container_of(helper, struct intel_fbdev, helper);
     128             :         struct drm_framebuffer *fb;
     129           0 :         struct drm_device *dev = helper->dev;
     130           0 :         struct drm_i915_private *dev_priv = to_i915(dev);
     131           0 :         struct drm_mode_fb_cmd2 mode_cmd = {};
     132             :         struct drm_i915_gem_object *obj = NULL;
     133             :         int size, ret;
     134             : 
     135             :         /* we don't do packed 24bpp */
     136           0 :         if (sizes->surface_bpp == 24)
     137           0 :                 sizes->surface_bpp = 32;
     138             : 
     139           0 :         mode_cmd.width = sizes->surface_width;
     140           0 :         mode_cmd.height = sizes->surface_height;
     141             : 
     142           0 :         mode_cmd.pitches[0] = round_up(mode_cmd.width *
     143             :                                     DIV_ROUND_UP(sizes->surface_bpp, 8), 64);
     144           0 :         mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
     145           0 :                                                           sizes->surface_depth);
     146             : 
     147           0 :         size = mode_cmd.pitches[0] * mode_cmd.height;
     148           0 :         size = PAGE_ALIGN(size);
     149             : 
     150             :         /* If the FB is too big, just don't use it since fbdev is not very
     151             :          * important and we should probably use that space with FBC or other
     152             :          * features. */
     153           0 :         if (size * 2 < dev_priv->gtt.stolen_usable_size)
     154           0 :                 obj = i915_gem_object_create_stolen(dev, size);
     155           0 :         if (obj == NULL)
     156           0 :                 obj = i915_gem_alloc_object(dev, size);
     157           0 :         if (!obj) {
     158           0 :                 DRM_ERROR("failed to allocate framebuffer\n");
     159             :                 ret = -ENOMEM;
     160           0 :                 goto out;
     161             :         }
     162             : 
     163           0 :         fb = __intel_framebuffer_create(dev, &mode_cmd, obj);
     164           0 :         if (IS_ERR(fb)) {
     165           0 :                 ret = PTR_ERR(fb);
     166           0 :                 goto out_unref;
     167             :         }
     168             : 
     169             :         /* Flush everything out, we'll be doing GTT only from now on */
     170           0 :         ret = intel_pin_and_fence_fb_obj(NULL, fb, NULL, NULL, NULL);
     171           0 :         if (ret) {
     172           0 :                 DRM_ERROR("failed to pin obj: %d\n", ret);
     173             :                 goto out_fb;
     174             :         }
     175             : 
     176           0 :         ifbdev->fb = to_intel_framebuffer(fb);
     177             : 
     178           0 :         return 0;
     179             : 
     180             : out_fb:
     181           0 :         drm_framebuffer_remove(fb);
     182             : out_unref:
     183           0 :         drm_gem_object_unreference(&obj->base);
     184             : out:
     185           0 :         return ret;
     186           0 : }
     187             : 
     188           0 : static int intelfb_create(struct drm_fb_helper *helper,
     189             :                           struct drm_fb_helper_surface_size *sizes)
     190             : {
     191             :         struct intel_fbdev *ifbdev =
     192           0 :                 container_of(helper, struct intel_fbdev, helper);
     193           0 :         struct intel_framebuffer *intel_fb = ifbdev->fb;
     194           0 :         struct drm_device *dev = helper->dev;
     195           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     196             :         struct fb_info *info;
     197             :         struct drm_framebuffer *fb;
     198             :         struct drm_i915_gem_object *obj;
     199             :         int size, ret;
     200             :         bool prealloc = false;
     201             : 
     202           0 :         mutex_lock(&dev->struct_mutex);
     203             : 
     204           0 :         if (intel_fb &&
     205           0 :             (sizes->fb_width > intel_fb->base.width ||
     206           0 :              sizes->fb_height > intel_fb->base.height)) {
     207             :                 DRM_DEBUG_KMS("BIOS fb too small (%dx%d), we require (%dx%d),"
     208             :                               " releasing it\n",
     209             :                               intel_fb->base.width, intel_fb->base.height,
     210             :                               sizes->fb_width, sizes->fb_height);
     211           0 :                 drm_framebuffer_unreference(&intel_fb->base);
     212           0 :                 intel_fb = ifbdev->fb = NULL;
     213           0 :         }
     214           0 :         if (!intel_fb || WARN_ON(!intel_fb->obj)) {
     215             :                 DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n");
     216           0 :                 ret = intelfb_alloc(helper, sizes);
     217           0 :                 if (ret)
     218             :                         goto out_unlock;
     219           0 :                 intel_fb = ifbdev->fb;
     220           0 :         } else {
     221             :                 DRM_DEBUG_KMS("re-using BIOS fb\n");
     222             :                 prealloc = true;
     223             : #ifdef __linux__
     224             :                 sizes->fb_width = intel_fb->base.width;
     225             :                 sizes->fb_height = intel_fb->base.height;
     226             : #endif
     227             :         }
     228             : 
     229           0 :         obj = intel_fb->obj;
     230           0 :         size = obj->base.size;
     231             : 
     232           0 :         info = drm_fb_helper_alloc_fbi(helper);
     233           0 :         if (IS_ERR(info)) {
     234           0 :                 ret = PTR_ERR(info);
     235           0 :                 goto out_unpin;
     236             :         }
     237             : 
     238           0 :         info->par = helper;
     239             : 
     240           0 :         fb = &ifbdev->fb->base;
     241             : 
     242           0 :         ifbdev->helper.fb = fb;
     243             : 
     244             : #ifdef __linux__
     245             :         strcpy(info->fix.id, "inteldrmfb");
     246             : 
     247             :         info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
     248             :         info->fbops = &intelfb_ops;
     249             : 
     250             :         /* setup aperture base/size for vesafb takeover */
     251             :         info->apertures->ranges[0].base = dev->mode_config.fb_base;
     252             :         info->apertures->ranges[0].size = dev_priv->gtt.mappable_end;
     253             : 
     254             :         info->fix.smem_start = dev->mode_config.fb_base + i915_gem_obj_ggtt_offset(obj);
     255             :         info->fix.smem_len = size;
     256             : 
     257             :         info->screen_base =
     258             :                 ioremap_wc(dev_priv->gtt.mappable_base + i915_gem_obj_ggtt_offset(obj),
     259             :                            size);
     260             :         if (!info->screen_base) {
     261             :                 ret = -ENOSPC;
     262             :                 goto out_destroy_fbi;
     263             :         }
     264             :         info->screen_size = size;
     265             : 
     266             :         /* This driver doesn't need a VT switch to restore the mode on resume */
     267             :         info->skip_vt_switch = true;
     268             : 
     269             :         drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
     270             :         drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height);
     271             : 
     272             :         /* If the object is shmemfs backed, it will have given us zeroed pages.
     273             :          * If the object is stolen however, it will be full of whatever
     274             :          * garbage was left in there.
     275             :          */
     276             :         if (ifbdev->fb->obj->stolen && !prealloc)
     277             :                 memset_io(info->screen_base, 0, info->screen_size);
     278             : 
     279             :         /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
     280             : #else
     281             : {
     282           0 :         struct rasops_info *ri = &dev_priv->ro;
     283           0 :         bus_space_handle_t bsh;
     284             :         int err;
     285             : 
     286           0 :         err = agp_map_subregion(dev_priv->agph,
     287           0 :             i915_gem_obj_ggtt_offset(obj), size, &bsh);
     288           0 :         if (err) {
     289           0 :                 ret = -err;
     290           0 :                 goto out_unpin;
     291             :         }
     292             : 
     293           0 :         ri->ri_bits = bus_space_vaddr(dev->bst, bsh);
     294           0 :         ri->ri_depth = fb->bits_per_pixel;
     295           0 :         ri->ri_stride = fb->pitches[0];
     296           0 :         ri->ri_width = sizes->fb_width;
     297           0 :         ri->ri_height = sizes->fb_height;
     298             : 
     299           0 :         switch (fb->pixel_format) {
     300             :         case DRM_FORMAT_XRGB8888:
     301           0 :                 ri->ri_rnum = 8;
     302           0 :                 ri->ri_rpos = 16;
     303           0 :                 ri->ri_gnum = 8;
     304           0 :                 ri->ri_gpos = 8;
     305           0 :                 ri->ri_bnum = 8;
     306           0 :                 ri->ri_bpos = 0;
     307           0 :                 break;
     308             :         case DRM_FORMAT_RGB565:
     309           0 :                 ri->ri_rnum = 5;
     310           0 :                 ri->ri_rpos = 11;
     311           0 :                 ri->ri_gnum = 6;
     312           0 :                 ri->ri_gpos = 5;
     313           0 :                 ri->ri_bnum = 5;
     314           0 :                 ri->ri_bpos = 0;
     315           0 :                 break;
     316             :         }
     317             : 
     318           0 :         memset(ri->ri_bits, 0, size);
     319           0 : }
     320             : #endif
     321             : 
     322             :         DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08llx, bo %p\n",
     323             :                       fb->width, fb->height,
     324             :                       i915_gem_obj_ggtt_offset(obj), obj);
     325             : 
     326           0 :         mutex_unlock(&dev->struct_mutex);
     327             : #ifdef __linux__
     328             :         vga_switcheroo_client_fb_set(dev->pdev, info);
     329             : #endif
     330           0 :         return 0;
     331             : 
     332             : #ifdef __linux__
     333             : out_destroy_fbi:
     334             :         drm_fb_helper_release_fbi(helper);
     335             : #endif
     336             : out_unpin:
     337           0 :         i915_gem_object_ggtt_unpin(obj);
     338           0 :         drm_gem_object_unreference(&obj->base);
     339             : out_unlock:
     340           0 :         mutex_unlock(&dev->struct_mutex);
     341           0 :         return ret;
     342           0 : }
     343             : 
     344             : /** Sets the color ramps on behalf of RandR */
     345           0 : static void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
     346             :                                     u16 blue, int regno)
     347             : {
     348           0 :         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
     349             : 
     350           0 :         intel_crtc->lut_r[regno] = red >> 8;
     351           0 :         intel_crtc->lut_g[regno] = green >> 8;
     352           0 :         intel_crtc->lut_b[regno] = blue >> 8;
     353           0 : }
     354             : 
     355           0 : static void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
     356             :                                     u16 *blue, int regno)
     357             : {
     358           0 :         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
     359             : 
     360           0 :         *red = intel_crtc->lut_r[regno] << 8;
     361           0 :         *green = intel_crtc->lut_g[regno] << 8;
     362           0 :         *blue = intel_crtc->lut_b[regno] << 8;
     363           0 : }
     364             : 
     365             : static struct drm_fb_helper_crtc *
     366           0 : intel_fb_helper_crtc(struct drm_fb_helper *fb_helper, struct drm_crtc *crtc)
     367             : {
     368             :         int i;
     369             : 
     370           0 :         for (i = 0; i < fb_helper->crtc_count; i++)
     371           0 :                 if (fb_helper->crtc_info[i].mode_set.crtc == crtc)
     372           0 :                         return &fb_helper->crtc_info[i];
     373             : 
     374           0 :         return NULL;
     375           0 : }
     376             : 
     377             : /*
     378             :  * Try to read the BIOS display configuration and use it for the initial
     379             :  * fb configuration.
     380             :  *
     381             :  * The BIOS or boot loader will generally create an initial display
     382             :  * configuration for us that includes some set of active pipes and displays.
     383             :  * This routine tries to figure out which pipes and connectors are active
     384             :  * and stuffs them into the crtcs and modes array given to us by the
     385             :  * drm_fb_helper code.
     386             :  *
     387             :  * The overall sequence is:
     388             :  *   intel_fbdev_init - from driver load
     389             :  *     intel_fbdev_init_bios - initialize the intel_fbdev using BIOS data
     390             :  *     drm_fb_helper_init - build fb helper structs
     391             :  *     drm_fb_helper_single_add_all_connectors - more fb helper structs
     392             :  *   intel_fbdev_initial_config - apply the config
     393             :  *     drm_fb_helper_initial_config - call ->probe then register_framebuffer()
     394             :  *         drm_setup_crtcs - build crtc config for fbdev
     395             :  *           intel_fb_initial_config - find active connectors etc
     396             :  *         drm_fb_helper_single_fb_probe - set up fbdev
     397             :  *           intelfb_create - re-use or alloc fb, build out fbdev structs
     398             :  *
     399             :  * Note that we don't make special consideration whether we could actually
     400             :  * switch to the selected modes without a full modeset. E.g. when the display
     401             :  * is in VGA mode we need to recalculate watermarks and set a new high-res
     402             :  * framebuffer anyway.
     403             :  */
     404           0 : static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
     405             :                                     struct drm_fb_helper_crtc **crtcs,
     406             :                                     struct drm_display_mode **modes,
     407             :                                     struct drm_fb_offset *offsets,
     408             :                                     bool *enabled, int width, int height)
     409             : {
     410           0 :         struct drm_device *dev = fb_helper->dev;
     411             :         int i, j;
     412             :         bool *save_enabled;
     413             :         bool fallback = true;
     414             :         int num_connectors_enabled = 0;
     415             :         int num_connectors_detected = 0;
     416             :         uint64_t conn_configured = 0, mask;
     417             :         int pass = 0;
     418             : 
     419           0 :         save_enabled = kcalloc(fb_helper->connector_count, sizeof(bool),
     420             :                                GFP_KERNEL);
     421           0 :         if (!save_enabled)
     422           0 :                 return false;
     423             : 
     424           0 :         memcpy(save_enabled, enabled, fb_helper->connector_count);
     425           0 :         mask = (1 << fb_helper->connector_count) - 1;
     426             : retry:
     427           0 :         for (i = 0; i < fb_helper->connector_count; i++) {
     428             :                 struct drm_fb_helper_connector *fb_conn;
     429             :                 struct drm_connector *connector;
     430             :                 struct drm_encoder *encoder;
     431             :                 struct drm_fb_helper_crtc *new_crtc;
     432             : 
     433           0 :                 fb_conn = fb_helper->connector_info[i];
     434           0 :                 connector = fb_conn->connector;
     435             : 
     436           0 :                 if (conn_configured & (1 << i))
     437           0 :                         continue;
     438             : 
     439           0 :                 if (pass == 0 && !connector->has_tile)
     440           0 :                         continue;
     441             : 
     442           0 :                 if (connector->status == connector_status_connected)
     443           0 :                         num_connectors_detected++;
     444             : 
     445           0 :                 if (!enabled[i]) {
     446             :                         DRM_DEBUG_KMS("connector %s not enabled, skipping\n",
     447             :                                       connector->name);
     448           0 :                         conn_configured |= (1 << i);
     449           0 :                         continue;
     450             :                 }
     451             : 
     452           0 :                 if (connector->force == DRM_FORCE_OFF) {
     453             :                         DRM_DEBUG_KMS("connector %s is disabled by user, skipping\n",
     454             :                                       connector->name);
     455           0 :                         enabled[i] = false;
     456           0 :                         continue;
     457             :                 }
     458             : 
     459           0 :                 encoder = connector->encoder;
     460           0 :                 if (!encoder || WARN_ON(!encoder->crtc)) {
     461           0 :                         if (connector->force > DRM_FORCE_OFF)
     462           0 :                                 goto bail;
     463             : 
     464             :                         DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n",
     465             :                                       connector->name);
     466           0 :                         enabled[i] = false;
     467           0 :                         conn_configured |= (1 << i);
     468           0 :                         continue;
     469             :                 }
     470             : 
     471           0 :                 num_connectors_enabled++;
     472             : 
     473           0 :                 new_crtc = intel_fb_helper_crtc(fb_helper, encoder->crtc);
     474             : 
     475             :                 /*
     476             :                  * Make sure we're not trying to drive multiple connectors
     477             :                  * with a single CRTC, since our cloning support may not
     478             :                  * match the BIOS.
     479             :                  */
     480           0 :                 for (j = 0; j < fb_helper->connector_count; j++) {
     481           0 :                         if (crtcs[j] == new_crtc) {
     482             :                                 DRM_DEBUG_KMS("fallback: cloned configuration\n");
     483           0 :                                 goto bail;
     484             :                         }
     485             :                 }
     486             : 
     487             :                 DRM_DEBUG_KMS("looking for cmdline mode on connector %s\n",
     488             :                               connector->name);
     489             : 
     490             :                 /* go for command line mode first */
     491           0 :                 modes[i] = drm_pick_cmdline_mode(fb_conn, width, height);
     492             : 
     493             :                 /* try for preferred next */
     494           0 :                 if (!modes[i]) {
     495             :                         DRM_DEBUG_KMS("looking for preferred mode on connector %s %d\n",
     496             :                                       connector->name, connector->has_tile);
     497           0 :                         modes[i] = drm_has_preferred_mode(fb_conn, width,
     498             :                                                           height);
     499           0 :                 }
     500             : 
     501             :                 /* No preferred mode marked by the EDID? Are there any modes? */
     502           0 :                 if (!modes[i] && !list_empty(&connector->modes)) {
     503             :                         DRM_DEBUG_KMS("using first mode listed on connector %s\n",
     504             :                                       connector->name);
     505           0 :                         modes[i] = list_first_entry(&connector->modes,
     506             :                                                     struct drm_display_mode,
     507             :                                                     head);
     508           0 :                 }
     509             : 
     510             :                 /* last resort: use current mode */
     511           0 :                 if (!modes[i]) {
     512             :                         /*
     513             :                          * IMPORTANT: We want to use the adjusted mode (i.e.
     514             :                          * after the panel fitter upscaling) as the initial
     515             :                          * config, not the input mode, which is what crtc->mode
     516             :                          * usually contains. But since our current
     517             :                          * code puts a mode derived from the post-pfit timings
     518             :                          * into crtc->mode this works out correctly.
     519             :                          */
     520             :                         DRM_DEBUG_KMS("looking for current mode on connector %s\n",
     521             :                                       connector->name);
     522           0 :                         modes[i] = &encoder->crtc->mode;
     523           0 :                 }
     524           0 :                 crtcs[i] = new_crtc;
     525             : 
     526             :                 DRM_DEBUG_KMS("connector %s on pipe %c [CRTC:%d]: %dx%d%s\n",
     527             :                               connector->name,
     528             :                               pipe_name(to_intel_crtc(encoder->crtc)->pipe),
     529             :                               encoder->crtc->base.id,
     530             :                               modes[i]->hdisplay, modes[i]->vdisplay,
     531             :                               modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" :"");
     532             : 
     533             :                 fallback = false;
     534           0 :                 conn_configured |= (1 << i);
     535           0 :         }
     536             : 
     537           0 :         if ((conn_configured & mask) != mask) {
     538           0 :                 pass++;
     539           0 :                 goto retry;
     540             :         }
     541             : 
     542             :         /*
     543             :          * If the BIOS didn't enable everything it could, fall back to have the
     544             :          * same user experiencing of lighting up as much as possible like the
     545             :          * fbdev helper library.
     546             :          */
     547           0 :         if (num_connectors_enabled != num_connectors_detected &&
     548           0 :             num_connectors_enabled < INTEL_INFO(dev)->num_pipes) {
     549             :                 DRM_DEBUG_KMS("fallback: Not all outputs enabled\n");
     550             :                 DRM_DEBUG_KMS("Enabled: %i, detected: %i\n", num_connectors_enabled,
     551             :                               num_connectors_detected);
     552             :                 fallback = true;
     553           0 :         }
     554             : 
     555           0 :         if (fallback) {
     556             : bail:
     557             :                 DRM_DEBUG_KMS("Not using firmware configuration\n");
     558           0 :                 memcpy(enabled, save_enabled, fb_helper->connector_count);
     559           0 :                 kfree(save_enabled);
     560           0 :                 return false;
     561             :         }
     562             : 
     563           0 :         kfree(save_enabled);
     564           0 :         return true;
     565           0 : }
     566             : 
     567             : static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
     568             :         .initial_config = intel_fb_initial_config,
     569             :         .gamma_set = intel_crtc_fb_gamma_set,
     570             :         .gamma_get = intel_crtc_fb_gamma_get,
     571             :         .fb_probe = intelfb_create,
     572             : };
     573             : 
     574             : #ifdef notyet
     575             : 
     576             : static void intel_fbdev_destroy(struct drm_device *dev,
     577             :                                 struct intel_fbdev *ifbdev)
     578             : {
     579             : 
     580             :         drm_fb_helper_unregister_fbi(&ifbdev->helper);
     581             :         drm_fb_helper_release_fbi(&ifbdev->helper);
     582             : 
     583             :         drm_fb_helper_fini(&ifbdev->helper);
     584             : 
     585             :         drm_framebuffer_unregister_private(&ifbdev->fb->base);
     586             :         drm_framebuffer_remove(&ifbdev->fb->base);
     587             : }
     588             : 
     589             : #endif
     590             : 
     591             : /*
     592             :  * Build an intel_fbdev struct using a BIOS allocated framebuffer, if possible.
     593             :  * The core display code will have read out the current plane configuration,
     594             :  * so we use that to figure out if there's an object for us to use as the
     595             :  * fb, and if so, we re-use it for the fbdev configuration.
     596             :  *
     597             :  * Note we only support a single fb shared across pipes for boot (mostly for
     598             :  * fbcon), so we just find the biggest and use that.
     599             :  */
     600           0 : static bool intel_fbdev_init_bios(struct drm_device *dev,
     601             :                                  struct intel_fbdev *ifbdev)
     602             : {
     603             :         struct intel_framebuffer *fb = NULL;
     604             :         struct drm_crtc *crtc;
     605             :         struct intel_crtc *intel_crtc;
     606             :         unsigned int max_size = 0;
     607             : 
     608             :         /* Find the largest fb */
     609           0 :         for_each_crtc(dev, crtc) {
     610             :                 struct drm_i915_gem_object *obj =
     611           0 :                         intel_fb_obj(crtc->primary->state->fb);
     612           0 :                 intel_crtc = to_intel_crtc(crtc);
     613             : 
     614           0 :                 if (!crtc->state->active || !obj) {
     615             :                         DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n",
     616             :                                       pipe_name(intel_crtc->pipe));
     617           0 :                         continue;
     618             :                 }
     619             : 
     620           0 :                 if (obj->base.size > max_size) {
     621             :                         DRM_DEBUG_KMS("found possible fb from plane %c\n",
     622             :                                       pipe_name(intel_crtc->pipe));
     623           0 :                         fb = to_intel_framebuffer(crtc->primary->state->fb);
     624           0 :                         max_size = obj->base.size;
     625           0 :                 }
     626           0 :         }
     627             : 
     628           0 :         if (!fb) {
     629             :                 DRM_DEBUG_KMS("no active fbs found, not using BIOS config\n");
     630             :                 goto out;
     631             :         }
     632             : 
     633             :         /* Now make sure all the pipes will fit into it */
     634           0 :         for_each_crtc(dev, crtc) {
     635             :                 unsigned int cur_size;
     636             : 
     637           0 :                 intel_crtc = to_intel_crtc(crtc);
     638             : 
     639           0 :                 if (!crtc->state->active) {
     640             :                         DRM_DEBUG_KMS("pipe %c not active, skipping\n",
     641             :                                       pipe_name(intel_crtc->pipe));
     642           0 :                         continue;
     643             :                 }
     644             : 
     645             :                 DRM_DEBUG_KMS("checking plane %c for BIOS fb\n",
     646             :                               pipe_name(intel_crtc->pipe));
     647             : 
     648             :                 /*
     649             :                  * See if the plane fb we found above will fit on this
     650             :                  * pipe.  Note we need to use the selected fb's pitch and bpp
     651             :                  * rather than the current pipe's, since they differ.
     652             :                  */
     653           0 :                 cur_size = intel_crtc->config->base.adjusted_mode.crtc_hdisplay;
     654           0 :                 cur_size = cur_size * fb->base.bits_per_pixel / 8;
     655           0 :                 if (fb->base.pitches[0] < cur_size) {
     656             :                         DRM_DEBUG_KMS("fb not wide enough for plane %c (%d vs %d)\n",
     657             :                                       pipe_name(intel_crtc->pipe),
     658             :                                       cur_size, fb->base.pitches[0]);
     659             :                         fb = NULL;
     660           0 :                         break;
     661             :                 }
     662             : 
     663           0 :                 cur_size = intel_crtc->config->base.adjusted_mode.crtc_vdisplay;
     664           0 :                 cur_size = intel_fb_align_height(dev, cur_size,
     665           0 :                                                  fb->base.pixel_format,
     666           0 :                                                  fb->base.modifier[0]);
     667           0 :                 cur_size *= fb->base.pitches[0];
     668             :                 DRM_DEBUG_KMS("pipe %c area: %dx%d, bpp: %d, size: %d\n",
     669             :                               pipe_name(intel_crtc->pipe),
     670             :                               intel_crtc->config->base.adjusted_mode.crtc_hdisplay,
     671             :                               intel_crtc->config->base.adjusted_mode.crtc_vdisplay,
     672             :                               fb->base.bits_per_pixel,
     673             :                               cur_size);
     674             : 
     675           0 :                 if (cur_size > max_size) {
     676             :                         DRM_DEBUG_KMS("fb not big enough for plane %c (%d vs %d)\n",
     677             :                                       pipe_name(intel_crtc->pipe),
     678             :                                       cur_size, max_size);
     679             :                         fb = NULL;
     680           0 :                         break;
     681             :                 }
     682             : 
     683             :                 DRM_DEBUG_KMS("fb big enough for plane %c (%d >= %d)\n",
     684             :                               pipe_name(intel_crtc->pipe),
     685             :                               max_size, cur_size);
     686           0 :         }
     687             : 
     688           0 :         if (!fb) {
     689             :                 DRM_DEBUG_KMS("BIOS fb not suitable for all pipes, not using\n");
     690             :                 goto out;
     691             :         }
     692             : 
     693           0 :         ifbdev->preferred_bpp = fb->base.bits_per_pixel;
     694           0 :         ifbdev->fb = fb;
     695             : 
     696           0 :         drm_framebuffer_reference(&ifbdev->fb->base);
     697             : 
     698             :         /* Final pass to check if any active pipes don't have fbs */
     699           0 :         for_each_crtc(dev, crtc) {
     700           0 :                 intel_crtc = to_intel_crtc(crtc);
     701             : 
     702           0 :                 if (!crtc->state->active)
     703             :                         continue;
     704             : 
     705           0 :                 WARN(!crtc->primary->fb,
     706             :                      "re-used BIOS config but lost an fb on crtc %d\n",
     707             :                      crtc->base.id);
     708           0 :         }
     709             : 
     710             : 
     711             :         DRM_DEBUG_KMS("using BIOS fb for initial console\n");
     712           0 :         return true;
     713             : 
     714             : out:
     715             : 
     716           0 :         return false;
     717           0 : }
     718             : 
     719             : #ifdef notyet
     720             : static void intel_fbdev_suspend_worker(struct work_struct *work)
     721             : {
     722             :         intel_fbdev_set_suspend(container_of(work,
     723             :                                              struct drm_i915_private,
     724             :                                              fbdev_suspend_work)->dev,
     725             :                                 FBINFO_STATE_RUNNING,
     726             :                                 true);
     727             : }
     728             : #endif
     729             : 
     730           0 : int intel_fbdev_init(struct drm_device *dev)
     731             : {
     732             :         struct intel_fbdev *ifbdev;
     733           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     734             :         int ret;
     735             : 
     736           0 :         if (WARN_ON(INTEL_INFO(dev)->num_pipes == 0))
     737           0 :                 return -ENODEV;
     738             : 
     739           0 :         ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL);
     740           0 :         if (ifbdev == NULL)
     741           0 :                 return -ENOMEM;
     742             : 
     743           0 :         drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs);
     744             : 
     745           0 :         if (!intel_fbdev_init_bios(dev, ifbdev))
     746           0 :                 ifbdev->preferred_bpp = 32;
     747             : 
     748           0 :         ret = drm_fb_helper_init(dev, &ifbdev->helper,
     749           0 :                                  INTEL_INFO(dev)->num_pipes, 4);
     750           0 :         if (ret) {
     751           0 :                 kfree(ifbdev);
     752           0 :                 return ret;
     753             :         }
     754             : 
     755           0 :         ifbdev->helper.atomic = true;
     756             : 
     757           0 :         dev_priv->fbdev = ifbdev;
     758             : #ifdef notyet
     759             :         INIT_WORK(&dev_priv->fbdev_suspend_work, intel_fbdev_suspend_worker);
     760             : #endif
     761             : 
     762           0 :         drm_fb_helper_single_add_all_connectors(&ifbdev->helper);
     763             : 
     764           0 :         return 0;
     765           0 : }
     766             : 
     767           0 : void intel_fbdev_initial_config(void *data, async_cookie_t cookie)
     768             : {
     769           0 :         struct drm_i915_private *dev_priv = data;
     770           0 :         struct intel_fbdev *ifbdev = dev_priv->fbdev;
     771             : 
     772             :         /* Due to peculiar init order wrt to hpd handling this is separate. */
     773           0 :         drm_fb_helper_initial_config(&ifbdev->helper, ifbdev->preferred_bpp);
     774           0 : }
     775             : 
     776             : #ifdef __linux__
     777             : void intel_fbdev_fini(struct drm_device *dev)
     778             : {
     779             :         struct drm_i915_private *dev_priv = dev->dev_private;
     780             :         if (!dev_priv->fbdev)
     781             :                 return;
     782             : 
     783             :         flush_work(&dev_priv->fbdev_suspend_work);
     784             : 
     785             :         async_synchronize_full();
     786             :         intel_fbdev_destroy(dev, dev_priv->fbdev);
     787             :         kfree(dev_priv->fbdev);
     788             :         dev_priv->fbdev = NULL;
     789             : }
     790             : 
     791             : void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous)
     792             : {
     793             :         struct drm_i915_private *dev_priv = dev->dev_private;
     794             :         struct intel_fbdev *ifbdev = dev_priv->fbdev;
     795             :         struct fb_info *info;
     796             : 
     797             :         if (!ifbdev)
     798             :                 return;
     799             : 
     800             :         info = ifbdev->helper.fbdev;
     801             : 
     802             :         if (synchronous) {
     803             :                 /* Flush any pending work to turn the console on, and then
     804             :                  * wait to turn it off. It must be synchronous as we are
     805             :                  * about to suspend or unload the driver.
     806             :                  *
     807             :                  * Note that from within the work-handler, we cannot flush
     808             :                  * ourselves, so only flush outstanding work upon suspend!
     809             :                  */
     810             :                 if (state != FBINFO_STATE_RUNNING)
     811             :                         flush_work(&dev_priv->fbdev_suspend_work);
     812             :                 console_lock();
     813             :         } else {
     814             :                 /*
     815             :                  * The console lock can be pretty contented on resume due
     816             :                  * to all the printk activity.  Try to keep it out of the hot
     817             :                  * path of resume if possible.
     818             :                  */
     819             :                 WARN_ON(state != FBINFO_STATE_RUNNING);
     820             :                 if (!console_trylock()) {
     821             :                         /* Don't block our own workqueue as this can
     822             :                          * be run in parallel with other i915.ko tasks.
     823             :                          */
     824             :                         schedule_work(&dev_priv->fbdev_suspend_work);
     825             :                         return;
     826             :                 }
     827             :         }
     828             : 
     829             :         /* On resume from hibernation: If the object is shmemfs backed, it has
     830             :          * been restored from swap. If the object is stolen however, it will be
     831             :          * full of whatever garbage was left in there.
     832             :          */
     833             :         if (state == FBINFO_STATE_RUNNING && ifbdev->fb->obj->stolen)
     834             :                 memset_io(info->screen_base, 0, info->screen_size);
     835             : 
     836             :         drm_fb_helper_set_suspend(&ifbdev->helper, state);
     837             :         console_unlock();
     838             : }
     839             : #endif
     840             : 
     841           0 : void intel_fbdev_output_poll_changed(struct drm_device *dev)
     842             : {
     843           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     844           0 :         if (dev_priv->fbdev)
     845           0 :                 drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
     846           0 : }
     847             : 
     848           0 : void intel_fbdev_restore_mode(struct drm_device *dev)
     849             : {
     850             :         int ret;
     851           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     852           0 :         struct intel_fbdev *ifbdev = dev_priv->fbdev;
     853             :         struct drm_fb_helper *fb_helper;
     854             : 
     855           0 :         if (!ifbdev)
     856           0 :                 return;
     857             : 
     858           0 :         fb_helper = &ifbdev->helper;
     859             : 
     860           0 :         ret = drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
     861           0 :         if (ret) {
     862             :                 DRM_DEBUG("failed to restore crtc mode\n");
     863             :         } else {
     864           0 :                 mutex_lock(&fb_helper->dev->struct_mutex);
     865           0 :                 intel_fb_obj_invalidate(ifbdev->fb->obj, ORIGIN_GTT);
     866           0 :                 mutex_unlock(&fb_helper->dev->struct_mutex);
     867             :         }
     868           0 : }

Generated by: LCOV version 1.13