Subversion Repositories Kolibri OS

Rev

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