Subversion Repositories Kolibri OS

Rev

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