Subversion Repositories Kolibri OS

Rev

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