xref: /haiku/src/add-ons/accelerants/nvidia/GetDeviceInfo.c (revision e0264ea1c4d119695912cf03149a255655aa69ef)
1 /*
2 	Author:
3 	Rudolf Cornelissen 7/2004-08/2009
4 */
5 
6 #define MODULE_BIT 0x04000000
7 
8 #include "acc_std.h"
9 
10 /* Get some info about the device */
GET_ACCELERANT_DEVICE_INFO(accelerant_device_info * adi)11 status_t GET_ACCELERANT_DEVICE_INFO(accelerant_device_info * adi)
12 {
13 	LOG(4,("GET_ACCELERANT_DEVICE_INFO: returning info\n"));
14 
15 	/* no info on version is provided, so presumably this is for my info */
16 	adi->version = 1;
17 
18 	strcpy(adi->name, si->adi.name);
19 	strcpy(adi->chipset, si->adi.chipset);
20 	strcpy(adi->serial_no, "unknown");
21 	adi->memory = si->ps.memory_size;
22 	adi->dac_speed = si->ps.max_dac1_clock;
23 
24 	return B_OK;
25 }
26 
27 #ifdef __HAIKU__
28 
29 /* Get the info fetched from the attached screen */
GET_EDID_INFO(void * info,size_t size,uint32 * _version)30 status_t GET_EDID_INFO(void* info, size_t size, uint32* _version)
31 {
32 	if (!si->ps.crtc1_screen.have_full_edid && !si->ps.crtc2_screen.have_full_edid) {
33 		LOG(4,("GET_EDID_INFO: EDID info not available\n"));
34 		return B_ERROR;
35 	}
36 	if (size < sizeof(struct edid1_info)) {
37 		LOG(4,("GET_EDID_INFO: not enough memory available\n"));
38 		return B_BUFFER_OVERFLOW;
39 	}
40 
41 	LOG(4,("GET_EDID_INFO: returning info\n"));
42 
43 	/* if we have two screens, make the best of it (go for the best compatible info) */
44 	if (si->ps.crtc1_screen.have_full_edid && si->ps.crtc2_screen.have_full_edid) {
45 		/* return info on screen with lowest aspect (4:3 takes precedence over ws)
46 		 * NOTE:
47 		 * allow 0.10 difference so 4:3 and 5:4 aspect screens are regarded as being the same. */
48 		if (si->ps.crtc1_screen.aspect < (si->ps.crtc2_screen.aspect - 0.10)) {
49 			memcpy(info, &si->ps.crtc1_screen.full_edid, sizeof(struct edid1_info));
50 		} else {
51 			if (si->ps.crtc1_screen.aspect > (si->ps.crtc2_screen.aspect + 0.10)) {
52 				memcpy(info, &si->ps.crtc2_screen.full_edid, sizeof(struct edid1_info));
53 			} else {
54 				/* both screens have the same aspect, return info on the one with
55 				 * the lowest native resolution */
56 				if (si->ps.crtc1_screen.timing.h_display < si->ps.crtc2_screen.timing.h_display)
57 					memcpy(info, &si->ps.crtc1_screen.full_edid, sizeof(struct edid1_info));
58 				if (si->ps.crtc1_screen.timing.h_display > si->ps.crtc2_screen.timing.h_display)
59 					memcpy(info, &si->ps.crtc2_screen.full_edid, sizeof(struct edid1_info));
60 
61 				/* if both screens have the same resolution and aspect, return info on the
62 				 * one used as main screen */
63 				if (si->ps.crtc1_screen.timing.h_display == si->ps.crtc2_screen.timing.h_display) {
64 					if (si->ps.crtc2_prim)
65 						memcpy(info, &si->ps.crtc2_screen.full_edid, sizeof(struct edid1_info));
66 					else
67 						memcpy(info, &si->ps.crtc1_screen.full_edid, sizeof(struct edid1_info));
68 				}
69 			}
70 		}
71 	} else {
72 		/* there's just one screen of which we have EDID information, return it */
73 		if (si->ps.crtc1_screen.have_full_edid)
74 			memcpy(info, &si->ps.crtc1_screen.full_edid, sizeof(struct edid1_info));
75 		else
76 			memcpy(info, &si->ps.crtc2_screen.full_edid, sizeof(struct edid1_info));
77 	}
78 
79 	*_version = EDID_VERSION_1;
80 	return B_OK;
81 }
82 
83 /* Return the optimum (native) mode for the attached screen */
GET_PREFERRED_DISPLAY_MODE(display_mode * preferredMode)84 status_t GET_PREFERRED_DISPLAY_MODE(display_mode* preferredMode)
85 {
86 	if (si->ps.crtc1_screen.have_full_edid || si->ps.crtc2_screen.have_full_edid) {
87 		LOG(4,("GET_PREFERRED_DISPLAY_MODE: full EDID known, aborting (fetch EDID instead).\n"));
88 		return B_ERROR;
89 	}
90 
91 	if (!si->ps.crtc1_screen.have_native_edid && !si->ps.crtc2_screen.have_native_edid) {
92 		LOG(4,("GET_PREFERRED_DISPLAY_MODE: native mode(s) not known\n"));
93 		return B_ERROR;
94 	}
95 
96 	/* if we got here then we're probably on a laptop, but DDC/EDID may have failed
97 	 * for another reason as well. */
98 	LOG(4,("GET_PREFERRED_DISPLAY_MODE: returning mode\n"));
99 
100 	/* if we have two screens, make the best of it (go for the best compatible mode) */
101 	if (si->ps.crtc1_screen.have_native_edid && si->ps.crtc2_screen.have_native_edid) {
102 		/* return mode of screen with lowest aspect (4:3 takes precedence over ws)
103 		 * NOTE:
104 		 * allow 0.10 difference so 4:3 and 5:4 aspect screens are regarded as being the same. */
105 		if (si->ps.crtc1_screen.aspect < (si->ps.crtc2_screen.aspect - 0.10)) {
106 			get_crtc1_screen_native_mode(preferredMode);
107 		} else {
108 			if (si->ps.crtc1_screen.aspect > (si->ps.crtc2_screen.aspect + 0.10)) {
109 				get_crtc2_screen_native_mode(preferredMode);
110 			} else {
111 				/* both screens have the same aspect, return mode of the one with
112 				 * the lowest native resolution */
113 				if (si->ps.crtc1_screen.timing.h_display < si->ps.crtc2_screen.timing.h_display)
114 					get_crtc1_screen_native_mode(preferredMode);
115 				if (si->ps.crtc1_screen.timing.h_display > si->ps.crtc2_screen.timing.h_display)
116 					get_crtc2_screen_native_mode(preferredMode);
117 
118 				/* if both screens have the same resolution and aspect, return mode of the
119 				 * one used as main screen */
120 				if (si->ps.crtc1_screen.timing.h_display == si->ps.crtc2_screen.timing.h_display) {
121 					if (si->ps.crtc2_prim)
122 						get_crtc2_screen_native_mode(preferredMode);
123 					else
124 						get_crtc1_screen_native_mode(preferredMode);
125 				}
126 			}
127 		}
128 	} else {
129 		/* there's just one screen of which we have native mode information, return it's mode */
130 		if (si->ps.crtc1_screen.have_native_edid)
131 			get_crtc1_screen_native_mode(preferredMode);
132 		else
133 			get_crtc2_screen_native_mode(preferredMode);
134 	}
135 
136 	return B_OK;
137 }
138 
139 #endif	// __HAIKU__
140