/ src / core / fb.cc
fb.cc
  1  /*
  2   * fb.cc
  3   *
  4   *
  5   */
  6  
  7  #include "version.h"
  8  #include "fb.h"
  9  #include "sysfs.h"
 10  #include "osutils.h"
 11  #include <sys/types.h>
 12  #include <sys/stat.h>
 13  #include <sys/ioctl.h>
 14  #include <fcntl.h>
 15  #include <unistd.h>
 16  #include <stdio.h>
 17  #include <string.h>
 18  #include <errno.h>
 19  #include <cstring>
 20  
 21  __ID("@(#) $Id$");
 22  
 23  #define FB_MODES_SHIFT  5                         /* 32 modes per framebuffer */
 24  #define FB_NUM_MINORS 256                         /* 256 Minors               */
 25  #define MAX_FB    (FB_NUM_MINORS / (1 << FB_MODES_SHIFT))
 26  
 27  /* ioctls
 28     0x46 is 'F'                                                          */
 29  #define FBIOGET_VSCREENINFO     0x4600
 30  #define FBIOPUT_VSCREENINFO     0x4601
 31  #define FBIOGET_FSCREENINFO     0x4602
 32  #define FBIOGETCMAP             0x4604
 33  #define FBIOPUTCMAP             0x4605
 34  #define FBIOPAN_DISPLAY         0x4606
 35  /* 0x4607-0x460B are defined below */
 36  /* #define FBIOGET_MONITORSPEC  0x460C */
 37  /* #define FBIOPUT_MONITORSPEC  0x460D */
 38  /* #define FBIOSWITCH_MONIBIT   0x460E */
 39  #define FBIOGET_CON2FBMAP       0x460F
 40  #define FBIOPUT_CON2FBMAP       0x4610
 41  
 42  #define FB_TYPE_PACKED_PIXELS           0         /* Packed Pixels        */
 43  #define FB_TYPE_PLANES                  1         /* Non interleaved planes */
 44  #define FB_TYPE_INTERLEAVED_PLANES      2         /* Interleaved planes   */
 45  #define FB_TYPE_TEXT                    3         /* Text/attributes      */
 46  #define FB_TYPE_VGA_PLANES              4         /* EGA/VGA planes       */
 47  
 48  #define FB_AUX_TEXT_MDA         0                 /* Monochrome text */
 49  #define FB_AUX_TEXT_CGA         1                 /* CGA/EGA/VGA Color text */
 50  #define FB_AUX_TEXT_S3_MMIO     2                 /* S3 MMIO fasttext */
 51  #define FB_AUX_TEXT_MGA_STEP16  3                 /* MGA Millenium I: text, attr, 14 reserved bytes */
 52  #define FB_AUX_TEXT_MGA_STEP8   4                 /* other MGAs:      text, attr,  6 reserved bytes */
 53  
 54  #define FB_AUX_VGA_PLANES_VGA4          0         /* 16 color planes (EGA/VGA) */
 55  #define FB_AUX_VGA_PLANES_CFB4          1         /* CFB4 in planes (VGA) */
 56  #define FB_AUX_VGA_PLANES_CFB8          2         /* CFB8 in planes (VGA) */
 57  
 58  #define FB_VISUAL_MONO01                0         /* Monochr. 1=Black 0=White */
 59  #define FB_VISUAL_MONO10                1         /* Monochr. 1=White 0=Black */
 60  #define FB_VISUAL_TRUECOLOR             2         /* True color   */
 61  #define FB_VISUAL_PSEUDOCOLOR           3         /* Pseudo color (like atari) */
 62  #define FB_VISUAL_DIRECTCOLOR           4         /* Direct color */
 63  #define FB_VISUAL_STATIC_PSEUDOCOLOR    5         /* Pseudo color readonly */
 64  
 65  #define FB_ACCEL_NONE           0                 /* no hardware accelerator      */
 66  #define FB_ACCEL_ATARIBLITT     1                 /* Atari Blitter                */
 67  #define FB_ACCEL_AMIGABLITT     2                 /* Amiga Blitter                */
 68  #define FB_ACCEL_S3_TRIO64      3                 /* Cybervision64 (S3 Trio64)    */
 69  #define FB_ACCEL_NCR_77C32BLT   4                 /* RetinaZ3 (NCR 77C32BLT)      */
 70  #define FB_ACCEL_S3_VIRGE       5                 /* Cybervision64/3D (S3 ViRGE)  */
 71  #define FB_ACCEL_ATI_MACH64GX   6                 /* ATI Mach 64GX family         */
 72  #define FB_ACCEL_DEC_TGA        7                 /* DEC 21030 TGA                */
 73  #define FB_ACCEL_ATI_MACH64CT   8                 /* ATI Mach 64CT family         */
 74  #define FB_ACCEL_ATI_MACH64VT   9                 /* ATI Mach 64CT family VT class */
 75  #define FB_ACCEL_ATI_MACH64GT   10                /* ATI Mach 64CT family GT class */
 76  #define FB_ACCEL_SUN_CREATOR    11                /* Sun Creator/Creator3D        */
 77  #define FB_ACCEL_SUN_CGSIX      12                /* Sun cg6                      */
 78  #define FB_ACCEL_SUN_LEO        13                /* Sun leo/zx                   */
 79  #define FB_ACCEL_IMS_TWINTURBO  14                /* IMS Twin Turbo               */
 80  #define FB_ACCEL_3DLABS_PERMEDIA2 15              /* 3Dlabs Permedia 2            */
 81  #define FB_ACCEL_MATROX_MGA2064W 16               /* Matrox MGA2064W (Millenium)  */
 82  #define FB_ACCEL_MATROX_MGA1064SG 17              /* Matrox MGA1064SG (Mystique)  */
 83  #define FB_ACCEL_MATROX_MGA2164W 18               /* Matrox MGA2164W (Millenium II) */
 84  #define FB_ACCEL_MATROX_MGA2164W_AGP 19           /* Matrox MGA2164W (Millenium II) */
 85  #define FB_ACCEL_MATROX_MGAG100 20                /* Matrox G100 (Productiva G100) */
 86  #define FB_ACCEL_MATROX_MGAG200 21                /* Matrox G200 (Myst, Mill, ...) */
 87  #define FB_ACCEL_SUN_CG14       22                /* Sun cgfourteen                */
 88  #define FB_ACCEL_SUN_BWTWO      23                /* Sun bwtwo                     */
 89  #define FB_ACCEL_SUN_CGTHREE    24                /* Sun cgthree                   */
 90  #define FB_ACCEL_SUN_TCX        25                /* Sun tcx                       */
 91  #define FB_ACCEL_MATROX_MGAG400 26                /* Matrox G400                   */
 92  
 93  #define FB_VMODE_NONINTERLACED  0                 /* non interlaced */
 94  #define FB_VMODE_INTERLACED     1                 /* interlaced   */
 95  #define FB_VMODE_DOUBLE         2                 /* double scan */
 96  #define FB_VMODE_MASK           255
 97  
 98  struct fb_fix_screeninfo
 99  {
100    char id[16];                                    /* identification string eg "TT Builtin" */
101    char *smem_start;                               /* Start of frame buffer mem */
102  /*
103   * (physical address)
104   */
105    u_int32_t smem_len;                             /* Length of frame buffer mem */
106    u_int32_t type;                                 /* see FB_TYPE_*                */
107    u_int32_t type_aux;                             /* Interleave for interleaved Planes */
108    u_int32_t visual;                               /* see FB_VISUAL_*              */
109    u_int16_t xpanstep;                             /* zero if no hardware panning  */
110    u_int16_t ypanstep;                             /* zero if no hardware panning  */
111    u_int16_t ywrapstep;                            /* zero if no hardware ywrap    */
112    u_int32_t line_length;                          /* length of a line in bytes    */
113    char *mmio_start;                               /* Start of Memory Mapped I/O   */
114  /*
115   * (physical address)
116   */
117    u_int32_t mmio_len;                             /* Length of Memory Mapped I/O  */
118    u_int32_t accel;                                /* Type of acceleration available */
119    u_int16_t reserved[3];                          /* Reserved for future compatibility */
120  };
121  
122  struct fb_bitfield
123  {
124    u_int32_t offset;                               /* beginning of bitfield        */
125    u_int32_t length;                               /* length of bitfield           */
126    u_int32_t msb_right;                            /* != 0 : Most significant bit is */
127  /*
128   * right
129   */
130  };
131  
132  struct fb_var_screeninfo
133  {
134    u_int32_t xres;                                 /* visible resolution           */
135    u_int32_t yres;
136    u_int32_t xres_virtual;                         /* virtual resolution           */
137    u_int32_t yres_virtual;
138    u_int32_t xoffset;                              /* offset from virtual to visible */
139    u_int32_t yoffset;                              /* resolution                   */
140  
141    u_int32_t bits_per_pixel;                       /* guess what                   */
142    u_int32_t grayscale;                            /* != 0 Graylevels instead of colors */
143  
144    struct fb_bitfield red;                         /* bitfield in fb mem if true color, */
145    struct fb_bitfield green;                       /* else only length is significant */
146    struct fb_bitfield blue;
147    struct fb_bitfield transp;                      /* transparency                 */
148  
149    u_int32_t nonstd;                               /* != 0 Non standard pixel format */
150  
151    u_int32_t activate;                             /* see FB_ACTIVATE_*            */
152  
153    u_int32_t height;                               /* height of picture in mm    */
154    u_int32_t width;                                /* width of picture in mm     */
155  
156    u_int32_t accel_flags;                          /* acceleration flags (hints)   */
157  
158  /*
159   * Timing: All values in pixclocks, except pixclock (of course)
160   */
161    u_int32_t pixclock;                             /* pixel clock in ps (pico seconds) */
162    u_int32_t left_margin;                          /* time from sync to picture    */
163    u_int32_t right_margin;                         /* time from picture to sync    */
164    u_int32_t upper_margin;                         /* time from sync to picture    */
165    u_int32_t lower_margin;
166    u_int32_t hsync_len;                            /* length of horizontal sync    */
167    u_int32_t vsync_len;                            /* length of vertical sync      */
168    u_int32_t sync;                                 /* see FB_SYNC_*                */
169    u_int32_t vmode;                                /* see FB_VMODE_*               */
170    u_int32_t reserved[6];                          /* Reserved for future compatibility */
171  };
172  
173  static int lookup_dev(const char *name)
174  {
175    FILE *f;
176    int n;
177    char s[32], t[32];
178  
179    f = fopen("/proc/devices", "r");
180    if (f == NULL)
181      return -errno;
182    while (fgets(s, 32, f) != NULL)
183    {
184      if (sscanf(s, "%d %s", &n, t) == 2)
185        if (strcmp(name, t) == 0)
186          break;
187    }
188    fclose(f);
189    if (strcmp(name, t) == 0)
190      return n;
191    else
192      return -ENODEV;
193  }
194  
195  
196  static int open_dev(dev_t dev)
197  {
198    static const char *paths[] =
199    {
200      "/var/run", "/dev", "/tmp", NULL
201    };
202    char const **p;
203    char fn[64];
204    int fd;
205  
206    for (p = paths; *p; p++)
207    {
208      sprintf(fn, "%s/fb-%d", *p, getpid());
209      if (mknod(fn, (S_IFCHR | S_IREAD), dev) == 0)
210      {
211        fd = open(fn, O_RDONLY);
212        unlink(fn);
213        if (fd >= 0)
214          return fd;
215      }
216    }
217    return -1;
218  }
219  
220  
221  bool scan_fb(hwNode & n)
222  {
223    int fd[MAX_FB];
224    unsigned int fbdevs = 0;
225    unsigned int i;
226    int major = lookup_dev("fb");
227  
228    if (major < 0)                                  // framebuffer support not loaded, there isn't
229      return false;                                 // much we can do
230  
231    memset(fd, 0, sizeof(fd));
232    for (i = 0; i < MAX_FB; i++)
233    {
234      fd[i] = open_dev((dev_t) ((major << 8) + i));
235  
236      if (fd[i] >= 0)
237      {
238        fbdevs++;
239        hwNode *fbdev = NULL;
240        struct fb_fix_screeninfo fbi;
241  
242        if (ioctl(fd[i], FBIOGET_FSCREENINFO, &fbi) == 0)
243        {
244          fbdev = n.findChildByBusInfo(sysfs::entry::byClass("graphics", "fb"+tostring(i)+"/device").businfo());
245  
246          if(!fbdev)
247          {
248          fbdev =
249            n.
250            findChildByResource(hw::resource::
251            iomem((unsigned long) fbi.smem_start,
252            fbi.smem_len));
253  	}
254  
255          if (fbdev)
256          {
257            char devname[20];
258            struct fb_var_screeninfo fbconfig;
259  
260            snprintf(devname, sizeof(devname), "/dev/fb%d", i);
261            fbdev->setLogicalName(devname);
262            fbdev->claim();
263            if (fbdev->getDescription() == "")
264              fbdev->setDescription(hw::strip(fbi.id));
265            fbdev->addCapability("fb");
266  
267            switch (fbi.visual)
268            {
269              case FB_VISUAL_MONO01:
270                fbdev->setConfig("visual", "mono01");
271                break;
272              case FB_VISUAL_MONO10:
273                fbdev->setConfig("visual", "mono10");
274                break;
275              case FB_VISUAL_TRUECOLOR:
276                fbdev->setConfig("visual", "truecolor");
277                break;
278              case FB_VISUAL_PSEUDOCOLOR:
279                fbdev->setConfig("visual", "pseudocolor");
280                break;
281              case FB_VISUAL_DIRECTCOLOR:
282                fbdev->setConfig("visual", "directcolor");
283                break;
284              case FB_VISUAL_STATIC_PSEUDOCOLOR:
285                fbdev->setConfig("visual", "static_pseudocolor");
286                break;
287            }
288  
289            if (fbi.accel != FB_ACCEL_NONE)
290              fbdev->addCapability("accelerated");
291  
292            if (ioctl(fd[i], FBIOGET_VSCREENINFO, &fbconfig) == 0)
293            {
294              char vidmode[20];
295              unsigned int htotal = 0;
296              unsigned int vtotal = 0;
297  
298              snprintf(vidmode, sizeof(vidmode), "%dx%d", fbconfig.xres,
299                fbconfig.yres);
300              fbdev->setConfig("mode", vidmode);
301              snprintf(vidmode, sizeof(vidmode), "%d", fbconfig.xres);
302              fbdev->setConfig("xres", vidmode);
303              snprintf(vidmode, sizeof(vidmode), "%d", fbconfig.yres);
304              fbdev->setConfig("yres", vidmode);
305              snprintf(vidmode, sizeof(vidmode), "%d", fbconfig.bits_per_pixel);
306              fbdev->setConfig("depth", vidmode);
307  
308              vtotal =
309                fbconfig.upper_margin + fbconfig.yres + fbconfig.lower_margin +
310                fbconfig.vsync_len;
311              htotal =
312                fbconfig.left_margin + fbconfig.xres + fbconfig.right_margin +
313                fbconfig.hsync_len;
314              switch (fbconfig.vmode & FB_VMODE_MASK)
315              {
316                case FB_VMODE_INTERLACED:
317                  vtotal >>= 1;
318                  break;
319                case FB_VMODE_DOUBLE:
320                  vtotal <<= 1;
321                  break;
322              }
323  
324              if (fbconfig.pixclock)
325              {
326                char freq[20];
327  
328                double drate = 1E12 / fbconfig.pixclock;
329                double hrate = drate / htotal;
330                double vrate = hrate / vtotal;
331  
332                snprintf(freq, sizeof(freq), "%5.2fHz", vrate);
333                fbdev->setConfig("frequency", freq);
334              }
335  
336            }
337          }
338        }
339      }
340      else
341        break;
342    }
343  
344    for (unsigned int j = 0; j < fbdevs; j++)
345    {
346      if (fd[j] >= 0)
347        close(fd[j]);
348    }
349  
350    return false;
351  }