]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blame - src/hwinfo/src/hd/fb.c
Kleiner netter neuer Versuch.
[people/teissler/ipfire-2.x.git] / src / hwinfo / src / hd / fb.c
CommitLineData
a6316ce4
MT
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
23typedef struct {
24 unsigned width;
25 unsigned height;
26 double pix_clock;
27 double h_freq;
28 double v_freq;
29} fb_info_t;
30
31static fb_info_t *fb_get_info(hd_data_t *hd_data);
32
33void 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
106fb_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}