Subversion Repositories Kolibri OS

Rev

Rev 1403 | Rev 1630 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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.      *  Modularization
  28.      */
  29.  
  30. #include <linux/module.h>
  31. #include <linux/fb.h>
  32.  
  33. #include "drmP.h"
  34. #include "drm.h"
  35. #include "drm_crtc.h"
  36. #include "drm_crtc_helper.h"
  37. #include "radeon_drm.h"
  38. #include "radeon.h"
  39.  
  40. #include "drm_fb_helper.h"
  41.  
  42. #include <drm_mm.h>
  43. #include "radeon_object.h"
  44.  
  45.  
  46. struct fb_info *framebuffer_alloc(size_t size, void *dev);
  47.  
  48. struct radeon_fb_device {
  49.     struct drm_fb_helper        helper;
  50.         struct radeon_framebuffer       *rfb;
  51.         struct radeon_device            *rdev;
  52. };
  53.  
  54. static struct fb_ops radeonfb_ops = {
  55. //   .owner = THIS_MODULE,
  56.         .fb_check_var = drm_fb_helper_check_var,
  57.         .fb_set_par = drm_fb_helper_set_par,
  58.         .fb_setcolreg = drm_fb_helper_setcolreg,
  59. //      .fb_fillrect = cfb_fillrect,
  60. //      .fb_copyarea = cfb_copyarea,
  61. //      .fb_imageblit = cfb_imageblit,
  62. //      .fb_pan_display = drm_fb_helper_pan_display,
  63.         .fb_blank = drm_fb_helper_blank,
  64.         .fb_setcmap = drm_fb_helper_setcmap,
  65. };
  66.  
  67. /**
  68.  * Currently it is assumed that the old framebuffer is reused.
  69.  *
  70.  * LOCKING
  71.  * caller should hold the mode config lock.
  72.  *
  73.  */
  74. int radeonfb_resize(struct drm_device *dev, struct drm_crtc *crtc)
  75. {
  76.         struct fb_info *info;
  77.         struct drm_framebuffer *fb;
  78.         struct drm_display_mode *mode = crtc->desired_mode;
  79.  
  80.         fb = crtc->fb;
  81.         if (fb == NULL) {
  82.                 return 1;
  83.         }
  84.         info = fb->fbdev;
  85.         if (info == NULL) {
  86.                 return 1;
  87.         }
  88.         if (mode == NULL) {
  89.                 return 1;
  90.         }
  91.         info->var.xres = mode->hdisplay;
  92.         info->var.right_margin = mode->hsync_start - mode->hdisplay;
  93.         info->var.hsync_len = mode->hsync_end - mode->hsync_start;
  94.         info->var.left_margin = mode->htotal - mode->hsync_end;
  95.         info->var.yres = mode->vdisplay;
  96.         info->var.lower_margin = mode->vsync_start - mode->vdisplay;
  97.         info->var.vsync_len = mode->vsync_end - mode->vsync_start;
  98.         info->var.upper_margin = mode->vtotal - mode->vsync_end;
  99.         info->var.pixclock = 10000000 / mode->htotal * 1000 / mode->vtotal * 100;
  100.         /* avoid overflow */
  101.         info->var.pixclock = info->var.pixclock * 1000 / mode->vrefresh;
  102.  
  103.         return 0;
  104. }
  105. EXPORT_SYMBOL(radeonfb_resize);
  106.  
  107. int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled)
  108. {
  109.         int aligned = width;
  110.         int align_large = (ASIC_IS_AVIVO(rdev)) || tiled;
  111.         int pitch_mask = 0;
  112.  
  113.         switch (bpp / 8) {
  114.         case 1:
  115.                 pitch_mask = align_large ? 255 : 127;
  116.                 break;
  117.         case 2:
  118.                 pitch_mask = align_large ? 127 : 31;
  119.                 break;
  120.         case 3:
  121.         case 4:
  122.                 pitch_mask = align_large ? 63 : 15;
  123.                 break;
  124.         }
  125.  
  126.         aligned += pitch_mask;
  127.         aligned &= ~pitch_mask;
  128.         return aligned;
  129. }
  130.  
  131. static struct drm_fb_helper_funcs radeon_fb_helper_funcs = {
  132.         .gamma_set = radeon_crtc_fb_gamma_set,
  133.         .gamma_get = radeon_crtc_fb_gamma_get,
  134. };
  135.  
  136. int radeonfb_create(struct drm_device *dev,
  137.                     uint32_t fb_width, uint32_t fb_height,
  138.                     uint32_t surface_width, uint32_t surface_height,
  139.                     uint32_t surface_depth, uint32_t surface_bpp,
  140.                     struct drm_framebuffer **fb_p)
  141. {
  142.         struct radeon_device *rdev = dev->dev_private;
  143.         struct fb_info *info;
  144.         struct radeon_fb_device *rfbdev;
  145.         struct drm_framebuffer *fb = NULL;
  146.         struct radeon_framebuffer *rfb;
  147.         struct drm_mode_fb_cmd mode_cmd;
  148.         struct drm_gem_object *gobj = NULL;
  149.         struct radeon_bo *rbo = NULL;
  150.   //  struct device *device = &rdev->pdev->dev;
  151.         int size, aligned_size, ret;
  152.         u64 fb_gpuaddr;
  153.         void *fbptr = NULL;
  154.         unsigned long tmp;
  155.         bool fb_tiled = false; /* useful for testing */
  156.         u32 tiling_flags = 0;
  157.         int crtc_count;
  158.  
  159.     mode_cmd.width  = surface_width;
  160.         mode_cmd.height = surface_height;
  161.  
  162.         /* avivo can't scanout real 24bpp */
  163.         if ((surface_bpp == 24) && ASIC_IS_AVIVO(rdev))
  164.                 surface_bpp = 32;
  165.  
  166.         mode_cmd.bpp = surface_bpp;
  167.         /* need to align pitch with crtc limits */
  168.         mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp, fb_tiled) * ((mode_cmd.bpp + 1) / 8);
  169.         mode_cmd.depth = surface_depth;
  170.  
  171.         size = mode_cmd.pitch * mode_cmd.height;
  172.         aligned_size = ALIGN(size, PAGE_SIZE);
  173.  
  174.         ret = radeon_gem_object_create(rdev, aligned_size, 0,
  175.                         RADEON_GEM_DOMAIN_VRAM,
  176.                         false, ttm_bo_type_kernel,
  177.                         &gobj);
  178.         if (ret) {
  179.                 printk(KERN_ERR "failed to allocate framebuffer (%d %d)\n",
  180.                        surface_width, surface_height);
  181.                 ret = -ENOMEM;
  182.                 goto out;
  183.         }
  184.         rbo = gobj->driver_private;
  185.  
  186.         if (fb_tiled)
  187.                 tiling_flags = RADEON_TILING_MACRO;
  188.  
  189. #ifdef __BIG_ENDIAN
  190.         switch (mode_cmd.bpp) {
  191.         case 32:
  192.                 tiling_flags |= RADEON_TILING_SWAP_32BIT;
  193.                 break;
  194.         case 16:
  195.                 tiling_flags |= RADEON_TILING_SWAP_16BIT;
  196.         default:
  197.                 break;
  198.         }
  199. #endif
  200.  
  201.         if (tiling_flags) {
  202.                 ret = radeon_bo_set_tiling_flags(rbo,
  203.                                         tiling_flags | RADEON_TILING_SURFACE,
  204.                                         mode_cmd.pitch);
  205.                 if (ret)
  206.                         dev_err(rdev->dev, "FB failed to set tiling flags\n");
  207.         }
  208.         mutex_lock(&rdev->ddev->struct_mutex);
  209.         fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj);
  210.         if (fb == NULL) {
  211.                 DRM_ERROR("failed to allocate fb.\n");
  212.                 ret = -ENOMEM;
  213.                 goto out_unref;
  214.         }
  215.         ret = radeon_bo_reserve(rbo, false);
  216.         if (unlikely(ret != 0))
  217.                 goto out_unref;
  218.         ret = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_gpuaddr);
  219.         if (ret) {
  220.                 radeon_bo_unreserve(rbo);
  221.                 goto out_unref;
  222.         }
  223.         if (fb_tiled)
  224.                 radeon_bo_check_tiling(rbo, 0, 0);
  225.         ret = radeon_bo_kmap(rbo, &fbptr);
  226.         radeon_bo_unreserve(rbo);
  227.         if (ret) {
  228.                 goto out_unref;
  229.         }
  230.  
  231.     list_add(&fb->filp_head, &rdev->ddev->mode_config.fb_kernel_list);
  232.  
  233.         *fb_p = fb;
  234.         rfb = to_radeon_framebuffer(fb);
  235.         rdev->fbdev_rfb = rfb;
  236.         rdev->fbdev_rbo = rbo;
  237.  
  238.     info = framebuffer_alloc(sizeof(struct radeon_fb_device), NULL);
  239.         if (info == NULL) {
  240.                 ret = -ENOMEM;
  241.                 goto out_unref;
  242.         }
  243.  
  244.         rdev->fbdev_info = info;
  245.         rfbdev = info->par;
  246.         rfbdev->helper.funcs = &radeon_fb_helper_funcs;
  247.         rfbdev->helper.dev = dev;
  248.         if (rdev->flags & RADEON_SINGLE_CRTC)
  249.                 crtc_count = 1;
  250.         else
  251.                 crtc_count = 2;
  252.         ret = drm_fb_helper_init_crtc_count(&rfbdev->helper, crtc_count,
  253.                                             RADEONFB_CONN_LIMIT);
  254.         if (ret)
  255.                 goto out_unref;
  256.  
  257.    
  258.         strcpy(info->fix.id, "radeondrmfb");
  259.  
  260.         drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
  261.  
  262.         info->flags = FBINFO_DEFAULT;
  263.         info->fbops = &radeonfb_ops;
  264.  
  265.         tmp = fb_gpuaddr - rdev->mc.vram_location;
  266.         info->fix.smem_start = rdev->mc.aper_base + tmp;
  267.         info->fix.smem_len = size;
  268.         info->screen_base = fbptr;
  269.         info->screen_size = size;
  270.  
  271.         drm_fb_helper_fill_var(info, fb, fb_width, fb_height);
  272.  
  273.         /* setup aperture base/size for vesafb takeover */
  274.         info->aperture_base = rdev->ddev->mode_config.fb_base;
  275.         info->aperture_size = rdev->mc.real_vram_size;
  276.  
  277.         info->fix.mmio_start = 0;
  278.         info->fix.mmio_len = 0;
  279. //   info->pixmap.size = 64*1024;
  280. //   info->pixmap.buf_align = 8;
  281. //   info->pixmap.access_align = 32;
  282. //   info->pixmap.flags = FB_PIXMAP_SYSTEM;
  283. //   info->pixmap.scan_align = 1;
  284.         if (info->screen_base == NULL) {
  285.                 ret = -ENOSPC;
  286.                 goto out_unref;
  287.         }
  288.         DRM_INFO("fb mappable at 0x%lX\n",  info->fix.smem_start);
  289.         DRM_INFO("vram apper at 0x%lX\n",  (unsigned long)rdev->mc.aper_base);
  290.         DRM_INFO("size %lu\n", (unsigned long)size);
  291.         DRM_INFO("fb depth is %d\n", fb->depth);
  292.         DRM_INFO("   pitch is %d\n", fb->pitch);
  293.  
  294.     dbgprintf("fb = %x\n", fb);
  295.  
  296.         fb->fbdev = info;
  297.         rfbdev->rfb = rfb;
  298.         rfbdev->rdev = rdev;
  299.  
  300.         mutex_unlock(&rdev->ddev->struct_mutex);
  301.         return 0;
  302.  
  303. out_unref:
  304.         if (rbo) {
  305.                 ret = radeon_bo_reserve(rbo, false);
  306.                 if (likely(ret == 0)) {
  307.                         radeon_bo_kunmap(rbo);
  308.                         radeon_bo_unreserve(rbo);
  309.                 }
  310.         }
  311.         if (fb && ret) {
  312.                 list_del(&fb->filp_head);
  313. //      drm_gem_object_unreference(gobj);
  314. //       drm_framebuffer_cleanup(fb);
  315.                 kfree(fb);
  316.         }
  317. //   drm_gem_object_unreference(gobj);
  318.    mutex_unlock(&rdev->ddev->struct_mutex);
  319. out:
  320.         return ret;
  321. }
  322.  
  323. int radeonfb_probe(struct drm_device *dev)
  324. {
  325.         struct radeon_device *rdev = dev->dev_private;
  326.         int bpp_sel = 32;
  327.  
  328.         /* select 8 bpp console on RN50 or 16MB cards */
  329.         if (ASIC_IS_RN50(rdev) || rdev->mc.real_vram_size <= (32*1024*1024))
  330.                 bpp_sel = 8;
  331.  
  332.         return drm_fb_helper_single_fb_probe(dev, 32, &radeonfb_create);
  333. }
  334.  
  335. int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
  336. {
  337.         struct fb_info *info;
  338.         struct radeon_framebuffer *rfb = to_radeon_framebuffer(fb);
  339.         struct radeon_bo *rbo;
  340.         int r;
  341.  
  342.         if (!fb) {
  343.                 return -EINVAL;
  344.         }
  345.         info = fb->fbdev;
  346.         if (info) {
  347.                 struct radeon_fb_device *rfbdev = info->par;
  348.                 rbo = rfb->obj->driver_private;
  349. //       unregister_framebuffer(info);
  350.                 r = radeon_bo_reserve(rbo, false);
  351.                 if (likely(r == 0)) {
  352.                         radeon_bo_kunmap(rbo);
  353.                         radeon_bo_unpin(rbo);
  354.                         radeon_bo_unreserve(rbo);
  355.                 }
  356.                 drm_fb_helper_free(&rfbdev->helper);
  357.                 framebuffer_release(info);
  358.         }
  359.  
  360.         printk(KERN_INFO "unregistered panic notifier\n");
  361.  
  362.         return 0;
  363. }
  364. EXPORT_SYMBOL(radeonfb_remove);
  365.  
  366.  
  367.  
  368.