Subversion Repositories Kolibri OS

Rev

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

  1.  
  2. #include <drm/drmP.h>
  3. #include <drm.h>
  4. #include <drm_mm.h>
  5. #include "radeon_drm.h"
  6. #include "radeon.h"
  7. #include "radeon_object.h"
  8. #include "display.h"
  9. #include "drm_fb_helper.h"
  10.  
  11. struct radeon_fbdev {
  12.     struct drm_fb_helper        helper;
  13.     struct radeon_framebuffer   rfb;
  14.     struct list_head fbdev_list;
  15.     struct radeon_device        *rdev;
  16. };
  17.  
  18. struct radeon_fbdev *kos_rfbdev;
  19.  
  20.  
  21. static cursor_t*  __stdcall select_cursor_kms(cursor_t *cursor);
  22. static void       __stdcall move_cursor_kms(cursor_t *cursor, int x, int y);
  23.  
  24. int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled);
  25.  
  26. void disable_mouse(void);
  27.  
  28. static void radeon_show_cursor_kms(struct drm_crtc *crtc)
  29. {
  30.     struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  31.     struct radeon_device *rdev = crtc->dev->dev_private;
  32.  
  33.     if (ASIC_IS_DCE4(rdev)) {
  34.         WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset);
  35.         WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_EN |
  36.                EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT));
  37.     } else if (ASIC_IS_AVIVO(rdev)) {
  38.         WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);
  39.         WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN |
  40.                  (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
  41.     } else {
  42.         switch (radeon_crtc->crtc_id) {
  43.         case 0:
  44.             WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL);
  45.             break;
  46.         case 1:
  47.             WREG32(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL);
  48.             break;
  49.         default:
  50.             return;
  51.         }
  52.  
  53.         WREG32_P(RADEON_MM_DATA, (RADEON_CRTC_CUR_EN |
  54.                       (RADEON_CRTC_CUR_MODE_24BPP << RADEON_CRTC_CUR_MODE_SHIFT)),
  55.              ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_CUR_MODE_MASK));
  56.     }
  57. }
  58.  
  59. static void radeon_lock_cursor_kms(struct drm_crtc *crtc, bool lock)
  60. {
  61.     struct radeon_device *rdev = crtc->dev->dev_private;
  62.     struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  63.     uint32_t cur_lock;
  64.  
  65.     if (ASIC_IS_DCE4(rdev)) {
  66.         cur_lock = RREG32(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset);
  67.         if (lock)
  68.             cur_lock |= EVERGREEN_CURSOR_UPDATE_LOCK;
  69.         else
  70.             cur_lock &= ~EVERGREEN_CURSOR_UPDATE_LOCK;
  71.         WREG32(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset, cur_lock);
  72.     } else if (ASIC_IS_AVIVO(rdev)) {
  73.         cur_lock = RREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset);
  74.         if (lock)
  75.             cur_lock |= AVIVO_D1CURSOR_UPDATE_LOCK;
  76.         else
  77.             cur_lock &= ~AVIVO_D1CURSOR_UPDATE_LOCK;
  78.         WREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset, cur_lock);
  79.     } else {
  80.         cur_lock = RREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset);
  81.         if (lock)
  82.             cur_lock |= RADEON_CUR_LOCK;
  83.         else
  84.             cur_lock &= ~RADEON_CUR_LOCK;
  85.         WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, cur_lock);
  86.     }
  87. }
  88.  
  89. cursor_t* __stdcall select_cursor_kms(cursor_t *cursor)
  90. {
  91.     struct radeon_device *rdev;
  92.     struct radeon_crtc   *radeon_crtc;
  93.     cursor_t *old;
  94.     uint32_t  gpu_addr;
  95.  
  96.     rdev = (struct radeon_device *)rdisplay->ddev->dev_private;
  97.     radeon_crtc = to_radeon_crtc(rdisplay->crtc);
  98.  
  99.     old = rdisplay->cursor;
  100.  
  101.     rdisplay->cursor = cursor;
  102.     gpu_addr = radeon_bo_gpu_offset(cursor->robj);
  103.  
  104.     if (ASIC_IS_DCE4(rdev)) {
  105.         WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
  106.                0);
  107.         WREG32(EVERGREEN_CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
  108.                gpu_addr);
  109.     } else if (ASIC_IS_AVIVO(rdev)) {
  110.         if (rdev->family >= CHIP_RV770)
  111.             WREG32(R700_D1CUR_SURFACE_ADDRESS_HIGH, 0);
  112.         WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, gpu_addr);
  113.     }
  114.     else {
  115.         radeon_crtc->legacy_cursor_offset = gpu_addr - rdev->mc.vram_start;
  116.         /* offset is from DISP(2)_BASE_ADDRESS */
  117.         WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, radeon_crtc->legacy_cursor_offset);
  118.     }
  119.  
  120.     return old;
  121. };
  122.  
  123. void __stdcall move_cursor_kms(cursor_t *cursor, int x, int y)
  124. {
  125.     struct radeon_device *rdev;
  126.     rdev = (struct radeon_device *)rdisplay->ddev->dev_private;
  127.     struct drm_crtc *crtc = rdisplay->crtc;
  128.     struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  129.  
  130.     int hot_x = cursor->hot_x;
  131.     int hot_y = cursor->hot_y;
  132.     int w = 32;
  133.  
  134.     radeon_lock_cursor_kms(crtc, true);
  135.  
  136.     if (ASIC_IS_DCE4(rdev)) {
  137.         WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset,
  138.                (x << 16) | y);
  139.         WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset,
  140.                (hot_x << 16) | hot_y);
  141.         WREG32(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset,
  142.                ((w - 1) << 16) | 31);
  143.     } else if (ASIC_IS_AVIVO(rdev)) {
  144.         WREG32(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset,
  145.                (x << 16) | y);
  146.         WREG32(AVIVO_D1CUR_HOT_SPOT + radeon_crtc->crtc_offset,
  147.                (hot_x << 16) | hot_y);
  148.         WREG32(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset,
  149.                ((w - 1) << 16) | 31);
  150.     } else {
  151.         if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)
  152.             y *= 2;
  153.  
  154.         uint32_t  gpu_addr;
  155.         int       xorg =0, yorg=0;
  156.  
  157.         x = x - hot_x;
  158.         y = y - hot_y;
  159.  
  160.         if( x < 0 )
  161.         {
  162.             xorg = -x + 1;
  163.             x = 0;
  164.         }
  165.  
  166.         if( y < 0 )
  167.         {
  168.             yorg = -hot_y + 1;
  169.             y = 0;
  170.         };
  171.  
  172.         WREG32(RADEON_CUR_HORZ_VERT_OFF,
  173.                (RADEON_CUR_LOCK | (xorg << 16) | yorg ));
  174.         WREG32(RADEON_CUR_HORZ_VERT_POSN,
  175.                (RADEON_CUR_LOCK | (x << 16) | y));
  176.  
  177.         gpu_addr = radeon_bo_gpu_offset(cursor->robj);
  178.  
  179.         /* offset is from DISP(2)_BASE_ADDRESS */
  180.         WREG32(RADEON_CUR_OFFSET,
  181.          (gpu_addr - rdev->mc.vram_start + (yorg * 256)));
  182.     }
  183.     radeon_lock_cursor_kms(crtc, false);
  184. }
  185.  
  186. static char *manufacturer_name(unsigned char *x)
  187. {
  188.     static char name[4];
  189.  
  190.     name[0] = ((x[0] & 0x7C) >> 2) + '@';
  191.     name[1] = ((x[0] & 0x03) << 3) + ((x[1] & 0xE0) >> 5) + '@';
  192.     name[2] = (x[1] & 0x1F) + '@';
  193.     name[3] = 0;
  194.  
  195.     return name;
  196. }
  197.  
  198. bool set_mode(struct drm_device *dev, struct drm_connector *connector,
  199.               videomode_t *reqmode, bool strict)
  200. {
  201.     struct drm_display_mode  *mode = NULL, *tmpmode;
  202.  
  203.     struct drm_fb_helper *fb_helper;
  204.  
  205.     fb_helper = &kos_rfbdev->helper;
  206.  
  207.  
  208.     bool ret = false;
  209.  
  210.     ENTER();
  211.  
  212.     dbgprintf("width %d height %d vrefresh %d\n",
  213.                reqmode->width, reqmode->height, reqmode->freq);
  214.  
  215.     list_for_each_entry(tmpmode, &connector->modes, head)
  216.     {
  217.         if( (drm_mode_width(tmpmode)    == reqmode->width)  &&
  218.             (drm_mode_height(tmpmode)   == reqmode->height) &&
  219.             (drm_mode_vrefresh(tmpmode) == reqmode->freq) )
  220.         {
  221.             mode = tmpmode;
  222.             goto do_set;
  223.         }
  224.     };
  225.  
  226.     if( (mode == NULL) && (strict == false) )
  227.     {
  228.         list_for_each_entry(tmpmode, &connector->modes, head)
  229.         {
  230.             if( (drm_mode_width(tmpmode)  == reqmode->width)  &&
  231.                 (drm_mode_height(tmpmode) == reqmode->height) )
  232.             {
  233.                 mode = tmpmode;
  234.                 goto do_set;
  235.             }
  236.         };
  237.     };
  238.  
  239. do_set:
  240.  
  241.     if( mode != NULL )
  242.     {
  243.         struct drm_framebuffer   *fb;
  244.         struct drm_encoder       *encoder;
  245.         struct drm_crtc          *crtc;
  246.  
  247. //        char  con_edid[128];
  248.         char *con_name;
  249.         char *enc_name;
  250.  
  251.         encoder = connector->encoder;
  252.         crtc = encoder->crtc;
  253.  
  254. //        fb = list_first_entry(&dev->mode_config.fb_kernel_list,
  255. //                              struct drm_framebuffer, filp_head);
  256.  
  257. //        memcpy(con_edid, connector->edid_blob_ptr->data, 128);
  258.  
  259. //        dbgprintf("Manufacturer: %s Model %x Serial Number %u\n",
  260. //        manufacturer_name(con_edid + 0x08),
  261. //        (unsigned short)(con_edid[0x0A] + (con_edid[0x0B] << 8)),
  262. //        (unsigned int)(con_edid[0x0C] + (con_edid[0x0D] << 8)
  263. //            + (con_edid[0x0E] << 16) + (con_edid[0x0F] << 24)));
  264.  
  265.         con_name = drm_get_connector_name(connector);
  266.         enc_name = drm_get_encoder_name(encoder);
  267.  
  268.         dbgprintf("set mode %d %d connector %s encoder %s\n",
  269.                    reqmode->width, reqmode->height, con_name, enc_name);
  270.  
  271.         fb = fb_helper->fb;
  272.  
  273.         fb->width  = reqmode->width;
  274.         fb->height = reqmode->height;
  275.         fb->pitch  = radeon_align_pitch(dev->dev_private, reqmode->width, 32, false) * ((32 + 1) / 8);
  276.         fb->bits_per_pixel = 32;
  277.  
  278.         crtc->fb = fb;
  279.         crtc->enabled = true;
  280.         rdisplay->crtc = crtc;
  281.  
  282.         ret = drm_crtc_helper_set_mode(crtc, mode, 0, 0, fb);
  283.  
  284.         select_cursor_kms(rdisplay->cursor);
  285.         radeon_show_cursor_kms(crtc);
  286.  
  287.         if (ret == true)
  288.         {
  289.             rdisplay->width    = fb->width;
  290.             rdisplay->height   = fb->height;
  291.             rdisplay->pitch    = fb->pitch;
  292.             rdisplay->vrefresh = drm_mode_vrefresh(mode);
  293.  
  294.             sysSetScreen(fb->width, fb->height, fb->pitch);
  295.  
  296.             dbgprintf("new mode %d x %d pitch %d\n",
  297.                        fb->width, fb->height, fb->pitch);
  298.         }
  299.         else
  300.             DRM_ERROR("failed to set mode %d_%d on crtc %p\n",
  301.                        fb->width, fb->height, crtc);
  302.     }
  303.  
  304.     LEAVE();
  305.     return ret;
  306. };
  307.  
  308. static int count_connector_modes(struct drm_connector* connector)
  309. {
  310.     struct drm_display_mode  *mode;
  311.     int count = 0;
  312.  
  313.     list_for_each_entry(mode, &connector->modes, head)
  314.     {
  315.         count++;
  316.     };
  317.     return count;
  318. };
  319.  
  320. static struct drm_connector* get_def_connector(struct drm_device *dev)
  321. {
  322.     struct drm_connector  *connector;
  323.     struct drm_connector_helper_funcs *connector_funcs;
  324.  
  325.     struct drm_connector  *def_connector = NULL;
  326.  
  327.     list_for_each_entry(connector, &dev->mode_config.connector_list, head)
  328.     {
  329.         struct drm_encoder  *encoder;
  330.         struct drm_crtc     *crtc;
  331.  
  332.         if( connector->status != connector_status_connected)
  333.             continue;
  334.  
  335.         connector_funcs = connector->helper_private;
  336.         encoder = connector_funcs->best_encoder(connector);
  337.         if( encoder == NULL)
  338.             continue;
  339.  
  340.         connector->encoder = encoder;
  341.  
  342.         crtc = encoder->crtc;
  343.  
  344.         dbgprintf("CONNECTOR %x ID:  %d status %d encoder %x\n crtc %x",
  345.                    connector, connector->base.id,
  346.                    connector->status, connector->encoder,
  347.                    crtc);
  348.  
  349. //        if (crtc == NULL)
  350. //            continue;
  351.  
  352.         def_connector = connector;
  353.  
  354.         break;
  355.     };
  356.  
  357.     return def_connector;
  358. };
  359.  
  360.  
  361.  
  362. bool init_display_kms(struct radeon_device *rdev, videomode_t *usermode)
  363. {
  364.     struct drm_device   *dev;
  365.  
  366.     cursor_t            *cursor;
  367.     bool                 retval = false;
  368.     u32_t                ifl;
  369.  
  370.     struct radeon_fbdev  *rfbdev;
  371.     struct drm_fb_helper *fb_helper;
  372.  
  373.     int i;
  374.  
  375.     ENTER();
  376.  
  377.     rdisplay = GetDisplay();
  378.  
  379.     dev = rdisplay->ddev = rdev->ddev;
  380.  
  381.     ifl = safe_cli();
  382.     {
  383.         list_for_each_entry(cursor, &rdisplay->cursors, list)
  384.         {
  385.             init_cursor(cursor);
  386.         };
  387.     };
  388.     safe_sti(ifl);
  389.  
  390.  
  391.  
  392.     rfbdev    = rdev->mode_info.rfbdev;
  393.     fb_helper = &rfbdev->helper;
  394.  
  395.  
  396. //    for (i = 0; i < fb_helper->crtc_count; i++)
  397. //    {
  398.         struct drm_mode_set *mode_set = &fb_helper->crtc_info[0].mode_set;
  399.         struct drm_crtc *crtc;
  400.         struct drm_display_mode *mode;
  401.  
  402.         crtc = mode_set->crtc;
  403.  
  404. //        if (!crtc->enabled)
  405. //            continue;
  406.  
  407.         mode = mode_set->mode;
  408.  
  409.         dbgprintf("crtc %d width %d height %d vrefresh %d\n",
  410.                crtc->base.id,
  411.                drm_mode_width(mode), drm_mode_height(mode),
  412.                drm_mode_vrefresh(mode));
  413. //    }
  414.  
  415.  
  416.     rdisplay->connector = get_def_connector(dev);
  417.     if( rdisplay->connector == 0 )
  418.     {
  419.         dbgprintf("no active connectors\n");
  420.         return false;
  421.     };
  422.  
  423.  
  424.     rdisplay->crtc = rdisplay->connector->encoder->crtc = crtc;
  425.  
  426.     rdisplay->supported_modes = count_connector_modes(rdisplay->connector);
  427.  
  428.     dbgprintf("current mode %d x %d x %d\n",
  429.               rdisplay->width, rdisplay->height, rdisplay->vrefresh);
  430.     dbgprintf("user mode mode %d x %d x %d\n",
  431.               usermode->width, usermode->height, usermode->freq);
  432.  
  433.     if( (usermode->width  != 0) &&
  434.         (usermode->height != 0) &&
  435.         ( (usermode->width  != rdisplay->width)  ||
  436.           (usermode->height != rdisplay->height) ||
  437.           (usermode->freq   != rdisplay->vrefresh) ) )
  438.     {
  439.  
  440.         retval = set_mode(dev, rdisplay->connector, usermode, false);
  441.     }
  442.  
  443.     ifl = safe_cli();
  444.     {
  445.         rdisplay->restore_cursor(0,0);
  446.         rdisplay->init_cursor    = init_cursor;
  447.         rdisplay->select_cursor  = select_cursor_kms;
  448.         rdisplay->show_cursor    = NULL;
  449.         rdisplay->move_cursor    = move_cursor_kms;
  450.         rdisplay->restore_cursor = restore_cursor;
  451.         rdisplay->disable_mouse  = disable_mouse;
  452.  
  453.         select_cursor_kms(rdisplay->cursor);
  454.         radeon_show_cursor_kms(rdisplay->crtc);
  455.     };
  456.     safe_sti(ifl);
  457.  
  458.     LEAVE();
  459.  
  460.     return retval;
  461. };
  462.  
  463. int get_modes(videomode_t *mode, int *count)
  464. {
  465.     int err = -1;
  466.  
  467.     ENTER();
  468.  
  469.     dbgprintf("mode %x count %d\n", mode, *count);
  470.  
  471.     if( *count == 0 )
  472.     {
  473.         *count = rdisplay->supported_modes;
  474.         err = 0;
  475.     }
  476.     else if( mode != NULL )
  477.     {
  478.         struct drm_display_mode  *drmmode;
  479.         int i = 0;
  480.  
  481.         if( *count > rdisplay->supported_modes)
  482.             *count = rdisplay->supported_modes;
  483.  
  484.         list_for_each_entry(drmmode, &rdisplay->connector->modes, head)
  485.         {
  486.             if( i < *count)
  487.             {
  488.                 mode->width  = drm_mode_width(drmmode);
  489.                 mode->height = drm_mode_height(drmmode);
  490.                 mode->bpp    = 32;
  491.                 mode->freq   = drm_mode_vrefresh(drmmode);
  492.                 i++;
  493.                 mode++;
  494.             }
  495.             else break;
  496.         };
  497.         *count = i;
  498.         err = 0;
  499.     };
  500.     LEAVE();
  501.     return err;
  502. }
  503.  
  504. int set_user_mode(videomode_t *mode)
  505. {
  506.     int err = -1;
  507.  
  508.     ENTER();
  509.  
  510.     dbgprintf("width %d height %d vrefresh %d\n",
  511.                mode->width, mode->height, mode->freq);
  512.  
  513.     if( (mode->width  != 0)  &&
  514.         (mode->height != 0)  &&
  515.         (mode->freq   != 0 ) &&
  516.         ( (mode->width   != rdisplay->width)  ||
  517.           (mode->height  != rdisplay->height) ||
  518.           (mode->freq    != rdisplay->vrefresh) ) )
  519.     {
  520.         if( set_mode(rdisplay->ddev, rdisplay->connector, mode, true) )
  521.             err = 0;
  522.     };
  523.  
  524.     LEAVE();
  525.     return err;
  526. };
  527.  
  528.  
  529.  
  530. int radeonfb_create_object(struct radeon_fbdev *rfbdev,
  531.                      struct drm_mode_fb_cmd *mode_cmd,
  532.                      struct drm_gem_object **gobj_p)
  533. {
  534.     struct radeon_device *rdev = rfbdev->rdev;
  535.     struct drm_gem_object *gobj = NULL;
  536.     struct radeon_bo *rbo = NULL;
  537.     bool fb_tiled = false; /* useful for testing */
  538.     u32 tiling_flags = 0;
  539.     int ret;
  540.     int aligned_size, size;
  541.     int height = mode_cmd->height;
  542.  
  543.     static struct radeon_bo kos_bo;
  544.     static struct drm_mm_node  vm_node;
  545.  
  546.     /* need to align pitch with crtc limits */
  547.     mode_cmd->pitch = radeon_align_pitch(rdev, mode_cmd->width, mode_cmd->bpp, fb_tiled) * ((mode_cmd->bpp + 1) / 8);
  548.  
  549.     if (rdev->family >= CHIP_R600)
  550.         height = ALIGN(mode_cmd->height, 8);
  551.     size = mode_cmd->pitch * height;
  552.     aligned_size = ALIGN(size, PAGE_SIZE);
  553.  
  554.     ret = drm_gem_object_init(rdev->ddev, &kos_bo.gem_base, aligned_size);
  555.     if (unlikely(ret)) {
  556.         return ret;
  557.     }
  558.  
  559.     kos_bo.rdev = rdev;
  560.     kos_bo.gem_base.driver_private = NULL;
  561.     kos_bo.surface_reg = -1;
  562.     kos_bo.domain = RADEON_GEM_DOMAIN_VRAM;
  563.  
  564.     INIT_LIST_HEAD(&kos_bo.list);
  565.  
  566.     gobj = &kos_bo.gem_base;
  567.     rbo = gem_to_radeon_bo(gobj);
  568.  
  569.     if (fb_tiled)
  570.         tiling_flags = RADEON_TILING_MACRO;
  571.  
  572.     if (tiling_flags) {
  573.         rbo->tiling_flags = tiling_flags | RADEON_TILING_SURFACE;
  574.         rbo->pitch = mode_cmd->pitch;
  575.     }
  576.  
  577.     vm_node.size = 0xC00000 >> 12;
  578.     vm_node.start = 0;
  579.     vm_node.mm = NULL;
  580.  
  581.     rbo->tbo.vm_node = &vm_node;
  582.     rbo->tbo.offset  = rbo->tbo.vm_node->start << PAGE_SHIFT;
  583.     rbo->tbo.offset += (u64)rbo->rdev->mc.vram_start;
  584.     rbo->kptr        = (void*)0xFE000000;
  585.     rbo->pin_count   = 1;
  586.  
  587. //    if (fb_tiled)
  588. //        radeon_bo_check_tiling(rbo, 0, 0);
  589.  
  590.     *gobj_p = gobj;
  591.     return 0;
  592. }
  593.  
  594.  
  595.  
  596.  
  597.