]> git.ipfire.org Git - ipfire-2.x.git/blob - src/hwinfo/src/hd/fb.c
HWInfo wieder eingefuegt, da mit kudzu zu viele Segmentation Faults liefert.
[ipfire-2.x.git] / src / hwinfo / src / hd / fb.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <sys/ioctl.h>
9 #include <linux/hdreg.h>
10 #include <linux/fb.h>
11
12 #include "hd.h"
13 #include "hd_int.h"
14 #include "fb.h"
15
16 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
17 *
18 * scan framebuffer devices
19 *
20 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
21 */
22
23 typedef struct {
24 unsigned width;
25 unsigned height;
26 double pix_clock;
27 double h_freq;
28 double v_freq;
29 } fb_info_t;
30
31 static fb_info_t *fb_get_info(hd_data_t *hd_data);
32
33 void hd_scan_fb(hd_data_t *hd_data)
34 {
35 fb_info_t *fb;
36 hd_t *hd;
37 hd_res_t *res;
38 unsigned imac_dev, imac_vend;
39 unsigned imac = 0;
40 monitor_info_t *mi = NULL;
41
42 if(!hd_probe_feature(hd_data, pr_fb)) return;
43
44 hd_data->module = mod_fb;
45
46 /* some clean-up */
47 remove_hd_entries(hd_data);
48
49 PROGRESS(1, 0, "read info");
50
51 fb = fb_get_info(hd_data);
52
53 if(fb) {
54 imac_dev = MAKE_ID(TAG_EISA, 0x9d03);
55 imac_vend = name2eisa_id("APP");
56
57 for(hd = hd_data->hd; hd; hd = hd->next) {
58 if(hd->base_class.id == bc_monitor) break;
59 }
60
61 if(hd && hd->device.id == imac_dev && hd->vendor.id == imac_vend) {
62 hd->tag.remove = 1;
63 remove_tagged_hd_entries(hd_data);
64 imac = 1;
65 hd = NULL;
66 }
67
68 /* add monitor entry based on fb data if we have no other info */
69 if(!hd) {
70 hd = add_hd_entry(hd_data, __LINE__, 0);
71 hd->base_class.id = bc_monitor;
72 if(imac) {
73 hd->vendor.id = imac_vend;
74 hd->device.id = imac_dev;
75 }
76 else {
77 hd->vendor.name = new_str("Generic");
78 hd->device.name = new_str("Monitor");
79 }
80
81 res = add_res_entry(&hd->res, new_mem(sizeof *res));
82 res->monitor.type = res_monitor;
83 res->monitor.width = fb->width;
84 res->monitor.height = fb->height;
85 res->monitor.vfreq = fb->v_freq + 0.5;
86
87 if(!hd->detail) {
88 mi = new_mem(sizeof *mi);
89 hd->detail = new_mem(sizeof *hd->detail);
90 hd->detail->type = hd_detail_monitor;
91 hd->detail->monitor.data = mi;
92
93 mi->min_vsync = 50;
94 mi->min_hsync = 31;
95 mi->max_vsync = fb->v_freq * 1.11 + 0.9;
96 mi->max_hsync = fb->h_freq / 1000.0 + 1.9;
97 if(mi->max_vsync <= mi->min_vsync) mi->max_vsync = mi->min_vsync + 10;
98 if(mi->max_hsync <= mi->min_hsync) mi->max_hsync = mi->min_hsync + 5;
99 /* round up */
100 mi->max_vsync = ((mi->max_vsync + 9) / 10) * 10;
101 }
102 }
103 }
104 }
105
106 fb_info_t *fb_get_info(hd_data_t *hd_data)
107 {
108 int fd;
109 struct fb_var_screeninfo fbv_info;
110 static fb_info_t fb_info;
111 fb_info_t *fb = NULL;
112 int h, v;
113
114 fd = open(DEV_FB, O_RDONLY);
115 if(fd < 0) fd = open(DEV_FB0, O_RDONLY);
116 if(fd < 0) return fb;
117
118 if(!ioctl(fd, FBIOGET_VSCREENINFO, &fbv_info)) {
119 h = fbv_info.left_margin + fbv_info.xres + fbv_info.right_margin + fbv_info.hsync_len;
120 v = fbv_info.upper_margin + fbv_info.yres + fbv_info.lower_margin + fbv_info.vsync_len;
121 if(fbv_info.pixclock && h && v) {
122 fb_info.width = fbv_info.xres;
123 fb_info.height = fbv_info.yres;
124 fb_info.pix_clock = 1e12 / fbv_info.pixclock;
125 fb_info.h_freq = fb_info.pix_clock / h;
126 fb_info.v_freq = fb_info.h_freq / v;
127 fb = &fb_info;
128 ADD2LOG("fb: size %d x %d\n", fb_info.width, fb_info.height);
129 ADD2LOG("fb: timing %.2f MHz, %.2f kHz, %.2f Hz\n", fb_info.pix_clock * 1e-6, fb_info.h_freq * 1e-3, fb_info.v_freq);
130 }
131 }
132
133 close(fd);
134
135 return fb;
136 }