Subversion Repositories Kolibri OS

Rev

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

  1.  
  2. #include <stdint.h>
  3. #include <drm/drmP.h>
  4. #include <drm.h>
  5. #include <drm_mm.h>
  6. #include "radeon_drm.h"
  7. #include "radeon.h"
  8. #include "radeon_object.h"
  9. #include "display.h"
  10.  
  11.  
  12. static cursor_t*  __stdcall select_cursor_kms(cursor_t *cursor);
  13. static void       __stdcall move_cursor_kms(cursor_t *cursor, int x, int y);
  14.  
  15. int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled);
  16.  
  17. void disable_mouse(void);
  18.  
  19. static void radeon_show_cursor_kms(struct drm_crtc *crtc)
  20. {
  21.     struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  22.     struct radeon_device *rdev = crtc->dev->dev_private;
  23.  
  24.     if (ASIC_IS_AVIVO(rdev)) {
  25.         WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);
  26.         WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN |
  27.                  (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
  28.     } else {
  29.         switch (radeon_crtc->crtc_id) {
  30.         case 0:
  31.             WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL);
  32.             break;
  33.         case 1:
  34.             WREG32(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL);
  35.             break;
  36.         default:
  37.             return;
  38.         }
  39.  
  40.         WREG32_P(RADEON_MM_DATA, (RADEON_CRTC_CUR_EN |
  41.                       (RADEON_CRTC_CUR_MODE_24BPP << RADEON_CRTC_CUR_MODE_SHIFT)),
  42.              ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_CUR_MODE_MASK));
  43.     }
  44. }
  45.  
  46. static void radeon_lock_cursor_kms(struct drm_crtc *crtc, bool lock)
  47. {
  48.     struct radeon_device *rdev = crtc->dev->dev_private;
  49.     struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  50.     uint32_t cur_lock;
  51.  
  52.     if (ASIC_IS_AVIVO(rdev)) {
  53.         cur_lock = RREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset);
  54.         if (lock)
  55.             cur_lock |= AVIVO_D1CURSOR_UPDATE_LOCK;
  56.         else
  57.             cur_lock &= ~AVIVO_D1CURSOR_UPDATE_LOCK;
  58.         WREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset, cur_lock);
  59.     } else {
  60.         cur_lock = RREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset);
  61.         if (lock)
  62.             cur_lock |= RADEON_CUR_LOCK;
  63.         else
  64.             cur_lock &= ~RADEON_CUR_LOCK;
  65.         WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, cur_lock);
  66.     }
  67. }
  68.  
  69. cursor_t* __stdcall select_cursor_kms(cursor_t *cursor)
  70. {
  71.     struct radeon_device *rdev;
  72.     struct radeon_crtc   *radeon_crtc;
  73.     cursor_t *old;
  74.     uint32_t  gpu_addr;
  75.  
  76.     rdev = (struct radeon_device *)rdisplay->ddev->dev_private;
  77.     radeon_crtc = to_radeon_crtc(rdisplay->crtc);
  78.  
  79.     old = rdisplay->cursor;
  80.  
  81.     rdisplay->cursor = cursor;
  82.     gpu_addr = cursor->robj->gpu_addr;
  83.  
  84.     if (ASIC_IS_AVIVO(rdev))
  85.         WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, gpu_addr);
  86.     else {
  87.         radeon_crtc->legacy_cursor_offset = gpu_addr - rdev->mc.vram_location;
  88.         /* offset is from DISP(2)_BASE_ADDRESS */
  89.         WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, radeon_crtc->legacy_cursor_offset);
  90.     }
  91.  
  92.     return old;
  93. };
  94.  
  95. void __stdcall move_cursor_kms(cursor_t *cursor, int x, int y)
  96. {
  97.     struct radeon_device *rdev;
  98.     rdev = (struct radeon_device *)rdisplay->ddev->dev_private;
  99.     struct drm_crtc *crtc = rdisplay->crtc;
  100.     struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  101.  
  102.     int hot_x = cursor->hot_x;
  103.     int hot_y = cursor->hot_y;
  104.  
  105.     radeon_lock_cursor_kms(crtc, true);
  106.     if (ASIC_IS_AVIVO(rdev))
  107.     {
  108.         int w = 32;
  109.         int i = 0;
  110.         struct drm_crtc *crtc_p;
  111.  
  112.         /* avivo cursor are offset into the total surface */
  113. //        x += crtc->x;
  114. //        y += crtc->y;
  115.  
  116. //        DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
  117. #if 0
  118.         /* avivo cursor image can't end on 128 pixel boundry or
  119.          * go past the end of the frame if both crtcs are enabled
  120.          */
  121.         list_for_each_entry(crtc_p, &crtc->dev->mode_config.crtc_list, head) {
  122.             if (crtc_p->enabled)
  123.                 i++;
  124.         }
  125.         if (i > 1) {
  126.             int cursor_end, frame_end;
  127.  
  128.             cursor_end = x + w;
  129.             frame_end = crtc->x + crtc->mode.crtc_hdisplay;
  130.             if (cursor_end >= frame_end) {
  131.                 w = w - (cursor_end - frame_end);
  132.                 if (!(frame_end & 0x7f))
  133.                     w--;
  134.             } else {
  135.                 if (!(cursor_end & 0x7f))
  136.                     w--;
  137.             }
  138.             if (w <= 0)
  139.                 w = 1;
  140.         }
  141. #endif
  142.         WREG32(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset,
  143.                (x << 16) | y);
  144.         WREG32(AVIVO_D1CUR_HOT_SPOT + radeon_crtc->crtc_offset,
  145.                (hot_x << 16) | hot_y);
  146.         WREG32(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset,
  147.                ((w - 1) << 16) | 31);
  148.     } else {
  149.         if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)
  150.             y *= 2;
  151.  
  152.         WREG32(RADEON_CUR_HORZ_VERT_OFF + radeon_crtc->crtc_offset,
  153.                (RADEON_CUR_LOCK | (hot_x << 16) | hot_y ));
  154.         WREG32(RADEON_CUR_HORZ_VERT_POSN + radeon_crtc->crtc_offset,
  155.                (RADEON_CUR_LOCK | (x << 16) | y));
  156.  
  157.         /* offset is from DISP(2)_BASE_ADDRESS */
  158.         WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset,
  159.          (radeon_crtc->legacy_cursor_offset + (hot_y * 256)));
  160.     }
  161.     radeon_lock_cursor_kms(crtc, false);
  162. }
  163.  
  164. static char *manufacturer_name(unsigned char *x)
  165. {
  166.     static char name[4];
  167.  
  168.     name[0] = ((x[0] & 0x7C) >> 2) + '@';
  169.     name[1] = ((x[0] & 0x03) << 3) + ((x[1] & 0xE0) >> 5) + '@';
  170.     name[2] = (x[1] & 0x1F) + '@';
  171.     name[3] = 0;
  172.  
  173.     return name;
  174. }
  175.  
  176. bool set_mode(struct drm_device *dev, struct drm_connector *connector,
  177.               mode_t *reqmode, bool strict)
  178. {
  179.     struct drm_display_mode  *mode = NULL, *tmpmode;
  180.  
  181.     bool ret = false;
  182.  
  183.     ENTER();
  184.  
  185.     dbgprintf("width %d height %d vrefresh %d\n",
  186.                reqmode->width, reqmode->height, reqmode->freq);
  187.  
  188.     list_for_each_entry(tmpmode, &connector->modes, head)
  189.     {
  190.         if( (drm_mode_width(tmpmode)    == reqmode->width)  &&
  191.             (drm_mode_height(tmpmode)   == reqmode->height) &&
  192.             (drm_mode_vrefresh(tmpmode) == reqmode->freq) )
  193.         {
  194.             mode = tmpmode;
  195.             goto do_set;
  196.         }
  197.     };
  198.  
  199.     if( (mode == NULL) && (strict == false) )
  200.     {
  201.         list_for_each_entry(tmpmode, &connector->modes, head)
  202.         {
  203.             if( (drm_mode_width(tmpmode)  == reqmode->width)  &&
  204.                 (drm_mode_height(tmpmode) == reqmode->height) )
  205.             {
  206.                 mode = tmpmode;
  207.                 goto do_set;
  208.             }
  209.         };
  210.     };
  211.  
  212. do_set:
  213.  
  214.     if( mode != NULL )
  215.     {
  216.         struct drm_framebuffer   *fb;
  217.         struct drm_encoder       *encoder;
  218.         struct drm_crtc          *crtc;
  219.  
  220. //        char  con_edid[128];
  221.         char *con_name;
  222.         char *enc_name;
  223.  
  224.         encoder = connector->encoder;
  225.         crtc = encoder->crtc;
  226.  
  227.         fb = list_first_entry(&dev->mode_config.fb_kernel_list,
  228.                               struct drm_framebuffer, filp_head);
  229.  
  230. //        memcpy(con_edid, connector->edid_blob_ptr->data, 128);
  231.  
  232. //        dbgprintf("Manufacturer: %s Model %x Serial Number %u\n",
  233. //        manufacturer_name(con_edid + 0x08),
  234. //        (unsigned short)(con_edid[0x0A] + (con_edid[0x0B] << 8)),
  235. //        (unsigned int)(con_edid[0x0C] + (con_edid[0x0D] << 8)
  236. //            + (con_edid[0x0E] << 16) + (con_edid[0x0F] << 24)));
  237.  
  238.         con_name = drm_get_connector_name(connector);
  239.         enc_name = drm_get_encoder_name(encoder);
  240.  
  241.         dbgprintf("set mode %d %d connector %s encoder %s\n",
  242.                    reqmode->width, reqmode->height, con_name, enc_name);
  243.  
  244.         fb->width  = reqmode->width;
  245.         fb->height = reqmode->height;
  246.         fb->pitch  = radeon_align_pitch(dev->dev_private, reqmode->width, 32, false) * ((32 + 1) / 8);
  247.  
  248.         crtc->fb = fb;
  249.         crtc->enabled = true;
  250.         rdisplay->crtc = crtc;
  251.  
  252.         ret = drm_crtc_helper_set_mode(crtc, mode, 0, 0, fb);
  253.  
  254.         select_cursor_kms(rdisplay->cursor);
  255.         radeon_show_cursor_kms(crtc);
  256.  
  257.         if (ret == true)
  258.         {
  259.             rdisplay->width    = fb->width;
  260.             rdisplay->height   = fb->height;
  261.             rdisplay->pitch    = fb->pitch;
  262.             rdisplay->vrefresh = drm_mode_vrefresh(mode);
  263.  
  264.             sysSetScreen(fb->width, fb->height, fb->pitch);
  265.  
  266.             dbgprintf("new mode %d x %d pitch %d\n",
  267.                        fb->width, fb->height, fb->pitch);
  268.         }
  269.         else
  270.             DRM_ERROR("failed to set mode %d_%d on crtc %p\n",
  271.                        fb->width, fb->height, crtc);
  272.     }
  273.  
  274.     LEAVE();
  275.     return ret;
  276. };
  277.  
  278. static int count_connector_modes(struct drm_connector* connector)
  279. {
  280.     struct drm_display_mode  *mode;
  281.     int count = 0;
  282.  
  283.     list_for_each_entry(mode, &connector->modes, head)
  284.     {
  285.         count++;
  286.     };
  287.     return count;
  288. };
  289.  
  290. static struct drm_connector* get_def_connector(struct drm_device *dev)
  291. {
  292.     struct drm_connector  *connector;
  293.     struct drm_connector  *def_connector = NULL;
  294.  
  295.     list_for_each_entry(connector, &dev->mode_config.connector_list, head)
  296.     {
  297.         struct drm_encoder  *encoder;
  298.         struct drm_crtc     *crtc;
  299.  
  300.         if( connector->status != connector_status_connected)
  301.             continue;
  302.  
  303.         encoder = connector->encoder;
  304.         if( encoder == NULL)
  305.             continue;
  306.  
  307.         crtc = encoder->crtc;
  308.         if(crtc == NULL)
  309.             continue;
  310.  
  311.         def_connector = connector;
  312.         break;
  313.     };
  314.  
  315.     return def_connector;
  316. };
  317.  
  318. bool init_display_kms(struct radeon_device *rdev, mode_t *usermode)
  319. {
  320.     struct drm_device   *dev;
  321.  
  322.     cursor_t            *cursor;
  323.     bool                 retval = false;
  324.     u32_t                ifl;
  325.  
  326.     ENTER();
  327.  
  328.     rdisplay = GetDisplay();
  329.  
  330.     dev = rdisplay->ddev = rdev->ddev;
  331.  
  332.     ifl = safe_cli();
  333.     {
  334.         list_for_each_entry(cursor, &rdisplay->cursors, list)
  335.         {
  336.             init_cursor(cursor);
  337.         };
  338.     };
  339.     safe_sti(ifl);
  340.  
  341.     rdisplay->connector = get_def_connector(dev);
  342.     if( rdisplay->connector == 0 )
  343.     {
  344.         dbgprintf("no active connectors\n");
  345.         return false;
  346.     };
  347.  
  348.     rdisplay->crtc = rdisplay->connector->encoder->crtc;
  349.     rdisplay->supported_modes = count_connector_modes(rdisplay->connector);
  350.  
  351.     dbgprintf("current mode %d x %d x %d\n",
  352.               rdisplay->width, rdisplay->height, rdisplay->vrefresh);
  353.     dbgprintf("user mode mode %d x %d x %d\n",
  354.               usermode->width, usermode->height, usermode->freq);
  355.  
  356.     if( (usermode->width  != 0) &&
  357.         (usermode->height != 0) &&
  358.         ( (usermode->width  != rdisplay->width)  ||
  359.           (usermode->height != rdisplay->height) ||
  360.           (usermode->freq   != rdisplay->vrefresh) ) )
  361.     {
  362.  
  363.         retval = set_mode(dev, rdisplay->connector, usermode, false);
  364.     }
  365.  
  366.     ifl = safe_cli();
  367.     {
  368.         rdisplay->restore_cursor(0,0);
  369.         rdisplay->init_cursor    = init_cursor;
  370.         rdisplay->select_cursor  = select_cursor_kms;
  371.         rdisplay->show_cursor    = NULL;
  372.         rdisplay->move_cursor    = move_cursor_kms;
  373.         rdisplay->restore_cursor = restore_cursor;
  374.         rdisplay->disable_mouse  = disable_mouse;
  375.  
  376.         select_cursor_kms(rdisplay->cursor);
  377.         radeon_show_cursor_kms(rdisplay->crtc);
  378.     };
  379.     safe_sti(ifl);
  380.  
  381.     LEAVE();
  382.  
  383.     return retval;
  384. };
  385.  
  386. int get_modes(mode_t *mode, int *count)
  387. {
  388.     int err = -1;
  389.  
  390.     ENTER();
  391.  
  392.     dbgprintf("mode %x count %d\n", mode, *count);
  393.  
  394.     if( *count == 0 )
  395.     {
  396.         *count = rdisplay->supported_modes;
  397.         err = 0;
  398.     }
  399.     else if( mode != NULL )
  400.     {
  401.         struct drm_display_mode  *drmmode;
  402.         int i = 0;
  403.  
  404.         if( *count > rdisplay->supported_modes)
  405.             *count = rdisplay->supported_modes;
  406.  
  407.         list_for_each_entry(drmmode, &rdisplay->connector->modes, head)
  408.         {
  409.             if( i < *count)
  410.             {
  411.                 mode->width  = drm_mode_width(drmmode);
  412.                 mode->height = drm_mode_height(drmmode);
  413.                 mode->bpp    = 32;
  414.                 mode->freq   = drm_mode_vrefresh(drmmode);
  415.                 i++;
  416.                 mode++;
  417.             }
  418.             else break;
  419.         };
  420.         *count = i;
  421.         err = 0;
  422.     };
  423.     LEAVE();
  424.     return err;
  425. }
  426.  
  427. int set_user_mode(mode_t *mode)
  428. {
  429.     int err = -1;
  430.  
  431.     ENTER();
  432.  
  433.     dbgprintf("width %d height %d vrefresh %d\n",
  434.                mode->width, mode->height, mode->freq);
  435.  
  436.     if( (mode->width  != 0)  &&
  437.         (mode->height != 0)  &&
  438.         (mode->freq   != 0 ) &&
  439.         ( (mode->width   != rdisplay->width)  ||
  440.           (mode->height  != rdisplay->height) ||
  441.           (mode->freq    != rdisplay->vrefresh) ) )
  442.     {
  443.         if( set_mode(rdisplay->ddev, rdisplay->connector, mode, true) )
  444.             err = 0;
  445.     };
  446.  
  447.     LEAVE();
  448.     return err;
  449. };
  450.  
  451.