Subversion Repositories Kolibri OS

Rev

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