Subversion Repositories Kolibri OS

Rev

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

  1. #include "drmP.h"
  2. #include "drm.h"
  3. #include "i915_drm.h"
  4. #include "i915_drv.h"
  5. #include "intel_drv.h"
  6.  
  7.  
  8. #include <linux/kernel.h>
  9. #include <linux/module.h>
  10. #include <linux/mod_devicetable.h>
  11. #include <errno-base.h>
  12. #include <linux/pci.h>
  13.  
  14. #include <syscall.h>
  15.  
  16. typedef struct tag_object  kobj_t;
  17. typedef struct tag_display display_t;
  18.  
  19. struct tag_object
  20. {
  21.     uint32_t   magic;
  22.     void      *destroy;
  23.     kobj_t    *fd;
  24.     kobj_t    *bk;
  25.     uint32_t   pid;
  26. };
  27.  
  28. typedef struct
  29. {
  30.     kobj_t     header;
  31.  
  32.     uint32_t  *data;
  33.     uint32_t   hot_x;
  34.     uint32_t   hot_y;
  35.  
  36.     struct list_head   list;
  37.     struct drm_i915_gem_object  *cobj;
  38. }cursor_t;
  39.  
  40. #define CURSOR_WIDTH 64
  41. #define CURSOR_HEIGHT 64
  42.  
  43.  
  44. struct tag_display
  45. {
  46.     int  x;
  47.     int  y;
  48.     int  width;
  49.     int  height;
  50.     int  bpp;
  51.     int  vrefresh;
  52.     int  pitch;
  53.     int  lfb;
  54.  
  55.     int  supported_modes;
  56.     struct drm_device    *ddev;
  57.     struct drm_connector *connector;
  58.     struct drm_crtc      *crtc;
  59.  
  60.     struct list_head   cursors;
  61.  
  62.     cursor_t   *cursor;
  63.     int       (*init_cursor)(cursor_t*);
  64.     cursor_t* (__stdcall *select_cursor)(cursor_t*);
  65.     void      (*show_cursor)(int show);
  66.     void      (__stdcall *move_cursor)(cursor_t *cursor, int x, int y);
  67.     void      (__stdcall *restore_cursor)(int x, int y);
  68.     void      (*disable_mouse)(void);
  69. };
  70.  
  71.  
  72. static display_t *os_display;
  73.  
  74. int init_cursor(cursor_t *cursor);
  75. static cursor_t*  __stdcall select_cursor_kms(cursor_t *cursor);
  76. static void       __stdcall move_cursor_kms(cursor_t *cursor, int x, int y);
  77.  
  78. void __stdcall restore_cursor(int x, int y)
  79. {};
  80.  
  81. void disable_mouse(void)
  82. {};
  83.  
  84. static int count_connector_modes(struct drm_connector* connector)
  85. {
  86.     struct drm_display_mode  *mode;
  87.     int count = 0;
  88.  
  89.     list_for_each_entry(mode, &connector->modes, head)
  90.     {
  91.         count++;
  92.     };
  93.     return count;
  94. };
  95.  
  96. int init_display_kms(struct drm_device *dev)
  97. {
  98.     struct drm_connector    *connector;
  99.     struct drm_connector_helper_funcs *connector_funcs;
  100.     struct drm_encoder      *encoder;
  101.     struct drm_crtc         *crtc = NULL;
  102.     struct drm_framebuffer  *fb;
  103.  
  104.     cursor_t  *cursor;
  105.     u32_t      ifl;
  106.  
  107.     ENTER();
  108.  
  109.     list_for_each_entry(connector, &dev->mode_config.connector_list, head)
  110.     {
  111.         if( connector->status != connector_status_connected)
  112.             continue;
  113.  
  114.         connector_funcs = connector->helper_private;
  115.         encoder = connector_funcs->best_encoder(connector);
  116.         if( encoder == NULL)
  117.         {
  118.             dbgprintf("CONNECTOR %x ID: %d no active encoders\n",
  119.                       connector, connector->base.id);
  120.             continue;
  121.         }
  122.         connector->encoder = encoder;
  123.  
  124.         dbgprintf("CONNECTOR %x ID:  %d status %d encoder %x\n crtc %x\n",
  125.                connector, connector->base.id,
  126.                connector->status, connector->encoder,
  127.                encoder->crtc);
  128.  
  129.         crtc = encoder->crtc;
  130.         break;
  131.     };
  132.  
  133.     if(connector == NULL)
  134.     {
  135.         dbgprintf("No active connectors!\n");
  136.         return -1;
  137.     };
  138.  
  139.     if(crtc == NULL)
  140.     {
  141.         struct drm_crtc *tmp_crtc;
  142.         int crtc_mask = 1;
  143.  
  144.         list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head)
  145.         {
  146.             if (encoder->possible_crtcs & crtc_mask)
  147.             {
  148.                 crtc = tmp_crtc;
  149.                 encoder->crtc = crtc;
  150.                 break;
  151.             };
  152.             crtc_mask <<= 1;
  153.         };
  154.     };
  155.  
  156.     if(crtc == NULL)
  157.     {
  158.         dbgprintf("No CRTC for encoder %d\n", encoder->base.id);
  159.         return -1;
  160.     };
  161.  
  162.  
  163.     DRM_DEBUG_KMS("[Select CRTC:%d]\n", crtc->base.id);
  164.  
  165.     os_display = GetDisplay();
  166.  
  167.     os_display->ddev = dev;
  168.     os_display->connector = connector;
  169.     os_display->crtc = crtc;
  170.  
  171.     os_display->supported_modes = count_connector_modes(connector);
  172.  
  173.  
  174.     ifl = safe_cli();
  175.     {
  176.         struct intel_crtc *intel_crtc = to_intel_crtc(os_display->crtc);
  177.  
  178.         list_for_each_entry(cursor, &os_display->cursors, list)
  179.         {
  180.             init_cursor(cursor);
  181.         };
  182.  
  183.         os_display->restore_cursor(0,0);
  184.         os_display->init_cursor    = init_cursor;
  185.         os_display->select_cursor  = select_cursor_kms;
  186.         os_display->show_cursor    = NULL;
  187.         os_display->move_cursor    = move_cursor_kms;
  188.         os_display->restore_cursor = restore_cursor;
  189.         os_display->disable_mouse  = disable_mouse;
  190.  
  191.         intel_crtc->cursor_x = os_display->width/2;
  192.         intel_crtc->cursor_y = os_display->height/2;
  193.  
  194.         select_cursor_kms(os_display->cursor);
  195.     };
  196.     safe_sti(ifl);
  197.  
  198.  
  199.     LEAVE();
  200.  
  201.     return 0;
  202. };
  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.     drm_i915_private_t *dev_priv = dev->dev_private;
  210.     struct drm_fb_helper *fb_helper = &dev_priv->fbdev->helper;
  211.  
  212.     bool ret = false;
  213.  
  214.     ENTER();
  215.  
  216.     dbgprintf("width %d height %d vrefresh %d\n",
  217.                reqmode->width, reqmode->height, reqmode->freq);
  218.  
  219.     list_for_each_entry(tmpmode, &connector->modes, head)
  220.     {
  221.         if( (drm_mode_width(tmpmode)    == reqmode->width)  &&
  222.             (drm_mode_height(tmpmode)   == reqmode->height) &&
  223.             (drm_mode_vrefresh(tmpmode) == reqmode->freq) )
  224.         {
  225.             mode = tmpmode;
  226.             goto do_set;
  227.         }
  228.     };
  229.  
  230.     if( (mode == NULL) && (strict == false) )
  231.     {
  232.         list_for_each_entry(tmpmode, &connector->modes, head)
  233.         {
  234.             if( (drm_mode_width(tmpmode)  == reqmode->width)  &&
  235.                 (drm_mode_height(tmpmode) == reqmode->height) )
  236.             {
  237.                 mode = tmpmode;
  238.                 goto do_set;
  239.             }
  240.         };
  241.     };
  242.  
  243. do_set:
  244.  
  245.     if( mode != NULL )
  246.     {
  247.         struct drm_framebuffer   *fb;
  248.         struct drm_encoder       *encoder;
  249.         struct drm_crtc          *crtc;
  250.  
  251.         char *con_name;
  252.         char *enc_name;
  253.  
  254.         encoder = connector->encoder;
  255.         crtc = encoder->crtc;
  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 = fb_helper->fb;
  264.  
  265.         fb->width  = reqmode->width;
  266.         fb->height = reqmode->height;
  267.         fb->pitch  = ALIGN(reqmode->width * 4, 64);
  268.         fb->bits_per_pixel = 32;
  269.         fb->depth == 24;
  270.  
  271.         crtc->fb = fb;
  272.         crtc->enabled = true;
  273.         os_display->crtc = crtc;
  274.  
  275.         ret = drm_crtc_helper_set_mode(crtc, mode, 0, 0, fb);
  276.  
  277. //        select_cursor_kms(rdisplay->cursor);
  278. //        radeon_show_cursor_kms(crtc);
  279.  
  280.         if (ret == true)
  281.         {
  282.             os_display->width    = fb->width;
  283.             os_display->height   = fb->height;
  284.             os_display->pitch    = fb->pitch;
  285.             os_display->vrefresh = drm_mode_vrefresh(mode);
  286.  
  287.             sysSetScreen(fb->width, fb->height, fb->pitch);
  288.  
  289.             dbgprintf("new mode %d x %d pitch %d\n",
  290.                        fb->width, fb->height, fb->pitch);
  291.         }
  292.         else
  293.             DRM_ERROR("failed to set mode %d_%d on crtc %p\n",
  294.                        fb->width, fb->height, crtc);
  295.     }
  296.  
  297.     LEAVE();
  298.     return ret;
  299. };
  300.  
  301.  
  302.  
  303. int get_videomodes(videomode_t *mode, int *count)
  304. {
  305.     int err = -1;
  306.  
  307.     ENTER();
  308.  
  309.     dbgprintf("mode %x count %d\n", mode, *count);
  310.  
  311.     if( *count == 0 )
  312.     {
  313.         *count = os_display->supported_modes;
  314.         err = 0;
  315.     }
  316.     else if( mode != NULL )
  317.     {
  318.         struct drm_display_mode  *drmmode;
  319.         int i = 0;
  320.  
  321.         if( *count > os_display->supported_modes)
  322.             *count = os_display->supported_modes;
  323.  
  324.         list_for_each_entry(drmmode, &os_display->connector->modes, head)
  325.         {
  326.             if( i < *count)
  327.             {
  328.                 mode->width  = drm_mode_width(drmmode);
  329.                 mode->height = drm_mode_height(drmmode);
  330.                 mode->bpp    = 32;
  331.                 mode->freq   = drm_mode_vrefresh(drmmode);
  332.                 i++;
  333.                 mode++;
  334.             }
  335.             else break;
  336.         };
  337.         *count = i;
  338.         err = 0;
  339.     };
  340.     LEAVE();
  341.     return err;
  342. };
  343.  
  344. int set_user_mode(videomode_t *mode)
  345. {
  346.     int err = -1;
  347.  
  348.     ENTER();
  349.  
  350.     dbgprintf("width %d height %d vrefresh %d\n",
  351.                mode->width, mode->height, mode->freq);
  352.  
  353.     if( (mode->width  != 0)  &&
  354.         (mode->height != 0)  &&
  355.         (mode->freq   != 0 ) &&
  356.         ( (mode->width   != os_display->width)  ||
  357.           (mode->height  != os_display->height) ||
  358.           (mode->freq    != os_display->vrefresh) ) )
  359.     {
  360.         if( set_mode(os_display->ddev, os_display->connector, mode, true) )
  361.             err = 0;
  362.     };
  363.  
  364.     LEAVE();
  365.     return err;
  366. };
  367.  
  368. void __attribute__((regparm(1))) destroy_cursor(cursor_t *cursor)
  369. {
  370.     list_del(&cursor->list);
  371. //    radeon_bo_unpin(cursor->robj);
  372. //    KernelFree(cursor->data);
  373.     __DestroyObject(cursor);
  374. };
  375.  
  376. int init_cursor(cursor_t *cursor)
  377. {
  378.     struct drm_i915_private *dev_priv = os_display->ddev->dev_private;
  379.     struct drm_i915_gem_object *obj;
  380.     uint32_t *bits;
  381.     uint32_t *src;
  382.  
  383.     int       i,j;
  384.     int       ret;
  385.  
  386.     ENTER();
  387.  
  388.     if (dev_priv->info->cursor_needs_physical)
  389.     {
  390.         bits = (uint32_t*)KernelAlloc(CURSOR_WIDTH*CURSOR_HEIGHT*4);
  391.         if (unlikely(bits == NULL))
  392.             return ENOMEM;
  393.         cursor->cobj = (struct drm_i915_gem_object *)GetPgAddr(bits);
  394.     }
  395.     else
  396.     {
  397.         obj = i915_gem_alloc_object(os_display->ddev, CURSOR_WIDTH*CURSOR_HEIGHT*4);
  398.         if (unlikely(obj == NULL))
  399.             return -ENOMEM;
  400.  
  401.         ret = i915_gem_object_pin(obj, CURSOR_WIDTH*CURSOR_HEIGHT*4, true);
  402.         if (ret) {
  403. //           drm_gem_object_unreference(&obj->base);
  404.             return ret;
  405.         }
  406.  
  407. /* You don't need to worry about fragmentation issues.
  408.  * GTT space is continuous. I guarantee it.                           */
  409.  
  410.         bits = (u32*)MapIoMem(get_bus_addr() + obj->gtt_offset,
  411.                     CURSOR_WIDTH*CURSOR_HEIGHT*4, PG_SW);
  412.  
  413.         if (unlikely(bits == NULL))
  414.         {
  415. //          i915_gem_object_unpin(obj);
  416. //           drm_gem_object_unreference(&obj->base);
  417.             return -ENOMEM;
  418.         };
  419.         cursor->cobj = obj;
  420.     };
  421.  
  422.     src = cursor->data;
  423.  
  424.     for(i = 0; i < 32; i++)
  425.     {
  426.         for(j = 0; j < 32; j++)
  427.             *bits++ = *src++;
  428.         for(j = 32; j < CURSOR_WIDTH; j++)
  429.             *bits++ = 0;
  430.     }
  431.     for(i = 0; i < CURSOR_WIDTH*(CURSOR_HEIGHT-32); i++)
  432.         *bits++ = 0;
  433.  
  434. // release old cursor
  435.  
  436. //    KernelFree(cursor->data);
  437.  
  438.     cursor->data = bits;
  439.  
  440.     cursor->header.destroy = destroy_cursor;
  441.     LEAVE();
  442.  
  443.     return 0;
  444. }
  445.  
  446.  
  447. static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
  448. {
  449.     struct drm_device *dev = crtc->dev;
  450.     struct drm_i915_private *dev_priv = dev->dev_private;
  451.     struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
  452.     int pipe = intel_crtc->pipe;
  453.     bool visible = base != 0;
  454.  
  455.     if (intel_crtc->cursor_visible != visible) {
  456.         uint32_t cntl = I915_READ(CURCNTR(pipe));
  457.         if (base) {
  458.             cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
  459.             cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
  460.             cntl |= pipe << 28; /* Connect to correct pipe */
  461.         } else {
  462.             cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
  463.             cntl |= CURSOR_MODE_DISABLE;
  464.         }
  465.         I915_WRITE(CURCNTR(pipe), cntl);
  466.  
  467.         intel_crtc->cursor_visible = visible;
  468.     }
  469.     /* and commit changes on next vblank */
  470.     I915_WRITE(CURBASE(pipe), base);
  471. }
  472.  
  473. void __stdcall move_cursor_kms(cursor_t *cursor, int x, int y)
  474. {
  475.     struct drm_i915_private *dev_priv = os_display->ddev->dev_private;
  476.     struct intel_crtc *intel_crtc = to_intel_crtc(os_display->crtc);
  477.     u32 base, pos;
  478.     bool visible;
  479.  
  480.     int pipe = intel_crtc->pipe;
  481.  
  482.     intel_crtc->cursor_x = x;
  483.     intel_crtc->cursor_y = y;
  484.  
  485.     x = x - cursor->hot_x;
  486.     y = y - cursor->hot_y;
  487.  
  488.  
  489.     pos = 0;
  490.  
  491.     base = intel_crtc->cursor_addr;
  492.     if (x >= os_display->width)
  493.         base = 0;
  494.  
  495.     if (y >= os_display->height)
  496.         base = 0;
  497.  
  498.     if (x < 0)
  499.     {
  500.         if (x + intel_crtc->cursor_width < 0)
  501.             base = 0;
  502.  
  503.         pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
  504.         x = -x;
  505.     }
  506.     pos |= x << CURSOR_X_SHIFT;
  507.  
  508.     if (y < 0)
  509.     {
  510.         if (y + intel_crtc->cursor_height < 0)
  511.             base = 0;
  512.  
  513.         pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
  514.         y = -y;
  515.     }
  516.     pos |= y << CURSOR_Y_SHIFT;
  517.  
  518.     visible = base != 0;
  519.     if (!visible && !intel_crtc->cursor_visible)
  520.         return;
  521.  
  522.     I915_WRITE(CURPOS(pipe), pos);
  523. //    if (IS_845G(dev) || IS_I865G(dev))
  524. //        i845_update_cursor(crtc, base);
  525. //    else
  526.         i9xx_update_cursor(os_display->crtc, base);
  527.  
  528. };
  529.  
  530.  
  531. cursor_t* __stdcall select_cursor_kms(cursor_t *cursor)
  532. {
  533.     struct drm_i915_private *dev_priv = os_display->ddev->dev_private;
  534.     struct intel_crtc *intel_crtc = to_intel_crtc(os_display->crtc);
  535.     cursor_t *old;
  536.  
  537.     old = os_display->cursor;
  538.     os_display->cursor = cursor;
  539.  
  540.     if (!dev_priv->info->cursor_needs_physical)
  541.        intel_crtc->cursor_addr = cursor->cobj->gtt_offset;
  542.     else
  543.         intel_crtc->cursor_addr = cursor->cobj;
  544.  
  545.     intel_crtc->cursor_width = 32;
  546.     intel_crtc->cursor_height = 32;
  547.  
  548.     move_cursor_kms(cursor, intel_crtc->cursor_x, intel_crtc->cursor_y);
  549.     return old;
  550. };
  551.  
  552. #if 0
  553. static void intel_crtc_update_cursor(struct drm_crtc *crtc,
  554.                      bool on)
  555. {
  556.     struct drm_device *dev = crtc->dev;
  557.     struct drm_i915_private *dev_priv = dev->dev_private;
  558.     struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
  559.     int pipe = intel_crtc->pipe;
  560.     int x = intel_crtc->cursor_x;
  561.     int y = intel_crtc->cursor_y;
  562.     u32 base, pos;
  563.     bool visible;
  564.  
  565.     pos = 0;
  566.  
  567.     if (on && crtc->enabled && crtc->fb) {
  568.         base = intel_crtc->cursor_addr;
  569.         if (x > (int) crtc->fb->width)
  570.             base = 0;
  571.  
  572.         if (y > (int) crtc->fb->height)
  573.             base = 0;
  574.     } else
  575.         base = 0;
  576.  
  577.     if (x < 0) {
  578.         if (x + intel_crtc->cursor_width < 0)
  579.             base = 0;
  580.  
  581.         pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
  582.         x = -x;
  583.     }
  584.     pos |= x << CURSOR_X_SHIFT;
  585.  
  586.     if (y < 0) {
  587.         if (y + intel_crtc->cursor_height < 0)
  588.             base = 0;
  589.  
  590.         pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
  591.         y = -y;
  592.     }
  593.     pos |= y << CURSOR_Y_SHIFT;
  594.  
  595.     visible = base != 0;
  596.     if (!visible && !intel_crtc->cursor_visible)
  597.         return;
  598.  
  599.     I915_WRITE(CURPOS(pipe), pos);
  600.     if (IS_845G(dev) || IS_I865G(dev))
  601.         i845_update_cursor(crtc, base);
  602.     else
  603.         i9xx_update_cursor(crtc, base);
  604.  
  605.     if (visible)
  606.         intel_mark_busy(dev, to_intel_framebuffer(crtc->fb)->obj);
  607. }
  608.  
  609. #endif
  610.  
  611.