Subversion Repositories Kolibri OS

Rev

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