Subversion Repositories Kolibri OS

Rev

Rev 1179 | Rev 1221 | 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. struct fb_info *framebuffer_alloc(size_t size);
  46.  
  47. struct radeon_fb_device {
  48.     struct drm_fb_helper        helper;
  49.         struct radeon_framebuffer       *rfb;
  50.         struct radeon_device            *rdev;
  51. };
  52.  
  53. static struct fb_ops radeonfb_ops = {
  54. //   .owner = THIS_MODULE,
  55.         .fb_check_var = drm_fb_helper_check_var,
  56.         .fb_set_par = drm_fb_helper_set_par,
  57.         .fb_setcolreg = drm_fb_helper_setcolreg,
  58. //      .fb_fillrect = cfb_fillrect,
  59. //      .fb_copyarea = cfb_copyarea,
  60. //      .fb_imageblit = cfb_imageblit,
  61. //      .fb_pan_display = drm_fb_helper_pan_display,
  62.         .fb_blank = drm_fb_helper_blank,
  63. };
  64.  
  65. /**
  66.  * Curretly it is assumed that the old framebuffer is reused.
  67.  *
  68.  * LOCKING
  69.  * caller should hold the mode config lock.
  70.  *
  71.  */
  72. int radeonfb_resize(struct drm_device *dev, struct drm_crtc *crtc)
  73. {
  74.         struct fb_info *info;
  75.         struct drm_framebuffer *fb;
  76.         struct drm_display_mode *mode = crtc->desired_mode;
  77.  
  78.         fb = crtc->fb;
  79.         if (fb == NULL) {
  80.                 return 1;
  81.         }
  82.         info = fb->fbdev;
  83.         if (info == NULL) {
  84.                 return 1;
  85.         }
  86.         if (mode == NULL) {
  87.                 return 1;
  88.         }
  89.         info->var.xres = mode->hdisplay;
  90.         info->var.right_margin = mode->hsync_start - mode->hdisplay;
  91.         info->var.hsync_len = mode->hsync_end - mode->hsync_start;
  92.         info->var.left_margin = mode->htotal - mode->hsync_end;
  93.         info->var.yres = mode->vdisplay;
  94.         info->var.lower_margin = mode->vsync_start - mode->vdisplay;
  95.         info->var.vsync_len = mode->vsync_end - mode->vsync_start;
  96.         info->var.upper_margin = mode->vtotal - mode->vsync_end;
  97.         info->var.pixclock = 10000000 / mode->htotal * 1000 / mode->vtotal * 100;
  98.         /* avoid overflow */
  99.         info->var.pixclock = info->var.pixclock * 1000 / mode->vrefresh;
  100.  
  101.         return 0;
  102. }
  103. EXPORT_SYMBOL(radeonfb_resize);
  104.  
  105. static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled)
  106. {
  107.         int aligned = width;
  108.         int align_large = (ASIC_IS_AVIVO(rdev)) || tiled;
  109.         int pitch_mask = 0;
  110.  
  111.         switch (bpp / 8) {
  112.         case 1:
  113.                 pitch_mask = align_large ? 255 : 127;
  114.                 break;
  115.         case 2:
  116.                 pitch_mask = align_large ? 127 : 31;
  117.                 break;
  118.         case 3:
  119.         case 4:
  120.                 pitch_mask = align_large ? 63 : 15;
  121.                 break;
  122.         }
  123.  
  124.         aligned += pitch_mask;
  125.         aligned &= ~pitch_mask;
  126.         return aligned;
  127. }
  128.  
  129. static struct drm_fb_helper_funcs radeon_fb_helper_funcs = {
  130.         .gamma_set = radeon_crtc_fb_gamma_set,
  131. };
  132.  
  133. int radeonfb_create(struct drm_device *dev,
  134.                     uint32_t fb_width, uint32_t fb_height,
  135.                     uint32_t surface_width, uint32_t surface_height,
  136.                     struct drm_framebuffer **fb_p)
  137. {
  138.         struct radeon_device *rdev = dev->dev_private;
  139.         struct fb_info *info;
  140.         struct radeon_fb_device *rfbdev;
  141.         struct drm_framebuffer *fb = NULL;
  142.         struct radeon_framebuffer *rfb;
  143.         struct drm_mode_fb_cmd mode_cmd;
  144.         struct drm_gem_object *gobj = NULL;
  145.         struct radeon_object *robj = NULL;
  146. //   struct device *device = &rdev->pdev->dev;
  147.         int size, aligned_size, ret;
  148.         u64 fb_gpuaddr;
  149.         void *fbptr = NULL;
  150.         unsigned long tmp;
  151.         bool fb_tiled = false; /* useful for testing */
  152.         u32 tiling_flags = 0;
  153.  
  154.     mode_cmd.width  = surface_width;
  155.         mode_cmd.height = surface_height;
  156.         mode_cmd.bpp = 32;
  157.         /* need to align pitch with crtc limits */
  158.         mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp, fb_tiled) * ((mode_cmd.bpp + 1) / 8);
  159.         mode_cmd.depth = 24;
  160.  
  161.         size = mode_cmd.pitch * mode_cmd.height;
  162.         aligned_size = ALIGN(size, PAGE_SIZE);
  163.  
  164.     ret = radeon_gem_fb_object_create(rdev, aligned_size, 0,
  165.                         RADEON_GEM_DOMAIN_VRAM,
  166.             false, 0,
  167.                         false, &gobj);
  168.  
  169.         if (ret) {
  170.                 printk(KERN_ERR "failed to allocate framebuffer (%d %d)\n",
  171.                        surface_width, surface_height);
  172.                 ret = -ENOMEM;
  173.                 goto out;
  174.         }
  175.         robj = gobj->driver_private;
  176.  
  177.         mutex_lock(&rdev->ddev->struct_mutex);
  178.         fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj);
  179.         if (fb == NULL) {
  180.                 DRM_ERROR("failed to allocate fb.\n");
  181.                 ret = -ENOMEM;
  182.                 goto out_unref;
  183.         }
  184.         ret = radeon_object_pin(robj, RADEON_GEM_DOMAIN_VRAM, &fb_gpuaddr);
  185.         if (ret) {
  186.                 printk(KERN_ERR "failed to pin framebuffer\n");
  187.                 ret = -ENOMEM;
  188.                 goto out_unref;
  189.         }
  190.  
  191.     list_add(&fb->filp_head, &rdev->ddev->mode_config.fb_kernel_list);
  192.  
  193.         *fb_p = fb;
  194.         rfb = to_radeon_framebuffer(fb);
  195.         rdev->fbdev_rfb = rfb;
  196.         rdev->fbdev_robj = robj;
  197.  
  198.         info = framebuffer_alloc(sizeof(struct radeon_fb_device));
  199.         if (info == NULL) {
  200.                 ret = -ENOMEM;
  201.                 goto out_unref;
  202.         }
  203.  
  204.         rdev->fbdev_info = info;
  205.         rfbdev = info->par;
  206.         rfbdev->helper.funcs = &radeon_fb_helper_funcs;
  207.         rfbdev->helper.dev = dev;
  208.         ret = drm_fb_helper_init_crtc_count(&rfbdev->helper, 2,
  209.                                             RADEONFB_CONN_LIMIT);
  210.         if (ret)
  211.                 goto out_unref;
  212.  
  213. //   ret = radeon_object_kmap(robj, &fbptr);
  214. //   if (ret) {
  215. //       goto out_unref;
  216. //   }
  217.  
  218.  
  219.     fbptr = (void*)0xFE000000; // LFB_BASE
  220.  
  221.         strcpy(info->fix.id, "radeondrmfb");
  222.  
  223.         drm_fb_helper_fill_fix(info, fb->pitch);
  224.  
  225.         info->flags = FBINFO_DEFAULT;
  226.         info->fbops = &radeonfb_ops;
  227.  
  228.         tmp = fb_gpuaddr - rdev->mc.vram_location;
  229.         info->fix.smem_start = rdev->mc.aper_base + tmp;
  230.         info->fix.smem_len = size;
  231.         info->screen_base = fbptr;
  232.         info->screen_size = size;
  233.  
  234.         drm_fb_helper_fill_var(info, fb, fb_width, fb_height);
  235.  
  236.         /* setup aperture base/size for vesafb takeover */
  237.         info->aperture_base = rdev->ddev->mode_config.fb_base;
  238.         info->aperture_size = rdev->mc.real_vram_size;
  239.  
  240.         info->fix.mmio_start = 0;
  241.         info->fix.mmio_len = 0;
  242. //   info->pixmap.size = 64*1024;
  243. //   info->pixmap.buf_align = 8;
  244. //   info->pixmap.access_align = 32;
  245. //   info->pixmap.flags = FB_PIXMAP_SYSTEM;
  246. //   info->pixmap.scan_align = 1;
  247.         if (info->screen_base == NULL) {
  248.                 ret = -ENOSPC;
  249.                 goto out_unref;
  250.         }
  251.         DRM_INFO("fb mappable at 0x%lX\n",  info->fix.smem_start);
  252.         DRM_INFO("vram apper at 0x%lX\n",  (unsigned long)rdev->mc.aper_base);
  253.         DRM_INFO("size %lu\n", (unsigned long)size);
  254.         DRM_INFO("fb depth is %d\n", fb->depth);
  255.         DRM_INFO("   pitch is %d\n", fb->pitch);
  256.  
  257.     dbgprintf("fb = %x\n", fb);
  258.  
  259.         fb->fbdev = info;
  260.         rfbdev->rfb = rfb;
  261.         rfbdev->rdev = rdev;
  262.  
  263.         mutex_unlock(&rdev->ddev->struct_mutex);
  264.         return 0;
  265.  
  266. out_unref:
  267.         if (robj) {
  268. //       radeon_object_kunmap(robj);
  269.         }
  270.         if (fb && ret) {
  271.                 list_del(&fb->filp_head);
  272.  //      drm_gem_object_unreference(gobj);
  273. //       drm_framebuffer_cleanup(fb);
  274.                 kfree(fb);
  275.         }
  276. //   drm_gem_object_unreference(gobj);
  277.    mutex_unlock(&rdev->ddev->struct_mutex);
  278. out:
  279.         return ret;
  280. }
  281.  
  282. int radeonfb_probe(struct drm_device *dev)
  283. {
  284.         int ret;
  285.         ret = drm_fb_helper_single_fb_probe(dev, &radeonfb_create);
  286.         return ret;
  287. }
  288. EXPORT_SYMBOL(radeonfb_probe);
  289.  
  290. int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
  291. {
  292.         struct fb_info *info;
  293.         struct radeon_framebuffer *rfb = to_radeon_framebuffer(fb);
  294.         struct radeon_object *robj;
  295.  
  296.         if (!fb) {
  297.                 return -EINVAL;
  298.         }
  299.         info = fb->fbdev;
  300.         if (info) {
  301.                 struct radeon_fb_device *rfbdev = info->par;
  302.                 robj = rfb->obj->driver_private;
  303. //       unregister_framebuffer(info);
  304. //       radeon_object_kunmap(robj);
  305. //       radeon_object_unpin(robj);
  306. //       framebuffer_release(info);
  307.         }
  308.  
  309.         printk(KERN_INFO "unregistered panic notifier\n");
  310.  
  311.         return 0;
  312. }
  313. EXPORT_SYMBOL(radeonfb_remove);
  314.  
  315.  
  316. /**
  317.  * Allocate a GEM object of the specified size with shmfs backing store
  318.  */
  319. struct drm_gem_object *
  320. drm_gem_object_alloc(struct drm_device *dev, size_t size)
  321. {
  322.     struct drm_gem_object *obj;
  323.  
  324.     BUG_ON((size & (PAGE_SIZE - 1)) != 0);
  325.  
  326.     obj = kzalloc(sizeof(*obj), GFP_KERNEL);
  327.  
  328.     obj->dev = dev;
  329. //    obj->filp = shmem_file_setup("drm mm object", size, VM_NORESERVE);
  330. //    if (IS_ERR(obj->filp)) {
  331. //        kfree(obj);
  332. //        return NULL;
  333. //    }
  334.  
  335. //    kref_init(&obj->refcount);
  336. //    kref_init(&obj->handlecount);
  337.     obj->size = size;
  338.  
  339. //    if (dev->driver->gem_init_object != NULL &&
  340. //        dev->driver->gem_init_object(obj) != 0) {
  341. //        fput(obj->filp);
  342. //        kfree(obj);
  343. //        return NULL;
  344. //    }
  345. //    atomic_inc(&dev->object_count);
  346. //    atomic_add(obj->size, &dev->object_memory);
  347.     return obj;
  348. }
  349.  
  350.  
  351. int radeon_gem_fb_object_create(struct radeon_device *rdev, int size,
  352.                  int alignment, int initial_domain,
  353.                  bool discardable, bool kernel,
  354.                  bool interruptible,
  355.                  struct drm_gem_object **obj)
  356. {
  357.     struct drm_gem_object *gobj;
  358.     struct radeon_object *robj;
  359.  
  360.     *obj = NULL;
  361.     gobj = drm_gem_object_alloc(rdev->ddev, size);
  362.     if (!gobj) {
  363.         return -ENOMEM;
  364.     }
  365.     /* At least align on page size */
  366.     if (alignment < PAGE_SIZE) {
  367.         alignment = PAGE_SIZE;
  368.     }
  369.  
  370.     robj = kzalloc(sizeof(struct radeon_object), GFP_KERNEL);
  371.     if (!robj) {
  372.         DRM_ERROR("Failed to allocate GEM object (%d, %d, %u)\n",
  373.               size, initial_domain, alignment);
  374. //       mutex_lock(&rdev->ddev->struct_mutex);
  375. //       drm_gem_object_unreference(gobj);
  376. //       mutex_unlock(&rdev->ddev->struct_mutex);
  377.         return -ENOMEM;;
  378.     }
  379.     robj->rdev = rdev;
  380.     robj->gobj = gobj;
  381.     INIT_LIST_HEAD(&robj->list);
  382.  
  383.     robj->flags = TTM_PL_FLAG_VRAM;
  384.  
  385.     struct drm_mm_node *vm_node;
  386.  
  387.     vm_node = kzalloc(sizeof(*vm_node),0);
  388.  
  389.     vm_node->free = 0;
  390.     vm_node->size = 0x800000 >> 12;
  391.     vm_node->start = 0;
  392.     vm_node->mm = NULL;
  393.  
  394.     robj->mm_node = vm_node;
  395.  
  396.     robj->vm_addr = ((uint32_t)robj->mm_node->start);
  397.  
  398.     gobj->driver_private = robj;
  399.     *obj = gobj;
  400.     return 0;
  401. }
  402.  
  403.  
  404. struct fb_info *framebuffer_alloc(size_t size)
  405. {
  406. #define BYTES_PER_LONG (BITS_PER_LONG/8)
  407. #define PADDING (BYTES_PER_LONG - (sizeof(struct fb_info) % BYTES_PER_LONG))
  408.         int fb_info_size = sizeof(struct fb_info);
  409.         struct fb_info *info;
  410.         char *p;
  411.  
  412.         if (size)
  413.                 fb_info_size += PADDING;
  414.  
  415.         p = kzalloc(fb_info_size + size, GFP_KERNEL);
  416.  
  417.         if (!p)
  418.                 return NULL;
  419.  
  420.         info = (struct fb_info *) p;
  421.  
  422.         if (size)
  423.                 info->par = p + fb_info_size;
  424.  
  425.         return info;
  426. #undef PADDING
  427. #undef BYTES_PER_LONG
  428. }
  429.  
  430. static char *manufacturer_name(unsigned char *x)
  431. {
  432.     static char name[4];
  433.  
  434.     name[0] = ((x[0] & 0x7C) >> 2) + '@';
  435.     name[1] = ((x[0] & 0x03) << 3) + ((x[1] & 0xE0) >> 5) + '@';
  436.     name[2] = (x[1] & 0x1F) + '@';
  437.     name[3] = 0;
  438.  
  439.     return name;
  440. }
  441.  
  442.  
  443. bool set_mode(struct drm_device *dev, int width, int height)
  444. {
  445.     struct drm_connector *connector;
  446.  
  447.     bool ret = false;
  448.  
  449.     list_for_each_entry(connector, &dev->mode_config.connector_list, head)
  450.     {
  451.         struct drm_display_mode *mode;
  452.  
  453.         struct drm_encoder  *encoder;
  454.         struct drm_crtc     *crtc;
  455.  
  456.         if( connector->status != connector_status_connected)
  457.             continue;
  458.  
  459.         encoder = connector->encoder;
  460.         if( encoder == NULL)
  461.             continue;
  462.  
  463.         crtc = encoder->crtc;
  464.  
  465.         if(crtc == NULL)
  466.             continue;
  467.  
  468.  
  469.         list_for_each_entry(mode, &connector->modes, head)
  470.         {
  471.             if (mode->type & DRM_MODE_TYPE_PREFERRED);
  472.                 break;
  473.         };
  474.  
  475. /*
  476.         struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
  477.         struct radeon_native_mode *native_mode = &radeon_encoder->native_mode;
  478.  
  479.         native_mode->panel_xres = mode->hdisplay;
  480.         native_mode->panel_yres = mode->vdisplay;
  481.  
  482.         native_mode->hblank = mode->htotal - mode->hdisplay;
  483.         native_mode->hoverplus = mode->hsync_start - mode->hdisplay;
  484.         native_mode->hsync_width = mode->hsync_end - mode->hsync_start;
  485.         native_mode->vblank = mode->vtotal - mode->vdisplay;
  486.         native_mode->voverplus = mode->vsync_start - mode->vdisplay;
  487.         native_mode->vsync_width = mode->vsync_end - mode->vsync_start;
  488.         native_mode->dotclock = mode->clock;
  489.         native_mode->flags = mode->flags;
  490. */
  491.         list_for_each_entry(mode, &connector->modes, head)
  492.         {
  493.             char *con_name, *enc_name;
  494.  
  495.             struct drm_framebuffer *fb;
  496.  
  497.             if (drm_mode_width(mode) == width &&
  498.                 drm_mode_height(mode) == height)
  499.             {
  500.                 char con_edid[128];
  501.  
  502.                 fb = list_first_entry(&dev->mode_config.fb_kernel_list,
  503.                                       struct drm_framebuffer, filp_head);
  504.  
  505.                 memcpy(con_edid, connector->edid_blob_ptr->data, 128);
  506.  
  507.                 dbgprintf("Manufacturer: %s Model %x Serial Number %u\n",
  508.                 manufacturer_name(con_edid + 0x08),
  509.                 (unsigned short)(con_edid[0x0A] + (con_edid[0x0B] << 8)),
  510.                 (unsigned int)(con_edid[0x0C] + (con_edid[0x0D] << 8)
  511.                     + (con_edid[0x0E] << 16) + (con_edid[0x0F] << 24)));
  512.  
  513.  
  514.                 con_name = drm_get_connector_name(connector);
  515.                 enc_name = drm_get_encoder_name(encoder);
  516.  
  517.                 dbgprintf("set mode %d %d connector %s encoder %s\n",
  518.                            width, height, con_name, enc_name);
  519.  
  520.                 fb->width = width;
  521.                 fb->height = height;
  522.                 fb->pitch = radeon_align_pitch(dev->dev_private, width, 32, false) * ((32 + 1) / 8);
  523.  
  524.                 crtc->fb = fb;
  525.  
  526.                 ret = drm_crtc_helper_set_mode(crtc, mode, 0, 0, fb);
  527.  
  528.                 sysSetScreen(fb->width, fb->height, fb->pitch);
  529.  
  530.                 if (ret == true)
  531.                 {
  532.                     dbgprintf("new mode %d %d pitch %d\n",fb->width, fb->height, fb->pitch);
  533.                 }
  534.                 else
  535.                 {
  536.                     DRM_ERROR("failed to set mode %d_%d on crtc %p\n",
  537.                                fb->width, fb->height, crtc);
  538.                 };
  539.             };
  540.         }
  541.     };
  542.  
  543.     return ret;
  544. };
  545.  
  546.  
  547.