intel_fb.c revision 262861
1167514Skmacy/* 2167514Skmacy * Copyright �� 2007 David Airlie 3167514Skmacy * 4167514Skmacy * Permission is hereby granted, free of charge, to any person obtaining a 5167514Skmacy * copy of this software and associated documentation files (the "Software"), 6167514Skmacy * to deal in the Software without restriction, including without limitation 7167514Skmacy * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8167514Skmacy * and/or sell copies of the Software, and to permit persons to whom the 9167514Skmacy * Software is furnished to do so, subject to the following conditions: 10167514Skmacy * 11167514Skmacy * The above copyright notice and this permission notice (including the next 12170076Skmacy * paragraph) shall be included in all copies or substantial portions of the 13167514Skmacy * Software. 14167514Skmacy * 15167514Skmacy * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16167514Skmacy * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17167514Skmacy * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18167514Skmacy * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19167514Skmacy * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20167514Skmacy * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21167514Skmacy * DEALINGS IN THE SOFTWARE. 22167514Skmacy * 23167514Skmacy * Authors: 24167514Skmacy * David Airlie 25167514Skmacy */ 26167514Skmacy 27167514Skmacy#include <sys/cdefs.h> 28167514Skmacy__FBSDID("$FreeBSD: stable/10/sys/dev/drm2/i915/intel_fb.c 262861 2014-03-06 18:30:56Z jhb $"); 29167514Skmacy 30167514Skmacy#include <dev/drm2/drmP.h> 31167514Skmacy#include <dev/drm2/drm.h> 32167514Skmacy#include <dev/drm2/drm_crtc.h> 33170076Skmacy#include <dev/drm2/drm_fb_helper.h> 34167514Skmacy#include <dev/drm2/i915/i915_drm.h> 35167514Skmacy#include <dev/drm2/i915/i915_drv.h> 36167514Skmacy#include <dev/drm2/i915/intel_drv.h> 37167514Skmacy 38167514Skmacystatic int intelfb_create(struct intel_fbdev *ifbdev, 39167514Skmacy struct drm_fb_helper_surface_size *sizes) 40167514Skmacy{ 41167514Skmacy struct drm_device *dev = ifbdev->helper.dev; 42167514Skmacy#if 0 43167514Skmacy struct drm_i915_private *dev_priv = dev->dev_private; 44167514Skmacy#endif 45167514Skmacy struct fb_info *info; 46167514Skmacy struct drm_framebuffer *fb; 47167514Skmacy struct drm_mode_fb_cmd2 mode_cmd; 48167514Skmacy struct drm_i915_gem_object *obj; 49167514Skmacy int size, ret; 50167514Skmacy 51167514Skmacy /* we don't do packed 24bpp */ 52167514Skmacy if (sizes->surface_bpp == 24) 53167514Skmacy sizes->surface_bpp = 32; 54167514Skmacy 55167514Skmacy mode_cmd.width = sizes->surface_width; 56167514Skmacy mode_cmd.height = sizes->surface_height; 57167514Skmacy 58167514Skmacy mode_cmd.pitches[0] = roundup2(mode_cmd.width * ((sizes->surface_bpp + 7) / 59167514Skmacy 8), 64); 60167514Skmacy mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, 61167514Skmacy sizes->surface_depth); 62167514Skmacy 63167514Skmacy size = mode_cmd.pitches[0] * mode_cmd.height; 64167514Skmacy size = roundup2(size, PAGE_SIZE); 65167514Skmacy obj = i915_gem_alloc_object(dev, size); 66167514Skmacy if (!obj) { 67167514Skmacy DRM_ERROR("failed to allocate framebuffer\n"); 68167514Skmacy ret = -ENOMEM; 69167514Skmacy goto out; 70167514Skmacy } 71167514Skmacy 72167514Skmacy DRM_LOCK(dev); 73167514Skmacy 74167514Skmacy /* Flush everything out, we'll be doing GTT only from now on */ 75167514Skmacy ret = intel_pin_and_fence_fb_obj(dev, obj, false); 76167514Skmacy if (ret) { 77167514Skmacy DRM_ERROR("failed to pin fb: %d\n", ret); 78167514Skmacy goto out_unref; 79167514Skmacy } 80167514Skmacy 81167514Skmacy#if 0 82167514Skmacy info = framebuffer_alloc(0, device); 83167514Skmacy if (!info) { 84167514Skmacy ret = -ENOMEM; 85167514Skmacy goto out_unpin; 86167514Skmacy } 87167514Skmacy 88167514Skmacy info->par = ifbdev; 89167514Skmacy#else 90167514Skmacy info = malloc(sizeof(struct fb_info), DRM_MEM_KMS, M_WAITOK | M_ZERO); 91167514Skmacy info->fb_size = size; 92167514Skmacy info->fb_bpp = sizes->surface_bpp; 93167514Skmacy info->fb_width = sizes->fb_width; 94167514Skmacy info->fb_height = sizes->fb_height; 95167514Skmacy info->fb_pbase = dev->agp->base + obj->gtt_offset; 96167514Skmacy info->fb_vbase = (vm_offset_t)pmap_mapdev_attr(info->fb_pbase, size, 97167514Skmacy PAT_WRITE_COMBINING); 98167514Skmacy 99167514Skmacy#endif 100167514Skmacy 101167514Skmacy ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj); 102167514Skmacy if (ret) 103167514Skmacy goto out_unpin; 104167514Skmacy 105167514Skmacy fb = &ifbdev->ifb.base; 106167514Skmacy 107167514Skmacy ifbdev->helper.fb = fb; 108167514Skmacy ifbdev->helper.fbdev = info; 109167514Skmacy#if 0 110167514Skmacy 111167514Skmacy strcpy(info->fix.id, "inteldrmfb"); 112167514Skmacy 113167514Skmacy info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; 114167514Skmacy info->fbops = &intelfb_ops; 115167514Skmacy 116167514Skmacy ret = fb_alloc_cmap(&info->cmap, 256, 0); 117167514Skmacy if (ret) { 118167514Skmacy ret = -ENOMEM; 119167514Skmacy goto out_unpin; 120167514Skmacy } 121167514Skmacy /* setup aperture base/size for vesafb takeover */ 122167514Skmacy info->apertures = alloc_apertures(1); 123167514Skmacy if (!info->apertures) { 124167514Skmacy ret = -ENOMEM; 125167514Skmacy goto out_unpin; 126167514Skmacy } 127167514Skmacy info->apertures->ranges[0].base = dev->mode_config.fb_base; 128167514Skmacy info->apertures->ranges[0].size = 129167514Skmacy dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; 130167514Skmacy 131167514Skmacy info->fix.smem_start = dev->mode_config.fb_base + obj->gtt_offset; 132167514Skmacy info->fix.smem_len = size; 133167514Skmacy 134167514Skmacy info->screen_base = ioremap_wc(dev->agp->base + obj->gtt_offset, size); 135167514Skmacy if (!info->screen_base) { 136167514Skmacy ret = -ENOSPC; 137167514Skmacy goto out_unpin; 138167514Skmacy } 139167514Skmacy info->screen_size = size; 140167514Skmacy 141167514Skmacy// memset(info->screen_base, 0, size); 142167514Skmacy 143167514Skmacy drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); 144167514Skmacy drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height); 145167514Skmacy 146167514Skmacy /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ 147167514Skmacy#endif 148167514Skmacy DRM_DEBUG_KMS("allocated %dx%d (s %dbits) fb: 0x%08x, bo %p\n", 149167514Skmacy fb->width, fb->height, fb->depth, 150167514Skmacy obj->gtt_offset, obj); 151167514Skmacy 152167514Skmacy DRM_UNLOCK(dev); 153167514Skmacy#if 1 154167514Skmacy KIB_NOTYET(); 155167514Skmacy#else 156167514Skmacy vga_switcheroo_client_fb_set(dev->pdev, info); 157167514Skmacy#endif 158167514Skmacy return 0; 159167514Skmacy 160167514Skmacyout_unpin: 161167514Skmacy i915_gem_object_unpin(obj); 162167514Skmacyout_unref: 163167514Skmacy drm_gem_object_unreference(&obj->base); 164167514Skmacy DRM_UNLOCK(dev); 165167514Skmacyout: 166167514Skmacy return ret; 167167514Skmacy} 168167514Skmacy 169167514Skmacystatic int intel_fb_find_or_create_single(struct drm_fb_helper *helper, 170167514Skmacy struct drm_fb_helper_surface_size *sizes) 171167514Skmacy{ 172167514Skmacy struct intel_fbdev *ifbdev = (struct intel_fbdev *)helper; 173167514Skmacy int new_fb = 0; 174167514Skmacy int ret; 175167514Skmacy 176167514Skmacy if (!helper->fb) { 177167514Skmacy ret = intelfb_create(ifbdev, sizes); 178167514Skmacy if (ret) 179167514Skmacy return ret; 180167514Skmacy new_fb = 1; 181167514Skmacy } 182167514Skmacy return new_fb; 183167514Skmacy} 184167514Skmacy 185167514Skmacystatic struct drm_fb_helper_funcs intel_fb_helper_funcs = { 186167514Skmacy .gamma_set = intel_crtc_fb_gamma_set, 187167514Skmacy .gamma_get = intel_crtc_fb_gamma_get, 188276959Snp .fb_probe = intel_fb_find_or_create_single, 189167514Skmacy}; 190167514Skmacy 191167514Skmacystatic void intel_fbdev_destroy(struct drm_device *dev, 192167514Skmacy struct intel_fbdev *ifbdev) 193167514Skmacy{ 194167514Skmacy#if 0 195167514Skmacy struct fb_info *info; 196167514Skmacy#endif 197167514Skmacy struct intel_framebuffer *ifb = &ifbdev->ifb; 198167514Skmacy 199167514Skmacy#if 0 200167514Skmacy if (ifbdev->helper.fbdev) { 201167514Skmacy info = ifbdev->helper.fbdev; 202167514Skmacy unregister_framebuffer(info); 203167514Skmacy iounmap(info->screen_base); 204167514Skmacy if (info->cmap.len) 205167514Skmacy fb_dealloc_cmap(&info->cmap); 206167514Skmacy framebuffer_release(info); 207167514Skmacy } 208167514Skmacy#endif 209276959Snp 210276959Snp drm_fb_helper_fini(&ifbdev->helper); 211276959Snp 212167514Skmacy drm_framebuffer_cleanup(&ifb->base); 213167514Skmacy if (ifb->obj) { 214167514Skmacy drm_gem_object_unreference_unlocked(&ifb->obj->base); 215167514Skmacy ifb->obj = NULL; 216167514Skmacy } 217167514Skmacy} 218167514Skmacy 219167514Skmacyextern int sc_txtmouse_no_retrace_wait; 220167514Skmacy 221176472Skmacyint intel_fbdev_init(struct drm_device *dev) 222176472Skmacy{ 223176472Skmacy struct intel_fbdev *ifbdev; 224176472Skmacy drm_i915_private_t *dev_priv = dev->dev_private; 225176472Skmacy int ret; 226176472Skmacy 227176472Skmacy ifbdev = malloc(sizeof(struct intel_fbdev), DRM_MEM_KMS, 228176472Skmacy M_WAITOK | M_ZERO); 229176472Skmacy 230176472Skmacy dev_priv->fbdev = ifbdev; 231167514Skmacy ifbdev->helper.funcs = &intel_fb_helper_funcs; 232167514Skmacy 233167514Skmacy ret = drm_fb_helper_init(dev, &ifbdev->helper, 234167514Skmacy dev_priv->num_pipe, 235167514Skmacy INTELFB_CONN_LIMIT); 236167514Skmacy if (ret) { 237167514Skmacy free(ifbdev, DRM_MEM_KMS); 238167514Skmacy return ret; 239167514Skmacy } 240167514Skmacy 241167514Skmacy drm_fb_helper_single_add_all_connectors(&ifbdev->helper); 242167514Skmacy drm_fb_helper_initial_config(&ifbdev->helper, 32); 243167514Skmacy sc_txtmouse_no_retrace_wait = 1; 244167514Skmacy return 0; 245167514Skmacy} 246167514Skmacy 247167514Skmacyvoid intel_fbdev_fini(struct drm_device *dev) 248167514Skmacy{ 249167514Skmacy drm_i915_private_t *dev_priv = dev->dev_private; 250167514Skmacy if (!dev_priv->fbdev) 251167514Skmacy return; 252167514Skmacy 253167514Skmacy intel_fbdev_destroy(dev, dev_priv->fbdev); 254167514Skmacy free(dev_priv->fbdev, DRM_MEM_KMS); 255167514Skmacy dev_priv->fbdev = NULL; 256167514Skmacy} 257167514Skmacy 258167514Skmacyvoid intel_fb_output_poll_changed(struct drm_device *dev) 259167514Skmacy{ 260167514Skmacy drm_i915_private_t *dev_priv = dev->dev_private; 261167514Skmacy drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper); 262167514Skmacy} 263167514Skmacy 264167514Skmacyvoid intel_fb_restore_mode(struct drm_device *dev) 265167514Skmacy{ 266167514Skmacy int ret; 267167514Skmacy drm_i915_private_t *dev_priv = dev->dev_private; 268167514Skmacy struct drm_mode_config *config = &dev->mode_config; 269167514Skmacy struct drm_plane *plane; 270167514Skmacy 271167514Skmacy sx_xlock(&dev->mode_config.mutex); 272167514Skmacy 273167514Skmacy ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper); 274167514Skmacy if (ret) 275167514Skmacy DRM_DEBUG("failed to restore crtc mode\n"); 276167514Skmacy 277176472Skmacy /* Be sure to shut off any planes that may be active */ 278167514Skmacy list_for_each_entry(plane, &config->plane_list, head) 279167514Skmacy plane->funcs->disable_plane(plane); 280167514Skmacy 281167514Skmacy sx_xunlock(&dev->mode_config.mutex); 282167514Skmacy} 283167514Skmacy